Header

  1. View current page

    wiki.0range.net

Profile_image?t=1255877728&type=small
지극히 개인적인 wiki입니다
1

jz_crackme 풀이

 

집에와서 jz님이 만드신 크랙미를 살펴보았습니다.

제 언팩미 1탄을 상세하게 풀어주셔서 고마운 마음에 답례(?)를 하기 위해서 열심히 IDA를 돌렸지요. ^^

순전히 저의 추측으로만 분석을 한것이어서 정답이 아닐수도 있어서 염려가 됩니다.

 

안티 디버깅은 2가지 정도 찾았는데 못찾은것이 더 있을 가능성도 있습니다.

안티디버깅 이후에 비로소 사용자 키값을 처리하는 루틴과 키값을 암호화후 비교하는 루틴이 있습니다.

살펴볼 루틴은 다음과 같습니다.

 

  • Explorer.exe의 프로세스와 jz_crackme.exe프로세스내 ntdll.dll의 코드섹션을 비교하여서 틀린 부분이 있으면 안티디버깅 루틴 수행
  • Trap Flag를 설정후 SEH핸들러가 실행되는지 확인하여 안티디버깅 루틴 수행
  • 시간측정 루틴(입력시간 초과 방지용)
  • 입력된 패스워드를 암호화하는 함수

 

안티 디버깅 루틴은 프로그램을 종료시키는 단순한 방식이 아닌, 정답이 제대로 안나오게 방해하는 역활을

수행하는것 같습니다. 덕분에 badfood를 밤새 많이 먹었네요 ;;

일단 안티디버깅 루틴부터 살펴보겠습니다.

 

1. explorer::ntdll.dll과  jz_crackme::ntdll.dll의 코드섹션 비교하는 안티디버깅 분석

 

explorer.exe PID검색 루틴

.text:004010E7 loc_4010E7:                             ; CODE XREF: _main+CEj

.text:004010E7                 lea     edx, [ebp+dwProcessId]

.text:004010ED                 push    edx

.text:004010EE                 push    offset aExplorer_exe ; "explorer.exe"

.text:004010F3                 call    maybe_GetPidByProcessName

.text:004010F8                 add     esp, 8

.text:004010FB                 test    eax, eax

.text:004010FD                 jnz     short loc_401104

.text:004010FF                 jmp     loc_4011D1


maybe_GetPidByProcessName 내부를 살펴보면 TlHelp32 함수를 이용하여 전달된 함수명으로 Pid를 구하고 있습니다.

 

 

explorer.exe의 ntdll 코드섹션을 읽어 오는 루틴

 

.text:00401104 loc_401104:                             ; CODE XREF: _main+FDj

.text:00401104                 mov     eax, [ebp+Size]

.text:0040110A                 push    eax             ; dwSize

.text:0040110B                 mov     ecx, [ebp+lpMem]

.text:00401111                 push    ecx             ; lpBuffer

.text:00401112                 mov     edx, [ebp+maybe_Ntdll_CodeSectionAddress]

.text:00401118                 push    edx             ; lpAddress

.text:00401119                 mov     eax, [ebp+dwProcessId]

.text:0040111F                 push    eax             ; dwProcessId

.text:00401120                 call    maybe_ReadMemoryFromPid

.text:00401125                 add     esp, 10h

.text:00401128                 test    eax, eax

.text:0040112A                 jnz     short loc_401131

.text:0040112C                 jmp     loc_4011D1

 

 

maybe_ReadMemoryFromPid 의 내부는 전달된 Pid를 OpenProcess하여 메모리를 읽어서 리턴하는 함수입니다.

 

for문을 돌면서 explorer::ntdll의 코드섹션과 jz_crackme.exe::ntdll의 코드섹션과 비교하는 루틴

 

.text:00401154 loc_401154:                             ; CODE XREF: _main+150j

.text:00401154                 mov     [ebp+maybe_for_i_value], 0

.text:0040115E                 jmp     short loc_40116F

.text:00401160 ; ---------------------------------------------------------------------------

.text:00401160

.text:00401160 loc_401160:                             ; CODE XREF: _main:loc_4011CFj

.text:00401160                 mov     ecx, [ebp+maybe_for_i_value]

.text:00401166                 add     ecx, 1

.text:00401169                 mov     [ebp+maybe_for_i_value], ecx

.text:0040116F

