리버싱 입문 시, 대부분 거치는 Lena's Reversing Tutorial의 Level 1이다.
이 카테고리만큼은 다른 것들에 비해 설명을 가능한 한 많이 넣을 예정이다.
1. Analyze
reverseMe.exe라는 파일이 있을 것이다.
우선 실행해보면, 아래와 같은 메시지가 뜬다.
Ollydbg로 이 파일을 열어보자.
어셈블리 어가 수두룩하게 보인다.
이전 게시물들을 보면 알겠지만, 이건 그나마 어셈블리어로 바로 짰기에 가독성 높은 코드에 속한다.
여타 게시물에서는 참조 문자열이나 호출된 함수들을 살펴보는 등 이것처럼 직관적으로 보이지 않아, 루틴 찾기에 급급했다.
각설하고, 아래 코드를 설명하자면, CreateFileA 함수를 통해 Keyfile.dat라는 파일이 있는지 판정한다.
파일이 없으면 -1을 반환하기 때문에, 반환값이 들어가는 레지스터(EAX)와 -1을 비교하여, 같으면 위에서 봤던 메시지박스가 뜨게 된다.
참고로, 파일이 있으면 임의의 양수를 반환하는데, file descriptor로 추정된다.
앞의 JNE 문을 통과하면 즉, 파일이 존재하면 이곳으로 오게 된다.
함수명을 보면 알겠지만, ReadFile 함수로 파일 내용을 읽는다.
반환값은 읽은 바이트 수인데, TEST 문을 통해, 반환값(EAX)이 0인지 아닌지 판단한다.
파일의 내용이 있으면 4010B4로, 없으면 JMP문을 통해 4010F7로 보낸다.
TEST문을 통과하면 즉, 파일에 내용이 있으면, 아래에 보이는 곳으로 간다.
위 이미지의 ReadFile 함수의 인자를 보면, 402173이 보일 것이다. 이 곳에 반환값을 넣는 것 같다.
그래서 그 값과 0x10(16)을 비교한 후, 그보다 작으면 4010F7로 보낸다.
즉, 16바이트 이상으로 내용을 채워야 한다.
이 비교문을 통과하면, 루프를 만나게 되는데, 파일 내용을 한 글자씩 추출한 후, 그것을 AL에 저장하고, 0x47('G')와 비교하여, 그 글자가 G이면 ESI를 0부터 증가시키고, 아니면 카운터 역할을 하는 EBX를 증가시킨다.
문자열이 NULL이면 루프를 빠져나오며, 4010D3의 CMP문으로 이동한다.
그 후, G의 개수를 담은 ESI 값과 8을 비교하여, 그보다 작으면 역시 4010F7로 보내고, 아니면 401205로 보낸다.
파일 내용이 없거나, 16바이트 미만일 때 이동하는, 4010F7부터의 루틴이다.
Keyfile is not valid, Sorry.라는 메시지를 담은 메시지박스를 띄운 후, 확인 버튼을 누르면 ExitProcess 함수를 통해 종료해버린다.
파일 내용 중 G가 8개 이상일 때 오게 되는 루틴이다. 드디어 성공 메시지가 보인다.
2. Patch
이제부터 위에서 분석한 분기문 중 하나를 패치할 것이다.
첫번째 분기문을 바꿔 성공 메시지로 바로 가도록 인증 절차를 우회할 것이다.
가장 처음에 본 비교문은 이것이었다. CreateFileA 함수의 반환값과 -1을 비교하는 부분이다.
위의 두 부분을 NOP(No Operation)이라는 instruction으로 채운 후,
401078에서 space를 눌러 아래처럼 써주자. 성공 메시지가 있는 곳으로 무조건 점프하게 된다.
이것으로 패치는 끝났다. 이제 패치한 것을 다른 파일로 저장하자.
수정한 부분에서 오른쪽 버튼 > Edit > Copy all modifications to executable을 클릭하면, 아래의 창을 볼 수 있다.
여기에 아무데서나 오른쪽 버튼 클릭 후, Save file...을 눌러주면,
이러한 창이 뜨는데, 파일 형식을 Source File에서 Any File로 변경 후, 적절하게 파일명을 짓고 저장하자.
새로 저장한 것을 실행하면, 바로 성공 메시지를 볼 수 있다.