gashtaan / sinowealth-8051-dumper

Flash memory dumper for 8051-based SinoWealth MCUs
GNU General Public License v3.0
20 stars 2 forks source link

Report of operation #2

Open swiftgeek opened 1 year ago

swiftgeek commented 1 year ago

Turns out my part is SH68F881 (I don't have markings on package)

Dumping part number:                                                                                                                                           
68F881000000

Binary was recreated using xxd -r -p test.hex > test.bin and it contains strings found in USB descriptor

$ strings test.bin -e l
Gaming KB 
Gaming KB 
0001
Gaming KB 
Bus 001 Device 010: ID 258a:001a Gaming KB  Gaming KB
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x258a
  idProduct          0x001a
  bcdDevice           30.90
  iManufacturer           1 Gaming KB
  iProduct                2 Gaming KB
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x003b
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              300mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      1 Keyboard
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      65
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              10
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      1 Keyboard
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     168
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              10
Device Status:     0x0002
  (Bus Powered)
  Remote Wakeup Enabled

First block of ~code/data starts at 0x1000, next 0x3000, then 0x5000, then 0x7000, and finally two tiny binary portions at 0x7F00 (65 bytes) and 5 bytes at 0x7FA0

Since my arduino board take quite a long time to start a sketch, I ended up using digital pin 6 as vref detection (using analog pin for this would be a massive overkill). https://github.com/swiftgeek/sinowealth-8051-dumper/commit/8b356de8aebf0a08b9e456207b836cfc9bcb71d5

gashtaan commented 1 year ago

Great, glad to hear it works.

I'm using optiboot bootloader in my Arduino board and have SUT fuses set to 4.1ms pre-delay, so I didn't have to complicate it.

gashtaan commented 1 year ago

Out of curiosity, what is that keyboard you have tested it on?

I've another keyboard - Genesis Thor 300 RGB. There is SH68F90 on PCB. I'll try it to check if it works on different chip too.

swiftgeek commented 1 year ago

Setup with relying on quick bootloader doesn't work for me, because, I would also need to connect external UART and complicate it even further, but detecting vref is rather clean though I will probably need to also add high side switch to mess with other ~opcodes so hopefully I can erase and write soon. (sadly there aren't many erased bytes remaining in my stock fw, and I don't have idea about opcode for mass/sector erase so I guess I will just try all 0x40-x4F until some sector erases)

Mechanical keyboard with single color LEDs (each row having different color) RE-K70-BYK800 on PCB silkscreen, HYKKER branding on case. I have some very partial pinouts for SH68F88 and they match so far (Power/USB/JTAG/Reset).

Not entirely sure which one should be VDP, but one of those two :)

SH68F88

gashtaan commented 1 year ago

@swiftgeek Why do you need to connect external UART? Optiboot just jump to sketch directly in case of POR, UART stuff should work the same as with stock one. Did you measure with oscilloscope what is going on in your case? How long was that boot delay?

When I started to experiment with this, I had it all on breadboard with power controlling circuit, but ultimately just wires to Arduino Nano was the most convenient solution when I got rid of boot delay.

20230218_100433

Thanks for the info. I read that BYK800 chip is supposed to be a clone of some SinoWealth MCU, but I wouldn't guess it's 1:1 copy of SH68F881 with the same part number programmed inside.

swiftgeek commented 1 year ago

It's just some company hiding MCU used, BYKxxx is using variety of chips and vendors. Sadly removing markings/replacing with your own markings is a common practice those days. I have seen even regular classic opamps parts having markings scratched off/replaced, to pretend device is much smarter than it is.

Additionally sinowealth supplies dice so it would be technically feasible to package it yourself with entirely different pinout/package, but I haven't seen that much effort put into hiding your supply chain chain yet.

If I hotplug UART with atmega, I have to deal not only with atmega boot time, but also that one from UART chip, and UART console app on host and entire enumeration. Sensing DUT Vcc is trivial in comparison, and pretty much eliminates all timing/enumeration issues.

gashtaan commented 1 year ago

You do what you need to do, but now I'm lost completely. What is your setup here? You don't need to do any of that. Just get your ATmega to execute code within first 20ms for first power-up to establish the connection, then any additional delays won't matter.

But you're right about that chinese practice of sanding out of IC markings or replacing them, find datasheets for those chips is pure luck. I'm surprised that SinoWealth let firmwares for their programmers to be downloaded without some NDA bullshit. I wish every IC manufacturer were like Microchip or Renesas...

gashtaan commented 1 year ago

BTW, I've failed to dump firmware of SH68F90 in second keyboard. It has all security bits set, even executing MOVC instruction is blocked at hardware level :(

swiftgeek commented 1 year ago

I prefer having less race conditions in my setup, and less things changing at a time. Makes debugging/troubleshooting easier (but cost/benefit also needs to be taken into account ofc, and the less connections/setup is actually required the better too)

