codeengn basic 20번 문제다.

드디어 basic 마지막문제. 

키 크랙 문제인 것 같다. crackme3.key라는 파일이 필요한 것 같다.

파일부터 실행해보자. 그냥 실행시키면 뭐가 없다. 

패킹은 따로 되어있지 않다. 바로 열어보자.

우선 문제에서도 나와있듯이 키 파일을 열고 파일내용을 읽는 CreateFile, ReadFile 함수가 보인다.

그냥 돌려보니 역시나 키파일이 없어 정상적으로 동작하지 않는다.

대충 아무값이나 넣고 crackme3.key라는 키 파일부터 만들어서 돌려봤다.

F8로 하나씩 실행하다보니 ReadFile 실행 후 CMP을 보면 4021A0의 값이 내가 입력한 bytes 크기인 9

라고 나온 것 같다. 저 값을 ReadFile에서 지정하고있는 최대바이트크기인 12(10진수로 18)bytes 랑

비교를 하는데 일반적으로 그냥 점프를 하도록 만들기 때문에 점프를 안하고 분기문 안에 있는 코드를

실행시켜보려면 JNZ를 통해 점프를 하면 안되므로 ZF가 1이 되어야 한다. 

파일의 내용을 다음과 같이 18bytes로 바꿔봤다.

동작시켜보니 정상적으로 JNZ SHORT 20.00401037을 통과한다. 그렇다면 이제 그 안을 분석할 차례이다.

우선 의심스러워 보이는 함수 두개를 BP걸고 내부로 들어가봤다. 여기서 이 알고리즘을 이해를 못해서

결국 검색의 힘을 빌려버렸다. 처음엔 풀이를 봐도 잘 이해가 안됬는데 이해하고 보니 그냥 내 어셈블

리어 실력이 문제였다. 명령어 흐름과 메모리구조에대해 공부좀하고 보니 크게 어려운 문제가 아니었다.

하... 어셈블리 ㅠ 

다음은 00401311 함수의 내부 코드다.

분석을 해보면 먼저 XOR을 통해 ECX,EAX를 0으로 초기화 한다.
그다음 키 값이 들어있는 ESP+4를 ESI에 입력한다. 그다음 BL을 0x41로 초기화 한다.

그다음으로는 AL에 키 값이 담긴 ESI를 BYTE단위로 첫번째 부터 넣어준다.

그 후 AL과 BL을 XOR하여 암호화 하는데 예를 들면 현재 내가 입력한 파일의 첫번 째 바이트값인 1의 16진수값인 31과 첫번째 BL값인 41을 XOR하는 경우다. 

다음으로 이렇게 암호화된 AL값을 원래의 바이트 값에 다시 넣어준다.

그 다음 ESI와 BL 값을 1씩 증가시키고 4020F9값에 암호화 시킨 값인 EAX값을 넣어준다.

이 때 암호화된 AL이 0 값이면 함수는 끝이나고 CL은 1씩 증가하는데 총 몇번 반복했는지에 대한 카운트를 나타낸다.

다음으로 BL이 1씩 증가하다가 4F(O)가 되면 함수가 끝이난다.


즉  정상적으로 진행된다면 41(A) ~ 4F(O) 1~14bytes동안 저 형식이 계속해서 반복이 되며  실제로 입

력한 키 값을 XOR를 통해 암호화 하며 변경한다. 그리고 추가적으로 4020F9에 값에는 암호화된 값들

의 총 합이 저장되게 된다.

이렇게 함수가 끝나고 다시 원래 실행흐름으로 돌아오면 

다음과 같이 함수를 통해 암호화된 값들의 총합이 저장된 4020F9의 값과 12345678을 XOR하고 

0040133C 함수를 호출한다. 함수 내부동작을 보기 위해 들어가 봤다.

분석해보면 ESP+4 부분이 파일의 입력한 키 값이 담겨있는데 이를 ESI에 입력하고 ESI값에 0E를 ADD

하여 15byte 위치로 이동한다. 그 후 ESI를 EAX에 넣고 리턴하게되면 EAX에는 파일의 입력된 키 값의

