writeup/해킹캠프CTF 2014

2014 동계 해킹캠프 미니 CTF WinRev 풀이

진모씨 2014. 2. 19. 15:21

대충 열어보면 Visual C++ 컴파일러로 컴파일한듯한 바이너리가 나온다.

main함수를 습관적으로 찾다보면 0x4016B0이 나온다. 어떻게 찾나면, ExitProcess라는 함수가 맨 마지막에 호출되는데 이때 넣는 인수값이 "오류 코드"이다. 실행 후 %errorlevel% 환경변수로 쓰일 수 있는 값인데 여기 쓰이는 인자를 0x4016B0 함수에서 리턴한다. 이 함수를 main함수라 보면 된다.

main함수는 인자가 이렇다.


int argc, char *argv[], char *envp[]

argc가 2인지 검사한 후 맞으면 argv[1] (첫번 째 인자이다) 값을 하나하나 비교하는데, 첫글자부터 0x77, 0x69, 0x73, 0x65, 0x4F랑 비교해서 틀릴때마다 nope 를 출력하고 끝낸다.


코드로 설명해보자.


.text:004016BE                 cmp     [ebp+arg_0], 2

.text:004016C2                 jz      short loc_4016E3


그렇다. arg_0(4를 뜻한다)이 2인지 체크해서 맞다면 4016E3으로 점프한다. 틀리면 argv[0]과 사용법을 출력한 후 바로 리턴한다.

4016E3으로 가보자.


.text:004016E3                 mov     eax, [ebp+arg_4]

.text:004016E6                 add     eax, 4

.text:004016E9                 mov     eax, [eax]

.text:004016EB                 movzx   eax, byte ptr [eax]

.text:004016EE                 cmp     al, 77h

.text:004016F0                 jnz     loc_4017A1

.text:004016F6                 mov     eax, [ebp+arg_4]

.text:004016F9                 add     eax, 4

.text:004016FC                 mov     eax, [eax]

.text:004016FE                 add     eax, 1

.text:00401701                 movzx   eax, byte ptr [eax]

.text:00401704                 cmp     al, 69h

.text:00401706                 jnz     loc_40178E

.text:0040170C                 mov     eax, [ebp+arg_4]

.text:0040170F                 add     eax, 4

.text:00401712                 mov     eax, [eax]

.text:00401714                 add     eax, 2

.text:00401717                 movzx   eax, byte ptr [eax]

.text:0040171A                 cmp     al, 73h

.text:0040171C                 jnz     short loc_40177B

.text:0040171E                 mov     eax, [ebp+arg_4]

.text:00401721                 add     eax, 4

.text:00401724                 mov     eax, [eax]

.text:00401726                 add     eax, 3

.text:00401729                 movzx   eax, byte ptr [eax]

.text:0040172C                 cmp     al, 65h

.text:0040172E                 jnz     short loc_401768

.text:00401730                 mov     eax, [ebp+arg_4]

.text:00401733                 add     eax, 4

.text:00401736                 mov     eax, [eax]

.text:00401738                 add     eax, 4

.text:0040173B                 movzx   eax, byte ptr [eax]

.text:0040173E                 cmp     al, 4Fh

.text:00401740                 jnz     short loc_401755

.text:00401742                 mov     [esp+10h+var_10], offset aGood ; "good!"

.text:00401749                 call    puts

.text:0040174E                 mov     eax, 0


그냥 보면 알 수 있다.


mov     eax, [ebp+arg_4]

라는건..

ebp+arg_4, 즉 argv의 값을 eax에 넣는다.

그다음

add     eax, 4

를 하는데, eax를 4만큼 더해준다. 즉 char *argv[]니까 argv[1]의 주소를 알려준다. 이 형식은 char *가 될것이다.


add      eax, 1~4 (각각 다르다)

mov     eax, [eax]


1, 2, 3, 4만큼 각각 더해준다. 0을 더하는건 생략되어있다.


그러니까 각각 argv[1][0], argv[1][1], argv[1][2], argv[1][3], argv[1][4]를 비교해서 wiseO면 된다.

wiseO의 아스키코드가 앞서 말했듯이 0x77, 0x69, 0x73, 0x65, 0x4F 이기 때문이다. 16진수로 그렇다.


실행해보면 good!이 뜬다.

cmd에서 그 경로로 가서

WinRev.exe wiseO

를 실행해보면 된다.