Skip to content
This repository has been archived by the owner on Jun 29, 2020. It is now read-only.

Commit

Permalink
QEMU + Debian MIPS
Browse files Browse the repository at this point in the history
  • Loading branch information
kholia committed Jun 27, 2017
0 parents commit 60245db
Show file tree
Hide file tree
Showing 14 changed files with 815 additions and 0 deletions.
90 changes: 90 additions & 0 deletions README.md
@@ -0,0 +1,90 @@
#### Get Debian for MIPS

* http://ftp.debian.org/debian/dists/stretch/main/installer-mips/current/images/malta/netboot/

* Download both files.

#### Building QEMU (optional)

```
./configure --prefix=$HOME/QEMU --target-list=mips-softmmu,mips-linux-user
make
make install
```

#### HOWTO

##### Install

```
qemu-img create -f qcow2 hda.img 32G
qemu-system-mips -M malta -m 256 -hda hda.img -kernel vmlinux-4.9.0-3-4kc-malta \
-initrd initrd.gz -append "console=ttyS0 nokaslr" -nographic
```

Copy `initrd.img-4.9.0-3-4kc-malta` from the installed VM to the host machine.

##### Boot:

```
qemu-system-mips -M malta -m 256 -hda hda.img -kernel vmlinux-4.9.0-3-4kc-malta \
-initrd initrd.img-4.9.0-3-4kc-malta \
-append "root=/dev/sda1 console=ttyS0 nokaslr" -nographic \
-netdev user,id=net0 \
-device e1000-82545em,netdev=net0,id=net0,mac=52:54:00:c9:18:27 \
-net user -redir tcp:2222::22
```

`C-a h` key combination is useful to interacting with QEMU in `-nographic` mode.

#### Notes

* Kernel (and initrd.gz) from Debian 9 MIPS (version 20170615) does not boot in
QEMU 2.9.0. It fails with `Initramfs unpacking failed: uncompression error` or
`Initramfs unpacking failed: junk in compressed archive` error messages.

Update: In Debian 9, the initrd load address clashes with kernel address
randomization due to a bug in QEMU. Pass "nokaslr" to the append option.

* Debugging a MIPS binary directly under QEMU,

```
$ qemu-mips -g 1234 ./mips.binary
$ gdb ./mips.binary # in another terminal
(gdb) set architecture mips
(gdb) target remote localhost:1234
```

Run dynamically linked MIPS binary with QEMU,

```
LD_LIBRARY_PATH=. qemu-mips ./routerlocker
```

Check behaviour of a MIPS binary,

```
LD_LIBRARY_PATH=. qemu-mips -strace ./routerlocker
```

#### References

* https://people.debian.org/~aurel32/qemu/mips/

* https://gmplib.org/~tege/qemu.html

* http://toolchains.free-electrons.com/

* https://en.wikibooks.org/wiki/QEMU/Networking

* https://github.com/kholia/kernel-configs

#### Thanks

* rofl0r

* aurel32
71 changes: 71 additions & 0 deletions hacks/README.md
@@ -0,0 +1,71 @@
#### Patching notes

Patching `ptrace` call,

```
$ sed -i 's|ptrace|isnanl|' routerlocker
```

For patching `fork` call, replace `jal fork@plt` instruction bytes with `move v0, zero` instruction bytes.

```
$ mips-linux-objdump -d routerlocker
...
4008d4: 0c1001d4 jal 400750 <fork@plt>
4008ec: 00001021 move v0,zero
```

### QEMU debugging

```
$ LD_LIBRARY_PATH=. qemu-mips -g 1234 ./routerlocker.patched
```

#### QEMU easier userspace emulation

```
$ sudo dnf install -C qemu-user-binfmt -y
$ sudo service systemd-binfmt restart
$ LD_LIBRARY_PATH=. ./ld.so.1 ./routerlocker
```

### Build GDB-with-Python for MIPS

Fetch and extract `gdb-8.0.tar.xz`.

```
$ sudo dnf builddep gdb
```

```
$ targets="--enable-targets=x86_64-linux,i386-linux,powerpc-linux,arm-linux,mips-linux,mipsel-linux"
$ ./configure --enable-64-bit-bfd $targets
$ make
$ make install
```

```
$ cat ~/.gdbinit
set history save on
set print pretty on
set pagination off
set confirm off
set follow-fork-mode child
```

```
$ /usr/local/bin/gdb ./routerlocker
```

#### References

* http://chortle.ccsu.edu/assemblytutorial/

#### Thanks

* rofl0r

