이것저것

[Reversing.kr] Easy Crack

pental 2025. 7. 12. 20:22

흠,, 포렌식만 공부하다가 이제 리버싱도 슬슬 해볼까 해서 reversing.kr 을 풀어보기 시작했다.

역시 리버싱은 공부해도 어려운것 같다.. 포렌식 보다 훨씬 더,, 해당 포스팅은 포렌식 7년차의 리버싱 입문기라고 생각하고, 틀린점이 있어도 그냥 귀엽게 넘어가 주면 좋겠다.

Easy_CrackMe.exe의 파일은 다음과 같다.

FileName Easy_CrackMe.exe
FileSize 40,960 Byte
CRC32 FE454D60
MD5 A74DB218A9175E0AE2CCFFB3476DD4CF
SHA-1 F153F26F16B5AE03E3A7BE7FFE5395E966051F3B

Easy_CrackMe.exe 를 실행하면 다음과 같은 창이 나타난다.

아무거나 입력 후 확인을 클릭하면 다음과 같이 Incorrect Password 와 같은 알림창이 나타난다.

IDA 9.1 Free를 통해서 파일을 연다.

IDA Free를 통해서 바이너리 파일을 열어보면 자동으로 시작점을 잡아 준다.

사실 IDA를 쓸줄은 모르지만 그래도 깔짝깔짝 써보려고 한다… 리버싱 입문자,,

먼저 초기에 정의되는 부분에서는 다음과 같은 힌트를 확인 할 수 있다.

이 상태에서 Tab 키를 누르면 디컴파일된 코드로 확인 할 수 있다.

사실 이게 중요한건 아니고, 위에서 순서대로 살펴보면 다음과 같다.

mov     eax, [esp+hInstance]
push    0               ; dwInitParam
push    offset DialogFunc ; lpDialogFunc
push    0               ; hWndParent
push    65h             ; lpTemplateName
push    eax             ; hInstance
call    ds:DialogBoxParamA
xor     eax, eax
retn    10h
_WinMain@16 endp

이 부분에서는 mov eax, [esp+hInstance] 에서는 스택에서 첫번쨰 인자 hInstace를 가져오는 것이다.

이 값은 WinMain(HINSTACE hInstace, …) 에서의 hInstace이다.

다음 push 인자들에서는 DialogBoxParamA함수의 인자들을 푸쉬하는 부분이다.

즉 다음과 같은 시그니처를 가진다고 할 수 있다.

INT_PTR DialogBoxParamA(
  HINSTANCE hInstance,
  LPCSTR lpTemplateName,
  HWND hWndParent,
  DLGPROC lpDialogFunc,
  LPARAM dwInitParam
);

중요한건 아닌것 같으니 넘어간다..

shift+F12를 통해서 사용되는 문자열을 확인 할 수 있으며, 위에서 Incorrect PAssword와 같은 문자열을 확인 했기에, IDA Strings 기능을 통해서 확인한다.

Strings에서는 74개의 문자열들이 발견 되었으며, Incorrect Password 및 Congratulaion !! 등의 문자열 패턴을 확인 할 수 있다.

아까 Incorrect Password 부분에서 잘못된 암호가 입력되었기 때문에, 해당 값을 더블클릭하여 어떤 구조로 되어 있는지 확인한다.

sub_401080에서 조건 문 들을 확인 할 수 있다.

cmp [esp+68h+Stirngs], 45h; ‘E’ 부분에서 cmp는 compare를 나타내며, 이 문자가 동일한지 확인하고, Congrautulation !! 이 출력되도록 하는 구조이다.

위에서 부터 차근차근 확인해 본다.

sub_401080 proc near

String= byte ptr -64h
var_63= byte ptr -63h
Str1= byte ptr -62h
var_60= byte ptr -60h
hDlg= dword ptr  4

sub     esp, 64h
push    edi
mov     ecx, 18h
xor     eax, eax
lea     edi, [esp+68h+var_63]
mov     [esp+68h+String], 0
push    64h ; 'd'       ; cchMax
rep stosd
stosw
stosb
mov     edi, [esp+6Ch+hDlg]
lea     eax, [esp+6Ch+String]
push    eax             ; lpString
push    3E8h            ; nIDDlgItem
push    edi             ; hDlg
call    ds:GetDlgItemTextA
cmp     [esp+68h+var_63], 61h ; 'a'
jnz     short loc_401135

첫 함수의 시작에서는 다이얼로그 박스에서 에디트박스의 텍스트를 읽어온 후, 그 텍스트의 첫번쨰 문자가 ‘a’ 인지 확인하는 함수이다.

push    2               ; MaxCount
lea     ecx, [esp+6Ch+Str1]
push    offset Str2     ; "5y"
push    ecx             ; Str1
call    _strncmp
add     esp, 0Ch
test    eax, eax
jnz     short loc_401135

그 다음 함수는 strcpm를 호출하여, Str1이라는 버퍼의 값이 문자열 “5y”와 같은지를 확인하고, 앞에서 부터 두 글자만 비교하고, 같지 않으면 loc_401135로 분기하는 함수이다.

push    ebx
push    esi
mov     esi, offset aR3versing ; "R3versing"
lea     eax, [esp+70h+var_60]

위에서 조건이 맞다면, 문자열 “R3versing”의 주소를 esi에 저장한다.

이 문자열은 PE 리소스의 .rdata 섹션 등에 존재하는 고정 문자열일 가능성이 높다.

그리고, 지역 변수 var_60의 주소를 계산해서 eax에 저장한다. 즉, eax = 문자열을 복사할 목적지 버퍼의 주소를 나타낸다.

cmp     [esp+68h+String], 45h ; 'E'
jnz     short loc_401135

이건 간단히 말하면 스택에 있는 String이라는 버퍼의 첫 번째 바이트가 ‘E’ 인지 검사하고, 그렇지 않으면 loc_401135로 점프하는 조건문이다.

결국 지금까지 나온 값들을 종합하면 ‘Ea5yR3versing’ 이 정답이 되게 된다.