.text:0040116F loc_40116F:                             ; CODE XREF: _main+15Ej

.text:0040116F                 mov     edx, [ebp+maybe_for_i_value]

.text:00401175                 cmp     edx, [ebp+Size]

.text:0040117B                 jge     short loc_4011D1

.text:0040117D                 mov     eax, [ebp+lpMem]

.text:00401183                 add     eax, [ebp+maybe_for_i_value]

.text:00401189                 xor     ecx, ecx

.text:0040118B                 mov     cl, [eax]

.text:0040118D                 mov     edx, [ebp+var_524]

.text:00401193                 add     edx, [ebp+maybe_for_i_value]

.text:00401199                 xor     eax, eax

.text:0040119B                 mov     al, [edx]

.text:0040119D                 cmp     ecx, eax

.text:0040119F                 jz      short loc_4011CF

.text:004011A1                 mov     ecx, maybe_DebuggerFuckRandomValue

.text:004011A7                 add     ecx, 900Dh

.text:004011AD                 mov     maybe_DebuggerFuckRandomValue, ecx

.text:004011B3                 mov     edx, [ebp+var_524]

.text:004011B9                 add     edx, [ebp+maybe_for_i_value]

.text:004011BF                 mov     eax, [ebp+lpMem]

.text:004011C5                 add     eax, [ebp+maybe_for_i_value]

.text:004011CB                 mov     cl, [eax]

.text:004011CD                 mov     [edx], cl

.text:004011CF

.text:004011CF loc_4011CF:                             ; CODE XREF: _main+19Fj

.text:004011CF                 jmp     short loc_401160

 

 

 

maybe_DebuggerFuckRandomValue는 틀린 부분이 발견될때마다 900dh 값을 더해주는 것을 볼 수 있습니다.

maybe_DebuggerFuckRandomValue는 정답비교시 방해하는 역활을 하는 값으로 0 값을 유지해야만 합니다.

 

Trap Flag를 설정후 SEH핸들러가 실행되는지 확인하여 안티디버깅 루틴 수행

 


.text:00401203 loc_401203:                             ; CODE XREF: _main+1F2j

.text:00401203                 push    offset seh_DebuggerNotFoundContinueExecution ; 디버거 체크

.text:00401208                 push    large dword ptr fs:0

.text:0040120F                 mov     large fs:0, esp

.text:00401216                 pushf

.text:00401217                 push    edx

.text:00401218                 or      [esp+584h+var_580], 100h ; eflag pushf후 trap 플래그를 설정하여 디버거 탐지

.text:00401220                 push    ebx

.text:00401221                 mov     ebx, [esp+588h+var_580]

.text:00401225                 push    ebx

.text:00401226                 popf

.text:00401227                 inc     edx             ; 예외 발생하고 준비된 핸들러가 실행되어야만 함

.text:00401227                                         ; 디버거가 캐치하여 실행하면 badfood -_-

.text:00401228                 inc     edx

.text:00401229                 pop     ebx

.text:0040122A                 pop     edx

.text:0040122B                 add     esp, 4

.text:0040122E                 pop     large dword ptr fs:0

.text:00401235                 add     esp, 4

.text:00401238                 inc     maybe_IsDebuggerFound

.text:0040123E                 rdtsc

.text:00401240                 add     maybe_DebuggerFuckRandomValue, eax

.text:00401246                 jmp     short loc_401268

.text:00401248 ; ---------------------------------------------------------------------------

.text:00401248

.text:00401248 seh_DebuggerNotFoundContinueExecution:  ; DATA XREF: _main:loc_401203o

.text:00401248                 mov     edx, [esp-4+envp]

.text:0040124C                 mov     dword ptr [edx+0B8h], offset seh_RunNextFunction

.text:00401256                 xor     eax, eax

.text:00401258                 retn

.text:00401259 ; ---------------------------------------------------------------------------

.text:00401259

.text:00401259 seh_RunNextFunction:                    ; DATA XREF: _main+24Co

.text:00401259                 pop     ebx

.text:0040125A                 pop     edx

.text:0040125B                 add     esp, 4

.text:0040125E                 pop     large dword ptr fs:0

.text:00401265                 add     esp, 4

 

 

seh_DebuggerNotFoundContinueExecution() 예외함수를 SEH Handler로 등록시키고 eflags값의 trap 비트를 설정하여 예외가 발생하게 하고 있습니다.