* csec
44 changes: 44 additions & 0 deletions hacks/app.c
@@ -0,0 +1,44 @@
// Sample program to test GDB brute-forcing script

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char ** argv)
{
unsigned char data[32];
int i = 0;

FILE *file = fopen("/tmp/router.lck", "r");
if (file == NULL) {
fwrite("License file not found.\n", 1, 24, stdout);
fwrite("Lock it up, and lock it out.\n", 1, 29, stdout);
return 1;
}

if (fread(data, 1, 29, file) >= 29) {
fclose(file);

while (1) {
if (data[i] == 'X') {
i++; // find out how many times this is getting hit!
}
else {
break;
}

if (i >= 29)
break;
}

if (i == 29) {
puts("Success!");
return 0;
}

}

puts("Serial is invalid!");
return 3;
}
1 change: 1 addition & 0 deletions hacks/flag.txt
@@ -0,0 +1 @@
that_ransomware_ran_somewhere
81 changes: 81 additions & 0 deletions hacks/gdb_bruteforce.py
@@ -0,0 +1,81 @@
#!/usr/bin/gdb -x
# Based on https://github.com/crossbowerbt/GDB-Python-Utils

import gdb
import traceback
import string


def usage():
print("Usage: gdb -x ./gdb_bruteforce.py")
gdb.execute('quit')


"""
amd64, i++ operation in app.c
0x0000000000400736 <+176>: add DWORD PTR [rbp-0x4],0x1
0x000000000040073a <+180>: cmp DWORD PTR [rbp-0x4],0x1c
mips, i++ operation in app.c
lw v0,24(s8)
addiu v0,v0,1
amd64, int v7 = i + 1; operation in routerlocker-clone.c
0x0000000000400cae <+1208>: mov eax,DWORD PTR [rbp-0x18]
0x0000000000400cb1 <+1211>: add eax,0x1
"""

count = 0


class SnifferBreakpoint(gdb.Breakpoint):
# Initialize the breakpoint
def __init__(self):
# super(SnifferBreakpoint, self).__init__('*0x400736')
# super(SnifferBreakpoint, self).__init__('*0x555559c8')
super(SnifferBreakpoint, self).__init__('*0x400cb1')

# Called when the breakpoint is hit
def stop(self):
global count
try:
# count = int(gdb.parse_and_eval('*(int*)($rbp - 0x4)'))
# count = int(gdb.parse_and_eval('$v0'))
count = int(gdb.parse_and_eval('$eax'))
count = count + 1
except:
traceback.print_exc()
return True

# GDB setup
gdb.execute("set print repeats unlimited")
gdb.execute("set print elements unlimited")
gdb.execute("set pagination off")
gdb.execute("set follow-fork-mode child")

# generate sniffer breakpoint
SnifferBreakpoint()

known = ""

for i in range(0, 29):
count = 0
# for c in "XYZ":
for c in string.printable:
# for c in "that":
output = known + (c + "a" * (29 - len(known) - 1))
print("Trying %s" % (output))
with open("/tmp/router.lck", "w") as f:
f.write(output)

gdb.execute('file ./a.out')
gdb.execute('run ./a.out')
if count > len(known):
known = known + c

gdb.execute('quit')
83 changes: 83 additions & 0 deletions hacks/mips_bruteforce.py
@@ -0,0 +1,83 @@
#!/usr/bin/gdb -x
# Based on https://github.com/crossbowerbt/GDB-Python-Utils

import gdb
import traceback
import string
import subprocess


def usage():
print("Usage: gdb -x ./gdb_bruteforce.py")
gdb.execute('quit')


"""
mips, int v7 = i + 1; operation in routerlocker-clone.c
lw $v0, 0x90+var_74($fp)
addiu $v0, 1 <-- track this, 0x00400fb8
sw $v0, 0x90+var_58($fp)
lw $v0, 0x90+var_74($fp)
addiu $v0, 1
sltiu $v0, 1
andi $s0, $v0, 0xFF
addiu $v0, $fp, 0x90+var_34
move $a0, $v0
la $v0, strlen
move $t9, $v0
jalr $t9 ; strlen
"""

count = 0


class SnifferBreakpoint(gdb.Breakpoint):
# Initialize the breakpoint
def __init__(self):
# super(SnifferBreakpoint, self).__init__('*0x400736')
# super(SnifferBreakpoint, self).__init__('*0x555559c8')
super(SnifferBreakpoint, self).__init__('*0x00400fb8')

# Called when the breakpoint is hit
def stop(self):
global count
try:
# count = int(gdb.parse_and_eval('*(int*)($rbp - 0x4)'))
# count = int(gdb.parse_and_eval('$v0'))
count = int(gdb.parse_and_eval('$v0'))
count = count + 1
except:
traceback.print_exc()
return True

# GDB setup
gdb.execute("set print repeats unlimited")
gdb.execute("set print elements unlimited")
gdb.execute("set pagination off")
gdb.execute("set follow-fork-mode child")

known = ""

# generate sniffer breakpoint
SnifferBreakpoint()

for i in range(0, 29):
count = 0
# for c in "XYZ":
for c in string.printable:
# for c in "that":
output = known + (c + "a" * (29 - len(known) - 1))
print("Trying %s" % (output))
with open("/tmp/router.lck", "w") as f:
f.write(output)

p = subprocess.Popen("qemu-mips -g 1234 ./routerlocker-clone", shell=True)
gdb.execute('file routerlocker-clone')
gdb.execute('target remote localhost:1234')
gdb.execute('continue')
if count > len(known):
known = known + c
break

gdb.execute('quit')

0 comments on commit 60245db

Please sign in to comment.