[RENA] 1번 Do you know CreateFile?

2017. 10. 23. 05:510x02 Reverse Engineer/0x03. Etc

728x90

우선 바이너리는 TASM / MASM / FASM - assembler 

즉, 순수한 어셈블리어로 컴파일 되어 있는 바이너리이다.


바이너리를 열어서 트레이싱 하다보면 CreateFile이 보인다.

0040105C   .  6A 00         push 0x0                                 ; |/hTemplateFile = NULL

0040105E   .  68 6F214000   push reverseM.0040216F                   ; ||Attributes = READONLY|HIDDEN|SYSTEM|ARCHIVE|TEMPORARY|402048

00401063   .  6A 03         push 0x3                                 ; ||Mode = OPEN_EXISTING

00401065   .  6A 00         push 0x0                                 ; ||pSecurity = NULL

00401067   .  6A 03         push 0x3                                 ; ||ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE

00401069   .  68 000000C0   push 0xC0000000                          ; ||Access = GENERIC_READ|GENERIC_WRITE

0040106E   .  68 79204000   push reverseM.00402079                   ; ||FileName = "Keyfile.dat"

00401073   .  E8 0B020000   call <jmp.&KERNEL32.CreateFileA>         ; |\CreateFileA


그 밑에 조건분기문이 존재한다.


00401078   .  83F8 FF       cmp eax,-0x1                             ; |

0040107B   .  75 1D         jnz short reverseM.0040109A              ; |


CreateFileA 함수의 리턴값 (eax)와 -1(0xFFFFFFFF)를 비교하게 되는데 만약 DES와 SOURCE가 같지 않으면 0x0040109A주소로 점프한다.


그렇다면, 0x0040109A주소를 살펴보자.

0040109A   > \6A 00         push 0x0                                 ; /pOverlapped = NULL

0040109C   .  68 73214000   push reverseM.00402173                   ; |pBytesRead = reverseM.00402173

004010A1   .  6A 46         push 0x46                                ; |BytesToRead = 46 (70.)

004010A3   .  68 1A214000   push reverseM.0040211A                   ; |Buffer = reverseM.0040211A

004010A8   .  50            push eax                                 ; |hFile

004010A9   .  E8 2F020000   call <jmp.&KERNEL32.ReadFile>            ; \ReadFile


현재 CreateFileA에서 요구하는 Keyfile.dat파일이 존재하지 않기 때문에 CreateFileA의 리턴 값은 -1(FFFFFFFF)이다.

따라서, CMP 는 -0x1, -0x1 이기 때문에 0이 되므로 jnz에 만족하지 못한다. 


그렇다면, jnz 바로 다음 주소로 진행되게 될 것이다. 그 주소를 알아보자.

메시지박스를 하나 출력하면서 프로세스를 종료시켜버린다.

메시지박스를 읽어보니 기간이 지났으니 라이센스를 새로 구입하라고 한다.

그렇다면, 게씽을 하게 되면, Keyfile.dat는 라이센스 파일이 될 것이다.

0040107D   .  6A 00         push 0x0                                 ; |/Style = MB_OK|MB_APPLMODAL

0040107F   .  68 00204000   push reverseM.00402000                   ; ||Title = " Key File ReverseMe"

00401084   .  68 17204000   push reverseM.00402017                   ; ||Text = "Evaluation period out of date. Purchase new license"

00401089   .  6A 00         push 0x0                                 ; ||hOwner = NULL

0040108B   .  E8 D7020000   call <jmp.&USER32.MessageBoxA>           ; |\MessageBoxA

00401090   .  E8 24020000   call <jmp.&KERNEL32.ExitProcess>         ; \ExitProcess


해당 바이너리의 경로에 Keyfile.dat를 생성한다.

그 후 재시작을 한다.

이번에 다시 한번 유심히 ReadFile함수를 보니 70(0x46)바이트를 요구하는 것으로 보인다.

0040109A   > \6A 00         push 0x0                                 ; /pOverlapped = NULL

0040109C   .  68 73214000   push reverseM.00402173                   ; |pBytesRead = reverseM.00402173

-------------------------------------------요기--------------------------------------------------------

004010A1   .  6A 46         push 0x46                                ; |BytesToRead = 46 (70.)

------------------------------------------------------------------------------------------------------

004010A3   .  68 1A214000   push reverseM.0040211A                   ; |Buffer = reverseM.0040211A

004010A8   .  50            push eax                                 ; |hFile

004010A9   .  E8 2F020000   call <jmp.&KERNEL32.ReadFile>            ; \ReadFile


지금 나의 Keyfile.dat는 0바이트이므로 eax값은 1이므로 

jnz에 만족하지 못한다.

그러므로 jmp short 004010F7로 점프되지 않고, jnz short 004010B4로 점프할 것이다.


jnz short 004010B4를 살펴보면 다음과 같다.

004010B8   .  833D 73214000>cmp dword ptr [0x402173],0x10

// [0x402173]주소의 값과 0x10(16)을 비교한다.

004010BF   . /7C 36         jl short reverseM.004010F7

16보다 [0x402173]의 주소의 값이 0x10보다 작은지 확인한다.

메모리 덤프를 보니 0x00이므로 작다.

따라서 0x4010F7로 그대로 점프 될 것이다.


이러한 결과가 나오게 될 것이다.

004010F7   > \6A 00         push 0x0                                 ; |/Style = MB_OK|MB_APPLMODAL

004010F9   .  68 00204000   push reverseM.00402000                   ; ||Title = " Key File ReverseMe"

004010FE   .  68 86204000   push reverseM.00402086                   ; ||Text = "Keyfile is not valid. Sorry."

00401103   .  6A 00         push 0x0                                 ; ||hOwner = NULL

00401105   .  E8 5D020000   call <jmp.&USER32.MessageBoxA>           ; |\MessageBoxA

0040110A   .  E8 AA010000   call <jmp.&KERNEL32.ExitProcess>         ; \ExitProcess


그렇다면, 우리가 지금 살펴봐야하는 요구사항을 나열해보자.


1) Keyfile.dat 생성

2) Keyfile.dat 안에 70(0x46)가 있어야 한다.


1)은 완료 되었으니 70바이트를 삽입해보자.


그 후 재시작


새로운 요구사항을 찾았다~

004010B8   .  833D 73214000>cmp dword ptr [0x402173],0x10

004010BF   .  7C 36         jl short reverseM.004010F7

004010C1   >  8A83 1A214000 mov al,byte ptr [ebx+0x40211A]

004010C7   .  3C 00         cmp al,0x0

004010C9   .  74 08         je short reverseM.004010D3

004010CB   .  3C 47         cmp al,0x47


여기서 mov al, byte ptr [ebx+0x40211A]를 하고 al과 0x47을 비교하게 되는데...

[ebx+0x40211A]는 Keyfile.dat에 입력해둔 값이 들어간다. 난 지금 A를 입력해두었는데 0x47과 비교를 하기 때문에

G를 입력해야한다. 우선 G로 70바이트 다시 삽입하자


풀었다~~ ^^;;




'0x02 Reverse Engineer > 0x03. Etc' 카테고리의 다른 글

[LENA 3] Let's patch nag !  (0) 2017.10.23
[LENA 2] CreateFile  (0) 2017.10.23
[파일 자동 삭제]  (0) 2017.09.19
[H4C CTF] Let's Bingo !  (0) 2017.09.09
[Basic] Tutorial Reversing - Controlled to printf  (0) 2017.08.25