[CodeEngn Basic 6] You Find OEP

2017. 8. 20. 04:400x02 Reverse Engineer/0x01. CodeEngn

728x90

문제 : Unpack, and find the serial, The solution should be in this format : OEP+SERIAL 


바이너리 실행 : 

 

 [그림 1] 시리얼을 찾아야 한다.


5번 문제와 동일하게 upx로 패킹 된 것을 볼 수 있다.


 

 [그림 2] upx 패킹 



뜯어보자 프로그램 !! 


OEP는 00401360이다. 


프로그램을 살펴보자.


0040146E    E8 9CFBFFFF     call 06.0040100F (bp)


바이너리가 GUI환경으로 이루어져 있기 때문에 다이어그램 텍스트를 찾아야 한다. 


user32.GetDigitemTextA에 BP를 걸었다.


0040105C    FF15 B0524200   call near dword ptr [0x4252B0]           ; user32.GetDlgItemTextA


UINT WINAPI GetDlgItemText(

  _In_  HWND   hDlg,

  _In_  int    nIDDlgItem,

  _Out_ LPTSTR lpString,

  _In_  int    nMaxCount

);


GetDlgItemText function

Retrieves the title or text associated with a control in a dialog box.

Syntax


C++


UINT WINAPI GetDlgItemText(

  _In_  HWND   hDlg,

  _In_  int    nIDDlgItem,

  _Out_ LPTSTR lpString,

  _In_  int    nMaxCount

);


Parameters


hDlg [in]

Type: HWND

A handle to the dialog box that contains the control.

nIDDlgItem [in]

Type: int

The identifier of the control whose title or text is to be retrieved.

lpString [out]

Type: LPTSTR

The buffer to receive the title or text.

nMaxCount [in]

Type: int

The maximum length, in characters, of the string to be copied to the buffer pointed to by lpString. If the length of the string, including the null character, exceeds the limit, the string is truncated.

Return value


Type: UINT

If the function succeeds, the return value specifies the number of characters copied to the buffer, not including the terminating null character.

If the function fails, the return value is zero. To get extended error information, call GetLastError.


출처 : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms645489(v=vs.85).aspx


CONSTANT를 입력하였다.

 

 [그림 3] 키 입력 



입력하자마자 답으로 추정되는 아이와 비교를 하기 위해 스택에 PUSH하는 것을 볼 수 있다.


00401069    68 D4354200     push 06.004235D4                         ; ASCII "CONSTANT"

0040106E    68 302A4200     push 06.00422A30                         ; ASCII "AD46DFS547"


00401073    E8 18020000     call 06.00401290


00401290    8B5424 04       mov edx,dword ptr [esp+0x4]

00401294    8B4C24 08       mov ecx,dword ptr [esp+0x8]

00401073    E8 18020000     call 06.00401290


EDX = AD46DFS547

ECX = CONSTANT 


004012A2    3A01            cmp al,byte ptr [ecx]

ds:[004235D4]=43 ('C')

al=41 ('A')


한 바이트 씩 비교를 하는데 지금 처음 부터 다르기 때문에 004012D4로 진입하게 된다.

004012A4    75 2E           jnz short 06.004012D4



004012D4    1BC0            sbb eax,eax

004012D6    D1E0            shl eax,1

004012D8    40              inc eax

004012D9    C3              retn


만약, 정확한 값이 었다면, 

004012A0    8B02            mov eax,dword ptr [edx]

004012A2    3A01            cmp al,byte ptr [ecx]

004012A4    75 2E           jnz short 06.004012D4

004012A6    0AC0            or al,al

004012A8    74 26           je short 06.004012D0

004012AA    3A61 01         cmp ah,byte ptr [ecx+0x1]

004012AD    75 25           jnz short 06.004012D4

004012AF    0AE4            or ah,ah

004012B1    74 1D           je short 06.004012D0

004012B3    C1E8 10         shr eax,0x10

004012B6    3A41 02         cmp al,byte ptr [ecx+0x2]

004012B9    75 19           jnz short 06.004012D4

004012BB    0AC0            or al,al

004012BD    74 11           je short 06.004012D0

004012BF    3A61 03         cmp ah,byte ptr [ecx+0x3]

004012C2    75 10           jnz short 06.004012D4

004012C4    83C1 04         add ecx,0x4

004012C7    83C2 04         add edx,0x4

004012CA    0AE4            or ah,ah

004012CC  ^ 75 D2           jnz short 06.004012A0

여기에서 JNZ가 만족하지 않게 되면, 


004012CE    8BFF            mov edi,edi

004012D0    33C0            xor eax,eax

004012D2    C3              retn

여기로 가게 되어 EAX=0 값을 반환 할 것이다.


하지만, 지금은 올바르지 않은 값을 세팅했기 때문에 EAX는 -1 (FFFF FFFF)를 가지고 해당 함수를 빠져 나오게 된다. 


0040107B    85C0            test eax,eax

0040107D    75 24           jnz short 06.004010A3


EAX & EAX = FFFF FFFF 


JNZ 이므로 004010A3으로 점프한다.

004010A3    8BF4            mov esi,esp

004010A5    6A 10           push 0x10

004010A7    68 30004200     push 06.00420030                         ; ASCII "ERROR"

004010AC    68 1C004200     push 06.0042001C                         ; ASCII "Wrong serial!!!"

004010B1    8B15 38364200   mov edx,dword ptr [0x423638]

004010B7    52              push edx

004010B8    FF15 B4524200   call near dword ptr [0x4252B4]           ; user32.MessageBoxA


메시지박스 안의 매개변수에 ERROR와 WRONG이 있다. 


올바른 루틴이라면 !!

0040107F    8BF4            mov esi,esp

00401081    6A 40           push 0x40

00401083    68 48004200     push 06.00420048                         ; ASCII "Good Job!"

00401088    68 38004200     push 06.00420038                         ; ASCII "You got it ;)"

0040108D    8B0D 38364200   mov ecx,dword ptr [0x423638]

00401093    51              push ecx

00401094    FF15 B4524200   call near dword ptr [0x4252B4]           ; user32.MessageBoxA


여기로 가게 될 것이다.