reverse engineering the tytera md380 - qsl.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08...

11
8 Reverse Engineering the Tytera MD380 by Travis Goodspeed KK4VCZ, with kind thanks to DD4CR and W7PCH. The following is an adventure of reverse engi- neering the Tytera MD380, a digital hand-held ra- dio that can be had for barely more than a hundred bucks. In this article, I explain how to read and write the radio’s configuration over USB, and how to break the readout protection on its firmware, so that you fine readers can write your own strange and clever software for this nifty gizmo. I also present patches to promiscuously receive audio from un- known talkgroups, creating the first hardware scan- ner for DMR. Far more importantly, these notes will be handy when you attempt to reverse engineer something similar on your own. This article does not go into the security prob- lems of the DMR protocol, but those are sufficiently similar to P25 that I’ll just refer you to Why (Spe- cial Agent) Johnny (Still) Can’t Encrypt by Sandy Clark and Friends. 59 8.1 Hardware Overview Speaker Microphone SP- D- SP+ D+ MIC The MD380 is a hand-held digital voice radio that uses either analog FM or Digital Mobile Radio (DMR). It is very similar to other DMR radios, such as the CS700 and CS750 from Connect Systems. 60 DMR is a trunked radio protocol using two-slot TDMA, so a single repeater tower can be used by one user in Slot 1 while another user is having a completely different conversation on Slot 2. Just like GSM, the tower coordinates which radio should transmit when. The CPU of this radio is an STM32F405 from STMicroelectronics. This contains a Cortex M4, so all instructions are Thumb and all function point- ers are odd. The LQFP100 package of this chip is used. It has a megabyte of Flash and 192 kilo- bytes of RAM. The STM32 has both JTAG and a ROM bootloader, but both of these are protected by a Readout Device Protection (RDP) feature. In Section 8.8, I’ll show you how to bypass these pro- tections and jailbreak your radio. There is also a radio baseband chip, the HR C5000. At first I was reconstructing the pinout of this chip from the CS700 Service Manual, but the full documentation can be had from DocIn, a Chi- nese PDF sharing website. Aside from a bunch of support components that we can take for granted, there is an SPI Flash chip for storing the codeplug. “Codeplug” is a Motorola term for the radio settings, such as frequencies, con- tacts, and talk groups; I use the term here to distin- guish the radio configuration in SPI Flash from the 59 unzip pocorgtfo10.pdf p25sec.pdf #from Proceedings of the 20th Usenix Security Symposium in 2011 60 The folks at Connect Systems are nice and neighborly, so please buy a radio from them. 76

Upload: others

Post on 16-Aug-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

8 Reverse Engineering the Tytera MD380by Travis Goodspeed KK4VCZ,

with kind thanks to DD4CR and W7PCH.

The following is an adventure of reverse engi-neering the Tytera MD380, a digital hand-held ra-dio that can be had for barely more than a hundredbucks. In this article, I explain how to read andwrite the radio’s configuration over USB, and howto break the readout protection on its firmware, sothat you fine readers can write your own strange andclever software for this nifty gizmo. I also presentpatches to promiscuously receive audio from un-known talkgroups, creating the first hardware scan-ner for DMR. Far more importantly, these noteswill be handy when you attempt to reverse engineersomething similar on your own.

This article does not go into the security prob-lems of the DMR protocol, but those are sufficiently

similar to P25 that I’ll just refer you to Why (Spe-cial Agent) Johnny (Still) Can’t Encrypt by SandyClark and Friends.59

8.1 Hardware Overview

Speaker

Microphone

SP- D- SP+

D+ MIC

The MD380 is a hand-held digital voice radiothat uses either analog FM or Digital Mobile Radio(DMR). It is very similar to other DMR radios, suchas the CS700 and CS750 from Connect Systems.60

DMR is a trunked radio protocol using two-slotTDMA, so a single repeater tower can be used byone user in Slot 1 while another user is having acompletely different conversation on Slot 2. Justlike GSM, the tower coordinates which radio shouldtransmit when.

The CPU of this radio is an STM32F405 fromSTMicroelectronics. This contains a Cortex M4, soall instructions are Thumb and all function point-ers are odd. The LQFP100 package of this chipis used. It has a megabyte of Flash and 192 kilo-bytes of RAM. The STM32 has both JTAG and aROM bootloader, but both of these are protectedby a Readout Device Protection (RDP) feature. InSection 8.8, I’ll show you how to bypass these pro-tections and jailbreak your radio.

There is also a radio baseband chip, theHR C5000. At first I was reconstructing the pinoutof this chip from the CS700 Service Manual, but thefull documentation can be had from DocIn, a Chi-nese PDF sharing website.

Aside from a bunch of support components thatwe can take for granted, there is an SPI Flash chipfor storing the codeplug. “Codeplug” is a Motorolaterm for the radio settings, such as frequencies, con-tacts, and talk groups; I use the term here to distin-guish the radio configuration in SPI Flash from the

59unzip pocorgtfo10.pdf p25sec.pdf #from Proceedings of the 20th Usenix Security Symposium in 201160The folks at Connect Systems are nice and neighborly, so please buy a radio from them.

76

Page 2: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

code and data in CPU Flash.

80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

6059

5857

5655

5453

5251

5049

4847

4645

4443

4241

1817

1615

1413

1211

109

87

65

43

21

1920

HRC_5000

HPVCC

HPOUT

HPGND

CDC_VREF

MIC2_N

MIC2_P

MIC1_N

MIC1_P

CDC_AVCC

LINEOUT

MICBIAS

PLL_AVCC

PLL_AVSS

XTALI

CKOut

MCLK

ADCDAT

BCLK

LRCK

DACDAT

DVCC

