├── hacks ├── flag.txt ├── routerlocker ├── routerlocker.patched ├── routerlocker-retdec.zip ├── app.c ├── README.md ├── gdb_bruteforce.py ├── mips_bruteforce.py ├── mips_bruteforce_v2.py ├── mips_bruteforce_v3.py ├── simple_tracer.c └── routerlocker-clone.c ├── mips-kernel-hacking.md └── README.md /hacks/flag.txt: -------------------------------------------------------------------------------- 1 | that_ransomware_ran_somewhere 2 | -------------------------------------------------------------------------------- /hacks/routerlocker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kholia/mips-hacking/HEAD/hacks/routerlocker -------------------------------------------------------------------------------- /hacks/routerlocker.patched: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kholia/mips-hacking/HEAD/hacks/routerlocker.patched -------------------------------------------------------------------------------- /hacks/routerlocker-retdec.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kholia/mips-hacking/HEAD/hacks/routerlocker-retdec.zip -------------------------------------------------------------------------------- /mips-kernel-hacking.md: -------------------------------------------------------------------------------- 1 | Building Linux kernel for MIPS 2 | ------------------------------ 3 | 4 | * Get "mips32 musl" cross-compilation toolchain from http://toolchains.free-electrons.com/. 5 | 6 | ``` 7 | $ cd ~ 8 | 9 | $ tar -xjvf mips32--musl--bleeding-edge-2017.05-toolchains-1-2.tar.bz2 10 | ``` 11 | 12 | * Build Linux kernel with this toolchain. 13 | 14 | ``` 15 | $ cd 16 | ``` 17 | 18 | ``` 19 | $ make ARCH=mips CROSS_COMPILE=$HOME/mips32--musl--bleeding-edge/bin/mips-linux- menuconfig 20 | ``` 21 | 22 | * Under Machine selection, Select System type (MIPS Malta board) 23 | 24 | * Under Linux Kernel Configuration, Select Endianess selection (Big endian) 25 | 26 | ``` 27 | $ make ARCH=mips CROSS_COMPILE=$HOME/mips32--musl--bleeding-edge/bin/mips-linux- -j8 28 | ``` 29 | 30 | * Use the generated `vmlinux` file for booting a MIPS system. 31 | -------------------------------------------------------------------------------- /hacks/app.c: -------------------------------------------------------------------------------- 1 | // Sample program to test GDB brute-forcing script 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char ** argv) 9 | { 10 | unsigned char data[32]; 11 | int i = 0; 12 | 13 | FILE *file = fopen("/tmp/router.lck", "r"); 14 | if (file == NULL) { 15 | fwrite("License file not found.\n", 1, 24, stdout); 16 | fwrite("Lock it up, and lock it out.\n", 1, 29, stdout); 17 | return 1; 18 | } 19 | 20 | if (fread(data, 1, 29, file) >= 29) { 21 | fclose(file); 22 | 23 | while (1) { 24 | if (data[i] == 'X') { 25 | i++; // find out how many times this is getting hit! 26 | } 27 | else { 28 | break; 29 | } 30 | 31 | if (i >= 29) 32 | break; 33 | } 34 | 35 | if (i == 29) { 36 | puts("Success!"); 37 | return 0; 38 | } 39 | 40 | } 41 | 42 | puts("Serial is invalid!"); 43 | return 3; 44 | } 45 | -------------------------------------------------------------------------------- /hacks/README.md: -------------------------------------------------------------------------------- 1 | #### Patching notes 2 | 3 | Patching `ptrace` call, 4 | 5 | ``` 6 | $ sed -i 's|ptrace|isnanl|' routerlocker 7 | ``` 8 | 9 | For patching `fork` call, replace `jal fork@plt` instruction bytes with `move v0, zero` instruction bytes. 10 | 11 | ``` 12 | $ mips-linux-objdump -d routerlocker 13 | ... 14 | 4008d4: 0c1001d4 jal 400750 15 | 4008ec: 00001021 move v0,zero 16 | ``` 17 | 18 | ### QEMU debugging 19 | 20 | ``` 21 | $ LD_LIBRARY_PATH=. qemu-mips -g 1234 ./routerlocker.patched 22 | ``` 23 | 24 | #### QEMU easier userspace emulation 25 | 26 | ``` 27 | $ sudo dnf install -C qemu-user-binfmt -y 28 | 29 | $ sudo service systemd-binfmt restart 30 | 31 | $ LD_LIBRARY_PATH=. ./ld.so.1 ./routerlocker 32 | ``` 33 | 34 | ### Build GDB-with-Python for MIPS 35 | 36 | Fetch and extract `gdb-8.0.tar.xz`. 37 | 38 | ``` 39 | $ sudo dnf builddep gdb 40 | ``` 41 | 42 | ``` 43 | $ targets="--enable-targets=x86_64-linux,i386-linux,powerpc-linux,arm-linux,mips-linux,mipsel-linux" 44 | $ ./configure --enable-64-bit-bfd $targets 45 | $ make 46 | $ make install 47 | ``` 48 | 49 | ``` 50 | $ cat ~/.gdbinit 51 | set history save on 52 | set print pretty on 53 | set pagination off 54 | set confirm off 55 | 56 | set follow-fork-mode child 57 | ``` 58 | 59 | ``` 60 | $ /usr/local/bin/gdb ./routerlocker 61 | ``` 62 | 63 | #### References 64 | 65 | * http://chortle.ccsu.edu/assemblytutorial/ 66 | 67 | #### Thanks 68 | 69 | * rofl0r 70 | 71 | * csec 72 | -------------------------------------------------------------------------------- /hacks/gdb_bruteforce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gdb -x 2 | # Based on https://github.com/crossbowerbt/GDB-Python-Utils 3 | 4 | import gdb 5 | import traceback 6 | import string 7 | 8 | 9 | def usage(): 10 | print("Usage: gdb -x ./gdb_bruteforce.py") 11 | gdb.execute('quit') 12 | 13 | 14 | """ 15 | amd64, i++ operation in app.c 16 | 17 | 0x0000000000400736 <+176>: add DWORD PTR [rbp-0x4],0x1 18 | 0x000000000040073a <+180>: cmp DWORD PTR [rbp-0x4],0x1c 19 | 20 | 21 | mips, i++ operation in app.c 22 | 23 | lw v0,24(s8) 24 | addiu v0,v0,1 25 | 26 | 27 | amd64, int v7 = i + 1; operation in routerlocker-clone.c 28 | 29 | 0x0000000000400cae <+1208>: mov eax,DWORD PTR [rbp-0x18] 30 | 0x0000000000400cb1 <+1211>: add eax,0x1 31 | """ 32 | 33 | count = 0 34 | 35 | 36 | class SnifferBreakpoint(gdb.Breakpoint): 37 | # Initialize the breakpoint 38 | def __init__(self): 39 | # super(SnifferBreakpoint, self).__init__('*0x400736') 40 | # super(SnifferBreakpoint, self).__init__('*0x555559c8') 41 | super(SnifferBreakpoint, self).__init__('*0x400cb1') 42 | 43 | # Called when the breakpoint is hit 44 | def stop(self): 45 | global count 46 | try: 47 | # count = int(gdb.parse_and_eval('*(int*)($rbp - 0x4)')) 48 | # count = int(gdb.parse_and_eval('$v0')) 49 | count = int(gdb.parse_and_eval('$eax')) 50 | count = count + 1 51 | except: 52 | traceback.print_exc() 53 | return True 54 | 55 | # GDB setup 56 | gdb.execute("set print repeats unlimited") 57 | gdb.execute("set print elements unlimited") 58 | gdb.execute("set pagination off") 59 | gdb.execute("set follow-fork-mode child") 60 | 61 | # generate sniffer breakpoint 62 | SnifferBreakpoint() 63 | 64 | known = "" 65 | 66 | for i in range(0, 29): 67 | count = 0 68 | # for c in "XYZ": 69 | for c in string.printable: 70 | # for c in "that": 71 | output = known + (c + "a" * (29 - len(known) - 1)) 72 | print("Trying %s" % (output)) 73 | with open("/tmp/router.lck", "w") as f: 74 | f.write(output) 75 | 76 | gdb.execute('file ./a.out') 77 | gdb.execute('run ./a.out') 78 | if count > len(known): 79 | known = known + c 80 | 81 | gdb.execute('quit') 82 | -------------------------------------------------------------------------------- /hacks/mips_bruteforce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gdb -x 2 | # Based on https://github.com/crossbowerbt/GDB-Python-Utils 3 | 4 | import gdb 5 | import traceback 6 | import string 7 | import subprocess 8 | 9 | 10 | def usage(): 11 | print("Usage: gdb -x ./gdb_bruteforce.py") 12 | gdb.execute('quit') 13 | 14 | 15 | """ 16 | mips, int v7 = i + 1; operation in routerlocker-clone.c 17 | 18 | lw $v0, 0x90+var_74($fp) 19 | addiu $v0, 1 <-- track this, 0x00400fb8 20 | sw $v0, 0x90+var_58($fp) 21 | lw $v0, 0x90+var_74($fp) 22 | addiu $v0, 1 23 | sltiu $v0, 1 24 | andi $s0, $v0, 0xFF 25 | addiu $v0, $fp, 0x90+var_34 26 | move $a0, $v0 27 | la $v0, strlen 28 | move $t9, $v0 29 | jalr $t9 ; strlen 30 | """ 31 | 32 | count = 0 33 | 34 | 35 | class SnifferBreakpoint(gdb.Breakpoint): 36 | # Initialize the breakpoint 37 | def __init__(self): 38 | # super(SnifferBreakpoint, self).__init__('*0x400736') 39 | # super(SnifferBreakpoint, self).__init__('*0x555559c8') 40 | super(SnifferBreakpoint, self).__init__('*0x00400fb8') 41 | 42 | # Called when the breakpoint is hit 43 | def stop(self): 44 | global count 45 | try: 46 | # count = int(gdb.parse_and_eval('*(int*)($rbp - 0x4)')) 47 | # count = int(gdb.parse_and_eval('$v0')) 48 | count = int(gdb.parse_and_eval('$v0')) 49 | count = count + 1 50 | except: 51 | traceback.print_exc() 52 | return True 53 | 54 | # GDB setup 55 | gdb.execute("set print repeats unlimited") 56 | gdb.execute("set print elements unlimited") 57 | gdb.execute("set pagination off") 58 | gdb.execute("set follow-fork-mode child") 59 | 60 | known = "" 61 | 62 | # generate sniffer breakpoint 63 | SnifferBreakpoint() 64 | 65 | for i in range(0, 29): 66 | count = 0 67 | # for c in "XYZ": 68 | for c in string.printable: 69 | # for c in "that": 70 | output = known + (c + "a" * (29 - len(known) - 1)) 71 | print("Trying %s" % (output)) 72 | with open("/tmp/router.lck", "w") as f: 73 | f.write(output) 74 | 75 | p = subprocess.Popen("qemu-mips -g 1234 ./routerlocker-clone", shell=True) 76 | gdb.execute('file routerlocker-clone') 77 | gdb.execute('target remote localhost:1234') 78 | gdb.execute('continue') 79 | if count > len(known): 80 | known = known + c 81 | break 82 | 83 | gdb.execute('quit') 84 | -------------------------------------------------------------------------------- /hacks/mips_bruteforce_v2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gdb -x 2 | # Based on https://github.com/crossbowerbt/GDB-Python-Utils 3 | 4 | import gdb 5 | import traceback 6 | import string 7 | import subprocess 8 | 9 | 10 | def usage(): 11 | print("Usage: gdb -x ./gdb_bruteforce.py") 12 | gdb.execute('quit') 13 | 14 | 15 | """ 16 | mips, int v7 = i + 1; operation in routerlocker-clone.c 17 | 18 | lw $v0, 0x90+var_74($fp) 19 | addiu $v0, 1 <-- track this, 0x00400fb8 20 | sw $v0, 0x90+var_58($fp) 21 | lw $v0, 0x90+var_74($fp) 22 | addiu $v0, 1 23 | sltiu $v0, 1 24 | andi $s0, $v0, 0xFF 25 | addiu $v0, $fp, 0x90+var_34 26 | move $a0, $v0 27 | la $v0, strlen 28 | move $t9, $v0 29 | jalr $t9 ; strlen 30 | """ 31 | 32 | count = 0 33 | 34 | 35 | class SnifferBreakpoint(gdb.Breakpoint): 36 | # Initialize the breakpoint 37 | def __init__(self): 38 | # super(SnifferBreakpoint, self).__init__('*0x400736') 39 | # super(SnifferBreakpoint, self).__init__('*0x555559c8') 40 | super(SnifferBreakpoint, self).__init__('*0x00400fb8') 41 | 42 | # Called when the breakpoint is hit 43 | def stop(self): 44 | global count 45 | try: 46 | # count = int(gdb.parse_and_eval('*(int*)($rbp - 0x4)')) 47 | # count = int(gdb.parse_and_eval('$v0')) 48 | # count = int(gdb.parse_and_eval('$v0')) 49 | count = count + 1 50 | except: 51 | traceback.print_exc() 52 | return True 53 | 54 | # GDB setup 55 | gdb.execute("set print repeats unlimited") 56 | gdb.execute("set print elements unlimited") 57 | gdb.execute("set pagination off") 58 | gdb.execute("set confirm off") 59 | gdb.execute("set architecture mips") 60 | gdb.execute("set follow-fork-mode child") 61 | 62 | known = "" 63 | 64 | # generate sniffer breakpoint 65 | SnifferBreakpoint() 66 | 67 | for i in range(0, 29): 68 | count = 0 69 | # for c in "XYZ": 70 | for c in string.printable: 71 | # for c in "that": 72 | count = 0 73 | output = known + (c + "a" * (29 - len(known) - 1)) 74 | print("Trying %s" % (output)) 75 | with open("/tmp/router.lck", "w") as f: 76 | f.write(output) 77 | 78 | p = subprocess.Popen("qemu-mips -g 1234 ./routerlocker-clone", shell=True) 79 | gdb.execute('file routerlocker-clone') 80 | gdb.execute('target remote localhost:1234') 81 | gdb.execute('continue') 82 | if count > len(known): 83 | known = known + c 84 | break 85 | 86 | gdb.execute('quit') 87 | -------------------------------------------------------------------------------- /hacks/mips_bruteforce_v3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gdb -x 2 | # Based on https://github.com/crossbowerbt/GDB-Python-Utils 3 | 4 | import gdb 5 | import time 6 | import traceback 7 | # import string 8 | import subprocess 9 | 10 | 11 | def usage(): 12 | print("Usage: gdb -x ./mips_bruteforce_v3.py") 13 | gdb.execute('quit') 14 | 15 | 16 | """ 17 | Idea: strlen is called in the "goodboy" code path and each call instance 18 | indicates a good input character. So count the number of calls to strlen. 19 | 20 | loc_400D10: 21 | addiu $v0, $fp, 0x98+var_34 22 | move $a0, $v0 23 | jal strlen <-- track hit to this, 0x400d18 24 | move $at, $at 25 | move $s1, $v0 26 | move $s0, $zero 27 | lw $v0, 0x98+var_80($fp) 28 | sltu $v0, $s0 29 | bnez $v0, loc_400C18 30 | move $at, $at 31 | """ 32 | 33 | count = 0 34 | 35 | 36 | class SnifferBreakpoint(gdb.Breakpoint): 37 | # Initialize the breakpoint 38 | def __init__(self): 39 | super(SnifferBreakpoint, self).__init__('*0x400d18') 40 | 41 | # Called when the breakpoint is hit 42 | def stop(self): 43 | global count 44 | try: 45 | count = count + 1 46 | except: 47 | traceback.print_exc() 48 | return True 49 | 50 | # GDB setup 51 | gdb.execute('file routerlocker.patched') 52 | # gdb.execute("set print repeats unlimited") # not supported in older gdb 53 | # gdb.execute("set print elements unlimited") # ditto 54 | gdb.execute("set pagination off") 55 | gdb.execute("set confirm off") 56 | gdb.execute("set architecture mips") 57 | gdb.execute("set follow-fork-mode child") 58 | 59 | known = "" 60 | 61 | # generate sniffer breakpoint 62 | SnifferBreakpoint() 63 | 64 | for i in range(0, 30): 65 | count = 0 66 | for c in "etaoinshrdlcumwfgypbvkjxqz_0345126789ETAOINSHRDLCUMWFGYPBVKJXQZ": # rofl0r 67 | # for c in string.printable: 68 | count = 0 69 | output = known + (c + "a" * (29 - len(known) - 1)) 70 | print("Trying %s" % (output)) 71 | with open("/tmp/router.lck", "w") as f: 72 | f.write(output) 73 | 74 | p = subprocess.Popen("LD_LIBRARY_PATH=. qemu-mips -g 1234 ./routerlocker.patched", shell=True) 75 | time.sleep(0.02) # rofl0r 76 | gdb.execute('target remote localhost:1234') 77 | gdb.execute('continue') 78 | # the first strlen call is done even if the input is totally wrong, 79 | # "count - 1" is done to skip this particular strlen call. 80 | if count - 1 > len(known): 81 | known = known + c 82 | break 83 | 84 | gdb.execute('quit') 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### (UPDATE) Easily start a MIPS VM with arm_now 2 | 3 | ```sh 4 | $ pip3 install --user https://github.com/nongiach/arm_now/archive/master.zip --upgrade 5 | 6 | $ arm_now start mips32 7 | Welcome to Buildroot 8 | buildroot login: root 9 | # uname -m 10 | mips 11 | # gdb /bin/ls 12 | (gdb) start 13 | Temporary breakpoint 1, 0x00405434 in main () 14 | (gdb) x/i $pc 15 | => 0x405434 : li a0,-1 16 | ``` 17 | 18 | Note: The `mips32` VM image seems to be pretty limited (no gdb, no 19 | apt-get/opkg). I recommend using the following method for getting a proper 20 | `mips32` image. 21 | 22 | 23 | #### Get Debian for MIPS 24 | 25 | * http://ftp.debian.org/debian/dists/stretch/main/installer-mips/current/images/malta/netboot/ 26 | 27 | * Download both files. 28 | 29 | #### Building QEMU (optional) 30 | 31 | ``` 32 | ./configure --prefix=$HOME/QEMU --target-list=mips-softmmu,mips-linux-user 33 | 34 | make 35 | 36 | make install 37 | ``` 38 | 39 | #### HOWTO 40 | 41 | ##### Install 42 | 43 | ``` 44 | qemu-img create -f qcow2 hda.img 32G 45 | 46 | qemu-system-mips -M malta -m 256 -hda hda.img -kernel vmlinux-4.9.0-3-4kc-malta \ 47 | -initrd initrd.gz -append "console=ttyS0 nokaslr" -nographic 48 | ``` 49 | 50 | Copy `initrd.img-4.9.0-3-4kc-malta` from the installed VM to the host machine. 51 | 52 | ##### Boot: 53 | 54 | ``` 55 | qemu-system-mips -M malta -m 256 -hda hda.img -kernel vmlinux-4.9.0-3-4kc-malta \ 56 | -initrd initrd.img-4.9.0-3-4kc-malta \ 57 | -append "root=/dev/sda1 console=ttyS0 nokaslr" -nographic \ 58 | -netdev user,id=net0 \ 59 | -device e1000-82545em,netdev=net0,id=net0,mac=52:54:00:c9:18:27 \ 60 | -net user -redir tcp:2222::22 61 | ``` 62 | 63 | `C-a h` key combination is useful to interacting with QEMU in `-nographic` mode. 64 | 65 | #### Notes 66 | 67 | * Kernel (and initrd.gz) from Debian 9 MIPS (version 20170615) does not boot in 68 | QEMU 2.9.0. It fails with `Initramfs unpacking failed: uncompression error` or 69 | `Initramfs unpacking failed: junk in compressed archive` error messages. 70 | 71 | Update: In Debian 9, the initrd load address clashes with kernel address 72 | randomization due to a bug in QEMU. Pass "nokaslr" to the append option. 73 | 74 | * Debugging a MIPS binary directly under QEMU, 75 | 76 | ``` 77 | $ qemu-mips -g 1234 ./mips.binary 78 | 79 | $ gdb ./mips.binary # in another terminal 80 | (gdb) set architecture mips 81 | (gdb) target remote localhost:1234 82 | ``` 83 | 84 | Run dynamically linked MIPS binary with QEMU, 85 | 86 | ``` 87 | LD_LIBRARY_PATH=. qemu-mips ./routerlocker 88 | ``` 89 | 90 | Check behaviour of a MIPS binary, 91 | 92 | ``` 93 | LD_LIBRARY_PATH=. qemu-mips -strace ./routerlocker 94 | ``` 95 | 96 | #### References 97 | 98 | * https://people.debian.org/~aurel32/qemu/mips/ 99 | 100 | * https://gmplib.org/~tege/qemu.html 101 | 102 | * http://toolchains.free-electrons.com/ 103 | 104 | * https://en.wikibooks.org/wiki/QEMU/Networking 105 | 106 | * https://github.com/kholia/kernel-configs 107 | 108 | #### Thanks 109 | 110 | * rofl0r 111 | 112 | * aurel32 113 | -------------------------------------------------------------------------------- /hacks/simple_tracer.c: -------------------------------------------------------------------------------- 1 | /* Code sample: using ptrace for simple tracing of a child process. 2 | ** 3 | ** Eli Bendersky (http://eli.thegreenplace.net) 4 | ** This code is in the public domain. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #if !defined(__mips__) 16 | #include 17 | #endif 18 | #include 19 | #include 20 | #include 21 | 22 | // from google-breakpad and http://elixir.free-electrons.com/linux/latest/source/arch/mips/include/uapi/asm/ptrace.h 23 | #if defined(__mips__) 24 | struct user_regs_struct { 25 | uint64_t regs[32]; 26 | uint64_t lo; 27 | uint64_t hi; 28 | uint64_t epc; 29 | uint64_t badvaddr; 30 | uint64_t status; 31 | uint64_t cause; 32 | }; 33 | #endif 34 | 35 | /* 36 | * Print a message to stdout, prefixed by the process ID 37 | */ 38 | void procmsg(const char* format, ...) 39 | { 40 | va_list ap; 41 | fprintf(stdout, "[%d] ", getpid()); 42 | va_start(ap, format); 43 | vfprintf(stdout, format, ap); 44 | va_end(ap); 45 | } 46 | 47 | 48 | void run_target(const char* programname) 49 | { 50 | procmsg("target started. will run '%s'\n", programname); 51 | 52 | /* Allow tracing of this process */ 53 | if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { 54 | perror("ptrace run_target"); 55 | return; 56 | } 57 | 58 | /* Replace this process's image with the given program */ 59 | execl(programname, programname, 0); 60 | } 61 | 62 | 63 | void run_debugger(pid_t child_pid) 64 | { 65 | int wait_status; 66 | unsigned icounter = 0; 67 | procmsg("debugger started\n"); 68 | 69 | /* Wait for child to stop on its first instruction */ 70 | wait(&wait_status); 71 | 72 | while (WIFSTOPPED(wait_status)) { 73 | icounter++; 74 | struct user_regs_struct regs; 75 | ptrace(PTRACE_GETREGS, child_pid, 0, ®s); 76 | // unsigned instr = ptrace(PTRACE_PEEKTEXT, child_pid, regs.rip, 0); 77 | // procmsg("icounter = %u. EIP = 0x%08x. instr = 0x%08x\n", icounter, regs.rip, instr); 78 | #if defined(__mips__) 79 | procmsg("icounter = %u. EIP = 0x%08x\n", icounter, regs.epc); 80 | #else 81 | procmsg("icounter = %u. EIP = 0x%08x\n", icounter, regs.rip); 82 | #endif 83 | // http://elixir.free-electrons.com/linux/latest/source/arch/mips/kernel/ptrace.c, 84 | // Linux/MIPS does not support PTRACE_SINGLESTEP because there 85 | // is no single step instruction feature on most MIPS processors. 86 | 87 | /* Make the child execute another instruction */ 88 | if (ptrace(PTRACE_SINGLESTEP, child_pid, 0, 0) < 0) { 89 | perror("ptrace run_debugger"); 90 | return; 91 | } 92 | 93 | /* Wait for child to stop on its next instruction */ 94 | wait(&wait_status); 95 | } 96 | 97 | procmsg("the child executed %u instructions\n", icounter); 98 | } 99 | 100 | 101 | int main(int argc, char** argv) 102 | { 103 | pid_t child_pid; 104 | 105 | if (argc < 2) { 106 | fprintf(stderr, "Expected a program name as argument\n"); 107 | return -1; 108 | } 109 | 110 | child_pid = fork(); 111 | if (child_pid == 0) 112 | run_target(argv[1]); 113 | else if (child_pid > 0) 114 | run_debugger(child_pid); 115 | else { 116 | perror("fork"); 117 | return -1; 118 | } 119 | 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /hacks/routerlocker-clone.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | char runtime_pad[] = 12 | "\xB6\xA5\x02\xB6\xDD\x73\x37\x35\x5F\x23\xA5\xC9\xB0\x8D\xE9\xAB\x81\xA3\xDF\x0C" 13 | "\x80\xAF\xB4\x7D\x63\x79\xF4\x5C\x4F\x16\x13\xC3\xFB\xBE\x5E\x30\x22\x2E\x82\x66" 14 | "\x1B\xDE\x67\xC1\x99\x4C\xBE\x23\x44\xB4\x7B\xF5\xE7\x2C\x41\x69\xD1\x78\xDF\xDB" 15 | "\x45\x5B\xCF\x49\x74\x07\x13\x8F\x40\x18\xE7\xE6\xCE\xFA\x56\x37\xFC\x74\x33\x81" 16 | "\xE3\xDC\xA4\x0C\x44\x80\x57\xBA\x3E\xF9\xD9\xA7\xB4\x5E\xCD\xA5\xEB\x44\x5B\xEF" 17 | "\x46\xF3\x5B\x6D\xCF\xE0\x38\xA7\xC7\xB8\x6A\x18\x16\xE1\xC5\x03\x1E\x18\x52\xDE" 18 | "\x84\xF6\x27\xF0\x60\x2D\x27\x4B"; 19 | 20 | 21 | int main(int argc, char ** argv) { 22 | int stat_loc = 0; 23 | if (fork() != 0) { 24 | wait(&stat_loc); 25 | return 0; 26 | } 27 | ptrace(0); 28 | FILE * file = fopen("/tmp/router.lck", "r"); // 0x400a1c 29 | if (file == NULL) { 30 | fwrite("License file not found.\n", 1, 24, stdout); 31 | fwrite("Lock it up, and lock it out.\n", 1, 29, stdout); 32 | return 1; 33 | } 34 | int v0, zero = 0, fp = -68; 35 | char byte[29]; 36 | v0 = zero - 0x78; 37 | byte[fp + 0x4c] = v0; 38 | v0 = zero + 0xa; 39 | byte[fp + 0x4e] = v0; 40 | v0 = zero - 0x21; 41 | byte[fp + 0x47] = v0; 42 | v0 = zero - 0x70; 43 | byte[fp + 0x58] = v0; 44 | v0 = zero - 0x22; 45 | byte[fp + 0x48] = v0; 46 | v0 = zero + 0x79; 47 | byte[fp + 0x55] = v0; 48 | v0 = zero - 0x46; 49 | byte[fp + 0x52] = v0; 50 | v0 = zero + 0x25; 51 | byte[fp + 0x50] = v0; 52 | v0 = zero - 0x64; 53 | byte[fp + 0x5c] = v0; 54 | v0 = zero - 0x4c; 55 | byte[fp + 0x5a] = v0; 56 | v0 = zero + 0x16; 57 | byte[fp + 0x53] = v0; 58 | v0 = zero - 0x3e; 59 | byte[fp + 0x44] = v0; 60 | v0 = zero + 0x6a; 61 | byte[fp + 0x5f] = v0; 62 | v0 = zero - 0x11; 63 | byte[fp + 0x59] = v0; 64 | v0 = zero - 0x6b; 65 | byte[fp + 0x4a] = v0; 66 | v0 = zero + 0x54; 67 | byte[fp + 0x4f] = v0; 68 | v0 = zero + 0x5d; 69 | byte[fp + 0x5e] = v0; 70 | v0 = zero + 0x73; 71 | byte[fp + 0x60] = v0; 72 | v0 = zero - 0x53; 73 | byte[fp + 0x4b] = v0; 74 | v0 = zero + 0x1b; 75 | byte[fp + 0x45] = v0; 76 | v0 = zero + 0x5e; 77 | byte[fp + 0x51] = v0; 78 | v0 = zero - 0x22; 79 | byte[fp + 0x57] = v0; 80 | v0 = zero - 0x40; 81 | byte[fp + 0x5b] = v0; 82 | v0 = zero + 6; 83 | byte[fp + 0x54] = v0; 84 | v0 = zero - 0x23; 85 | byte[fp + 0x49] = v0; 86 | v0 = zero + 0x41; 87 | byte[fp + 0x4d] = v0; 88 | v0 = zero - 0x3c; 89 | byte[fp + 0x46] = v0; 90 | v0 = zero - 0x65; 91 | byte[fp + 0x5d] = v0; 92 | v0 = zero + 0x38; 93 | byte[fp + 0x56] = v0; 94 | 95 | char data[30] = {0}; 96 | int result; 97 | if (fread(data, 1, 29, file) >= 29) { 98 | fclose(file); 99 | if (strlen(data) != 0) { 100 | int i = 0; // 0x400d484857 101 | while (true) { 102 | int j = ((i << 2) & 0xff) + (i & 3); 103 | if (byte[i] != (data[i] ^ runtime_pad[j])) { 104 | fwrite("Serial is invalid.\n", 1, 19, stdout); 105 | fwrite("Ambrocious, unlock this door!\n", 1, 30, stdout); 106 | return 3; 107 | } 108 | int v7 = i + 1; 109 | if (i == -1 | v7 >= strlen(data)) { 110 | break; 111 | } 112 | i = v7; 113 | } 114 | } 115 | puts("Thank you for purchasing RouterLocker v2.0"); 116 | printf("Your flag is: PAN{%s}\n", data); 117 | result = 0; 118 | } else { 119 | fwrite("License file invalid.\n", 1, 22, stdout); 120 | fwrite("Lock it up, and lock it out.\n", 1, 29, stdout); 121 | result = 2; 122 | } 123 | return result; 124 | } 125 | --------------------------------------------------------------------------------