PADOCON 2010 hand-ray 리버싱 풀이 3rd
문제
다음 코드에서 입력코드가 k1n0TheBest 일 때 출력될 값은 무엇인가?00401000 /$ 83EC 70 SUB ESP,70
00401003 |. A1 34604000 MOV EAX,DWORD PTR DS:[406034]
00401008 |. 8B0D 38604000 MOV ECX,DWORD PTR DS:[406038]
0040100E |. 8B15 3C604000 MOV EDX,DWORD PTR DS:[40603C]
00401014 |. 894424 0C MOV DWORD PTR SS:[ESP+C],EAX
00401018 |. 894C24 10 MOV DWORD PTR SS:[ESP+10],ECX
0040101C |. 33C0 XOR EAX,EAX
0040101E |. 33C9 XOR ECX,ECX
00401020 |. 895424 14 MOV DWORD PTR SS:[ESP+14],EDX
00401024 |. 894C24 01 MOV DWORD PTR SS:[ESP+1],ECX
00401028 |. BA 0C000000 MOV EDX,0C
0040102D |. 894C24 05 MOV DWORD PTR SS:[ESP+5],ECX
00401031 |. 895424 30 MOV DWORD PTR SS:[ESP+30],EDX
00401035 |. 66:894C24 09 MOV WORD PTR SS:[ESP+9],CX
0040103A |. 895424 3C MOV DWORD PTR SS:[ESP+3C],EDX
0040103E |. B9 09000000 MOV ECX,9
00401043 |. BA 01000000 MOV EDX,1
00401048 |. 884424 00 MOV BYTE PTR SS:[ESP],AL
0040104C |. C74424 18 02000000 MOV DWORD PTR SS:[ESP+18],2
00401054 |. C74424 1C 0A000000 MOV DWORD PTR SS:[ESP+1C],0A
0040105C |. C74424 20 04000000 MOV DWORD PTR SS:[ESP+20],4
00401064 |. C74424 24 08000000 MOV DWORD PTR SS:[ESP+24],8
0040106C |. C74424 28 0B000000 MOV DWORD PTR SS:[ESP+28],0B
00401074 |. C74424 2C 05000000 MOV DWORD PTR SS:[ESP+2C],5
0040107C |. 894C24 34 MOV DWORD PTR SS:[ESP+34],ECX
00401080 |. C74424 38 0F000000 MOV DWORD PTR SS:[ESP+38],0F
00401088 |. 894424 40 MOV DWORD PTR SS:[ESP+40],EAX
0040108C |. C74424 44 04000000 MOV DWORD PTR SS:[ESP+44],4
00401094 |. C74424 48 02000000 MOV DWORD PTR SS:[ESP+48],2
0040109C |. C74424 4C 03000000 MOV DWORD PTR SS:[ESP+4C],3
004010A4 |. 895424 50 MOV DWORD PTR SS:[ESP+50],EDX
004010A8 |. 894C24 54 MOV DWORD PTR SS:[ESP+54],ECX
004010AC |. C74424 58 06000000 MOV DWORD PTR SS:[ESP+58],6
004010B4 |. C74424 5C 08000000 MOV DWORD PTR SS:[ESP+5C],8
004010BC |. 894C24 60 MOV DWORD PTR SS:[ESP+60],ECX
004010C0 |. C74424 64 05000000 MOV DWORD PTR SS:[ESP+64],5
004010C8 |. 894C24 68 MOV DWORD PTR SS:[ESP+68],ECX
004010CC |. 895424 6C MOV DWORD PTR SS:[ESP+6C],EDX
004010D0 |> 8B5484 44 /MOV EDX,DWORD PTR SS:[ESP+EAX*4+44]
004010D4 |. 8B4C84 18 |MOV ECX,DWORD PTR SS:[ESP+EAX*4+18]
004010D8 |. 33CA |XOR ECX,EDX
004010DA |. 894C84 18 |MOV DWORD PTR SS:[ESP+EAX*4+18],ECX
004010DE |. 40 |INC EAX
004010DF |. 8A4C0C 0C |MOV CL,BYTE PTR SS:[ESP+ECX+C]
004010E3 |. 83F8 0B |CMP EAX,0B
004010E6 |. 884C04 FF |MOV BYTE PTR SS:[ESP+EAX-1],CL
004010EA |.^ 7C E4 \JL SHORT Q3.004010D0
004010EC |. 8D5424 00 LEA EDX,DWORD PTR SS:[ESP]
004010F0 |. 52 PUSH EDX
004010F1 |. 68 30604000 PUSH Q3.00406030 ; ASCII "%s"
004010F6 |. E8 15000000 CALL Q3.00401110 ; printf
004010FB |. 33C0 XOR EAX,EAX
004010FD |. 83C4 78 ADD ESP,78
00401100 \. C3 RETN
방금 전 얘기했듯이 예선전의 ddanjin과 같은 유형입니다. PADOCON 2010 CTF 예선 문제를 보신 분이라면 대충 눈치 채시겠죠? 문제를 푸는 요령은 핸드레이 두 번째 문제와 같습니다.
- Encoding Routine이 어디인가?
- Encoding Routine 직전의 스택은 어떤 모습인가?
- Encoding Routine 직전의 레지스터의 값은 무엇인가?
- ASCII 테이블
풀이
여기서부터 풀이입니다. [열기]
간단한 안티 리버싱 기법이 적용되어 있는 문제입니다. ddanjin 처럼요. 키 테이블의 값들을 일일이 하나씩 입력해놓아서 분석하는 것을 힘들게 하지요. 하지만, 삽질의 핸드레이 리버싱 앞에서는 이런 것은 작은 기교에 불과합니다.요령은 두 번째 문제와 같습니다. 먼저 Encoding Routine을 찾습니다. 이번에는 친절하게 주석이 달려 있어서 금방 찾을 수 있네요. 0x004010D0~0x004010EA 가 for/while 문으로 이루어진 Encoding Routine입니다. Encoding Routine을 찾았으니 이전까지의 스택과 레지스터를 그립니다.