RF_TX_EN

RF_RX_EN

U_SCLK

U_CS

U_SDI

DVDD

U_SDO

RF_RX_INTER

RF_TX_INTER

SYS_INTER

TIME_SLOT_INTER

NULL

PWD

RESETn

TESTMODE

DVSS

C_SDO

C_SCLK

C_CS

McB

SP_

RxD

McB

SP_T

xD

McB

SP_

CLKR

McB

SP_F

SX

McB

SP_C

LKX

McB

SP_F

SR

PKT_R

X_W

AKE

RTS

TX_R

QST

TX_R

DY

STDBY_E

NABLE

DVDD

V_S

DI

V_S

DO

V_S

CLK

V_C

S

C_S

DI

NULL

DVSS

DVCC

DCD

C_S

W

DCD

C_V

DD50

DCDC_V

SS

DCDC_V

DD12

DAC_I

VOUT

DAC_A

VDD33

DAC_A

VSS

33

DAC_Q

VOUT

AVC_V

GB_I

ADC_I

VIN

N

ADC_I

VIN

P

ADC_A

VDD33

_I

ADC_A

VDD

ADC_A

GND

ADC_A

VDD33

_Q

ADC_Q

VIN

P

ADC_Q

VIN

N

ADC_V

GB_Q

NULL

ADC_A

GND

8.2 A Partial Dump

From lsusb -v on Linux, we can see that the de-vice implements USB DFU, most likely as a fork ofsome STMicro example code. The MD380 appearsas an STMicro DFU device with storage for InternalFlash and SPI Flash with a VID:PID of 0483:df11.

1 iMac% dfu−u t i l − l i s tFound DFU: [ 0 4 8 3 : df11 ]

3 devnum=0, c f g =1, i n t f =0, a l t =0,name="@Internal Flash

5 /0 x08000000 /03∗016Kg"Found DFU: [ 0 4 8 3 : df11 ]

7 devnum=0, c f g =1, i n t f =0, a l t =1,name="@SPI Flash Memory

9 /0 x00000000 /16∗064Kg"

Further, the .rdt codeplug files are SPI Flashimages in the DMU format, which is pretty muchjust wrapper with a bare minimum of metadataaround a flat, uncompressed memory image. Thesecodeplug files contain the radio’s contact list, re-peater frequencies, and other configuration info.We’ll get back to this later, as what we really wantto do is dump and patch the firmware.

Unfortunately, dumping memory from the deviceby the standard DFU protocol doesn’t seem to yielduseful results, just the same repeating binary string,regardless of the alternate we choose or the startingposition.

1 iMac% dfu−u t i l −d 0483: df11 −−a l t 1 −s 0 :0 x200000 −Uf i r s t 1 k . bin

F i l t e r on vendor = 0x0483 product = 0xdf113 Opening DFU capable USB dev ice . . . ID 0483: df11

Run−time dev ice DFU ver s i on 011a5 Found DFU: [ 0 483 : df11 ] devnum=0, c fg =1, i n t f =0, a l t =1,

name="@SPI Flash Memory /0x00000000 /16∗064Kg"7 Claiming USB DFU In t e r f a c e . . .

Se t t ing Alternate Se t t ing #1 . . .9 Determining dev ice s ta tu s : s t a t e = dfuUPLOAD−IDLE

abort ing prev ious incomplete t r a n s f e r11 Determining dev ice s ta tu s : s t a t e = dfuIDLE , s ta tu s = 0

dfuIDLE , cont inu ing13 DFU mode dev ice DFU ver s i on 011a

Device returned t r a n s f e r s i z e 102415 Limit ing default upload to 2097152 bytes