디버거가 예외를 무시하게 되면 maybe_IsDebuggerFound와 maybe_DebuggerFuckRandomValue값이 설정되고 결국에는 badfood를 맛보게 될 것이지요.

정상적으로 실행이 되면 예외핸들러를 타게 되고 사용자 암호를 물어보는 메인 코드가 실행되게 됩니다

 

입력된 패스워드를 암호화하는 함수

 

정답 확인하는 루틴

 

.text:00401354 loc_401354:                             ; CODE XREF: _main+31Aj

.text:00401354                 mov     ecx, maybe_DebuggerFuckRandomValue

.text:0040135A                 mov     maybe_1st_Copied_DebuggerFuckRandomValue, ecx

.text:00401360                 mov     edx, [ebp+maybe_UserInputedPasswordStrLen]

.text:00401366                 push    edx

.text:00401367                 lea     eax, [ebp+maybe_UserInputedPasswordBuffer]

.text:0040136D                 push    eax

.text:0040136E                 call    maybe_Encryption

.text:00401373                 add     esp, 8

.text:00401376                 mov     [ebp+maybe_EncryptedResultValue], eax

.text:0040137C                 mov     ecx, maybe_1st_Copied_DebuggerFuckRandomValue

.text:00401382                 mov     maybe_2nd_Copied_DebuggerFuckRandomValue, ecx

.text:00401388                 mov     edx, [ebp+maybe_EncryptedResultValue]

.text:0040138E                 xor     edx, maybe_IsDebuggerFound

.text:00401394                 mov     [ebp+maybe_EncryptedResultValue], edx

.text:0040139A                 mov     eax, maybe_2nd_Copied_DebuggerFuckRandomValue

.text:0040139F                 mov     maybe_3rd_Copied_DebuggerFuckRandomValue, eax

.text:004013A4                 mov     ecx, [ebp+maybe_EncryptedResultValue]

.text:004013AA                 xor     ecx, maybe_3rd_Copied_DebuggerFuckRandomValue

.text:004013B0                 mov     [ebp+maybe_EncryptedResultValue], ecx

.text:004013B6                 cmp     [ebp+maybe_EncryptedResultValue], 0AF006DC3h

.text:004013C0                 jz      short loc_4013D1

.text:004013C2                 push    offset aWrong   ; "wrong!\n"

.text:004013C7                 call    maybe_printf

.text:004013CC                 add     esp, 4

.text:004013CF                 jmp     short loc_4013E5

.text:004013D1 ; ---------------------------------------------------------------------------

.text:004013D1

.text:004013D1 loc_4013D1:                             ; CODE XREF: _main+3C0j

.text:004013D1                 lea     edx, [ebp+maybe_UserInputedPasswordBuffer]

.text:004013D7                 push    edx

.text:004013D8                 push    offset aDFS@gmail_comNF ; "정답! %s@gmail.com으로 메일을 보내서 인"...

.text:004013DD                 call    maybe_printf

.text:004013E2                 add     esp, 8

.text:004013E5

.text:004013E5 loc_4013E5:                             ; CODE XREF: _main+3CFj

.text:004013E5                 push    offset aPause   ; "pause"

.text:004013EA                 call    sub_401DB6

 

 

maybe_Encryption 함수가 사용자가 입력한 내용과 길이를 가지고 어떤값을 만들고 리턴해주는 함수입니다.

maybe_Encryption함수의 리턴값을 가지고 maybe_DebuggerFuckRandomValue와 xor 연산을 2번 시켜주고 있습니다.

리턴값은 결국 0AF006DC3h 값이 되어야 함을 004013B6 주소에 알 수가 있습니다.

그러면 maybe_Encryption함수의 내부를 살펴보겠습니다.

 

maybe_Encryption() 함수의 내부

 

maybe_Encryption을 처음보고 해쉬값의 원래 데이터를 찾는게 아닌가 하고 좌절했습니다만, 곧 차근 차근 따라 가보니 힌트가 나오는것을 알 수 있었습니다.

일단 분석을 방해하는 코드를 빨간색으로 색칠후 따라가보겠습니다.

 

방해코드.PNG

 

 

 

.text:00401420 maybe_Encryption proc near              ; CODE XREF: _main+36Ep

.text:00401420

.text:00401420 var_8           = byte ptr -8

.text:00401420 var_4           = dword ptr -4

.text:00401420 InputBuffer     = dword ptr  8

