NefMoto

Technical => Reverse Engineering => Topic started by: setzi62 on May 19, 2011, 09:21:12 AM



Title: How to patch in code changes
Post by: setzi62 on May 19, 2011, 09:21:12 AM
Setzi,
Can you provide a detailed explanation of the process you use to incorporate this function?
As you can imagine, there is no standard way to integrate a new function into different ECUs.
As a very highlevel description, the following steps have to be done to integrate a new function
into a binary:
1) Produce disassembled code of the image.
   - Need a disassembler for C167 to do this.
   - Useful if you have a disassembly of a similar image with symbol names inside for comparison.

2) Find the addresses of all global variables in the image that are needed in the new function.
   - This is done normally by looking into the disassembled code and roughly "knowing"
     which things/patterns to look for or comparing code of a reference image.
   - These variable addresses vary with each image version, same as it is with map addresses.

3) Find unused parameter space in flash, if configurable parameters are needed in the function.
   - some smaller areas are still found to be unused, best is to verify in the
     disassembled code if the selected space is really not accessed by regular code.

4) Find unused RAM space, if local variables are needed in the function.
   - also here, some areas are still found to be unused, best is to verify in the
     disassembled code if the selected space is really not accessed by regular code.

5) Find a free space in the flash to store the new function.
   - after end of regular code there is normally enough unused space found in the flash.

6) Find the point where to link-in the new function in the image.
   - This is done by searching again in the disassembled code.

7) Finally, write the new function in assembler, assemble the code of the new function
   with the correct addresses of global variables, parameters, and local variables.
   - Need an assembler for C167 to do this.
   - Be careful: don't disturb the stack, don't change registers which are used by the orig code.
   - If you write position independent code, you don't have to care at which address
     the code gets stored.

8 ) Store the assembled function at the selected address in the flash, and link it in
   at the selected point by replacing the existing instruction by a call to your function.
   - The new function should perform the replaced instruction as last instruction.

9) Test the image.
   - If you made a fault, the ecu will start the application at first, but then reboot repeatedly
     -> time for bootmode flashing  ;).

All of the above steps besides the final testing can also be done by tool (kind of
self-installing-patch). Such a tool needs to be created specifically for each use case.
Makes sense only if you want to implement the same/similar function to many different images.



Title: Re: How to patch in code changes
Post by: Tony@NefMoto on May 19, 2011, 12:33:41 PM
This post was split from this thread: http://www.nefariousmotorsports.com/forum/index.php/topic,607.0title,.html


Title: Re: How to patch in code changes
Post by: phila_dot on May 20, 2011, 12:07:08 PM
Thank you Setzi. This is a little above my skill set at the moment, but it gives me an idea of what to look into.


Title: Re: How to patch in code changes
Post by: DJGonzo on May 24, 2011, 08:55:20 PM
Thank you Setzi. This is a little above my skill set at the moment, but it gives me an idea of what to look into.
You can say that again...
Try disassembling a binary dump in IDA Pro.. Trust me, your head will hurt, guaranteed lol.

Im not a wiz with IDA Pro. Maybe someone can post some really basic tuts for identifying routines? I think that's what this forum should be more focused in :)


Title: Re: How to patch in code changes
Post by: krazydbiker on July 01, 2012, 01:31:59 PM
I have been reading through almost every post on this forum, so interesting all the information thats on it, this is by far one of the ones that completely stumps me, so i would like to understand it, im kind of new here, i actually started digging into volvo me7 computers, and have gotten pretty far with it by learning most of me7's internal workings from this site, but the one thing i have left is trying to implement some sort of code like this post shows, proving to be a little bit over my head at the moment, im not sure if im selecting the right processer when loading in IDA pro


Title: Re: How to patch in code changes
Post by: elRey on November 22, 2012, 09:37:03 AM
Question.... how do you keep from using a registry spot that may have been set before calling the new function and used afterward?

Say in your new function you:
Code:
mov r9, something

And you call your new function in some other subroutine. But somewhere before your call, the subroutine has already set r9 and then uses/reads r9 later on after you call?

How do you avoid conflicts like that?


Title: Re: How to patch in code changes
Post by: matchew on November 22, 2012, 09:57:14 AM
Pop and push the Register on/off the stack.


