Open igorcalabria opened 4 years ago
I don't know which keyboard you are looking at, but I found a firmware updater for the CM Masterkeys Pro L White on CM's website. I was able to extract and decrypt the firmware with my existing program. See updatepackage.cpp
. I just added the following to the packages
array:
// Cooler Master Masterkeys Pro L
{ 0x38cc849b2e54b6df, MAAV102 },
And ran it as:
pok3rtool decode masterkeys-pro-l-white-v1.08.exe v108.bin
You will notice in the output there are six "sections". There are actually three firmware images with different layouts: US, EU, and KR(?). For each there is a firmware section, and a version info section. That is why you see the code reading from multiple locations. You'll have to hack updatepackage.cpp
to dump the correct firmware section.
I broke the XOR key for one firmware updater a long time ago, and it keeps working. You can compare the XOR key you found to the one at the bottom of proto_cykb.cpp
.
I suspect pok3rtool will work as-is for uploading firmware to this keyboard. You can try some of the more harmless commands before trying to flash firmware. The bootloader
command will reset the keyboard to the bootloader. You can confirm it is in the bootloader with the version
command. The setversion
command will write the version string.
I assume your goal is to extract the bootloader? I've done this on a bunch of these keyboards. My method is to disassemble and patch the application to allow me to read flash unrestricted using the update protocol. Look at https://github.com/pok3r-custom/pok3r_re_firmware/blob/master/disassemble/core/v104/patch_v104.txt for an idea of what these patches look like. With the patched firmware, the pok3rtool dump
command will dump the whole flash, which I can extract the bootloader from.
I'll try to explain how the boot process works.
There is a builtin bootloader firmware at 0x0 in flash. The bootloader will look for the main application firmware at a specific address. It looks like the firmware is loaded at 0x3000 (it should be a multiple of 0x400 to align to the flash page size). Different keyboards place the firmware at slightly different locations, depending on the size of the bootloader. The flash page before the application (e.g. 0x2c00) contains some information about the firmware, including the version string. The bootloader does a couple of things before jumping to the main firmware:
If any of these tests fail, the bootloader works as a simple keyboard. The firmware download function can also be used when the bootloader is running.
If all the checks pass, the bootloader jumps to the application firmware. The reason the application has its own vector table is so that different interrupt handlers can be different in the application. The VTOR register (vector table offset) can be used to specify the base of the vector table, for exactly this use case.
I don't know which keyboard you are looking at
My model is the masterkeys pro m white model. I'll run your tool and compare the output against my own version.
I assume your goal is to extract the bootloader?
Yeah. Thanks a lot for the info. The boot process makes a lot more sense now, and I'll try to patch the firmware in a similar way to your example. I'm also guessing that flashing a non matching layout won't break the usb protocol, so I could eventually fix it on my own if some keys stop working. Have you ever flashed a mismatched layout?
It worked, got a full firmware dump and the patch is pretty much the same as your example
FW offset is 3200
00006388 ff 28 cmp r0,#0xff
0000638a 05 d1 bne LAB_00006398
0000638c 68 68 ldr r0,[r5,#0x4]
0000638e 3c 21 mov r1,#0x3c
00006390 30 e0 b LAB_000063f4
00006392 00 bf nop
00006394 00 bf nop
00006396 00 bf nop
If you are interested, I could PR the changes. It's only a few modifications adding the correct device ids and mappings.
I am interested in this effort! I started working on support for Pro S RGB, but ran into issues along the way.
From my testing poking around USB with python scripts (and looking at disassembly), I found Pro S RGB had a lot in common with both POK3R and CYKB protocols (documented partially https://github.com/m-radomski/re-masterkeys/issues/1). With my findings, I started working on my own fork to better support my device (and other cooler master keyboards): https://github.com/hansemro/pok3rtool/tree/cooler-master-dev.
Unfortunately, I ended up bricking my keyboard by erasing firmware region (@0x3400) in my attempt to write patched firmware with pok3rtool. This result is leading me to believe that something is wrong with the write command (which works fine for setting version). @ChaoticEnigma if you have time, can you help identify the cause of the issue? I have packet captures of firmware upgrade via OEM software and my failed attempt with custom pok3rtool.
pok3rtool attempt: pok3rtool_fw_flash_attempt_with_erase.zip flash_log.txt
OEM: fw-upgrade.zip
Pro S RGB firmware: https://github.com/hansemro/re-masterkeys/tree/Pro_S_RGB/binaries/Pro_S_RGB
@hansemro did you make any progress on the Pro S RGB? I have one here if I can create any dumps for you.
@ciarancoffey No further progress on fixing USB writes with Pro S RGB as I did not get a replacement keyboard.
@ciarancoffey Picked up one Pro S RGB and one Pro L White for cheap. I am going to learn from my mistake and avoid directly wiping my board before I figure out how to write to an arbitrary address.
Managed to dump Pro L White bootloader and firmware without much difficulty.
Documented here: https://github.com/mateuszradomski/re-masterkeys/issues/3.
FW Patch + dump can be found here: https://github.com/hansemro/re-masterkeys/tree/Pro_L_White/binaries/Pro_L_White
pok3rtool with this patch should be sufficient: https://github.com/hansemro/re-masterkeys/blob/Pro_L_White/patches/pok3rtool/ProLWhite.patch
The glaring difference between my failed pok3rtool flash attempt and OEM software is that I did not encode firmware before writing. I did not notice this since I was not being thorough...
# bad pok3rtool
0000 01 01 [6c 06] 08 36 00 00 3b 36 00 00 40 f0 01 03
0010 94 e8 07 00 98 47 10 34 ac 42 f6 d3 ff f7 b6 ff
0020 94 a1 00 00 b4 a1 00 00 70 b5 8c 18 10 f8 01 5b
0030 15 f0 07 03 01 d1 10 f8 01 3b 2a 11 06 d1 10 f8
# OEM
0000 01 01 [db c9] 08 36 00 00 3b 36 00 00 a9 a5 ea 54
0010 55 42 c1 ad cb 47 98 10 d3 bd ac f6 ff f7 00 b6
0020 00 a1 94 ff 00 a1 b4 00 e7 4a 8f 73 54 f7 1f 0e
0030 f3 00 e5 f7 52 7b ab ba 44 6e 54 7f f8 d1 06 10
# pok3rtool after encoding firmware (with ProtoPOK3R::encode_firmware)
0000 01 01 [db c9] 08 36 00 00 3b 36 00 00 a9 a5 ea 54
0010 55 42 c1 ad cb 47 98 10 d3 bd ac f6 ff f7 00 b6
0020 00 a1 94 ff 00 a1 b4 00 e7 4a 8f 73 54 f7 1f 0e
0030 f3 00 e5 f7 52 7b ab ba 44 6e 54 7f f8 d1 06 10
Simulation logs (comment out packet send and recv): pok3rtool_without_encoding-simulation.log pok3rtool_with_encoding-simulation.log
Firmware patch for Pro S RGB is confirmed working on my (unlocked; previously-bricked) Pro S RGB with modified Vortex Core bootloader. Relevant commit: https://github.com/hansemro/re-masterkeys/commit/d5290eea057872d1318e6a2c73e9d700c03f3d1f
Now I just need to flash my new Pro S RGB with stock bootloader (although it is on 1.1.5 firmware that cannot be recovered).
Yup. Fixed firmware flashing with https://github.com/hansemro/pok3rtool/commit/11b822daccf6230801e9e4c1574e27bc54f884a1. Did a firmware upgrade from 1.1.5 to 1.2.2.
Flashing patched firmware (from 1.2.2):
$ pok3rtool_cm -t prosrgb flash 1.2.3 ProSRGB_fw_patched.bin --ok
Opened MasterKeys Pro S RGB
Update Firmware: ProSRGB_fw_patched.bin
Reset to Bootloader
Current Version: 1.2.2
Clear Version
Erase...
Write...
Check...
Flashed succesfully
Clear Version
Writing Version: 1.2.3
Reset to Firmware
true
$ pok3rtool_cm -t prosrgb dump flash.dump
WARNING: THIS TOOL IS RELATIVELY UNTESTED, AND HAS A VERY REAL RISK OF CORRUPTING YOUR KEYBOARD, MAKING IT UNUSABLE WITHOUT EXPENSIVE DEVELOPMENT TOOLS. PROCEED AT YOUR OW
N RISK.
Type "OK" to continue:
OK
Proceeding...
Opened MasterKeys Pro S RGB
Dump Flash
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Out: flash.dump, 65520 bytes
$ xxd flash.dump | head -n 5
00000000: 480d 0020 1901 0000 2501 0000 2501 0000 H.. ....%...%...
00000010: 2501 0000 2501 0000 2501 0000 0000 0000 %...%...%.......
00000020: dff8 0cd0 00f0 30f8 0048 0047 8924 0000 ......0..H.G.$..
00000030: 480d 0020 0168 8d46 4168 0847 4115 0000 H.. .h.FAh.GA...
00000040: 40ea 0103 9b07 03d0 09e0 08c9 121f 08c0 @...............
@ciarancoffey We should be good now :) https://github.com/hansemro/re-masterkeys/blob/Pro_S_RGB/binaries/Pro_S_RGB/flash.dump
Time for me to recover my other board.
EDIT: fully recovered my board!
@ChaoticEnigma Got QMK up on the Pro S RGB and wrote fully working (3-cascade) MBIA043 RGB matrix driver. This should hopefully be useful for Vortex boards with the same LED driver (although it is unclear to me how RGB is achieved with 2-cascade configuration).
Note: I only flashed on board with security bits cleared, so I am not sure if I will run into hardfaults if I try flashing on a spare board with those bits set.
MBIA043 info: https://github.com/mateuszradomski/re-masterkeys/issues/1#issuecomment-1274826627 MBIA043 driver: https://github.com/hansemro/qmk_firmware/blob/prosrgb_mbia043_dev/keyboards/masterkeys/prosrgb/mbia043.c
On GK68XS, RGB is not separated by IC but by the individual channels on the ICs. This is likely what is being done for keyboards with just 2 LED drivers.
@hansemro That's awesome work, very cool! I was out of town last week, best I could do at the time was an emote!
It looks like I'll have to get back on the Vortex boards soon. I'll be stealing your MBIA043 driver!
I believe I did trace out the POK3R RGB LED rows/columns, and I think it's exactly as you say for the GK68XS.
@ChaoticEnigma It is only fair since pok3rtool and your firmware disassembly annotations were incredibly useful.
Here is Pro L White QMK port with MBI5042 LED driver support: https://github.com/hansemro/qmk_firmware/tree/prolwhite_mbi5042_test/keyboards/masterkeys/prolwhite This unfortunately requires a chibios patch to align vector table to 512 bytes instead of 1024 (since FW starts at 0x3200), so I am not sure if I will be able upstream support for this keyboard.
MBI5042 driver: https://github.com/hansemro/qmk_firmware/blob/prolwhite_mbi5042_test/keyboards/masterkeys/prolwhite/mbi5042.c
One thing to note here is that you may need additional "LED matrix to LED index" look-up-matrix if LED matrix and Key matrix do not map to the same keys (as done on Pro L White). On Pro S RGB, LED and Key matrices were mapped to the same keys so I did not have to define this extra mapping.
@ChaoticEnigma Let me know if you have questions or improvements.
Update: Patch is no longer required with https://github.com/hansemro/qmk_firmware/commit/afaff3699377156220cf22a88cc3d6a4420942bc
Hi, I'm trying to add support for these models and I figured you guys could help me get past some issues. This is my first RE project, so feel free to point at any bizarre thing I'm doing.
Ok, so here's what I've got so far
Reversed part of the fw updater software. Basically, I've traced fread calls to figure out where the fw is inside the executable. This also led me to a de-mangling function that partially "decrypts" the firmware. A funny thing that I've noticed is that it reads both the fw version string and the actual fw twice, from different locations. Maybe they're trying to "protect" patching?
As expected, the extracted binary is still "encrypted". I brute forced a 52 byte XOR key and it worked partially, some readable strings appeared and the vector table at the top took some shape.
At this point, I began looking for similar firmwares so I could fix the rest of the XOR key, turns out that my firmware is really similar to the one used by cypher model. I managed to fix the rest of key and now I may have a working dump.
Fiddled a bit with pok3rtool to add the right HID's for my model and both
info
andversion
commands worked. The offsets looks the same as cypher model(got it from the vector table) and the commands working point to that too, but I'm not sure.The thing that broke my legs, is that I can't run the official update to capture the protocol. My model is already at the last version and It seems they never released a update for an ISO model. This means that I basically have two alternatives
Both alternatives seems kinda dangerous, since I'm not sure what happens if a different layout is used. Any pointers? Oh, and I also could use some help understanding the boot model for these devices. From the data sheets, I thought that vector table was loaded from 0x0, but all of the firmwares start at an offset in the flash and they also have a vector table. If there was a builtin fw at 0x0, why the uploaded fw also needs a vector table?
Any help is really appreciated, so thanks in advance. This project was a great source of information