bytes_per_hash=102417 Sta r t ing upload : [####...####] f i n i s h e d !

iMac% hexdump f i r s t 1 k . bin19 0000000 30 1a 00 20 15 56 00 08 29 54 00 08 2b 54 00 08

0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 0021 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00 08

0000030 35 54 00 08 00 00 00 00 83 30 00 08 37 54 00 0823 0000040 61 56 00 08 65 56 00 08 69 56 00 08 5b 54 00 08

. . .25 00003 c0 10 eb 01 60 df f8 34 1a 08 60 df f8 1c 0c 00 78

00003d0 40 28 c0 f0 e6 81 df f8 24 0a 00 68 00 f0 0e f f27 00003 e0 df e1 df f8 10 1a 09 78 a2 29 0 f d1 df f8 f8 19

00003 f0 09 68 02 29 0a d1 df f8 00 0a 02 21 01 70 df f829 . . . [ same 1024 bytes repeated ]

In this brave new world, where folks break theirbytes on the little side by order of Golbasto Mo-marem Evlame Gurdilo Shefin Mully Ully Gue,Tyrant of Lilliput and Eternal Enemy of Big En-dians and Blefuscu, to break them on the little side,it’s handy to spot four byte sequences that could beinterrupt handlers. In this case, what we’re lookingat is the first few pointers of an interrupt vector ta-ble. This means that we are grabbing memory fromthe beginning of internal flash at 0x08000000!

Note that the data repeats every kilobyte, andalso that dfu-util is reporting a transfer size of1,024 bytes. The -t switch will order dfu-util todump more than a kilobyte per transfer, but every-thing after the first transfer remains corrupted.

This is because dfu-util isn’t sending theproper commands to the radio firmware, and it’s get-ting the page as a bug rather than through properuse of the protocol. (There are lots of weird variantsof DFU, created by folks only using DFU with theirown tools and never testing for compatibility witheach other. This variant is particularly weird, butmanageable.)

8.3 Tapping USB with VMWare

Before going further, it was necessary to learn theradio’s custom dialect of DFU. Since my Total PhaseUSB sniffers weren’t nearby, I used VMWare to sniffthe transactions of both the MD380’s firmware up-dater and codeplug configuration tools.

I did this by changing a few lines of my VMWare.vmx configuration to dump USB transactions out

77

Page 3: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

to vmware.log, which I parsed with ugly regexes inPython. These are the additions to the .vmx file.

1 monitor = "debug"usb . ana lyze r . enable = TRUE

3 usb . ana lyze r . maxLine = 8192mouse . vusb . enable = FALSE

The logs showed that the MD380’s variant ofDFU included non-standard commands. In partic-ular, the LCD screen would say “PC Program USBMode” for the official client applications, but notfor any 3rd party application. Before I could do aproper read, I had to find the commands that wouldenter this programming mode.

DFU normally hides extra commands in theUPLOAD and DNLOAD commands when the block ad-dress is less than two. (Hiding them in blocks0xFFFF and 0xFFFE would make more sense, but ifwishes were horses, then beggars would ride.)

To erase a block, a DFU host sends 0x41 followedby a little endian address. To set the address pointer(block 2’s address), the host sends 0x21 followed bya little endian address.

In addition to those standard commands, theMD380 also uses a number of two-byte (rather thanfive-byte) DNLOAD transactions, none of which existin the standard DMU protocol. I observed the fol-lowing, which I still only partially understand.

Non-Standard DNLOAD Extensions91 01 Enables programming mode on LCD.a2 01 Seems to return model number.a2 02 Sent only by config read.a2 31 Sent only by firmware update.a2 03 Sent by both.a2 04 Sent only by config read.a2 07 Sent by both.91 31 Sent only by firmware update.91 05 Reboots, exiting programming mode.

8.4 Custom Codeplug Client

Once I knew the extra commands, I built a customDFU client that would send them to read and writecodeplug memory. With a little luck, this mighthave given me control of firmware, but as you’ll see,it only got me half way.

Because I’m familiar with the code from a priortarget, I forked the DFU client from an old versionof Michael Ossmann’s Ubertooth project.61

Sure enough, changing the VID and PID of theubertooth-dfu script was enough to start dumpingmemory, but just like dfu-util, the result was arepeating sequence of the first block’s contents. Be-cause the block size was 256 bytes, I received onlythe first 0x100 bytes repeated.

Adding support for the non-standard commandsin the same order as the official software, I got acopy of the complete 256K codeplug from SPI Flashinstead of the beginning of Internal Flash. Hooray!

To upload a codeplug back into the radio, I mod-ified the download() function to enable program-ming mode and properly wait for the state to returnto dfuDNLOAD_IDLE before sending each block.

This was enough to write my own codeplug fromone radio into a second, but it had a nasty little bug!I forgot to erase the codeplug memory, so the radiogot a bitwise AND of two valid codeplugs.62

A second trip with the USB sniffer shows thatthese four blocks were erased, and that the uploadaddress must be set to zero after the erasure.0x00000000 0x00010000 0x00020000 0x00030000

Erasing the blocks properly gave me a tool thatcorrectly reads and writes the radio codeplug!

8.5 Codeplug FormatNow that I could read and write the codeplug mem-ory of my MD380, I wanted to be able to edit it.Parts of the codeplug are nice and easy to reverse,with strings as UTF16L and numbers being eitherintegers or BCD. Checksums don’t seem to matter,and I’ve not yet been able to brick my radios byuploading damaged firmware images.

The Radio Name is stored as a string at 0x20b0,while the Radio ID Number is an integer at 0x2080.The intro screen’s text is stored as two strings at0x2040 and 0x2054.

#s eekto 0x5F80 ;2 struct {

ul24 c a l l i d ; //DMR Account Number4 u8 f l a g s ; //c2 pr i va te , no tone

//e1 group , with rx tone6 char name [ 3 2 ] ; //U16L chars

} contac t s [ 1 0 0 0 ] ;

61In particular, I used r543 of the old SVN repository, a version from 4 July 2012.62See PoC‖GTFO 2:5.63http://chirp.danplanet.com

78

Page 4: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

CHIRP,63 a ham radio application for editingradio codeplugs, has a bitwise library that expectsmemory formats to be defined as C structs with baseaddresses. By loading a bunch of contacts into myradio and looking at the resulting structure, it waseasy to rewrite it for CHIRP.

Repeatedly changing the codeplug with the man-ufacturer’s application, then comparing the hex-dumps gave me most of the radio’s important fea-tures. Patience and a few more rounds will give methe rest of them, and then my CHIRP plugin can becleaned up for inclusion.

Unfortunately, not everything of importance ex-ists within the codeplug. It would be nice to exportthe call log or the text messages, but such commandsdon’t exist and the messages themselves are nowhereto be found inside of the codeplug. For that, we’llneed to break into the firmware.

8.6 Dumping the Bootloader

Now that I had a working codeplug tool, I’d like acleartext dump of firmware. Recall from Section 8.2that forgetting to send the custom command 0x910x01 leaves the radio in a state where the beginningof code memory is returned for every read. This isan interrupt table!

MD380 Recovery Bootloader Interrupts0x20001a30 Top of the call stack.0x08005615 Reset Handler0x08005429 Non-Maskable Interrupt (NMI)0x0800542b Hard Fault0x0800542d MMU Fault0x0800542f Bus Fault0x08005431 Usage Fault

From this table and the STM32F405 datasheet,we know the code flash begins at 0x08000000 andRAM begins at 0x20000000. Because the firmwareupdater only writes to regions at and after 0x0800-C000, we can guess that the first 48k are a recoverybootloader, with the region after that holding theapplication firmware. As all of the interrupts areodd, and because the radio uses a Cortex M4 core,we know that the firmware is composed exclusivelyof Thumb (and Thumb2) code, with no old fash-ioned ARM instructions.