Title: Re: How to patch in code changes
Post by: rajivc666 on November 22, 2012, 11:56:20 AM
 push/pop is rarely used in most subroutines. Use the instruction mov [-r0],r9 to push it and instruction mov r9,[r0+] to pop it.     


Title: Re: How to patch in code changes
Post by: elRey on November 23, 2012, 10:10:24 AM
Thanks guys. So, to be safe I should [-r0] all Registies used in a new function at the beginning and then [+r0] then back at the end?

Does this sound unreasonable? 


Title: Re: How to patch in code changes
Post by: rajivc666 on November 23, 2012, 10:39:00 AM
If you are replacing an original subroutine with yours look for clues there, some registers will be used to return values which obviously need not be saved, I use the rule if in doubt then save.


Title: Re: How to patch in code changes
Post by: fknbrkn on January 17, 2015, 11:29:36 PM
how to determine what memory adresses are unused? i have dissasembled binary and see many unused RAM space (#38), but when i log a few adresses (without conversion) which im planned to use with my own routine i see a strange freezed values in it like a 57990 or 63078.

and second question - i have used ALS routine`s calls() function but where i can make my own link? 


Title: Re: How to patch in code changes
Post by: elRey on September 24, 2015, 06:11:48 PM
What is the easiest way to add ability to PASTE a hex code chunk into IDA hex view ?

IDA version 5.5

Thanks,
Rey


Title: Re: How to patch in code changes
Post by: wannabee900 on September 25, 2015, 01:58:33 AM
put the hex code in a binary file and import it to specific offset works well


Title: Re: How to patch in code changes
Post by: elRey on September 25, 2015, 04:01:34 AM
does this insert and offset the existing code while increasing file size? or does this overwrite existing code? I need it to overwrite.

Thanks,
Rey


Title: Re: How to patch in code changes
Post by: elRey on September 28, 2015, 01:43:10 PM
I tried this and it worked great. Thank you.



To expand on the original topic, can we discuss deleting unused functions to reclaim space and repurposing that space for new, custom functions? I've done it with SLS and am currently deleting DSLSLRS.

My concern is identifying if deleted function was called or was part of the main runtime loop and how to handle either case with new functions. i.e. if a want to write a called function in the place of a runtime loop function that gets ran all the time.


Title: Re: How to patch in code changes
Post by: hackish on October 20, 2015, 07:36:38 AM
I tried this and it worked great. Thank you.

To expand on the original topic, can we discuss deleting unused functions to reclaim space and repurposing that space for new, custom functions? I've done it with SLS and am currently deleting DSLSLRS.

My concern is identifying if deleted function was called or was part of the main runtime loop and how to handle either case with new functions. i.e. if a want to write a called function in the place of a runtime loop function that gets ran all the time.

You can easily just write a stub patch. Replace the function call with a branch to your stub, make the function call along with whatever extra function you want, then jump back to the instruction after the branch. In high level code it's the equivalent of using a couple of GOTO's. For your patches you're better off to follow the ABI so you can write the patches in C rather than assembler. It's far more productive and a good C compiler makes all sorts of messy optimizations without you having to think about it.


Title: Re: How to patch in code changes
Post by: dream3R on December 27, 2015, 08:57:57 PM
Thanks guys. So, to be safe I should [-r0] all Registies used in a new function at the beginning and then [+r0] then back at the end?

Does this sound unreasonable? 

Think of it as pop and push (stack)


Title: Re: How to patch in code changes
Post by: flamy on December 28, 2015, 12:39:53 AM
I also started with IDA Pro a few days ago to try out some code changes.
Is there any possibility to mass-rename adresses?

ME7Info is able to extract lots of RAM variables from a binary.
It would be nice to import them to IDA Pro.


Title: Re: How to patch in code changes
Post by: dream3R on December 28, 2015, 01:37:29 AM
I also started with IDA Pro a few days ago to try out some code changes.
Is there any possibility to mass-rename adresses?

ME7Info is able to extract lots of RAM variables from a binary.
It would be nice to import them to IDA Pro.

I think everyone want a python script to-do that, give it a shot?


Title: Re: How to patch in code changes
Post by: TijnCU on December 28, 2015, 01:46:49 AM
You can write them into the disassembly with this AutoIt script  (http://nefariousmotorsports.com/forum/index.php?topic=2431.0title=)from prj.


Title: Re: How to patch in code changes
Post by: dream3R on December 30, 2015, 06:59:56 PM
You can easily just write a stub patch. Replace the function call with a branch to your stub, make the function call along with whatever extra function you want, then jump back to the instruction after the branch. In high level code it's the equivalent of using a couple of GOTO's. For your patches you're better off to follow the ABI so you can write the patches in C rather than assembler. It's far more productive and a good C compiler makes all sorts of messy optimizations without you having to think about it.

Like the idea dude.   There's a few empty ones in most code (stubs)


Title: Re: How to patch in code changes
Post by: Khendal on December 18, 2016, 03:07:02 PM
I'm interesenting to apply a patch code...but i need first to disassembly the bin file...

i have this one :

Seat Leon Cupra R 1.8T BAM 225HP ME7.5 1ML906032A 0261208221 367220

Could you please advice me which settings i need to use with IDA pro?
Thanks
 


Title: Re: How to patch in code changes
Post by: TijnCU on March 14, 2018, 11:36:35 AM
A summary of options to code in IDA:

- You can go to hex-view and press F2 to manually write code.
- you can use the patch functionality (edit>patch program>byte/word/assemble), in the patch byte function you can paste 16 bytes at a time. For most smaller functions this works quite well.
In my IDA version 6.1, patch code was not enabled. I manually enabled it by going to IDA\cfg\>idagui.cfg and look for patch submenu and set it to YES.
- You can import a bin file to a specific offset: go to File>Load file>Additional binary file... Leave "loading segments" empty, fill in the correct offset in "Loading Offset" (for example 0x8F0000) and uncheck Create segments to load it directly into your project.


Title: Re: How to patch in code changes
Post by: totti on August 07, 2021, 01:12:23 PM
Hi,

If I would like to add a custom code which has to changes more variables what is the best solution? 1 function which contains all of the variable changes and link every original variable change to the function or have more functions which are just changes only 1 variable and link the specified variable changes to the functions.
Maybe I give a short example: For pops and bangs I changes only zwout and fuel cut. I have 2 functions 1 is for zwout changes 1 is for fuel cut. I found 3 zwout chang functions in the original code and I changed these movb commands to call with the cutom function address. I also found fuel cut movb and changed it to the custom function.

Now I think about the merge the 2 functions and link all of the relevant movb commands.


Title: Re: How to patch in code changes
Post by: prometey1982 on September 11, 2022, 06:58:08 AM
Slightly modified prj's Python code for loading a2l
It's also define constants and bitfield enums and assign adress to it.

Code:
import idc
import idaapi

def processrom(min, max):
if min > 0:
min = min - 1
curaddr = idc.FindUnexplored(min, idc.SEARCH_DOWN)
while curaddr < max:
if idc.MakeFunction(curaddr) != True:
idc.MakeCode(curaddr)
curaddr = idc.FindUnexplored(curaddr, idc.SEARCH_DOWN)

return

def a2l(filename):
lastvarname = ""
lastaddress = ""
with open(filename) as fp:
                f = fp.read()
measurements = f.split("/begin MEASUREMENT")
measurements.pop(0)
print("Found: %d measurement(s)" % len(measurements))
for m in measurements:
namefound = 0
addrfound = 0
name = ""
addr = ""
                        is_enum = False
                        bit_mask = 0
for l in m.split("\n"):
l = l.strip()
if (len(l) > 0):
if (namefound == 0):
name = l
namefound = 1
                                        elif (l.startswith("BIT_MASK")):
                                                is_enum = True
                                                bit_mask = int(l.split(" ")[1], 16)
elif (l.startswith("ECU_ADDRESS")):
addr = l[12:]
addrfound = 1
break
if (addrfound != 1):
print("ERROR")
                        elif (is_enum):
                                enum_name = "enum_" + addr[2:]
                                enum_id = idc.GetEnum(enum_name)
                                if (enum_id == 4294967295L):
                                        enum_id = idc.AddEnum(-1, enum_name, 0)
                                        idc.OpEnumEx(int(addr, 0), -1, enum_id, 0)
                                        idc.MakeNameEx(int(addr, 0), "", 0)
                                if (not idc.IsBitfield(enum_id)):
                                        idc.SetEnumBf(enum_id, 1)
                                idc.AddConstEx(enum_id, name, bit_mask, bit_mask)
else:
idc.MakeNameEx(int(addr, 0), name, 1)
characteristics = f.split("/begin CHARACTERISTIC")
characteristics.pop(0)
print("Found: %d characteristics(s)" % len(characteristics))
for m in characteristics:
namefound = 0
addrfound = 0
name = ""
addr = ""
                        is_enum = False
                        bit_mask = 0
for l in m.split("\n"):
l = l.strip()
if (len(l) > 0):
if (namefound == 0):
name = l
namefound = 1
elif (l.startswith("/begin IF_DATA ETK")):
                                                addr = l.split(" ")[5]
#addr = l[28:7]
addrfound = 1
break
if (addrfound != 1):
print("ERROR", name)
else:
                                idc.MakeUnknown(int(addr, 0), 1, idaapi.DOUNK_SIMPLE)
idc.MakeNameEx(int(addr, 0), name, 1)
return


Title: Re: How to patch in code changes
Post by: sonflasch on October 23, 2022, 05:56:29 AM
Slightly modified prj's Python code for loading a2l
It's also define constants and bitfield enums and assign adress to it.

Code:
import idc
import idaapi

def processrom(min, max):
if min > 0:
min = min - 1
curaddr = idc.FindUnexplored(min, idc.SEARCH_DOWN)
while curaddr < max:
if idc.MakeFunction(curaddr) != True:
idc.MakeCode(curaddr)
curaddr = idc.FindUnexplored(curaddr, idc.SEARCH_DOWN)

return

def a2l(filename):
lastvarname = ""
lastaddress = ""
with open(filename) as fp:
                f = fp.read()
measurements = f.split("/begin MEASUREMENT")
measurements.pop(0)
print("Found: %d measurement(s)" % len(measurements))
for m in measurements:
namefound = 0
addrfound = 0
name = ""
addr = ""
                        is_enum = False
                        bit_mask = 0
for l in m.split("\n"):
l = l.strip()
if (len(l) > 0):
if (namefound == 0):
name = l
namefound = 1
                                        elif (l.startswith("BIT_MASK")):
                                                is_enum = True
                                                bit_mask = int(l.split(" ")[1], 16)
elif (l.startswith("ECU_ADDRESS")):
addr = l[12:]
addrfound = 1
break
if (addrfound != 1):
print("ERROR")
                        elif (is_enum):
                                enum_name = "enum_" + addr[2:]
                                enum_id = idc.GetEnum(enum_name)
                                if (enum_id == 4294967295L):
                                        enum_id = idc.AddEnum(-1, enum_name, 0)
                                        idc.OpEnumEx(int(addr, 0), -1, enum_id, 0)
                                        idc.MakeNameEx(int(addr, 0), "", 0)
                                if (not idc.IsBitfield(enum_id)):
                                        idc.SetEnumBf(enum_id, 1)
                                idc.AddConstEx(enum_id, name, bit_mask, bit_mask)
else:
idc.MakeNameEx(int(addr, 0), name, 1)
characteristics = f.split("/begin CHARACTERISTIC")
characteristics.pop(0)
print("Found: %d characteristics(s)" % len(characteristics))
for m in characteristics:
namefound = 0
addrfound = 0
name = ""
addr = ""
                        is_enum = False
                        bit_mask = 0
for l in m.split("\n"):
l = l.strip()
if (len(l) > 0):
if (namefound == 0):
name = l
namefound = 1
elif (l.startswith("/begin IF_DATA ETK")):
                                                addr = l.split(" ")[5]
#addr = l[28:7]
addrfound = 1
break
if (addrfound != 1):
print("ERROR", name)
else:
                                idc.MakeUnknown(int(addr, 0), 1, idaapi.DOUNK_SIMPLE)
idc.MakeNameEx(int(addr, 0), name, 1)
return


Hello all
I use the code from prometey1982 so far without any problems.

now i have another a2l which looks a little different.
here as an example:
Code:
/begin MEASUREMENT B_dslvh 
 "Bedingung Ladedrucksensor vorhanden"
 UWORD
 B_TRUE
 1
 100
 0.0
 255.0
 /begin IF_DATA DIM_X
  KP_BLOB 0xFD00 INTERN BYTE 
 /end IF_DATA
 /begin IF_DATA MCMESS
 
  KP_BLOB 0xFD00 INTERN 
 /end IF_DATA
 BIT_MASK 0x8000
/end MEASUREMENT

I have rewritten the code so far and everything works except for the ENUMS entry (it does not write ENUMS as a list).
he writes eg the enum mentioned above as a single measured value
(all others under the address will be ignored)

someone an idea? thanks for any hint

Code:
#Load a2l = a2l("C:\my.a2l")
import idc
import idaapi

def processrom(min, max):
if min > 0:
min = min - 1
curaddr = idc.FindUnexplored(min, idc.SEARCH_DOWN)
while curaddr < max:
if idc.MakeFunction(curaddr) != True:
idc.MakeCode(curaddr)
curaddr = idc.FindUnexplored(curaddr, idc.SEARCH_DOWN)

return

def a2l(filename):
lastvarname = ""
lastaddress = ""
with open(filename) as fp:
                f = fp.read()
measurements = f.split("/begin MEASUREMENT")
measurements.pop(0)
print("Found: %d measurement(s)" % len(measurements))
for m in measurements:
namefound = 0
addrfound = 0
name = ""
addr = ""
                        is_enum = False
                        bit_mask = 0
for l in m.split("\n"):
l = l.strip()
if (len(l) > 0):
if (namefound == 0):
name = l
namefound = 1
                                        elif (l.startswith("BIT_MASK")):
                                                is_enum = True
                                                bit_mask = int(l.split(" ")[1], 16)
elif (l.startswith("KP_BLOB")):
#addr = l[12:]
#print(l)
addr = l
addr = addr.replace("EXTERN","")
addr = addr.replace("WORD","")
addr = addr.replace("BYTE","")
  addr = addr.replace("LONG","")                       
addr = addr.replace("DP_BLOB","")
addr = addr.replace("KP_BLOB","")
addr = addr.replace("INDIRECT","")
addr = addr.replace(" ","")
addr = addr.replace("INTERN","")
addr = addr.replace("EXTERN","")
addr = addr.replace("IN","")
addr = addr.replace("DIRECT","")
#print(addr)
addrfound = 1
break
if (addrfound != 1):
print("ERROR")
                        elif (is_enum):
                                enum_name = "enum_" + addr[2:]
                                enum_id = idc.GetEnum(enum_name)
                                if (enum_id == 4294967295L):
                                        enum_id = idc.AddEnum(-1, enum_name, 0)
                                        idc.OpEnumEx(int(addr, 0), -1, enum_id, 0)
                                        idc.MakeNameEx(int(addr, 0), "", 0)
                                if (not idc.IsBitfield(enum_id)):
                                        idc.SetEnumBf(enum_id, 1)
                                idc.AddConstEx(enum_id, name, bit_mask, bit_mask)
else:
idc.MakeNameEx(int(addr, 0), name, 1)
characteristics = f.split("/begin CHARACTERISTIC")
characteristics.pop(0)
print("Found: %d characteristics(s)" % len(characteristics))
for m in characteristics:
namefound = 0
addrfound = 0
name = ""
addr = ""
                        is_enum = False
                        bit_mask = 0
for l in m.split("\n"):
l = l.strip()
if (len(l) > 0):
if (namefound == 0):
name = l
namefound = 1
elif (l.startswith("DP_BLOB DIRECT")):
                                                addr = l
                                                addr = addr.replace("DP_BLOB DIRECT","")
#addr = l[18:7]
addrfound = 1
break
if (addrfound != 1):
print("ERROR", name)
else:
                                idc.MakeUnknown(int(addr, 0), 1, idaapi.DOUNK_SIMPLE)
idc.MakeNameEx(int(addr, 0), name, 1)
return