.text:00401420 InputLen        = dword ptr  0Ch

.text:00401420

.text:00401420                 push    ebp

.text:00401421                 mov     ebp, esp

.text:00401423                 sub     esp, 8

.text:00401426                 push    ebx

.text:00401427                 push    esi

.text:00401428                 push    edi

.text:00401429                 mov     [ebp+var_4], 0FEBAF001h

.text:00401430                 mov     eax, [ebp+InputBuffer]

.text:00401433                 movsx   ecx, byte ptr [eax]

.text:00401436                 cmp     ecx, 74h

.text:00401439                 jz      short loc_40144E

.text:0040143B                 mov     edx, [ebp+InputBuffer]

.text:0040143E                 movsx   eax, byte ptr [edx+2]

.text:00401442                 mov     ecx, [ebp+var_4]

.text:00401445                 xor     ecx, eax

.text:00401447                 mov     [ebp+var_4], ecx

.text:0040144A                 rol     [ebp+var_4], 4

.text:0040144E

.text:0040144E loc_40144E:                             ; CODE XREF: maybe_Encryption+19j

.text:0040144E                 rol     [ebp+var_4], 8

.text:00401452                 cmp     [ebp+InputLen], 7

.text:00401456                 jz      short loc_401467

.text:00401458                 mov     edx, [ebp+InputBuffer]

.text:0040145B                 movsx   eax, byte ptr [edx+5]

.text:0040145F                 mov     ecx, [ebp+var_4]

.text:00401462                 xor     ecx, eax

.text:00401464                 mov     [ebp+var_4], ecx

 

 

00401436 를 보시면 InputBuffer는 00000074('t')로 시작되는 것을 알 수 있습니다. 또 00401452에서는 문자열 길이가 7이어야 된다는 것을 알 수 있습니다.

그러면 InputBuffer는 t _ _ _ _ _ _ 이 되겠군요. var_4 값은 FEBAF001 로 설정되고요

 

 

.text:00401467 loc_401467:                             ; CODE XREF: maybe_Encryption+36j

.text:00401467                 rol     [ebp+var_4], 4

.text:0040146B                 mov     edx, [ebp+InputBuffer]

.text:0040146E                 movsx   eax, byte ptr [edx]

.text:00401471                 mov     ecx, [ebp+InputBuffer]

.text:00401474                 movsx   edx, byte ptr [ecx+4]

.text:00401478                 sub     eax, edx

.text:0040147A                 cmp     eax, 2

.text:0040147D                 jz      short loc_401490

.text:0040147F                 mov     eax, [ebp+InputBuffer]

.text:00401482                 movsx   ecx, byte ptr [eax+6]

.text:00401486                 mov     edx, [ebp+var_4]

.text:00401489                 xor     edx, ecx

.text:0040148B                 mov     [ebp+var_4], edx

.text:0040148E                 jmp     short loc_40149F

.text:00401490 ; ---------------------------------------------------------------------------

.text:00401490

.text:00401490 loc_401490:                             ; CODE XREF: maybe_Encryption+5Dj

.text:00401490                 mov     eax, [ebp+InputBuffer]

.text:00401493                 movsx   ecx, byte ptr [eax+4]

.text:00401497                 mov     edx, [ebp+var_4]

.text:0040149A                 xor     edx, ecx

.text:0040149C                 mov     [ebp+var_4], edx

.text:0040149F

.text:0040149F loc_40149F:                             ; CODE XREF: maybe_Encryption+6Ej

.text:0040149F                 mov     eax, [ebp+InputBuffer]

.text:004014A2                 movsx   ecx, byte ptr [eax+4]

.text:004014A6                 mov     edx, [ebp+InputBuffer]

.text:004014A9                 movsx   eax, byte ptr [edx+1]

.text:004014AD                 sub     ecx, eax

.text:004014AF                 cmp     ecx, 0Ah

.text:004014B2                 jz      short loc_4014BA

.text:004014B4                 rol     [ebp+var_4], 10h

.text:004014B8                 jmp     short loc_4014CD

 

00401467 ~ 0040147D 루틴을 분석해 보면, 

var_4 = BAF001FE 가 되고, InputBuffer[0]와 InputBuffer[4]의 차가 2가 된다는 것을 알 수 있습니다.

그러므로 InputBuffer는  t _ _ _ r _ _ 가 됩니다.

 

 

00401490 ~ 004014B2 를 해석 하면,