Sure enough, I was able to dump the whole boot-loader by reading a single page of 0xC000 bytes fromthe application mode. This bootloader is the one

used for firmware updates, which can be startedby holding PTT and the unlabeled button aboveit when turning on the power switch.64

This trick doesn’t expose enough memory todump the application, but it was valuable to me fortwo very important reasons. First, this bootloadergave me some proper code to begin reverse engineer-ing, instead of just external behavioral observations.Second, the recovery bootloader contains the keysand code needed to decrypt an application image,but to get at that decrypted image, I first had to dosome soldering.

STFM32F405LQFP100

PA3

VSS

VDD

PA4

PA5

PA6

PA7

PC4

PC5

PB0

PB1

PB2

PE7

PE8

PE9

PE10

PE11

PE12

PE13

PE14

PE15

PB10

PB11

VCAP_1

VDD

VDD

VSS

PE1

PE0

PB9

PB8

BOOT0

PB7

PB6

PB5

PB4

PB3

PD7

PD6

PD5

PD4

PD3

PD2

PD1

PD0

PC12

PC11

PC10

PA15

PA14

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

12345678910111213141516171819202122232425

75747372717069686766656463626160595857565554535251

PE2PE3PE4PE5PE6VBAT

PC14PC15VSSVDDPH0

NRSTPC0PC1PC2PC3VDDVSSAVREF+VDDAPA0PA1PA2

VDDVSSVCAP_2PA13PA12PA11PA10PA9PA8PC9PC8PC7PC6PD15PD14PD13PD12PD11PD10PD9PD8PB15PB14PB13PB12

PC13

PH1

100

99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76

8.7 Radio Disassembly (BOOT0 Pin)

As I stress elsewhere, the MD380 has three appli-cations in it: (1) Tytera’s Radio Application, (2)Tytera’s Recovery Bootloader, and (3) STMicro’sBootloader ROM. The default boot process is forthe Recovery Bootloader to immediately start theRadio Application unless Push-To-Talk (PTT) andthe button above it are held during boot, in whichcase it waits to accept a firmware update. Thereis no key sequence to start the STMicro BootloaderROM, so a bit of disassembly and soldering is re-quired.

This ROM contains commands to read and writeall of memory, as well as to begin execution at anyarbitrary address. These commands are initiallylocked down, but in Section 8.8, I’ll show how toget around the restrictions.

64Transfers this large work on Mac but not Linux.

79

Page 5: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

To open your radio, first remove the battery andthe four Torx screws that are visible from the backof the device. Then unscrew the antenna and care-fully pry off the two knob covers. Beneath each knoband the antenna, there are rings that screw in placeto secure them against the radio case; these shouldbe moved by turning them counter-clockwise usinga pair of sturdy, dull tweezers.

Once the rings have been removed, the radio’smain board can be levered up at the bottom of theradio, then pulled out. Be careful when removing it,as it is attached with a Zero Insertion Force (ZIF)connector to the LCD/Keypad board, as well as bya short connector to the speaker.

The STMicro Bootloader is started by pullingthe BOOT0 pin of the STM32F405 high whilerestarting the radio. I did this by soldering a thinwire to the test pad near that pin, wrapping thewire around a screw for strain relief, then carefullyfeeding it out through the microphone/speaker port.

(An alternate method involves removingBOOT0’s pull-down resistor, then fly-wiring it tothe pull-up on the PTT button. Thanks to trickypower management, this causes the radio to bootnormally, but to reboot into the Mask ROM.)

8.8 Bootloader RE

Once I finally had a dump of Tytera’s bootloader,it was time to reverse engineer it.65

The image is 48K in size and should be loaded to0x08000000. Additionally, I placed 192K of RAMat 0x20000000. It’s also handy to create regions forthe I/O banks of the chip, in order to help trackthose accesses. (IDA and Radare2 will think thatperipherals are global variables near 0x40000000.)

After wasting a few days exploring the commandset, I had a decent, if imperfect, understanding ofthe Tytera Bootloader but did not yet have a clear-text copy of the application image. Getting a bitimpatient, I decided to patch the bootloader to keepthe device unprotected while loading the applicationimage using the official tools.

I had to first explore the STM32 Standard Pe-ripheral Library to find the registers responsible forlocking the chip, then hunt for matching code.

1 /∗ STM32F4xx f l a s h regs from stm32f4xx . h ∗/#@0x40023c00

3 typedef struct {__IO uint32_t ACR; // access c t r l 0x00

5 __IO uint32_t KEYR; // key 0x04__IO uint32_t OPTKEYR; // opt ion key 0x08

7 __IO uint32_t SR; // s t a t u s 0x0C__IO uint32_t CR; // con t ro l 0x10

9 __IO uint32_t OPTCR; // opt ion c t r l 0x14__IO uint32_t OPTCR1; // opt ion c t r l 1 0x18

11 } FLASH;

65The MD5 of my image is 721df1f98425b66954da8be58c7e5d55, but you might have a different one in your radio.

81

Page 6: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

The way flash protection works is that byte 1of FLASH->OPTCR (at 0x40023C15) is set to the pro-tection level. 0xAA is the unprotected state, while0xCC is the permanent lock. Anything else, such as0x55, is a sort of temporary lock that allows theapplication to be wiped away by the Mask ROMbootloader, but does not allow the application to beread out.

Tytera is using this semi-protected mode, so youcan pull the BOOT0 pin of the STM32F4xx chip highto enter the Mask ROM bootloader.66 This processis described in Section 8.7.

