Title: disassembling med9.1.1 (2.5mb) on ghidra Post by: lgtmelo on April 15, 2024, 03:45:19 PM i found ghidra to be easier to use than ida (maybe this is the case for ppc only, but this is what worked for me), so ill share how i did it. thanks for basano for posting his med9.1 guide which helped, elias too, and prj for calling me stupid for trying to do this for months using a 2mb file only. please forgive any dumbness i might say here, im not very familiar with most technical terms (even basic stuff).
first of all, be aware med9.1.1 is a 2.5mb flash ecu, so besides the actual usual 2mb read (which is all mpps will give me), you need a 512kb file that i gathered would only come if a full read/bench was performed. for this reason, i just searched for a full read from someone in the hope it would make my stuff work, since i dont have the tool to do it myself. im attaching the 512kb file i got (i think originally from a 8T0907560F, while mine ends in AD), and my own 2mb ori read. this ECU needs to be loaded differently from basano's med9.1 post because of this 512kb file. here's how i did it: 1-open ghidra, load the 2mb file, under language select powerpc, default, 32, big. under options, you dont need to change anything for now. set the block name as "bin" if you want, just for organization. if it asks if you want to analyze, click no. 2-go to file, add to program, then add the 512kb file. language will already be selected. click options, then on base address, put 0x400000. dont change offset and length. set the block name as "mpc" if you want. 3-go to file, add to program, then add the 2mb file AGAIN. this is how the ECU sees the maps (calibration) area. the reason for that can be checked at basano's original thread, where he or someone else posted a portion of the damos file which references the memory map. under options, put base address as 0x5c2000 and offset 0x1c2000 and length 0x3e000. this means from the 2mb file, we are getting data starting at the address 0x1c2000 until 0x1c2000+0x3e000. this data is being then inserted into our project at the address 0x5c2000. call this block "calibration" if you want. 4-now we need to create the RAM block. go to window -> memory map. click the green + sign at the top right. under block name put "ram", start address is 0x600000, length is 0x300000. see to it that "read, write and execute" checkbox are marked. 5-now we need to define base registers for MPC. r2 and r13. these are important because they serve as references throughout the whole program. on ghidra's main text window, select all (ctrl+a), then type ctrl+R and in the dropdown menu, just type r2 and it will select r2 (r32). put 0x5C9FF0 as value. do the same for r13 and use 0x7FFFF0 as value. 6-now everything is set to begin decompiling. before doing the automatic stuff we will help ghidra by manually setting some stuff. go to 0 and manually decompile vectors using D button. usually vectors starts with 48 00 at 0x0 address and at 400000 address (go there by typing G button). this tip came from user kur4o in another forum which i dont know if i can link to, so i just wont to avoid headaches. but thanks for the help if you ever read this! this just means you'll go to a line such as Code: 00000008 48 ?? 48h H and observe that the next line is Code: 00000009 00 ?? 00h so you can go to the first one that has the 48, and type D. this will turn it into LAB_address, an auto-generated label (usually a jump target within a function). you can also type D in the first lines of these sectors that show as 48 01 (this is how i did by mistake and it worked out. again, not a pro here). now it should look like the screenshot below, so you can go to analysis -> auto analyze, or simply type A. from this on, you can follow basano's thread, the main difference is the offset when comparing stuff to WINOLS. for example, he finds KLPROV (from the axis, not the actual map), which for my ECU, is at 1D50A0. to find it in ghidra, i subtract the offset 1c2000, which gives me 130A0. then, considering i loaded it at 5c2000, we sum it, resulting in 5D50A0. type G to go to 5D50A0, which is where the actual map is (so you'll see some raw data that we dont care). by the right side, theres XREF[amount of references to this address]: FUN_function that calls it:line that contains it. double click it, and it will take you to the actual function which is what we are looking for. :) hope this helps someone, someday. Title: Re: disassembling med9.1.1 (2.5mb) on ghidra Post by: prj on April 15, 2024, 11:05:58 PM You need to have the 512k and 2mb from the same file..
If you load them from different bins then you're gonna have garbage. Unless the EPK is the same of course. Title: Re: disassembling med9.1.1 (2.5mb) on ghidra Post by: lgtmelo on April 16, 2024, 05:27:54 AM You need to have the 512k and 2mb from the same file.. If you load them from different bins then you're gonna have garbage. Unless the EPK is the same of course. yes, i had to just run with it because its what i could get my hands in, but if someone has a full read for a 8t0907560ad and is willing to share, please do :D Title: Re: disassembling med9.1.1 (2.5mb) on ghidra Post by: prj on April 18, 2024, 04:40:52 AM There is nothing to "run with".
You need to load the flash that is for the mpc file. The software is one whole. The flash calls into the MPC and the MPC calls into the flash. If they are different versions, then the calls go in the wrong place and the code is complete garbage. Completely useless to perform any reversing work. It's like cutting a car in half, welding a half of another car on and then wondering why the propshaft is not connected to the rear wheels anymore. Because it's in the wrong place and cut through. Title: Re: disassembling med9.1.1 (2.5mb) on ghidra Post by: lgtmelo on April 18, 2024, 05:59:03 AM There is nothing to "run with". You need to load the flash that is for the mpc file. The software is one whole. The flash calls into the MPC and the MPC calls into the flash. If they are different versions, then the calls go in the wrong place and the code is complete garbage. Completely useless to perform any reversing work. It's like cutting a car in half, welding a half of another car on and then wondering why the propshaft is not connected to the rear wheels anymore. Because it's in the wrong place and cut through. Yes, you are correct. But this is good enough for me to begin with, and as long as people are aware of that, it should be good enough for first contact purposes and as a learning kickstart. All the maps and variables I have gone through so far do match as expected (which does NOT mean there won't be eventual discrepancies). Again, it is unfortunate I dont have the tools to get a full read, but if someone has the file and would like to share, please do :) Title: Re: disassembling med9.1.1 (2.5mb) on ghidra Post by: prj on April 19, 2024, 03:07:42 AM I did not check your file, it is always possible that both are the same EPK, in which case it's fine.
Title: Re: disassembling med9.1.1 (2.5mb) on ghidra Post by: lgtmelo on May 02, 2024, 04:21:17 PM very happy to have found the ram variables address table. this will make life easier regarding following and identifying stuff. it wouldnt be possible without nubcake's MED9info tool (posted in this forum 6 years ago), since i reverse engineered his program to understand how he did it. for those interested in the process, first you need to find the following pattern, which i believe will work not only for med9.1.1 but any med9.1, based on Basano's post.
Code: 38 21 00 10 4e 80 00 20 00 03 this final 00 03 is already the beginning of the map. its a 1x2400 map, 32bit (HiLo) if you want to save it. now comes the tricky part. those addresses arent the actual ram addresses to the var, but the addresses to the instruction that will load the var. lets see nmot for example. it is the first non-empty var in the FR list. so we skip the very first value of the table (which is var 0 Leeranzeige (blank display) in FR). var 1 is nmot. my bytes for this var are labeled as REF_1_nmot, you can do this too by pressing L in ghidra. originally it comes in a strange name like LAB_0003ccdc (LAB as in label, then the address it points to). when I double click my label, it takes me somewhere. this somewhere will have the instruction lbz or lhz or lha (all these load stuff into a register), and ghidra is so kind as to translate what is being saved into the register as =>something. it will come originally as DAT_007fce9a (DAT as in data, then the address of our actual var this time). again, you can type L over it and rename it like i did, so now my points to =>nmot. if you double click it, you will again be sent somewhere else, where you can actually see every place nmot is being called, by clicking XREF[number of calls] on the left. |