Wargame/Lenas Reversing

[Lenas Reversing for Newbies] 02

maple19out 2021. 1. 26. 23:10

1. 프로그램 실행

01편 강좌와 동일한 reverseMe.exe 파일을 이번에는 패치를 이용하지 않고 크랙을 이용해 문제를 해결한다.

 

2. Debugging(with OllyDbg)

reverseMe.exe 초기 화면

위의 동그라미 친 부분에서 CreateFileA() API가 호출되는 것을 확인할 수 있다. CreateFileA() API는 다음과 같은 형태다.

 

HANDLE CreateFileA(
  LPCSTR                lpFileName,
  DWORD                 dwDesiredAccess,
  DWORD                 dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD                 dwCreationDisposition,
  DWORD                 dwFlagsAndAttributes,
  HANDLE                hTemplateFile
);

OllyDbg에서 넘어가는 argument들을 확인해보면 대상 파일이 "Keyfile.dat"라는 것을 확인할 수 있고 dwCreationDisposition으로 OPEN_EXISTING을 넘겨주었으므로 "Keyfile.dat"가 존재해야 EAX 레지스터(리턴 값)에 -1이 아닌 값이 저장된다. 일단은 "Keyfile.dat"라는 내용 없는 파일을 메모장으로 만들어 reverseMe.exe 파일과 동일한 디렉터리에 위치시킨 후, CreateFileA() API가 호출될 때까지 디버깅을 해보자.

 

Keyfile.dat

 

CreateFileA() API 호출 직후

위와 같이 CreateFileA() API가 호출된 후 EAX 레지스터에는 -1이 아닌 값("Keyfile.dat"의 파일 핸들)이 담겨져 있어 성공적으로 해당 API가 호출되었음을 알 수 있다. 계속 디버깅을 진행해보면 다음과 같은 코드가 나타난다. 

 

ReadFile() API

우선 ReadFile() API가 호출된다. ReadFile() API의 형태는 다음과 같다.

BOOL ReadFile(
  HANDLE       hFile,
  LPVOID       lpBuffer,
  DWORD        nNumberOfBytesToRead,
  LPDWORD      lpNumberOfBytesRead,
  LPOVERLAPPED lpOverlapped
);

위 정보를 바탕으로 OllyDbg의 코드를 해석하면 "Keyfile.dat"로 부터 최대 0x46개의 byte를 읽어서 0040211A 주소(메모리 버퍼)에 저장한다는 뜻이다. 그러나 현재 "Keyfile.dat"에는 아무 내용이 없다. 계속 디버깅을 진행하다 보면 동그라미 친 부분의 

 

2. CMP DWORD PTR DS:[402173], 10

 

코드를 발견할 수 있는데 바로 다음에 JL SHORT 004010F7에 의해 만약에 읽은 바이트 수가 0x10보다 작게되면 크랙에 실패한 문구를 출력하는 부분으로 점프하게 된다. 따라서 "Keyfile.dat"에는 적어도 0x10 byte만큼의 내용이 존재해야 한다. "Keyfile.dat"를 아무 문자나 16개 입력하고 저장한 후, 다시 reverseMe.exe 프로세스를 시작하여 위 CMP 명령어가 나오는 부분까지 디버깅을 진행하자.

 

"Keyfile.dat" 수정
파일 수정 후

위와 같이 "Keyfile.dat"를 'a' 문자 16개로 채운 경우, CMP 명령어에서 sign flag가 세팅이 되지 않으므로 JL 명령어가 수행되지 않는다. 이제 마지막 밑에 몇 줄 안 남은 코드를 살펴보자.

 

마지막 조건 검사

0040211A 주소는 위에서 ReadFile() API가 호출될 때 Buffer의 시작 주소다. 파랗게 표시한 부분을 살펴보면 ESI가 8보다 작을 동안 반복되는 루프인 것을 알 수 있다. 버퍼로부터 한 byte 씩 가져와서 0(NULL)인지 먼저 확인한 후, 0x47와 같은지 확인한다. 이때 0x47은 아스키코드 표를 통해 문자 'G'임을 알 수 있다. 즉 버퍼 시작 부분부터 G가 8번 나와야 조건을 통과할 수 있다. "Keyfile.dat"의 앞 8 문자를 'G'로 바꾼 후, 다시 OllyDbg로 reverseMe.exe를 실행시켜보자.

 

"Keyfile.dat" 수정

 

수정 후 실행 결과

 

3. Comment

이전의 reversing.kr과 dreamhack.io의 쉬운 리버싱 워게임을 풀면서 flag 인증 형태의 문제는 올바른 input 값(주로 단순 문자열)을 찾는 문제가 대다수였다. 물론 이 문제도 올바른 input 값에 대응되는 파일을 만들어야 하지만, API의 매개변수에 초점을 맞춰 올바른 flag 파일을 만드는 과정이 새로웠다.

반응형