├── ARM-flashpatch01.jpg ├── ARM-flashpatch02.jpg ├── Dumping ├── Infineon-FLASH_USB_DIRECT_Programmer-DevelopmentTools-v01_00-EN (1).zip ├── README.MD ├── dump01.jpg ├── dump02.jpg ├── fujitsu_dump_ds4.py ├── sram_code.bin └── vcccom01.jpg ├── JDM-011-BOTTOMHighlight.jpg ├── JDM-011-Held.jpg ├── README.MD ├── fujitsu_rom.jpg ├── fwdump01.jpg ├── gdbserver01.jpg ├── jmgao_explanation.jpg ├── nRF52-DK.jpg ├── nrfDev01.jpg ├── nrfDev02.jpg ├── sram_written.jpg └── vcccom01.jpg /ARM-flashpatch01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/ARM-flashpatch01.jpg -------------------------------------------------------------------------------- /ARM-flashpatch02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/ARM-flashpatch02.jpg -------------------------------------------------------------------------------- /Dumping/Infineon-FLASH_USB_DIRECT_Programmer-DevelopmentTools-v01_00-EN (1).zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/Dumping/Infineon-FLASH_USB_DIRECT_Programmer-DevelopmentTools-v01_00-EN (1).zip -------------------------------------------------------------------------------- /Dumping/README.MD: -------------------------------------------------------------------------------- 1 | # Dumping DS4 in Windows 2 | 3 | --- 4 | 5 | Required Files List: 6 | 7 | 1. `fujitsu_dump_ds4.py` 8 | 9 | 2. `sram_code.bin` 10 | 11 | 3. `Infineon-FLASH_USB_DIRECT_Programmer-DevelopmentTools-v01_00-EN (1).zip` 12 | 13 | ## Install USB Drivers 14 | 15 | Install the drivers located in the `Infineon-FLASH_USB_DIRECT_Programmer-DevelopmentTools-v01_00-EN.zip` file. Alternatively, you can download this from the Infineon website directly. 16 | 17 | ## Solder Jumpers 18 | 19 | Ensure you have jumper wires soldered to MD0, VCC, GND (capacitor was used in this write-up), and RST. You can verify these are the correct points by plugging in the Dualshock controller, holding MD0 and VCC together, and pressing RST to GND. The device will reconnect to the USBVCOM and give you a COM number. 20 | 21 | ## Connect to Serial Write (USBVCOM) Mode 22 | 23 | Connect the Dualshock 4 controller while holding MD0 to VCC and touching RST to GND. Once the device has been booted into USBVCOM, you no longer need to hold MD0 to VCC. 24 | 25 | ![vcccom01.jpg](vcccom01.jpg "VCom") 26 | 27 | You should see this device appear. If Windows cannot find the device drivers, make sure you've installed the Infineon Flash-USB Direct programmer. 28 | 29 | ## Run fujitsu_dump_ds4.py 30 | 31 | Run the dump file with the following commands: 32 | 33 | `python fujitsu_dump_ds4.py --port COM06 --exec_file sram_code.bin` 34 | 35 | Change your port to the corresponding COM number and ensure that you have sram_code.bin in the folder. You should see the following screen: 36 | 37 | ![dump01.jpg](dump01.jpg "Dumping Fujitsu") 38 | 39 | Follow the instructions on the tool, ensuring that you let the USB disconnect and reconnect with MD0 held after each step. 40 | 41 | Once you've dumped all 9 parts, the script will automatically combine the parts into dump.bin as seen here. 42 | 43 | ![dump02.jpg](dump02.jpg "Dump Complete Fujitsu") 44 | 45 | Done! Run your dump.bin through `jedi_crypto-3Files.py` or any other conversion tool to load into a game controller project. -------------------------------------------------------------------------------- /Dumping/dump01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/Dumping/dump01.jpg -------------------------------------------------------------------------------- /Dumping/dump02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/Dumping/dump02.jpg -------------------------------------------------------------------------------- /Dumping/fujitsu_dump_ds4.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import struct 3 | import code 4 | import serial 5 | import binascii 6 | import argparse 7 | 8 | 9 | def fmt_from_size(size): 10 | if size == 1: 11 | return 'B' 12 | if size == 2: 13 | return 'H' 14 | if size == 4: 15 | return 'L' 16 | return None 17 | 18 | 19 | class RomCom: 20 | # loaded code may optionally reconfigure this 21 | # fujitsu's provided code switches to 115200 for example 22 | BR_ROM = 9600 23 | BR_SRAM = 115200 24 | CMD_WRITE = 0 25 | CMD_PING = 0x18 26 | CMD_READ = 0x20 27 | CMD_READV = 0x21 28 | CMD_WRITEV = 0x22 29 | CMD_EXEC = 0x23 30 | CMD_FINALIZE = 0xc0 31 | STATUS_OK = 1 32 | STATUS_NG = 2 33 | STATUS_UNK_CMD = 4 34 | # for usb, rom hardcodes where it jumps to 35 | # for uart, jump target is last addr passed to CMD_WRITE 36 | USB_CODE_ENTRY = 0x20000000 37 | 38 | def _open_dev(s, path, baud_rate): 39 | s.path = path 40 | s.dev = serial.Serial(s.path, s.BR_ROM, timeout=1) 41 | 42 | def __init__(s, path, debug=False): 43 | s._open_dev(path, s.BR_ROM) 44 | s.dbg = debug 45 | 46 | def close_dev(s): 47 | s.dev.close() 48 | 49 | def reopen_dev(s): 50 | # seems to work, so why not! 51 | # perhaps the USBVCOM driver is just lying to us... 52 | s.dev.close() 53 | s._open_dev(s.path, s.BR_SRAM) 54 | 55 | def print(s, *args): 56 | if s.dbg: 57 | print(*args) 58 | 59 | def _checksum(s, buf): 60 | return struct.pack('>B', sum(buf) & 0xff) 61 | 62 | def _send(s, buf): 63 | s.print('write: %s' % (binascii.hexlify(buf))) 64 | s.dev.write(buf) 65 | 66 | def recv_u8(s): 67 | d = struct.unpack('>B', s.dev.read(1))[0] 68 | s.print('read: %02x' % (d)) 69 | return d 70 | 71 | def _cmd_with_checksum(s, cmd, buf): 72 | d = struct.pack('>B', cmd) + buf 73 | s._send(d + s._checksum(d)) 74 | 75 | def _check_rv(s, cmd, check_cmd=True): 76 | rv = s.recv_u8() 77 | s.print('cmd %02x rv %02x' % (cmd, rv)) 78 | if check_cmd and (rv & 0xf0) != (cmd & 0xf0): 79 | print('rv for wrong cmd') 80 | return False 81 | status = rv & 0xf 82 | if status == s.STATUS_OK: 83 | return True 84 | elif status == s.STATUS_NG: 85 | return False 86 | elif status == s.STATUS_UNK_CMD: 87 | print('unknown cmd') 88 | return False 89 | else: 90 | print('unknown status') 91 | return False 92 | 93 | def ping(s): 94 | d = struct.pack('>B', s.CMD_PING) 95 | s._send(d) 96 | return s._check_rv(s.CMD_PING) 97 | 98 | def try_ping(s): 99 | try: 100 | return s.ping() 101 | except: 102 | return False 103 | 104 | def read(s, addr, size): 105 | d = struct.pack('>LHH', addr, 0, size) 106 | s._cmd_with_checksum(s.CMD_READ, d) 107 | d = s.dev.read(size) 108 | if not s._check_rv(s.CMD_READ): 109 | return b'' 110 | return d 111 | 112 | def write(s, addr, buf): 113 | d = struct.pack('>LHH', addr, 0, len(buf)) + buf 114 | s._cmd_with_checksum(s.CMD_WRITE, d) 115 | return s._check_rv(s.CMD_WRITE) 116 | 117 | def finalize(s): 118 | # contents of this buffer are not actually used but 119 | # it must still have correct checksum 120 | d = b'\0' * 8 121 | s._cmd_with_checksum(s.CMD_FINALIZE, d) 122 | # the return value comes from rom OR loaded code 123 | # rom returns 0xc2 if it fails, but fujitsu's loaded code 124 | # will return 0x31, which would normally be considered 125 | # a response for the wrong cmd... 126 | return s._check_rv(s.CMD_FINALIZE, False) 127 | 128 | def exec_file(s, path): 129 | try: 130 | with open(path, 'rb') as f: 131 | if not s.write(s.USB_CODE_ENTRY, f.read()): 132 | return False 133 | if not s.ping(): 134 | return False 135 | if not s.finalize(): 136 | return False 137 | except: 138 | return False 139 | return True 140 | 141 | def _read_v(s, addr, type_len): 142 | d = struct.pack(' REBOOT USING RST PIN TO GND** 58 | 59 | **> DUMP SRAM AGAIN** 60 | 61 | **> SEARCH FOR 0xCC PATTERN**` 62 | 63 | And we get a hit! 64 | 65 | ![sramhit](sram_written.jpg "SRAM hit") 66 | 67 | NICE! We have persistence at `0x20038000` all the way to `0x2003FFFF`. That gives us `0x20038000 to 0x2003FFFF` or 32767 bytes to inject a payload and dump chunks of firmware into the persistence area of SRAM. 68 | 69 | So, we have the following: 70 | 71 | 1. A working JDM-011 PCB with MD0 Serial Write mode enabled 72 | 2. SRAM reading and writing via Fujitsu ROM COM replacement 73 | 3. Persistent SRAM storage for writing an exploit payload of some type and outputting our firmware chunks 74 | 75 | Now, the next step is really what was "missing" from all of these blogs and dumps about DS4 do-it-yourself. 76 | 77 | ## Failing at Flash Patching on ARM Cortex-M3 78 | 79 | The fail0verflow blog from 2018 [here](https://fail0verflow.com/blog/2018/ps4-ds4/) describes the process they used to pull DS4 firmware into SRAM. The Flash Patch and Breakpoint Unit (PFB) seemed to have some magic code space fetch actions that remap system space. However, the critical component of "how" you do this was left to the reader, and no other blogs or githubs have actual code or examples of how this was done. 80 | 81 | ![fail0verflow](failoverflow_explanation.jpg "Fail0verflow Blog") 82 | 83 | The author of [Passing Link](https://github.com/passinglink/passinglink) also mentions a code injection using the FPB unit, but fails to explain the "how". This seems to be a bit more detailed, but.... what does it mean "FPB unit only works on code fetches"? 84 | 85 | ![jmgao](jmgao_explanation.jpg "Passinglink Issues") 86 | 87 | I was really flying blind here, as I had never written a flash patch or messed with hardware level breakpoints on an ARM chip. I did not really understand the "usual tricks" comment made by jmgao, but figured I could play around with it and try out a few different payloads until something hit. 88 | 89 | Here was the ARM assembly I ended up using for copying memory. This ended up working just fine for my final payload. 90 | 91 | ``` 92 | mov r0, 0x0000; // lower part of address 93 | movt r0, 0x0000; // upper part of address 94 | mov r1, 0x8200; // output SRAM: 95 | movt r1, 0x2003; // [payload] [padding] 0x20038200 96 | mov r4, 0x400; 97 | up: ldr r3, [r0], #4; 98 | str r3, [r1], #4; 99 | subs r4, r4, #1; 100 | BNE up; 101 | ``` 102 | 103 | But now I had to generate an FPB SRAM table. I found a few tutorials and diagrams as well as the ARM documentation, but nothing really made sense. Here was the two diagrams I tried to follow: 104 | 105 | ![fpbpatch01](ARM-flashpatch01.jpg "Arm Flash Patch 01") 106 | 107 | ![fpbpatch01](ARM-flashpatch02.jpg "Arm Flash Patch 01") 108 | 109 | It looks like you just simply create a remap table and then code magically appears. But, nothing I did worked. I couldn't just enter the address I wanted to jump to, and I was crashing the firmware every time I restarted into a patch. So, it was time to dig a bit more. 110 | 111 | ## Analyzing the Flash Patch and Breakpoint (FPB) on an nRF52DK 112 | 113 | I was pretty stumped at this point, there was no way to verify my patch worked and I was crashing anytime I'd try applying a flash patch. Then I found this tutorial on breakpoints by Interrupt: [How do breakpoints even work?](https://interrupt.memfault.com/blog/cortex-m-breakpoints). This blog linked to a github that had a lot of really useful functions, including running functions that had been patched by the debugger. 114 | 115 | I remembered I have a [Nordic nRF52 DK](https://www.nordicsemi.com/Products/Development-hardware/nRF52-DK) laying around with an ARM Cortex-M4 chip inside of it. These boards can run a J-Link GDB instance that gives you full control of the running operating system. This means I can setup a Flash Patch then monitor it with GDB to see how the chip reacts to different SRAM patch tables. 116 | 117 | ![nrf25DK](nRF52-DK.jpg "NRF52DK") 118 | 119 | This lets us run a GDB server using the J-Link software and connect to it through the ARM GDB Windows application (Arm GNU Toolchain arm-none-eabi 11.3 rel1). 120 | 121 | ![gdbserver](gdbserver01.jpg "J-Link GDB") 122 | 123 | I combined this tutorial with the [Nordic-Playground](https://github.com/NordicPlayground/nRF52-flash-patch/blob/master/example/flash_patch.c) flash patch project example. In this example, the author generates an SRAM flash patch table using the following logic: 124 | 125 | ``` 126 | uint32_t calc_branch_instr(uint32_t instr_addr, uint32_t target_addr) 127 | { 128 | uint32_t offset = target_addr - instr_addr; 129 | uint16_t offset_10_upper = (offset >> 12) & 0x03FF; 130 | uint16_t offset_11_lower = ((offset - 4) >> 1) & 0x07FF; // UNCERTAIN about this! 131 | 132 | uint8_t s_pos = 24; 133 | uint8_t s = (offset - 4) & (1 << s_pos); 134 | uint8_t i1 = (offset - 4) & (1 << (s_pos - 1)); 135 | uint8_t i2 = (offset - 4) & (1 << (s_pos - 2)); 136 | 137 | uint8_t j1 = 0x01 & ((~i1) ^ s); 138 | uint8_t j2 = 0x01 & ((~i2) ^ s); 139 | 140 | uint16_t upper_bl_instr = ((0x1E << 11) | (s << 10) | offset_10_upper); 141 | uint16_t lower_bl_instr = ((0x02 << 14) | (j1 << 13) | (0x01 << 12) | (j2 << 11) | offset_11_lower); 142 | 143 | return ((upper_bl_instr << 16) | lower_bl_instr); 144 | } 145 | ``` 146 | 147 | I can now try to make a flash patch SRAM table using this branch instruction patch, and try it out. 148 | 149 | ![nrfDev01](nrfDev01.jpg "nrf52 Dev GDB") 150 | 151 | ![nrfDev02](nrfDev02.jpg "nrf52 Patch") 152 | 153 | After patching the dummy function 1 with my dummy function 6, it works! I'm able to redirect calls from 1 to 6. So now let's try setting up an SRAM memory copy and redirecting calls. 154 | 155 | Hmmm... this isn't working. When I manually inspect the calc_branch_instr(), I notice the distance from my SRAM to the flash patch location is not properly set. 156 | 157 | ## Defeating the ARM Branch Range 158 | 159 | The problem is my lack of deep knowledge in ARM assembly. The Branch instruction has a limit in how far we can travel. The [ARM documentation](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/branch-and-call-sequences-explained) covers this pretty well, so there is no way we can go from 0x00001234 to 0x20038200 with a standard branch instruction. 160 | 161 | I think I finally understand jmgao's "usual tricks" at least slightly at this point. After stumbling around, I finally land on Raymond Chen's explanation of [The ARM Process (Thumb-2), part 13: Trampolines](https://devblogs.microsoft.com/oldnewthing/20210616-00/?p=105314) where he outlines the following code: 162 | 163 | ``` 164 | bl toofar_trampoline 165 | ... 166 | 167 | toofar_trampoline: 168 | mov r12, #lo(|toofar|+1) 169 | movt r12, #hi(|toofar|+1) 170 | bx r12 ; jump to r12 171 | ``` 172 | 173 | Now this is looking almost verbatim with jmgao's explanation of how to do a trampoline. So we have to move our exploit/payload location into r12 using two move operations, then bx (branch with code switch) to r12. 174 | 175 | The other "A-HA!" moment here is the fact we have 3 assembly operations we need to run in order to properly patch and exploit the ARM Cortex chip. To do this, we need to patch the code 3 times. This was determined by looking at how the calc_branch_instr() worked (1 single 4 byte patch), which we need to replace with 3 instruction sets. 176 | 177 | So we now know we have to do the following: 178 | 179 | ``` 180 | FP_CTRL = enable to patch system 181 | FP_REMAP = patch table address consisting of 4-byte instructions 182 | FP_COMP[0] = mov r12, #lo(toofar+1) 183 | FP_COMP[1] = movt r12, #hi(toofar+1) 184 | FP_COMP[2] = bx r12, nop for padding 185 | ``` 186 | 187 | 188 | Writing a little test branch in our nRF52 code, we can test this to make sure it works: 189 | 190 | ``` 191 | bool fpb_set_patch(size_t comp_id, uint32_t instr_addr, uint32_t target_addr) { 192 | sFpbConfig config; 193 | fpb_get_config(&config); 194 | if (config.revision != 0) { 195 | EXAMPLE_LOG("Revision %d Parsing Not Supported", config.revision); 196 | return false; 197 | } 198 | 199 | const size_t num_comps = config.num_code_comparators; 200 | if (comp_id >= num_comps) { 201 | EXAMPLE_LOG("Instruction Comparator %d Not Implemented", num_comps); 202 | return false; 203 | } 204 | 205 | if (instr_addr >= 0x20000000) { 206 | EXAMPLE_LOG("Address 0x%x is not in code region", instr_addr); 207 | return false; 208 | } 209 | 210 | if (!config.enabled) { 211 | EXAMPLE_LOG("Enabling FPB."); 212 | fpb_enable(); 213 | } 214 | 215 | FPB->FP_COMP[comp_id] = (instr_addr | 0x01UL); 216 | 217 | trampoline = bytes([0x48,0xf2,0xff,0x0c, 218 | 0xc2,0xf2,0x03,0x0c, 219 | 0x60,0x47,0x09,0x46]) 220 | 221 | // set 4 patches 222 | // [nop][mov r2,lower][mov.t r2,higher][nop][bx r2] 223 | uint8_t bytes[] = {0x09,0x46,0x09,0x46,0x4f,0xf4,0x41,0x4c,0xc2,0xf2,0x00,0x0c,0x09,0x46,0x60,0x47}; 224 | memcpy(((uint32_t *) (remap_table_addr)), bytes, sizeof(bytes)); 225 | 226 | // lets drop a shellcode and make sure this works 227 | uint8_t shell[] = { 228 | 0x4f,0xf0,0x00,0x00,0xc0,0xf2,0x00,0x00, 229 | 0x4f,0xf4,0x42,0x41,0xc2,0xf2,0x00,0x01, 230 | 0x4f,0xf4,0x80,0x74,0x50,0xf8,0x04,0x3b, 231 | 0x41,0xf8,0x04,0x3b,0x01,0x3c,0xf9,0xd1 232 | }; 233 | 234 | memcpy(((uint32_t *) (shell_addr)), shell, sizeof(shell)); 235 | 236 | return true; 237 | } 238 | ``` 239 | 240 | Now we can run fpb_set_patch and patch our function call to verify this works on the nRF52DK. It works! As long as we do our patching in multiple steps and set the patch tables accordingly, we can run up to 8 full 4-byte patches and execute any code we want. This means we have flash patching working by setting 3 different "breakpoints" with patch locations, and the final instruction patch will branch to our SRAM allowing code execution. Our payload now looks like this: 241 | 242 | ``` 243 | Set our Flash Patch registers: 244 | 245 | FP_REMAP_ADDRESS 246 | 0x20038200 247 | FP_COMP[0] Enabled 1, Replace: 0, Function to Overwrite Address 248 | FP_COMP[1] Enabled 1, Replace: 0, Function to Overwrite Address + 4 249 | FP_COMP[2] Enabled 1, Replace: 0, Function to Overwrite Address + 8 250 | ``` 251 | 252 | ``` 253 | Copy our payload to the remap address "table" which is 4-byte instructions 254 | 255 | 0x20038200: mov r12, #lo(|0x20038200|+1) ; FP_COMP[0] 256 | 0x20038204: movt r12, #hi(|0x20038200|+1) ; FP_COMP[1] 257 | 0x20038008: bx r12 ; FP_COMP[2] 258 | 0x2003800A: mov r1,r1 ; NOP for padding 259 | ``` 260 | 261 | Now we just need to line this up to the DS4 SRAM dump and we should have running code in SRAM using the FPB. 262 | 263 | ## Moment of Truth: Flash Patching on the DS4 264 | 265 | In jmgao's blog, he mentions using `0x00000000` as the patch address, but I found this crashes when I rebooted into serial mode. Instead, I looked up some information about the known FW to see if there were any addresses I could piggy-back off that would land in controller mode and skip in serial mode. I found a nice landing spot at `0x8214` that would lock the wireless controller in USB mode and work on serial writer in USB mode. There are many spots that would work, but this seemed to do the trick for what I needed. Fail0verflow mentioned looking at the stack returns, but this saved me a lot of time guessing on return values. 266 | 267 | I wrote the following Python code to help generate a set of commands for the Fujitsu python script. The assembly code was generated by compiling the ASM manually and dumping the GDB bytes, but this could be much cleaner. The Python script included in this repo contains a much more helpful dumping script. 268 | 269 | ``` 270 | # Trampoline to 0x20038100 271 | # mov r12, 0x80FF; PATCH[0] 4 bytes 272 | # movt r12, 0x2003; PATCH[1] 4 bytes 273 | # bx r12; PATCH[2] 2 bytes .. 274 | # mov r1,r1; NOP (4 byte aligns our table) 2 bytes .. 275 | trampoline = bytes([0x48,0xf2,0xff,0x0c, 276 | 0xc2,0xf2,0x03,0x0c, 277 | 0x60,0x47,0x09,0x46]) 278 | 279 | # "mov r0, 0x0000;" Change Offset Here 280 | # "movt r0, 0x0000;" 281 | # "mov r1, 0x8200;" 0x20038200 Dump SRAM 282 | # "movt r1, 0x2003;" 283 | # "mov r4, 0x7F00;" Copy 0x7F00 bytes 284 | # "up: ldr r3, [r0],#4;" 285 | # "str r3, [r1],#4;" 286 | # "subs r4, r4,#1;" 287 | # "BNE up;" 288 | copyFlash = bytes([0x4f, 0xf0, 0x00, 0x00, 0xc0, 0xf2, 0x00, 0x00, 289 | 0x4f, 0xf4, 0x02, 0x41, 0xc2, 0xf2, 0x03, 0x01, 290 | 0x4f, 0xf4, 0xfe, 0x44, 0x50, 0xf8, 0x04, 0x3b, 291 | 0x41, 0xf8, 0x04, 0x3b, 0x01, 0x3c, 0xf9, 0xd1]) 292 | 293 | print("c.write32(0xE0002000,0x03)") # enable FPB 294 | print("c.write32(0xE0002004,0x20038000)") # remap table 295 | print("c.write32(0xE0002008,0x8214|1)") # address | enable 296 | print("c.write32(0xE000200C,0x8218|1)") # address + 0x4 | enable 297 | print("c.write32(0xE0002010,0x821C|1)") # address + 0x8 | enable 298 | print("c.write(0x20038000, bytes.fromhex('"+trampoline.hex()+"'))") 299 | print("c.write(0x20038100, bytes.fromhex('"+copyFlash.hex()+"'))") 300 | print("c.write(0x20038200, ('A'*256).encode('utf-8'))") # watch the canary 301 | 302 | ``` 303 | 304 | I also manually generated a canary (repeating 'A') to make sure my memory copy worked. I could then do a `c.read(0x20038200, 256)` and check for A's. Running this code resulted in the first `0x7F00` bytes of the firmware! It works!!!!! 305 | 306 | ![fwdump01.jpg](fwdump01.jpg "FW Works") 307 | 308 | Now, all that was left was changing the memory copy location in the copyFlash payload to grab the rest of the firmware and dump it all into a file. This is a manual processto reset the controller into standard mode, then back to serial mode between each read. Ultimately this results in 9 parts at `0x7F00` size reads a piece. Combining those together into a single file, and we have a full dump from our own DS4! 309 | 310 | Running this through _jedi_crypto-3Files.py_, we get our private key, serial, and signature binary file! We have successfully backed up our own Dualshock 4 controller for private use! 311 | 312 | As an added bonus, I automated this whole process in `fujitsu_dump_ds4.py` which you can find in the `Dumping` folder of this repo. 313 | -------------------------------------------------------------------------------- /fujitsu_rom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/fujitsu_rom.jpg -------------------------------------------------------------------------------- /fwdump01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/fwdump01.jpg -------------------------------------------------------------------------------- /gdbserver01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/gdbserver01.jpg -------------------------------------------------------------------------------- /jmgao_explanation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/jmgao_explanation.jpg -------------------------------------------------------------------------------- /nRF52-DK.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/nRF52-DK.jpg -------------------------------------------------------------------------------- /nrfDev01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/nrfDev01.jpg -------------------------------------------------------------------------------- /nrfDev02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/nrfDev02.jpg -------------------------------------------------------------------------------- /sram_written.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/sram_written.jpg -------------------------------------------------------------------------------- /vcccom01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymousps4/ds4blog/527c9f700113296971aa23361cd6224e6da79d54/vcccom01.jpg --------------------------------------------------------------------------------