var_4 = AF001F99 가 되고, InputBuffer[4]와  InputBuffer[1]의 차가 0ah가 된다는 것을 알 수 있습니다.

그러므로 InputBuffer t h _ _ r _ _ 가 됩니다.

 

 

.text:004014BA loc_4014BA:                             ; CODE XREF: maybe_Encryption+92j

.text:004014BA                 mov     ecx, [ebp+InputBuffer]

.text:004014BD                 movsx   edx, byte ptr [ecx+2]

.text:004014C1                 mov     eax, [ebp+var_4]

.text:004014C4                 xor     eax, edx

.text:004014C6                 mov     [ebp+var_4], eax

.text:004014C9                 rol     [ebp+var_4], 8

.text:004014CD

.text:004014CD loc_4014CD:                             ; CODE XREF: maybe_Encryption+98j

.text:004014CD                 mov     ecx, [ebp+InputBuffer]

.text:004014D0                 movsx   edx, byte ptr [ecx+1]

.text:004014D4                 mov     eax, [ebp+InputBuffer]

.text:004014D7                 movsx   ecx, byte ptr [eax+2]

.text:004014DB                 sub     edx, ecx

.text:004014DD                 cmp     edx, 35h

.text:004014E0                 jz      short loc_4014F3

.text:004014E2                 mov     edx, [ebp+InputBuffer]

.text:004014E5                 movsx   eax, byte ptr [edx+5]

.text:004014E9                 mov     ecx, [ebp+var_4]

.text:004014EC                 xor     ecx, eax

.text:004014EE                 mov     [ebp+var_4], ecx

.text:004014F1                 jmp     short loc_4014F7

 

004014BA ~ 004014E0 을 분석해 보면,

var_4 = AF001F99  ^ arg0[2] 가 되고, InputBuffer[1]과 InputBuffer[2]의 차가 35h 가 되며 이는 곳 숫자 '3' 인것을 알 수 있습니다.

그러므로 InputBuffer 는 t h 3 _ r _ _ 가 됩니다.

 

 

이제 마지막 남은 루틴을 분석할 차례입니다. 빨간 부분이 얼마 남아있있지 않군요 ㅎㅎ

 

 

.text:004014F3 loc_4014F3:                             ; CODE XREF: maybe_Encryption+C0j

.text:004014F3                 rol     [ebp+var_4], 10h

.text:004014F7

.text:004014F7 loc_4014F7:                             ; CODE XREF: maybe_Encryption+D1j

.text:004014F7                 mov     edx, [ebp+InputBuffer]

.text:004014FA                 movsx   eax, byte ptr [edx]

.text:004014FD                 mov     ecx, [ebp+InputBuffer]

.text:00401500                 movsx   edx, byte ptr [ecx+3]

.text:00401504                 sub     eax, edx

.text:00401506                 mov     [ebp+var_8], al

.text:00401509                 movsx   eax, [ebp+var_8]

.text:0040150D                 mov     ecx, [ebp+var_4]

.text:00401510                 xor     ecx, eax        ; var4 = AAAF001F

.text:00401510                                               ; var8 = 't' - arg0[3]

.text:00401512                 mov     [ebp+var_4], ecx

.text:00401515                 mov     edx, [ebp+InputBuffer]

.text:00401518                 movsx   eax, byte ptr [edx+4]

.text:0040151C                 mov     ecx, [ebp+var_4]

.text:0040151F                 xor     ecx, eax

.text:00401521                 mov     [ebp+var_4], ecx

.text:00401524                 rol     [ebp+var_4], 8

.text:00401528                 mov     edx, [ebp+InputBuffer]

.text:0040152B                 movsx   eax, byte ptr [edx+5]

.text:0040152F                 cmp     eax, 69h

.text:00401532                 jz      short loc_40153B

.text:00401534                 mov     [ebp+var_4], 0F001F001h

.text:0040153B

.text:0040153B loc_40153B:                             ; CODE XREF: maybe_Encryption+112j

.text:0040153B                 mov     ecx, [ebp+InputBuffer]

.text:0040153E                 movsx   edx, byte ptr [ecx+5]

.text:00401542                 mov     eax, [ebp+var_4]

.text:00401545                 xor     eax, edx

.text:00401547                 mov     [ebp+var_4], eax

.text:0040154A                 mov     ecx, [ebp+InputBuffer]