As for SH68F90 I guess "mass erase" would unlock it, but I have no expectations on how would that opcode look like / what parameters would it take (or additional opcodes required like address opcodes for read/write operations), so it's up to your reversing skills there. It's probably better to test that on SH68F88 and related dies since it doesn't seem to mention code protection capabilities but I might be wrong about that. In any case I think I can test any ideas about remaining opcodes if you run into any (I'm starting to guess that 0xFF is a NOP opcode, but need to test that more).

The mass erase operation will erase all the contents of program code, code option, code protect bit and customer code ID, regardless the status of code-protect control mode

swiftgeek commented 1 year ago

Ah sorry now I get that making dump is important for backing up stock firmware, then I would guess it would easily fall to voltage glitching attacks. I have so little interest in original firmware that it completely went over my head.

Though SH68F90 exposes less rails than SH68F88 so it might be a bit challenging

gashtaan commented 1 year ago

Mass erase would help, but my goal is to dump the firmware, not programming or erasing the chip. I broke some firmwares out of protected chips before, but I have a feeling that this one will be hard.

gashtaan commented 1 year ago

There is no 0xFF opcode, if it works for you, it just skipped it because it's invalid.

It would help to get boot ROM from one of these chips, I guess there is communication protocol implemented. But I don't have chip that have boot ROM programmable, don't know if it's possible to read it from the chips we're dealing with now.

swiftgeek commented 1 year ago

I'm just going off sinowealth using 0xFF in sorta that way, and making the most sense I can out of it, likening it to other programming protocols like serprog. If it skips on invalid opcodes then that's great to hear.

gashtaan commented 1 year ago

I don't know if it skip invalid commands, but if 0xFF does nothing for you, it seems so. What I can say, programmer firmware never send such command to the chip. It does send 0x46 0xFF command to it every few ms when it's in connection mode 150 (0x96 for you :)), so I suppose it's some PING or SYNC or whatever.

swiftgeek commented 1 year ago

I already started using defines heavily in hexed branch, but if my 0xFF guess is correct then my changes are currently misguiding in few places. Not trying to push that any time soon to not give you more troubles with reversing JET51, and would prefer to be more confident first in what each opcode does.

I don't know what opcode 0x46 does yet, but it seems to take a parameter, other possible value than 0xFE being 0xF0.

Do you have a list of opcodes used by programmer (especially erase if identified that far)?

gashtaan commented 1 year ago

It's not just single opcode to do flash erase/program, I'll try to document it.

gashtaan commented 1 year ago

As I'm looking on it now, 0x46 is probably some connection state: 0x46 0xFF - idle 0x46 0xFE 0xFF - during programming/erasing? (chip type 0) 0x46 0xF0 0xFF - during programming/erasing? (chip type 2,6)

swiftgeek commented 1 year ago

If 0xFF is indeed NOP, then I would guess it's similar stuffing as last extra bit after each 8bit word - some commands have shifted output by 1 cycle (like what happens with/during 0xAA opcode), so I guess they added it to account for that. I mean I guess NOP would give MCU more time to finish some operation.

gashtaan commented 1 year ago

If programmer give MCU time to do something, it just wait or emits clock pulses. It never sends 0xFF alone, but who knows.

It sends NOPs instructions in JTAG mode, but this is completely different story. In that mode raw instruction opcodes can be send and CPU executes them directly. That is why MOVC can be blocked with security bit.

gashtaan commented 1 year ago

I just realized I mixed it up. The command that is sent every few milliseconds (PING, SYNC?) is 0x49 0xFF, command sent during programming is 0x46.

carlossless commented 1 year ago

Hey,

Just reporting that I was able to do a partially successful dump firmware from a NuPHY Air60 which has an SH68F90A (labeled as BYK916, reports as 68F90A0000).

flash-dump

Firmware seems to be intact:

$ strings docs/dumps/nuphy-air60-flash-dump.bin -e l
Gaming KB
SINO WEALTH
0001
BY Tech

USB Descriptor:

Bus 001 Device 003: ID 05ac:024f Apple, Inc. Aluminium Keyboard (ANSI)
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x05ac Apple, Inc.
  idProduct          0x024f Aluminium Keyboard (ANSI)
  bcdDevice            1.10
  iManufacturer           1 BY Tech
  iProduct                2 Air60
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x003b
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      1 Keyboard
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      89
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     227
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               1
Device Status:     0x0000
  (Bus Powered)

P.S. Yes, it really does use Apple's idVendor (probably the idProduct too)

gashtaan commented 1 year ago

@carlossless Many thanks for the valuable info :)

swiftgeek commented 1 year ago

Started working on recreating schematics and boardview in kicad for my board, based on CCD scans annotated in gimp. So far I have following results that could be applicable for more BYKxxx boards:

swiftgeek commented 1 year ago

Pushed early WIP schematics, waiting for new kicad release to hit distro's repo to generate boardview