CodeEngn Reversing Advance_Level09


이름과 비밀번호를 입력한다. 이후 결과에 따라 메시지를 띄운다.

PEiD가 감지한 패킹은 없다.

함수 호출을 따라가 프로그램 로직이 시작하는 부분을 찾았다.

비밀번호를 입력한 뒤 호출하는 함수에서 아이디와 비밀번호를 검증한다.

입력한 아이디와 DonaldDuck을 비교한다. 일단 Username은 DonaldDuck임을 알 수 있다.

비교한 뒤 긴 push문과 함수 호출로 한 글자씩 출력한다. 이는 실패 메시지이다.


Username을 비교하는 부분이다. 맨 밑의 JNZ에서 점프를 해야한다. Username이 DonaldDuck이 아닐 때 점프를 한다.

하지만 이를 피해 점프를 해도 실패한다. BL 레지스터 값이 0이면 실패 루틴으로 점프한다. EBX가 어디서 설정되는지 살펴보자.

처음 함수에 들어와 TEST EAX, EAX 후 Z flag 값을 EBX 값으로 설정한다.

EAX에는 Username을 저장한 주소가 있다.
SBB EAX, EAX는 EAX -= (EAX - carry) 를 의미하고, SBB EAX, -1은 EAX -= (-1 - carry)를 의미한다.
일반적으로 이름을 입력하면 SBB 코드로 점프한다. SBB 코드 위의 XOR 코드로 점프할 수 있다면 우회할 수 있다.
XOR 코드로 도달하는 방법을 찾아본다.

이는 함수에 처음 들어왔을 때이다. ECX에는 NULL 문자로 채워진 곳의 주소가 있고, EAX에는 Username을 저장한 주소가 있다. 입력값이 NULL이라면 XOR 코드로 갈 수 있다. 메모리를 조작하여 NULL로 바꿔준다.

BL 레지스터를 해결해도 한 가지 더 해결해야 하는 일이 있다. ESP+0xB 주소에 있는 값이 0이 아니어야 한다.

이는 이 위치에서 조작된다. 앞의 BL을 설정하는 코드 바로 다음에 있다. CMP EAX, DWORD PTR [ECX] 결과로 설정한 Z flag의 값을 저장한다. 즉, EAX와 ECX가 가리키는 위치의 4바이트 값이 같아야 한다.

하드웨어 브레이크 포인트를 이용하여 이 메모리에 어떻게 값이 설정되는지 살펴본다. ECX가 가리키는 값은 위의 루틴에서 설정된다.
이 값은 000302A0으로 고정 값이다. 이 주소에는 아래와 같은 값이 있다. 위의 코드에서 VirtualAlloc 함수 후 88228F를 채워넣는 모습을 볼 수 있다.

EAX 값은 길이가 Password를 입력하여 넣을 수 있다. 이 때, 값은 숫자만 가능하다. 10진수 숫자를 입력받아 저장한다. 따라서 0x88228f를 10진수로 쓴 8921743를 쓴다.

flag는 8921743 이다.