Sure enough, at 0x08001FB0, I found a functionthat’s very much like the example FLASH_OB_RDP-Config function from stm32f4xx_flash.c. I callthe local variant rdp_lock().

1 /∗ Sets the read p ro t e c t i on l e v e l .∗ OB_RDP s p e c i f i e s the p ro t e c t i on l e v e l .

3 ∗ AA: No pro t e c t i on .∗ 55: Read pro t e c t i on memory .

5 ∗ CC: Fu l l ch ip p ro t e c t i on .∗ WARNING: When enab l ing OB_RDP l e v e l 2

7 ∗ i t ’ s no longer p o s s i b l e to go∗ back to l e v e l 1 or 0 .

9 ∗/void FLASH_OB_RDPConfig( uint8_t OB_RDP){

11 FLASH_Status s t a tu s = FLASH_COMPLETE;

13 /∗ Check the parameters ∗/assert_param (IS_OB_RDP(OB_RDP) ) ;

15s t a tu s = FLASH_WaitForLastOperation ( ) ;

17 i f ( s t a tu s == FLASH_COMPLETE)∗(__IO uint8_t ∗)

19 OPTCR_BYTE1_ADDRESS = OB_RDP;}

66Confusingly enough, this is the third implementation of DFU for this project! The radio application, the recovery bootloader,and the ROM bootloader all implement different variants of DFU. Take care not to confuse the them.

82

Page 7: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

This function is called from main() with a pa-rameter of 0x55 in the instruction at 0x080044A8.

0x080044a0 fd f 7a0 fd bl rdp_isnot locked2 0x080044a4 0028 cmp r0 , 0

,=< 0x080044a6 04d1 bne 0x80044b24 | ; Change t h i s immediate from 0x55 to 0xAA

| ; to j a i l b r e a k the boo t l oade r .6 | 0x080044a8 5520 movs r0 , 0x55

| 0x080044aa fd f 781 fd bl rdp_lock8 | 0x080044ae fd f78b fd bl rdp_applylock

‘−> 0x080044b2 fd f 776 fd bl 0 x8001fa210 0x080044b6 00 f097 f a bl bootloader_pin_test

Patching that instruction to instead send 0xAAas a parameter prevents the bootloader from lock-ing the device. (We’re just swapping aa 20 in where55 20 used to be.)

iMac% d i f f o ld . txt j a i l b r e a k . txt2 < 00044 a0 fd f7 a0 fd 00 28 04 d1

55 20 fd f7 81 fd fd f74 −−−> 00044a0 fd f7 a0 fd 00 28 04 d1

6 aa 20 fd f7 81 fd fd f7

8.9 Dumping the Application

Once I had a jailbroken version of the recovery boot-loader, I flashed it to a development board and in-stalled an encrypted MD380 firmware update usingthe official Windows tool. Sure enough, the appli-cation installed successfully!

After the update was installed, I rebooted theboard into its ROM by holding the BOOT0 pin high.Since the recovery bootloader has been patched toleave the chip unlocked, I was free to dump all ofFlash to a file for reverse engineering and patching.

8.10 Reversing the Application

Reverse engineering the application isn’t terribly dif-ficult, provided a few tricks are employed. In thissection, I’ll share a few; note that all pointers inthis section are specific to Version 2.032, but similarfunctionality exists in newer firmware revisions.

At the beginning, the image appears almost en-tirely without symbols. Not one function or systemcall comes with a name, but it’s easy to identifya few strings and I/O ports. Starting from those,related functions—those in the same .C source file—are often located next to one another in memory,providing hints as to their meaning.

The operating system for the application is anARM port of MicroC/OS-II, an embedded real-timeoperating system that’s quite well documented inthe book of the same name by Jean J. Labrosse. Alarge function at 0x0804429C that calls the operat-ing system’s OSTaskCreateExt function to make abaker’s dozen of threads. Each of these convenientlyhas a name, conveniently describing the system in-terrupt, the real-time clock timer, the RF PLL, andother useful functions.

As I had already reverse engineered most of theSPI Flash codeplug, it was handy to work backwardfrom codeplug addresses to identify function behav-ior. I did this by identifying spiflash_read at0x0802fd82 and spiflash_write at 0x0802fbea,then tracing all calls to these functions. Once thesehave been identified, finding codeplug functions iseasy. Knowing that the top line of startup text is 32bytes stored at 0x2040 in the codeplug, finding thecode that prints the text is as simple as looking forcalls to spiflash_read(&foo, 0x2040, 20).

Thanks to the firmware author’s stubborn in-sistence on 1-indexing, many of the structures inthe codeplug are indexed by an address just be-fore the real one. For example, the list of ra-dio channel settings is an array that begins at0x1ee00, but the functions that access this arrayhave code along the lines of spiflash_read(&foo,64*index+0x1edc0, 64).

One mystery that struck me when reverse engi-neering the codeplug was that I didn’t find a missedcall list or any sent or received text messages. Sureenough, the firmware shows that text messages arestored after the end of the 256K image that the radioexposes to the world.

Code that accesses the C5000 baseband chip canbe reverse engineered in a similar fashion to thecodeplug. The chip’s datasheet67 is very well han-dled by Google Translate, and plenty of dandy func-tions can be identified by writes to C5000 registersof similar functions.

Be careful to note that the C5000 has multiplememories on its primary SPI bus; if you’re not care-ful, you’ll confuse the registers, internal RAM, andthe Vocoder buffers. Also note that a lot of registersare missing from the datasheet; please get in touchwith me if you happen to know what they do.

Finally, it is crucially important to be able tosort through the DMR packet parsing and construc-tion routines quickly. For this, I’ve found it handy

67unzip pocorgtfo10.pdf hrc5000.pdf