.text:0040154D                 movsx   edx, byte ptr [ecx+6]

.text:00401551                 cmp     edx, 6Eh

.text:00401554                 jz      short loc_40155D

.text:00401556                 mov     [ebp+var_4], 0BADDF00Dh

.text:0040155D

.text:0040155D loc_40155D:                             ; CODE XREF: maybe_Encryption+134j

.text:0040155D                 mov     eax, [ebp+var_4]

.text:00401560                 pop     edi

.text:00401561                 pop     esi

.text:00401562                 pop     ebx

.text:00401563                 mov     esp, ebp

.text:00401565                 pop     ebp

.text:00401566                 retn

.text:00401566 maybe_Encryption endp

 

 

004014F3 ~ 00401524 까지는 InputBuffer[3]값과 InputBuffer[4]값을 가지고 var_4를 변화시킵니다.

 

여기서 부터는 var_4값을 따라가는 것을 포기했습니다. InputBuffer[3]값을 알 수 없었기 때문에 머리가 안돌아가 더라구요;;

0040152B ~ 00401532 을 보시면, InputBuffer[5]값이 'i'(69h)와 같은 지 비교하는 것을 알 수 있기 떄문에,

InputBuffer는 t h 3 _ r i _ 가 됩니다.

 

0040154A ~ 00401554를 해석해 보면, InputBuffer[6]이 'n'(6eh)가 되는 것을 알 수 있습니다.

그러므로 InputBuffer는 t h 3 _ r i n 이 됩니다.

함수의 끝은 현재까지 변화된 var_4를 리턴하게 됩니다. 그러나 저는 var_4를 분석을 중간에 포기했기때문에 th3_rin 값만 알 수 있었습니다.

 

여기서 선택할 수 있습니다. bruteforce 입력을 하여서 남은 1자리의 문자를 맞출 수 있기도 합니다. 실제로 성질 급한 저는 그렇게도 해보았습니다.

그러나 'wrong'만 나오더라구요. 나중에 알고 보니 안티디버깅 루틴중 ntdll의 code section비교 루틴이 있는데, 제 컴퓨터에서는 디버거가

없어도 코드 섹션 비교가 동일하지 않게 나오는 지 정상적인 상태에서도 답을 알아 낼 수 가 없었습니다. OTL

그래서 엄청나게 많은 badfood를 맛보았습니다.

결국 올리를 붙여서 값을 추적할 수 밖에 없었습니다.

 

앞서 설명드린 내용중에 다음과 같이 Encryption함수가 리턴하는 값을 비교하는 루틴을 아래와 같이 보여 드렸습니다.

 

 

.text:00401360                 mov     edx, [ebp+maybe_UserInputedPasswordStrLen]

.text:00401366                 push    edx

.text:00401367                 lea     eax, [ebp+maybe_UserInputedPasswordBuffer]

.text:0040136D                 push    eax

.text:0040136E                 call    maybe_Encryption

.text:00401373                 add     esp, 8

.text:00401376                 mov     [ebp+maybe_EncryptedResultValue], eax

... 생략 ...

.text:004013B6                 cmp     [ebp+maybe_EncryptedResultValue], 0AF006DC3h

.text:004013C0                 jz      short loc_4013D1

... 생략 ...

.text:004013D8                 push    offset aDFS@gmail_comNF ; "정답! %s@gmail.com으로 메일을 보내서 인"...

.text:004013DD                 call    maybe_printf

.text:004013E2                 add     esp, 8

 

 

여기서 00401373에 브레이크포인트를 걸고 'th3_rin'값을 입력하였을때 결과를 확인하여 보았습니다.

AF0078C3 값이 리턴됩니다. 이번에는 'th3arin'값을 입력하여 보았습니다. AF007EC3 값이 나옵니다. '_'문자와 'a'문자를

다르게 입력하여도 AF00??C3h 값이 유지되는것을 볼 수 있었습니다. 여기서 위에서 포기한 var_4 변경 루틴을

조금더 살펴 보겠습니다.

 

살펴볼 부분은 다음과 같습니다.

 

 

.text:004014F7 loc_4014F7:                             ; CODE XREF: maybe_Encryption+D1j

.text:004014F7                 mov     edx, [ebp+InputBuffer]

.text:004014FA                 movsx   eax, byte ptr [edx]

.text:004014FD                 mov     ecx, [ebp+InputBuffer]