15~18bytes내용이 들어가게 된다.

다음으로 넘어가면 EAX값을 위에서 암호화하였던 4020F9값과 비교한다. 이 부분이 중요한데 다음의 SETE AL을 통해 AL값이 1이 나와야 TEST AL,AL구문을 통해 JE내부로 들어가 성공함수인 00401346으로 들어 갈 수 있다. 그렇다면 SETE AL을 통해 AL값이 1이 나오게 하는게 중요하는데 이를 위해선 CMP EAX,4020F9를 통해 ZF가 1이 되어야 하므로 EAX값이 4020F9값과 같아야한다.  

※SETE에 대해 모르시는 분들이 있으실까 동작원리를 적어드리면 ZF가 1이되면 Byte형 레지스터 즉 여기서 AL을 1로 set하는 명령어다.


현재 값을 확인해 보니 다음과 같았다. 일단 저 부분이 통과될 수 있도록 004020F9부분을 EAX와 같도록 다음과 같이 수정을 해보았다.

실행해보니 다음과 같이 값이 뜬다. 

무슨 값인가 했더니 다음 에서 볼 수 있듯이15~18bytes값을 담고있던 EAX의 앞부분이다. 즉 1~14bytes 부분인 암호화 되어 나온 키 값 부분에 마지막에 !가 함께 나온 것을 알 수 있다.


그렇다면 이제 저 부분이 CodeEngn가 나오도록 하면 CodeEngn!가 출력될 것 같다. 그렇다면

처음에 키 값을 가지고 암호화 해주도록 하는 함수에서 41^입력값첫번째byte=C , 42^입력값두번째byte=o 와 같은 방식으로 8바이트 까지 CodeEngn을 만들고 9번째부터는 null값이 들어가야 되므로 함수를 빠져나올 수 있도록 9번째 byte에 49^00을 통해 AL에 0값을 입력하여 함수를 빠져나오는 조건을 달성시켜준다.

이제 그럼 어떤 값을 입력해야 될지가 문제인데 

xor의 특성인 a^b=c, a^c=b를 활용한다. 즉 2가지값만 알고있으면 나머지하나를 구할 수 있다.

우리는 41~4F의 값과 우리가 도출해내고 싶은 CodeEngn값을 알고있기 때문에 위의 방식을 이용하여

헥스에디터를 통해 다음과 같은 파일을 만들어낸다. 


다음과 같이 넣고 돌려보니. 실패를 했다. ㅡㅡ? 문제가 뭐지 제대로 흐름탄거 같은데 뭔가 했더니 거의 다왔다는생각에 흥분을 했다.


저 CMP구문에서 새로 수정한  파일의 1~14bytes를 통해 만들어진 4020F9값이 1234557B인걸 확인했다. 그렇다면 15~18bytes값을 EAX가 가지고 있기 때문에 파일 내용에서 15~18bytes부분을 다음과 같이 바꾸어봤다.

 


정상적으로 통과하고 다음과 같이 성공하게 된다.


basic이라 쉽게 생각하고 있었는데 마지막 문제풀면서 역시 쌩초보구나 라는걸 다시한번 느꼈다. 혼자

풀다 막혀서 다른분들 풀이까지 참고를 했는데도 어셈블리어를 한번도 제대로 공부해보지 않고 문제풀

면서 하나둘 검색해서 배워가다보니 처음에 흐름이 제대로 이해가 안가서 완벽히 이해하고 푸는데 하루

시간이 걸렸다. 공부를하면할수록 부족하다는 것만 더 느끼게 되는것 같다. 앞으로도 더 열심히 해야

것 같다. 일단 basic은 clear해서 나름 뿌듯한 것 같다. 이제 한숨돌리고 advance로 넘어가보도록 하

다.


'Wargame > CodeEngn' 카테고리의 다른 글

code engn advance 2번  (0) 2018.02.05
code engn advance 1번  (0) 2018.02.04
code engn basic 19번  (0) 2018.02.04
code engn basic 18번  (0) 2018.02.04
code engn basic 17번  (0) 2018.02.04
블로그 이미지

JeonYoungSin

메모 기록용 공간

,