83

Page 8: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

to keep paper printouts of the DMR standard, whichare freely available from ETSI.68 Link-Local ad-dresses (LLIDs) are 24 bits wide in DMR, and youcan often locate them by searching for code thatmasks against 0xFFFFFF.69

8.11 Patching for PromiscuityWhile it’s fun to reverse engineer code, it’s all abit pointless until we write a nifty patch. Complexpatches can be introduced by hooking function calls,but let’s start with some useful patches that only re-quire changing a couple of bits. Let’s enable promis-cuous receive mode, so the MD380 can receive fromall talk groups on a known repeater and timeslot.

In DMR, audio is sent to either a Public Talk-group or a Private Contact. These each have a 24-bitLLID, and they are distinguished by a bit flag else-where in the packet. For a concrete example, 3172 isused for the Northeast Regional amateur talkgroup,while 444 is used for the Bronx TRBO talkgroup. Ifan unmodified MD380 is programmed for just 3172,it won’t decode audio addressed to 444.

There is a function at 0x0803ec86 that takes aDMR audio header as its first parameter and decideswhether to play the audio or mute it as addressedto another group or user. I found it by looking foraccess to the user’s local address, which is held inRAM at 0x2001c65c, and the list of LLIDs for in-coming listen addresses, stored at 0x2001c44c.

To enable promiscuous reception to unknowntalkgroups, the following talkgroup search routinecan be patched to always match on the first el-ement of listengroup[]. This is accomplishedby changing the instruction at 0x0803ee36 from0xd1ef (JNE) to 0x46c0 (NOP).

for ( i = 0 ; i < 0x20u ; ++i ) {2 i f ( ( l i s t e ng r oup [ i ] & 0xFFFFFF)

== dst_l l id_adr ) {4 something = 16 ;

r ecogn i zed_l l id_dst = dst_l l id_adr ;6 current_l l id_group = var_lgroup [ i +16] ;

sub_803EF6C ( ) ;8 dmr_squelch_thing = 9 ;

i f ( ∗( v4 + 4) & 0x80 )10 byte_2001D0C0 |= 4u ;

break ;12 }

}

A similar JNE instruction at 0x0803ef10 can bereplaced with a NOP to enable promiscuous recep-tion of private calls. Care in real-world patchesshould be taken to reduce side effects, such as byforcing a match only when there’s no correct match,or by skipping the missed-call logic when promiscu-ously receiving private calls.

8.12 DMR ScanningAfter testing to ensure that my patches worked, Iused Radio Reference to find a few local DMR sta-tions and write them into a codeplug for my mod-ified MD380. Soon enough, I was hearing the bestgossip from a university’s radio dispatch.70

Later, I managed to find a DMR network thatused the private calling feature. Sure enough, myradio would ring as if I were the one being called,and my missed call list quickly grew beyond my twolocal friends with DMR radios.

8.13 A New BootloaderUnfortunately, the MD380’s application consumesall but the first 48K of Flash, and that 48K is con-sumed by the recovery bootloader. Since we neigh-bors have jailbroken radios with a ROM bootloaderaccessible, we might as well wipe the Tytera boot-loader and replace it with something completelynew, while keeping the application intact.

Luckily, the fine folks at Tytera have madethis easy for us! The application has its owninterrupt table at 0x0800C000, and the RESEThandler—whose address is stored at 0x0800C004—automatically moved the interrupt table, cleans upthe stack, and performs other necessary chores.

1 //Minimal is t boo t l oader .void main ( ) {

3 //Function po in t e r to the app l i c a t i on .void (∗ appmain ) ( ) ;

5 //The handler address i s the s to red in the// i n t e r r up t t a b l e .

7 uint32_t ∗ r e s e thand l e r =( uint32_t ∗) 0x0800C004 ;

9 // Set the func t i on po in t e r to t ha t va lue .appmain = (void (∗ ) ( ) ) ∗ r e s e thand l e r ;

11 //Away we go !appmain ( ) ;

13 }

68ETSI TS 102 361, Parts 1 to 4.69In assembly, this looks like LSLS r0, r0, #8; LSRS r0, r0, #8.70Two days of scanning presented nothing more interesting than a damaged elevator and an undergrad too drunk to remember

his dorm room keys. Almost gives me some sympathy for those poor bastards who have to listen to wiretaps.

84

Page 9: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

8.14 Firmware Distribution

Since this article was written, DD4CR has managedto free up 200K of the application by gutting theChinese font. She also broke the (terrible) updateencryption scheme, so patched or rewritten firmwarecan be packaged to work with the official updatertools from the manufacturer.

Patrick Hickey W7PCH has been playing aroundwith from-scratch firmware for this platform, builtaround the FreeRTOS scheduler. His code is al-ready linking into the memory that DD4CR freedup, and it’s only a matter of time before fully-functional community firmware can be dual-bootedon the MD380.

– — — – — — — — – — –In this article, you have learned how to jailbreak

your MD380 radio, dump a copy of its application,and begin patching that application or writing yourown, new application.

Perhaps you will add support for P25, D-Star,or System Fusion. Perhaps you will write a properscanner, to identify unknown stations at a whim.Perhaps you will make DMR adapter firmware, sothat a desktop could send and receiver DMR framesin the raw over USB. If you do any of these things,please tell me about it!

Your neighbor,Travis

85

Page 10: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

DATE:

Approve:

Check:

ofPage:

REV:

Model:

Filename:

File NO

.:

Designer:

36

PETER

1.02014.08.11

R314

180R

LED303RED

R315

220R

LED301GREEN

Q301

DTC

144EEQ

302D

TC144EE

R31647K

C316

103 R31747K

C317

103 R31847K

C318

103 R31947K

