reverse engineering the tytera md380 - qsl.net · 2016. 2. 14. · 0000010 2d 54 00 08 2 f 54 00 08...
Post on 16-Aug-2020
5 Views
Preview:
TRANSCRIPT
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
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
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
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
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
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
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
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
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
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
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
top related