heap1도 heap0과 마찬가지로 heap overflow 문제다.
main()에서 malloc으로 struct internet의 크기 만큼 i1에 할당을 한다.
i1->name = malloc(8);을 하는 것을 볼 수 있다.
총 4개의 chunk를 할당받는다.
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x080484b9 <main+0>: push ebp
0x080484ba <main+1>: mov ebp,esp
0x080484bc <main+3>: and esp,0xfffffff0
0x080484bf <main+6>: sub esp,0x20
0x080484c2 <main+9>: mov DWORD PTR [esp],0x8
0x080484c9 <main+16>: call 0x80483bc <malloc@plt>
0x080484ce <main+21>: mov DWORD PTR [esp+0x14],eax
0x080484d2 <main+25>: mov eax,DWORD PTR [esp+0x14]
0x080484d6 <main+29>: mov DWORD PTR [eax],0x1
0x080484dc <main+35>: mov DWORD PTR [esp],0x8
0x080484e3 <main+42>: call 0x80483bc <malloc@plt>
0x080484e8 <main+47>: mov edx,eax
0x080484ea <main+49>: mov eax,DWORD PTR [esp+0x14]
0x080484ee <main+53>: mov DWORD PTR [eax+0x4],edx
0x080484f1 <main+56>: mov DWORD PTR [esp],0x8
0x080484f8 <main+63>: call 0x80483bc <malloc@plt>
0x080484fd <main+68>: mov DWORD PTR [esp+0x18],eax
0x08048501 <main+72>: mov eax,DWORD PTR [esp+0x18]
0x08048505 <main+76>: mov DWORD PTR [eax],0x2
0x0804850b <main+82>: mov DWORD PTR [esp],0x8
0x08048512 <main+89>: call 0x80483bc <malloc@plt>
0x08048517 <main+94>: mov edx,eax
0x08048519 <main+96>: mov eax,DWORD PTR [esp+0x18]
0x0804851d <main+100>: mov DWORD PTR [eax+0x4],edx
0x08048520 <main+103>: mov eax,DWORD PTR [ebp+0xc]
0x08048523 <main+106>: add eax,0x4
0x08048526 <main+109>: mov eax,DWORD PTR [eax]
0x08048528 <main+111>: mov edx,eax
0x0804852a <main+113>: mov eax,DWORD PTR [esp+0x14]
0x0804852e <main+117>: mov eax,DWORD PTR [eax+0x4]
0x08048531 <main+120>: mov DWORD PTR [esp+0x4],edx
0x08048535 <main+124>: mov DWORD PTR [esp],eax
0x08048538 <main+127>: call 0x804838c <strcpy@plt>
0x0804853d <main+132>: mov eax,DWORD PTR [ebp+0xc]
0x08048540 <main+135>: add eax,0x8
0x08048543 <main+138>: mov eax,DWORD PTR [eax]
0x08048545 <main+140>: mov edx,eax
0x08048547 <main+142>: mov eax,DWORD PTR [esp+0x18]
0x0804854b <main+146>: mov eax,DWORD PTR [eax+0x4]
0x0804854e <main+149>: mov DWORD PTR [esp+0x4],edx
0x08048552 <main+153>: mov DWORD PTR [esp],eax
0x08048555 <main+156>: call 0x804838c <strcpy@plt>
0x0804855a <main+161>: mov DWORD PTR [esp],0x804864b
0x08048561 <main+168>: call 0x80483cc <puts@plt>
---Type <return> to continue, or q <return> to quit---
0x08048566 <main+173>: leave
0x08048567 <main+174>: ret
End of assembler dump.
각각의 chunk가 어디에 존재하고, 어떤 구조를 갖고 있는지 해당 위치에 bp를 걸고 확인해봤다.
다음과 같은 형태를 띈다.
딱 봐도 got overwrie를 해야한다.
heap 은 좀 다르게 chunk라는 애들이 존재하니까...
그럼 이걸로 어떻게 winner()를 띄우냐...
소스코드를 보면 답이 나온다.
strcpy() 호출 이후 printf()가 호출되니까 printf()의 got를 winner()의 주소로 바꾸면 된다.
chunk i1에서 마지막 data 부분이 i1->name의 값이 들어가는 주소를 가리킨다.
chunk 2도 마찬가지다.
chunk i2에서 마지막 data 즉 0x0804a038 부분을 printf의 got로 overwrite 하면 된다.
그리면 두 번째 strcpy()가 호출될 때 인자 정보가 다음과 같게 된다.
따라서 argv[2]에는 winner()의 주소를 넣어서 다음 printf() 호출 때 winner()를 띄우면 된다.
끗.