C319

103

R320

0R

R321

10K

1EC

12

G1

6EC

0

7 G0

4EC

35

G2

3EC

2

8 G0

SW302

CO

DE-SW

ITCH

C320

104

R362

4K7R

3634K7

C362

104

1C

SN2

SO6

SCK

5SI

4VSS

3W

PN

7H

OLD

N

8VC

C

U302

W25Q

128FVSIG

4SD

A

3SC

L

2G

ND

5VPP

1R

STO

6VD

D

U307

HR

_V3000S

C307

104

C305104

C306

104

C308

105

5 PE614 NRST1 PE22 PE33 PE44 PE57 PC13_ANTI_TAMP8 PC14_OSC32_IN9 PC15_OSC32_OUT12 OSC_IN13 OSC_OUT73 VCAP_215 PC016 PC117 PC218 PC320 VREF-23 PA0_WKUP24 PA162 PD1563 PC664 PC765 PC866 PC967 PA8

72PA13

25PA2

26PA3

29PA4

30PA5

31PA6

32PA7

33PC

434

PC5

35PB0

36PB1

37PB2

38PE7

39PE8

40PE9

41PE10

42PE11

43PE12

44PE13

45PE14

46PE15

47PB10

48PB11

68PA9

69PA10

51PB12 52PB13 53PB14 54PB15 55PD8 56PD9 57PD10 58PD11 59PD12 60PD13 61PD14 49VCAP_1 74VSS_2 10VSS_5 27VSS_4 99VSS_3 22VDDA 21VREF+ 19VDD 50VDD_1 11VDD_5 28VDD_4 100VDD_3 75VDD_2 6VBAT

76PA14

77PA15

78PC

1079

PC11

80PC

1281

PD0

82PD

183

PD2

84PD

385

PD4

86PD

587

PD6

88PD

789

PB390

PB491

PB592

PB693

PB794

BOO

T095

PB896

PB997

PE098

PE170

PA1171

PA12

U301

STM32F405VG

T6

C3038P

C3028P

R313

10K

1

TP301JTAG

_SWC

LK

R306

10K

R305

NC

1TP303BO

OT0

C343

105

C345

103

R336

22K

C332

153 R335

15K

C333183

C312

103

C313

103

3VEE2

2VEE1

1N

C

4O

UT

5VC

CU303

PST9124

R342

10KC

338104C

339103

R301 1K

R3394K7C

335392

R338

4K7C

336183

R341

2K2

1

TP305JTAG

_RESET

C337

105

R310

10K

R304N

C

R340

22K

1

TP304JTAG_SWDIO

R311

1KR

3121K

C352

105

R303

10K

C344

105

C360104

C361104

R350 NC

R3911K

R370

1K

R3340R

13 X301

8MH

z

R308 1K

R3091K

C301

10P

C304

10P

14

23

X30232.768KH

z

D304

NC

R392

1K

R393

220R

C340N

C

Q303

NC

R348 1K

R349

47KC

341

104

R352

1K

54321 6 7

FPC301

PTT_PAD

R345

10K

R355 100R

R354 100R

R359

1KR

3581K

R357

1KR

3561K

1H

OLD

/IO3

2VC

C3

RESET#

4D

NU

5D

UN

6C

S2#7

CS1#

8SO

/IO1

9W

P#/IO2

10VSS

11D

NU

12D

NU

13N

C14

VIO/R

FU15

SI/IO0

16SC

K

U305

NC

C350

NC

R364

NC

R367

NC

R365

NC

R366

NC

R347N

C

C349

NC

R360

1KR

3801K

R3021K

D305

KDS160E

BAT301M

S412F-FL26E

BAT+

3V3

3V3

FLASH_SD

O

FLASH_SC

LK

FLASH_C

S0

FLASH_SD

I

ECN

0EC

N1

ECN

2EC

N3

RX_LED

TX_LED

3V3

3V3

BSHIFT

LCD_D1

APC/TV

MO

D2_BIAS

LCD

_D4

LCD

_D5

VOX

BUSY

5RC

USB_D

+

LCD

_RD

SCL

3V3LC

D_W

R

K1

3V3

VOL_O

UT

3V3

SAVE

5TC

ECN

1EC

N2

ECN

3

ECN

0

LCD_RSLCD_RST

LCD

_D2

LCD

_D3

K2K3

USB_D

-

PLL_LDPLL_CS

LCD_D0

SDA

DMR_SLEEP

TIME_SLOT_INTERSYS_INTER

RF_TX_INTERRF_RX_INTER

QT_D

QT_IN

RSSI

LCD

_D6

2T/5T/DTM

F_OU

T

BATT

LAMP

FM_SW

CTC

/DC

S_OU

T

POW

_C

DM

R_SW

VCO

VCC

_SW

EXT_PTT

LCD

_CS

FLASH_SC

LKFLASH

_SDO

FLASH_SD

I I2S_FSI2S_C

KI2S_R

XI2S_TX

RF_APC

_SW

2T/5T

BEEP

W/N

_SW

C5000_RST

MIC

PWR

_SW

32.768K_OUT32.768K_IN

32.768K_IN

TX_LED

BSHIFT

32.768K_OUT

DMR_SDO

DMR_CSDMR_SCLK

DMR_SDI

PTT_KEY3V3

K3LC

D_D

6LC

D_D

7

LCD

_D7

3V3

PLL_DAT

PLL_CLK

FM_M

UTE

V_CSV_SCLKV_SDOV_SDI

FLASH_CS1FLASH_CS2

SPK_CAFC

OR

X_LED

SDA

SCL

3V3

3V3

FLASH_SD

O FLASH_C

S2FLASH

_CS1

FLASH_SC