[그림1]이 제가 그린 스택입니다. 이번 문제에서 스택을 그릴 때 주의할 게 두 가지 있습니다. 하나는 DWORD, WORD, BYTE를 혼동하지 않는 것입니다. DWORD는 4바이트, WORD는 2바이트, BYTE는 1바이트의 메모리를 참조하거나 쓸 때 사용하는 지시어입니다. 또 하나는 중간중간 레지스터 값을 놓치지 않아야 하는 것입니다. 키 테이블을 만들 때 상수 대신 레지스터 값을 집어넣을 수도 있거든요. 그리고 Little Endian 고려하는 것은 기본이겠죠?
스택을 그렸으니 Encoding Routine을 분석할 차례인데요. 아래에 그 과정만 살짝 빼놓았습니다.
004010D0 |> 8B5484 44 /MOV EDX,DWORD PTR SS:[ESP+EAX*4+44]
004010D4 |. 8B4C84 18 |MOV ECX,DWORD PTR SS:[ESP+EAX*4+18]
004010D8 |. 33CA |XOR ECX,EDX
004010DA |. 894C84 18 |MOV DWORD PTR SS:[ESP+EAX*4+18],ECX
004010DE |. 40 |INC EAX
004010DF |. 8A4C0C 0C |MOV CL,BYTE PTR SS:[ESP+ECX+C]
004010E3 |. 83F8 0B |CMP EAX,0B
004010E6 |. 884C04 FF |MOV BYTE PTR SS:[ESP+EAX-1],CL
004010EA |.^ 7C E4 \JL SHORT Q3.004010D0
자세히 보시면 참조하는 키 테이블이 2개라는 것을 알 수 있는데요. esp+18 ~ esp+40가 하나이고, esp+44 ~ esp+68이 또 하나입니다. EAX 값을 인덱스로 사용하죠. 그리고 각각의 인덱스에 위치한 값끼리 순서대로 XOR 연산을 합니다.
XOR 연산을 해서 얻은 값은 또 다시 인덱스로 쓰입니다. esp+c부터 위치한 입력된 문자열의 인덱스로 참조되어서 그 위치의 문자를 esp에 초기화 해놓은 메모리로 순서대로 복사하지요. 즉, 입력된 문자열의 순서를 섞는 애너그램 코드입니다.
애너그램 코드인 게 파악되니까 그 다음부터는 일사천리였습니다. 두 키 테이블의 값들을 XOR 연산해서 애너그램 순서를 구하기만 하면 되니까요. 그리하여 답은 “eeBsn0Tkth1” 입니다.
참고 문헌
Intel Instruction Set pages :: http://www3.itu.edu.tr/~kesgin/mul06/intel/index.htmlASCII printable characters :: http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
반갑습니다. 덕분에 재밌는 문제도 풀고 USB도 받고… 고맙습니다.
안녕하세요 SecurityFirst의 대표입니다^^
재미로 만들어봤던 핸드리버싱이었는데
멋지게풀이를해주셔서 감사드려요^^
다음에한번만나뵐 기회가있겟지요?ㅋㅋ
제가 버스를 타서 핸드레이 디컴파일 작업을 할수 없었던 것이었군요……
갑자기 제 고향에 기차가 없다는게 슬퍼집니다..
아뇨 오히려 핸드레이 리버싱이 더 쉽고 재미나요. 특히, 기차 타고 가면서 핸드레이 리버싱하는 낭만이 있죠.
ㅎㄷㄷ…….핸드리버싱은 정말 무서워요….. 물론 내용은 안봤습니다(무서워서…)