Setup IDA Pro to disassemble preFL Convers+ Firmware 7M2T-14C026-AG
Setup IDA Pro to disassemble preFL Convers+ Firmware 7M2T-14C026-AG
In this topic i'd like to show how i setup my reverse engineering environment to disassemble the IPC firmware of release 7M2T-14C026-AG.
Re: Setup IDA Pro to disassemble preFL Convers+ Firmware 7M2T-14C026-AG
Part 1) What is needed?
To answer this question let's take a look at the memory layout of the MAC7116: The important parts we need are:
Part 2) Gathering the needed data (binary images)
For the firmware itself, those VBF files are needed:
Now we also need the PBL code and the Reset-Vectors.Those are not available as VBF files, since they are programmed by the manufacturer. One way to get them is to download it from an working device having the same(!) firmware applied. I did it using JTAG, my Segger J-Link and J-Mem, a tool to read out memory locations through JTAG.
To do so, connect the J-Link probe to the IPC board, attach a 12V source to it (no IGN simulation needed), open "J-Link Commander" shell and issue these commands to connect to the device:
After that, you can type in these commands to readout the memory locations from the MAC and save them to a local file (adapt target path/name as needed):
Part 3) Putting it all together
For a quick startup, i've added a ZIP containing all the files needed.
1.) Startup IDA Pro and choose "New" 2.) Start with the bootvectors file "7M2T-14C026_VECTORS_0x00000000-0x0000001F.bin" file using "File" -> "Open...".
3.) Choose "ARM Big-endian [ARMB]" processor type (this can't change this afterwards!) 4.) Just accept the following dialog: 5.) Go to "View" -> "Open subviews..." -> "Segments" (or just press "Shift-F7") to open the "Program Segmentation" view. There, right-click and "Edit segment" (or just press "Ctrl+E") on the newly created "ROM" segment. Change segment name to "VECT" and check the "Execute" and "Read" permissions. 6.) Load the PBL file "7M2T-14C026_PBL_0x00001000_0x00004FFF.bin" with "File" -> "Load file" -> "Additional binary file...". Set "Loading segment" to "0x0" and "Loading offset" to "0x1000" ("Create segments" and "Code segment" should be checked): After loading, edit the newly created segment (usually called "seg...") and change it's name to "PBL" and also check the "Execute" and "Read" boxes. 7.) Do the very same (load additional file) with the Main-Firmware file called "7M2T-14C026-AG_MAIN_0x00005000-0x000FFFFF.bin". Set "Loading segment" to "0x0" and "Loading offset" to "0x5000". Edit the segment and change name to "MAIN" and check "Execute", "Read".
8.) Now load the external Flash file "7M2T-14C026-BC_FLASH_0x30000000-0x30200000.bin" in either the same way. Set "Loading segment" to "0x0" and "Loading offset" to "0x30000000", but this time uncheck the "Code segment" box as this file only contains data. Edit the new segment and change it's name to "FLASH", segment class to "DATA" and only check the "Read" box. 9.) The last file to add is the RAM file "7M2T-14C026_RAM-SNAP-NOIGN_0x40000000-0x4000C000.bin". This is only a J-Mem snapshot of a booted Convers+ having this firmware (no ignition, no other signals attached) and it should only aid us as a hint to have reasonable values in there instead of 0x00
. Load it as any other file before, set "Loading segment" to "0x0" and "Loading offset" to 0x40000000. Again enshure "Code segment" is unchecked. Change segment name to "RAM", segment class to "RAM" also (just enter it, if it's not there) and only check "Read", "Write" boxes.
10.) In the end your segmentation should look like this: And now it's time to save your work! So go to "File" -> "Save as..." (use a filename and directory you like)
11.) The very last thing to prepare is to do a inital analyzing of the code, where IDA try to detect the code out of the bytes in the segments flagged als executeable. Therefore double-click the "VECT" segment in the segmentation view, which leads you to the "IDA-View A" window: Now choose "Edit" -> "Select all", which will select the whole bytes of all segments, and hit "C" to auto-analyze all data: Answer "Yes" to this question: Now, it takes a while to analyze the code: You got functions detected on the left pane and see how IDA has changed from simply showing bytes to an Assembler view of commands: IDA gave you an impression of the memory layout in the top bar: What you find here is, where IDA could automatically detect code during analysis (blue) and where not (grey).
Now you are ready to go!
And beware: IDA Pro HAS NO UNDO (CTRL-Z) so "save early - save often".
To answer this question let's take a look at the memory layout of the MAC7116: The important parts we need are:
Start address | End address | Size | Content | Comment |
---|---|---|---|---|
0x0000_0000 | 0x0000_001F | 0x0000_0020 | Reset Vector table | Used for the MAC to know where to jump under certain conditions (e.g. Reset, Interrupt, ...) |
0x0000_1000 | 0x0000_3FFFF | 0x0000_4000 | Primary Bootloader (PBL) | This code is needed to bring the MAC and it's periphals up and running, like the BIOS of a PC |
0x0000_5000 | 0x00FB_4FFF | 0x00FB_0000 | MAIN Firmware | 1 MB of Firmware code, placed into internal Flash of MAC |
0x3000_0000 | 0x3001F_FFFF | 0x0020_0000 | FLASH Firmware | 2 MB of Firmware code/data, placed into the external Flash attached to the MAC |
0x4000_0000 | 0x4000_BFFF | 0x0000_C000 | SRAM | 48 KB internal SRAM of the MAC |
0xFC00_0000 | 0xFC0F_FFFF | 0x0010_0000 | Control Register Space | 1 MB address space to access periphals of the MAC |
Part 2) Gathering the needed data (binary images)
For the firmware itself, those VBF files are needed:
- 7M2T-14C026-AG.vbf -> MAIN
- 7M2T-14C026-BC.vbf -> FLASH
Now we also need the PBL code and the Reset-Vectors.Those are not available as VBF files, since they are programmed by the manufacturer. One way to get them is to download it from an working device having the same(!) firmware applied. I did it using JTAG, my Segger J-Link and J-Mem, a tool to read out memory locations through JTAG.
To do so, connect the J-Link probe to the IPC board, attach a 12V source to it (no IGN simulation needed), open "J-Link Commander" shell and issue these commands to connect to the device:
Code: Select all
selectinterface 0
speed 750
jtagconf -1,-1
device MAC7116
BE
connect
Code: Select all
savebin c:\temp\bootvectors.bin, 0x0, 0x20
savebin c:\temp\pbl.bin, 0x1000, 0x4000
Part 3) Putting it all together
For a quick startup, i've added a ZIP containing all the files needed.
1.) Startup IDA Pro and choose "New" 2.) Start with the bootvectors file "7M2T-14C026_VECTORS_0x00000000-0x0000001F.bin" file using "File" -> "Open...".
3.) Choose "ARM Big-endian [ARMB]" processor type (this can't change this afterwards!) 4.) Just accept the following dialog: 5.) Go to "View" -> "Open subviews..." -> "Segments" (or just press "Shift-F7") to open the "Program Segmentation" view. There, right-click and "Edit segment" (or just press "Ctrl+E") on the newly created "ROM" segment. Change segment name to "VECT" and check the "Execute" and "Read" permissions. 6.) Load the PBL file "7M2T-14C026_PBL_0x00001000_0x00004FFF.bin" with "File" -> "Load file" -> "Additional binary file...". Set "Loading segment" to "0x0" and "Loading offset" to "0x1000" ("Create segments" and "Code segment" should be checked): After loading, edit the newly created segment (usually called "seg...") and change it's name to "PBL" and also check the "Execute" and "Read" boxes. 7.) Do the very same (load additional file) with the Main-Firmware file called "7M2T-14C026-AG_MAIN_0x00005000-0x000FFFFF.bin". Set "Loading segment" to "0x0" and "Loading offset" to "0x5000". Edit the segment and change name to "MAIN" and check "Execute", "Read".
8.) Now load the external Flash file "7M2T-14C026-BC_FLASH_0x30000000-0x30200000.bin" in either the same way. Set "Loading segment" to "0x0" and "Loading offset" to "0x30000000", but this time uncheck the "Code segment" box as this file only contains data. Edit the new segment and change it's name to "FLASH", segment class to "DATA" and only check the "Read" box. 9.) The last file to add is the RAM file "7M2T-14C026_RAM-SNAP-NOIGN_0x40000000-0x4000C000.bin". This is only a J-Mem snapshot of a booted Convers+ having this firmware (no ignition, no other signals attached) and it should only aid us as a hint to have reasonable values in there instead of 0x00
![Wink ;-)](./images/smilies/icon_e_wink.gif)
10.) In the end your segmentation should look like this: And now it's time to save your work! So go to "File" -> "Save as..." (use a filename and directory you like)
11.) The very last thing to prepare is to do a inital analyzing of the code, where IDA try to detect the code out of the bytes in the segments flagged als executeable. Therefore double-click the "VECT" segment in the segmentation view, which leads you to the "IDA-View A" window: Now choose "Edit" -> "Select all", which will select the whole bytes of all segments, and hit "C" to auto-analyze all data: Answer "Yes" to this question: Now, it takes a while to analyze the code: You got functions detected on the left pane and see how IDA has changed from simply showing bytes to an Assembler view of commands: IDA gave you an impression of the memory layout in the top bar: What you find here is, where IDA could automatically detect code during analysis (blue) and where not (grey).
Now you are ready to go!
And beware: IDA Pro HAS NO UNDO (CTRL-Z) so "save early - save often".
You do not have the required permissions to view the files attached to this post.
-
- Pro
- Posts: 364
- Joined: 04 Aug 2019, 22:47
Re: Setup IDA Pro to disassemble preFL Convers+ Firmware 7M2T-14C026-AG
RAM is shadowed to multiple ranges
For Ghidra I could use a separate file I created from MAC7116 PDF to describe its peripherals and their subsystems (a CMSIS-SVD format as it is described here: https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html). This way the 0xFC00_0000 - 0xFC0F_FFFF memory range is automatically translated to names of pheriperals / subsystem of peripherals... and it is easier to understand what a function does.
Couldn't find this option in IDA![Neutral :|](./images/smilies/icon_neutral.gif)
For Ghidra I could use a separate file I created from MAC7116 PDF to describe its peripherals and their subsystems (a CMSIS-SVD format as it is described here: https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html). This way the 0xFC00_0000 - 0xFC0F_FFFF memory range is automatically translated to names of pheriperals / subsystem of peripherals... and it is easier to understand what a function does.
Couldn't find this option in IDA
![Neutral :|](./images/smilies/icon_neutral.gif)
Re: Setup IDA Pro to disassemble preFL Convers+ Firmware 7M2T-14C026-AG
Yeah, i know what you mean and i did create such file for IDA Pro myself, but for a different processor type (HCS12). Will look forward to have this done for the MAC7100 family as well. In IDA this is set in a *.cfg file inside the "cfg" folder of the program directory.
The only thing that is tricky here is that we see the Firmware code does not contain direct pointers to those periphal addresses, but use "add" to create them from a base address, an module offset and also then using index-commands to access the serveral registers. How could IDA Pro relate those constructs to the final registers?
The only thing that is tricky here is that we see the Firmware code does not contain direct pointers to those periphal addresses, but use "add" to create them from a base address, an module offset and also then using index-commands to access the serveral registers. How could IDA Pro relate those constructs to the final registers?
Re: Disassemble MAC7116 software (Ford IPC)
Let's start from there... The first lines of code shows the vectortable:
As you can see these are just commands ("B" = Branch to, a jump instruction). IDA Pro generates dynamic labels (names) for the targets, prefixed with "loc_" (short for "location"), followed by the hex address of the destination. So here we see the first vector jumps into the PBL code (0x1000-0x4FFF) and all the other ones goes into the MAIN firmware code (0x5000 up). I think it's obvious that the first vector is the RESET vector (cold start) and the others are vectors for different purposes. BUT - there is a datasheet telling us excactly what they are used for:
This is called the "Core exception table", which are all some kind of "interrupt". The first one is caused by a Reset, regardless if it was triggered by poweron, soft-reset or watchdog-reset. The next one is caused whenever the PC (Program Counter) of the CPU is placed to something which is not executable/known opcode, and so on.
Rename locations/functions
So now, that we knew what they are used for and how they are called, we could give them more readable names. Therefore click on the name "loc_1018" and press "N" and this dialog comes up: Here i put "reset_entryPoint" in, and so it changes the name everywhere it was mentioned in the code:
We can repeat this for the other destinations, without knowing how they get handled by code, this does not matter.
Follow references
Now, to get to the code of the handler, just double-click on the label "reset_handler" here and IDA jumps to the location and shows us the code:
This is a typicall bootstrap init code for ARM. After loading the value "0xx4000BEFC" to register R0. That's of no use now, but later.
Next "MSR CPSR" set's the CPSR (Current Program Status Regsiter). This ARM-Register contains flags (bits) which enabled/disables some behaviour of the CPU. First it is loaded with direct value "0xD2", and it is more usefull here to have it shown as Binary not Hexadecimal expression. To change it, just click on the value and it get' marked, then press "B" and it changes to Binary view:
This will not change the code, just the way it is displayed. The same could be achieved by right-clicking the value and choose the appropriate entry from the context-menu.
Code: Select all
VECT:00000000 ; Segment type: Pure code
VECT:00000000 AREA VECT, CODE, ALIGN=0
VECT:00000000 CODE32
VECT:00000000 B loc_1018
VECT:00000000 ; DATA XREF: sub_2DF82+34↓r
VECT:00000000 ; sub_2DF82:loc_2DFCE↓r
VECT:00000004 ; ---------------------------------------------------------------------------
VECT:00000004 B loc_5308
VECT:00000008 ; ---------------------------------------------------------------------------
VECT:00000008 B loc_530C
VECT:0000000C ; ---------------------------------------------------------------------------
VECT:0000000C B loc_5310
VECT:00000010 ; ---------------------------------------------------------------------------
VECT:00000010 B loc_5314
VECT:00000014 ; ---------------------------------------------------------------------------
VECT:00000014 B loc_5318
VECT:00000018 ; ---------------------------------------------------------------------------
VECT:00000018 B loc_531C
VECT:0000001C ; ---------------------------------------------------------------------------
VECT:0000001C B loc_5320
VECT:0000001C ; VECT ends
Rename locations/functions
So now, that we knew what they are used for and how they are called, we could give them more readable names. Therefore click on the name "loc_1018" and press "N" and this dialog comes up: Here i put "reset_entryPoint" in, and so it changes the name everywhere it was mentioned in the code:
Code: Select all
VECT:00000000 B reset_handler
Follow references
Now, to get to the code of the handler, just double-click on the label "reset_handler" here and IDA jumps to the location and shows us the code:
Code: Select all
PBL:00001018 ; ---------------------------------------------------------------------------
PBL:00001018
PBL:00001018 reset_handler ; CODE XREF: VECT:00000000↑j
PBL:00001018 LDR R0, =0x4000BEFC
PBL:0000101C MSR CPSR_c, #0xD2
PBL:00001020 SUB SP, R0, #0x100
PBL:00001024 MSR CPSR_c, #0x5F ; '_'
PBL:00001028 B loc_3E50
PBL:00001028 ; ---------------------------------------------------------------------------
Next "MSR CPSR" set's the CPSR (Current Program Status Regsiter). This ARM-Register contains flags (bits) which enabled/disables some behaviour of the CPU. First it is loaded with direct value "0xD2", and it is more usefull here to have it shown as Binary not Hexadecimal expression. To change it, just click on the value and it get' marked, then press "B" and it changes to Binary view:
Code: Select all
PBL:0000101C MSR CPSR_c, #0b11010010
You do not have the required permissions to view the files attached to this post.
Re: Setup IDA Pro to disassemble preFL Convers+ Firmware 7M2T-14C026-AG
first time i have under stood how to use ida thanks
Digimod
Re: Setup IDA Pro to disassemble preFL Convers+ Firmware 7M2T-14C026-AG
Detecting strings
Another cool feature of IDA Pro is to detect strings in the images. This gives also valuable hints, especially of we found where those strings are "used". Before we let IDA look for them we need to setup some parameters that it knows what a string is and what not. This is done in "Options" -> "General" -> "Strings": The most important settings here are:
"Default string literal type" =>"C-style" is used if strings terminated with an 0x00
("Pascal style" is used if strings have a char-count as first, followed by the string chars itself, without an termination char)
After setting that, go to "View" -> "Open subviews" -> "Strings" (or hit "Shift+F12") and IDA starts collecting strings from the image an show them in a separate tab called "Strings window": As you see, IDA Pro has also added labels to the strings starting with "a" (see setup above) and continued by a CamelCase representation of the string. This way, if it was directly referred to in the code, you see it where it is used.
Very interesting what we can find here! And a good starting point for reverse engineering the code!
Another cool feature of IDA Pro is to detect strings in the images. This gives also valuable hints, especially of we found where those strings are "used". Before we let IDA look for them we need to setup some parameters that it knows what a string is and what not. This is done in "Options" -> "General" -> "Strings": The most important settings here are:
"Default string literal type" =>"C-style" is used if strings terminated with an 0x00
("Pascal style" is used if strings have a char-count as first, followed by the string chars itself, without an termination char)
After setting that, go to "View" -> "Open subviews" -> "Strings" (or hit "Shift+F12") and IDA starts collecting strings from the image an show them in a separate tab called "Strings window": As you see, IDA Pro has also added labels to the strings starting with "a" (see setup above) and continued by a CamelCase representation of the string. This way, if it was directly referred to in the code, you see it where it is used.
Very interesting what we can find here! And a good starting point for reverse engineering the code!
You do not have the required permissions to view the files attached to this post.
Re: Setup IDA Pro to disassemble preFL Convers+ Firmware 7M2T-14C026-AG
Sometimes IDA is wrong...
Beware that even if IDA Pro is a smart tool, i may sometimes convert nonsense to code. Most often easy to identify, like here:
The first lines containing "SVC 0xEFEFEF" are just because of empty Flash. Normally it should be 0xFF but somebody has decided to make empty flash areas 0xEF.
The rest "ANDEQ, STRDEQ" makes no sense at all, could be some leftovers from old code or data which hasn't referred to right now. You can turn such "false positive code" back to pure data by selecting the area with the mouse and hitting "U" for "undefine".
Beware that even if IDA Pro is a smart tool, i may sometimes convert nonsense to code. Most often easy to identify, like here:
Code: Select all
MAIN:000050D0 SVC 0xEFEFEF
MAIN:000050D4 SVC 0xEFEFEF
MAIN:000050D8 SVC 0xEFEFEF
MAIN:000050DC SVC 0xEFEFEF
MAIN:000050E0 SVC 0xEFEFEF
MAIN:000050E4 SVC 0xEFEFEF
MAIN:000050E8 SVC 0xEFEFEF
MAIN:000050EC SVC 0xEFEFEF
MAIN:000050F0 SVC 0xEFEFEF
MAIN:000050F4 SVC 0xEFEFEF
MAIN:000050F8 SVC 0xEFEFEF
MAIN:000050FC SVC 0xEFEFEF
MAIN:00005100 STRHEQ R6, [R0],-R4
MAIN:00005104 STRHEQ R6, [R0],-R12
MAIN:00005108 ANDEQ R6, R0, R4,ASR#7
MAIN:0000510C ANDEQ R6, R0, R12,ASR#7
MAIN:00005110 LDRDEQ R6, R7, [R0],-R4
MAIN:00005114 LDRDEQ R6, R7, [R0],-R12
MAIN:00005118 ANDEQ R6, R0, R4,ROR#7
MAIN:0000511C ANDEQ R6, R0, R12,ROR#7
MAIN:00005120 STRDEQ R6, R7, [R0],-R4
MAIN:00005124 STRDEQ R6, R7, [R0],-R12
MAIN:00005128 ANDEQ R6, R0, R4,LSL#8
MAIN:0000512C ANDEQ R6, R0, R12,LSL#8
MAIN:00005130 ANDEQ R6, R0, R4,LSL R4
MAIN:00005134 ANDEQ R6, R0, R12,LSL R4
MAIN:00005138 ANDEQ R6, R0, R4,LSR#8
MAIN:0000513C ANDEQ R6, R0, R12,LSR#8
MAIN:00005140 ANDEQ R6, R0, R4,LSR R4
MAIN:00005144 ANDEQ R6, R0, R12,LSR R4
MAIN:00005148 ANDEQ R6, R0, R0,ASR#8
MAIN:0000514C ANDEQ R6, R0, R8,LSR#9
MAIN:00005150 STRHEQ R6, [R0],-R0
MAIN:00005154 STRHEQ R6, [R0],-R4
MAIN:00005158 STRHEQ R6, [R0],-R8
MAIN:0000515C ANDEQ R6, R0, R8,ROR#9
MAIN:00005160 STRDEQ R6, R7, [R0],-R0
MAIN:00005164 STRDEQ R6, R7, [R0],-R4
MAIN:00005168 STRDEQ R6, R7, [R0],-R12
MAIN:0000516C ANDEQ R6, R0, R0,LSL R5
MAIN:00005170 ANDEQ R6, R0, R8,LSL R5
MAIN:00005174 ANDEQ R6, R0, R0,LSR#10
MAIN:00005178 ANDEQ R6, R0, R8,LSR#10
MAIN:0000517C ANDEQ R6, R0, R0,LSR R5
MAIN:00005180 ANDEQ R6, R0, R8,LSR R5
MAIN:00005184 ANDEQ R6, R0, R0,ASR#10
MAIN:00005188 ANDEQ R6, R0, R4,ASR#10
MAIN:0000518C ANDEQ R6, R0, R12,ASR#10
MAIN:00005190 ANDEQ R6, R0, R0,ROR#10
MAIN:00005194 ANDEQ R6, R0, R4,ROR#10
MAIN:00005198 ANDEQ R6, R0, R12,ROR#10
MAIN:0000519C ANDEQ R6, R0, R4,ROR R5
MAIN:000051A0 ANDEQ R6, R0, R12,ROR R5
MAIN:000051A4 ANDEQ R6, R0, R4,LSL#11
MAIN:000051A8 ANDEQ R6, R0, R12,LSL#11
MAIN:000051A8 ; ---------------------------------------------------------------------------
The rest "ANDEQ, STRDEQ" makes no sense at all, could be some leftovers from old code or data which hasn't referred to right now. You can turn such "false positive code" back to pure data by selecting the area with the mouse and hitting "U" for "undefine".