LKFLASH

_SDI

BACK3V3

3V3

PTT_KEY

FLASH_C

S0

86

Page 11: Reverse Engineering the Tytera MD380 - QSL.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08 31 54 00 08 00 00 00 00 21 0000020 00 00 00 00 00 00 00 00 00 00 00 00 33 54 00

Che

ck:

Appr

ove:

DAT

E:of

Page

:R

EV:

Mod

el:

File

nam

e:

File

NO

.:

Des

igne

r:

26

PETE

R

1.0

2014

.08.

11

R22

6N

C

R23

81K

R23

210

K

L202

BLM

18AG

601S

C24

4

220P

R22

7N

C

R23

110

K

C24

122

0P

R23

61K

1H

PVC

C9

CD

C_A

VCC

12PL

L_VD

D33

66AD

C_A

VDD

33_Q

67AD

C_A

VDD

33_I

76D

AC_A

VDD

3379

DC

DC

_VD

D33

32VD

D12

53VD

D12

69AD

C_A

VDD

12_I

64AD

C_A

VDD

12_Q

77D

CD

C_V

DD

1280

DC

DC

_SW

18BC

LK17

LRC

K16

MC

LK19

ADC

DAT

39R

ESET

N45

DBI

ST_I

N38

TEST

_MO

DE 21VSS12 33VSS12 52VSS12 3HPGND 13PLL_VSS33 65ADC_AGND_Q 68ADC_AGND_I 73DAC_AVSS33 78DCDC_VSS 41V_SDI 42V_SDO 43V_SCLK 44V_CS 59RF_RX_EN 60RF_TX_EN 61ADC_VBG_Q 14XTAL 15CLKOUT 62ADC_QVINN 63ADC_QVINP

4C

DC

_VR

EF71

ADC

_IVI

NN

70AD

C_I

VIN

P34

C_S

DI

35C

_SD

O36

C_S

CLK

37C

_CS

48TI

ME_

SLO

T_IN

TER

49SY

S_IN

TER

50R

F_TX

_IN

TER

51R

F_R

X_IN

TER

55U

_SD

O56

U_S

DI

57U

_SC

LK58

U_C

S2

HPO

UT

72AD

C_V

BG_I

10LI

NEO

UT

74D

AC_Q

VOU

T75

DAC

_IVO

UT

22 MCBSP_RXD23 MCBSP_TXD24 MCBSP_CLKR25 MCBSP_FSX26 MCBSP_CLKX27 MCBSP_FSR28 PKT_RX_WAKE29 RTS30 TX_RDY31 STDBY_ENB47 PWD40 VDD3354 VDD3346 DBIST_OUT20 DACDAT8 MIC1_P5 MIC2_P11 MICBIAS7 MIC1_N6 MIC2_N

U20

1H

R_C

5000

C23

310

2

C23

210

4

R22

910

R

C23

510

4C

236

10U

/10V

C22

7

103

C22

810

U/1

0V

C23

0

104

C22

510

4

C24

0

104

C23

9

104

C22

610

4

C27

9

105

C27

6

103

C27

8

103

C28

0

103

C28

1

105

C28

2

103

C28

3

105

C28

4

103

C26

9

105

C27

0

103

C27

1

105

C27

2

103

C27

4

104

C27

3

104

R24

910

0R

R23

310

KR

234

10K

R23

5N

CC

234

NC

R22

51K

C22

410

51

12

-V3

34

4

5+V

U20

3TC

75S5

1F

R24

010

K

R24

122

K

C24

810

2

C25

010

5

R24

322

0K

R24

410

0K

C25

347

0PC

252

104

R25

31K

C23

110

P

L208

BLM

18AG

601S

C24

910

5

C23

810

5

C29

0

104

C29

1

10U

/10V

C23

7

103

C31

0

104

C31

1

104

C26

110

4

R25

810

K

C26

010

3

R26

72K

2

R26

110

R

C26

847

0P

Q20

1D

TC14

4EE

EC26

410

0uF/

6.3V

C26

310

4

12L201

BLM

21PG

221S

R26

510

0K

C26

210

4

C25

7

103

C26

710

4

R25

91K

C26

6

105

Q20

2FM

MT7

17

R26

810

R

Q20

3D

TC14

4EE

C25

810

5

1O

UTP

UT1

2VC

C

3O

UTP

UT2

4G

ND

5N

F2

6IN

PUT2

7IN

PUT1

8N

F1

U20

4TD

A282

2D

R26

010

R

R26

647

K

R29

9N

C

1

23

Q20

4ST

2302

1

23

Q20

7ST

2302

R28

010

KC

286

105

C28

9

103

C28

7

103

C28

5

104

+

EC25

910

uF/1

0V

+

C26522U/10V

1N

C

2G

ND

4VC

C

3O

UTX2

0129

.491

2MH

z

L203

47uH

123

45

SW40

1VO

L-SW

ITC

H

A3V3

3V3

3V3

ADC

_IN

_N

A3V3

BAT+

3V3

3V3

DM

R_V

CC

VOL_

OU

T

V_CSV_SCLK

V_SDOV_SDI

2T/5T/DTMF_OUTMIC_OUT

DMR_SLEEP

DM

R_C

SD

MR

_SC

LKD

MR

_SD

I

IF_O

UT

VOL_

OU

T

MO

D2

MO

D1

I2S_

RX

I2S_

TXI2

S_C

KI2

S_FS

DM

R_S

DO

RF_

RX_

INTE

RR

F_TX

_IN

TER

SYS_

INTE

RTI

ME_

SLO

T_IN

TER

POW

_SW

BAT+

AFC

O

SPK_

C

EXT_

SPK+

SPK-

C5000_RST

87