.text:00401500                 movsx   edx, byte ptr [ecx+3]

.text:00401504                 sub     eax, edx

.text:00401506                 mov     [ebp+var_8], al

.text:00401509                 movsx   eax, [ebp+var_8]

.text:0040150D                 mov     ecx, [ebp+var_4]

.text:00401510                 xor     ecx, eax

.text:00401512                 mov     [ebp+var_4], ecx

.text:00401515                 mov     edx, [ebp+InputBuffer]

.text:00401518                 movsx   eax, byte ptr [edx+4]

.text:0040151C                 mov     ecx, [ebp+var_4]

.text:0040151F                 xor     ecx, eax

.text:00401521                 mov     [ebp+var_4], ecx

.text:00401524                 rol     [ebp+var_4], 8

.text:00401528                 mov     edx, [ebp+InputBuffer]

.text:0040152B                 movsx   eax, byte ptr [edx+5]

.text:0040152F                 cmp     eax, 69h

.text:00401532                 jz      short loc_40153B

 

 

입력값을 'th3_rin'을 입력하고 0040151F에 브레이크포인트를 걸고 eax값과 var_4를 확인해 보았습니다.

eax = 00000072 ('r')  InputBuffer[4] 문자

ecx = AAAF000A

이 되며, var4에는 eax xor ecx한 값 AAAF0078이 들어가게 됩니다. 그리고 이 값을 8bit 왼쪽으로 로테이트 쉬프트 시키면

AF0078AA값 됩니다. AA값은 maybe_Encryption함수가 리턴할 즈음에 C3값으로 바뀝니다. 그래서 리턴되는 값은

AF0078C3 이 됩니다. AF0078C3 값은 AF00??C3 패턴과 유사합니다. 즉 InputBuffer[3]값에 따라서 ??가 정해지고, ??값은

6d가 되어야 비교문(0AF006DC3h와 비교)을 통과할 수 있는 것입니다. 

 

다시 0040151F 을 살펴보겠습니다. xor ecx, eax('r')=00000072 을 했을 때, 결과값이 6d가 되는 값을 찾으면 되겠습니다.

 

           ??  = 0001 1111 -> 1f

xor)     72  = 0111 0010 -> 72

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

           6d  = 0110 1101

 

이렇게 계산 해보니, 1f 가 나옵니다. 그러면 ecx값은 AAAF000A(th3_rin 입력시의 값)이 아닌 AAAF001F(올바른 값입력시)이 되어야만

한다는 것을 알 수 있습니다. 그러면 과연 InputBuffer[3]에 어떤값을 넣어야 var4의 값이 AAAF001F값이 나올까요..?

답을 찾기 위해 이번에는 조금 더 윗부분을 조사해 보겠습니다.

 

00401510 을 보시면 var_4 값을 가지고 eax값이 xor연산을 하는 부분이 있습니다. 이번에는 여기에 브레이크포인트를 걸고 살펴 보겠습니다.

마찬가지로 입력값은 'th3_rin' 입니다.

eax = 00000015

ecx = AAAF001F

 

여기서 xor연산을 하게 되면 ecx는 AAAF000A로 바뀌게 됩니다. 그러나 위에서 살펴보았듯이 우리가 원하는 값은 AAAF001F가 되어야만

합니다. AAAF001F = AAAF001F xor eax 의 연산에서 eax가 0이 되면 자기 자신값 AAAF001F이 나올수 있습니다.

 

그렇다면 이번에는 eax값을 0이 되도록 하는 부분을 살펴보겠습니다.

00401504 을 보시면 eax(InputBuffer[3])에서 edx(InputBuffer[0] = 74('t'))을 빼주는 것을 볼 수 있습니다. 여기서 eax가 0이 되려면

edx와 동일한 값 74('t')이면 되겠습니다. 즉 InputBuffer[3]은 74('t')라는 것을 알 수 있겠습니다.

 

종합해보면 InputBuffer는 't h 3 t r i n'이 되어야 maybe_Encryption함수가 올바른 리턴값 0AF006DC3h을 리턴하는 것을 알 수 있습니다.

 

최종적으로 확인해 보겠습니다.

 

최종.PNG

 

이제 제대로 맞게 풀었는지 여쭤봐야겠습니다. 


 

 

 

 

 

 

History

Last edited on 05/01/2009 15:10 by seyool

Comments (0)

You must log in to leave a comment. Please sign in.