NefMoto

Technical => Reverse Engineering => Topic started by: prj on January 25, 2018, 03:14:28 AM



Title: IDA Pro helper functions
Post by: prj on January 25, 2018, 03:14:28 AM
Convert range to code (e.g. processrom(0x10000, 0x20000))

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

Load a2l (e.g. a2l("C:\my.a2l")):
Code:
def a2l(filename):
lastvarname = ""
lastaddress = ""
with open(filename) as fp:
measurements = fp.read().split("/begin MEASUREMENT")
measurements.pop(0)
print("Found: %d measurement(s)" % len(measurements))
for m in measurements:
namefound = 0
addrfound = 0
name = ""
addr = ""
for l in m.split("\n"):
l = l.strip()
if (len(l) > 0):
if (namefound == 0):
name = l
namefound = 1
elif (l.startswith("ECU_ADDRESS")):
addr = l[12:]
addrfound = 1
break
if (addrfound != 1):
print("ERROR")
else:
idc.MakeNameEx(int(addr, 0), name, 1)
return

Parse tricore indirect registers. Will replace ram+offset with actual value, so it can be crossreferenced and maps to a2l (e.g. indirect("a0", 0xDA80)):
Code:
def indirect(register, address):
print("Loading assembly...")
counter = 0
heads = list(idautils.Heads())
total = len(heads)
last = 0
replaced = 0
print("Parsing assembly...")
for line in idautils.Heads():
if (idc.Byte(line) == 0xD9 or idc.Byte(line) == 0x19 or idc.Byte(line) == 0x59 or idc.Byte(line) == 0x99):
dis = idc.GetDisasm(line)
pos = dis.find("[" + register + "]0x")
if (pos == -1):
pos = dis.find("[" + register + "]-0x")
if pos != -1:
replaced += 1
idc.OpOffEx(line, 1, idc.REF_OFF32, -1, address, 0x0)
cur = math.floor(counter*100/total)
if (cur >= (last+10)):
print("%d" % cur, end="%...")
last = cur
counter += 1

print("100%")
print("All done, %d entries replaced." % replaced)
return

Should be useful to those who know what they are doing.


Title: Re: IDA Pro helper functions
Post by: _nameless on January 25, 2018, 06:25:57 AM
Thanks


Title: Re: IDA Pro helper functions
Post by: gt-innovation on January 25, 2018, 08:03:29 AM
This will save so much time. Thanks PRJ. Will this work on any Ida ? 6.8? 7?


Title: Re: IDA Pro helper functions
Post by: prj on January 25, 2018, 10:37:34 AM
It's python, so ... I think pretty much any version.


Title: Re: IDA Pro helper functions
Post by: superglitch on January 25, 2018, 11:18:23 AM
This will help greatly!  Thank you.


Title: Re: IDA Pro helper functions
Post by: IamwhoIam on January 25, 2018, 01:43:27 PM
wow!


Title: Re: IDA Pro helper functions
Post by: vwaudiguy on January 25, 2018, 02:56:46 PM
Thanks, D!


Title: Re: IDA Pro helper functions
Post by: jcsbanks on January 25, 2018, 04:31:17 PM
Superb, thanks.

The first one in particular solves a big problem :)


Title: Re: IDA Pro helper functions
Post by: Teitek on January 29, 2018, 04:32:05 PM
Great work, thank you prj.


Title: Re: IDA Pro helper functions
Post by: prj on February 05, 2018, 08:00:56 AM
Realized I posted an old version of the indirect function, updated with newer one - it actually does something now.


Title: Re: IDA Pro helper functions
Post by: prj on February 07, 2018, 05:33:16 AM
Needed to load some older stuff, so wrote this:
Code:
def dam(filename):
with open(filename) as fp:
lines = fp.read().split("\n")
lines.pop(0)
print("Found: %d lines" % len(lines))
for line in lines:
if (len(line) > 0):
l = line.split(",")
if (len(l) > 4):
if (l[1].strip() == "/SRC"):
addr = l[-5].replace("$", "0x")
idc.MakeNameEx(int(addr, 0), l[2].strip(), 1)
elif (l[0].strip() == "/UMP"):
addr = l[-7].replace("$", "0x")
idc.MakeNameEx(int(addr, 0), l[2].strip(), 1)
return


Title: Re: IDA Pro helper functions
Post by: Polo35580 on March 06, 2019, 04:31:34 AM
Hello

Great work prj !!

I had a "can't rename tail byte" with some measurements.

So I added a small
Code:
idc.MakeUnKnown(int(addr, 0), 1, idaapi.DOUNK_SIMPLE)
before
Code:
idc.MakeNameEx(int(addr, 0), name, 1)
in a2l script to make sure the byte is not already defined as a word by IDA.

ps: You need to import idaapi also.

Best regards

Polo


Title: Re: IDA Pro helper functions
Post by: fluke9 on October 17, 2019, 12:55:50 PM
sorry for threadjacking, dumping my hack also here:

Rudimentary damos parer which will output a python script which can be executed in the ida console,
this thing will label variables, also it will create enums for bitfields and apply them to the correct locations.

Also names the variables with repeatable comments,
your disassembly will then look something like this:
Code:
843214 loc_843214:                             ; CODE XREF: sub_842C26+46E↑j
843214                                         ; sub_842C26+47A↑j
843214                 jnb     word_FD7C.B_sa, loc_8432DC
843218                 mov     r4, ATM_bits
84321C                 and     r4, #100h
843220                 jmpa    cc_NZ, loc_8432DC
843224                 jnb     word_FD20.B_atmtpk, loc_843270
843228                 jnb     word_FD7C.B_sa, loc_843270
84322C                 extp    #206h, #1
843230                 movbz   r4, TATMSAE     ; exotherme Temperaturerh_hung im Schub
843234                 sub     r4, #0Ah
843238                 movbz   r5, tikatm      ; Abgastemperatur im Katalysator aus Modell
84323C                 cmp     r4, #0


script here, which will generate namebytes.py :

Code:
#!/usr/bin/python

import sys

if len(sys.argv) != 2:
    print 'please specify filename'
    exit

f = open(sys.argv[1], "r")
lines = f.readlines()
f.close()

#print 'loaded ' + sys.argv[1] + ' with ' + str(len(lines)) + ' lines'
print '# -*- coding: latin-1 -*-'

for line in lines:

    data = line.split(',')
    if len(data) > 1:
        data[1] = data[1].strip()

        if data[1].startswith('/SPZ'):
            data = line.split(',')
            varname = data[2].strip()
            varcomment = (line[line.find("{")+1 : line.find("}")] )

            temp = line[line.find("}")+1 : -1]
            aftercomment = temp[temp.find("}")+1 : -1]
            dataac = aftercomment.split(',')
            varoffset = int(dataac[2].strip()[1:], 16)

            print("set_name(" + hex(varoffset) +", \"" + varname + "\");")
            if len(varcomment):
                print("set_cmt(" + hex(varoffset) +", \"" + varcomment.replace('"', '\\"') + "\", 1);")


        if data[1].startswith('/SRC'):
            data = line.split(',')
            varname = data[2].strip()
            varcomment = (line[line.find("{")+1 : line.find("}")] )

            temp = line[line.find("}")+1 : -1]
            aftercomment = temp[temp.find("}")+1 : -1]
            dataac = aftercomment.split(',')
            varoffset = int(dataac[1].strip()[1:], 16)

            print("set_name(" + hex(varoffset) +", \"" + varname + "\");")
            if len(varcomment):
                print("set_cmt(" + hex(varoffset) +", \"" + varcomment.replace('"', '\\"') + "\", 1);")


    if line.startswith('/UMP'):
#        /UMP, {}, afnmn, {Bereichsfenster Aussetzer, minimale Drehzahl}, $3830B5, 513, 160, nmot_ub_q40, 3, $FF, K;

        data = line.split(',')

        temp = line[line.find("}")+1 : -1]
        varcomment = (temp[temp.find("{")+1 : temp.find("}")] )

        temp = line[line.find("}")+1 : -1]
        aftercomment = temp[temp.find("}")+1 : -1]
        dataac = aftercomment.split(',')

        varname = data[2].strip()
        varoffset = int(dataac[1].strip()[1:], 16)
        varmask = dataac[6].strip()[1:]

        if varmask == 'FF' or varmask == 'FFFF':
            #print(varname + " | " + hex(varoffset) + " | " + varcomment + " | " + varmask)
            print("set_name(" + hex(varoffset) +", \"" + varname + "\");")
            if len(varcomment):
                print("set_cmt(" + hex(varoffset) +", \"" + varcomment.replace('"', '\\"') + "\", 1);")
            #print(varmask)
        else:
            enumname = "enum_" + str(hex(varoffset))[2:]
            maskstr = hex(int(varmask, 16))
            print("add_enum(-1, \"" + enumname + "\", 0)")
            print("set_enum_bf(get_enum(\"" + enumname + "\"), 1)")
            print("add_enum_member(get_enum(\"" + enumname + "\"), \"" + varname + "\"," + maskstr + ", " + maskstr + ")")


run with:
parsedamos.py file.dam > namebytes.py

After generating the namebytes.py copy to your ida project dir and execute in the ida console with:
execfile("namebytes.py")



Title: Re: IDA Pro helper functions
Post by: Chipburn on October 28, 2019, 10:20:38 AM
Hello there guys,

Im not so good with IDA and python and im a bit puzzled of how exactly i can run the scripts.

For example for the first one how can i define min and max ? Does IDA support any interactive way where you can type the variables ?

Kind regards.


Title: Re: IDA Pro helper functions
Post by: nyet on October 28, 2019, 10:40:13 AM
Does IDA support any interactive way where you can type the variables ?

Yes, of course you can. But the whole point of the tools is to avoid having to do it via UI because GUIs suck for handling large amounts of data that is best handled by automation.


Title: Re: IDA Pro helper functions
Post by: fluke9 on October 28, 2019, 10:42:53 AM
Hello there guys,

Im not so good with IDA and python and im a bit puzzled of how exactly i can run the scripts.

For example for the first one how can i define min and max ? Does IDA support any interactive way where you can type the variables ?

Kind regards.

copy script to a file in your disassembly directory as for example script.py

then type: execfile("script.py") in the IDA python console
afterwards type the functionname and arguments in the console, for example:
processrom(0x80000, 0x80FFFF)



Title: Re: IDA Pro helper functions
Post by: Chipburn on October 28, 2019, 12:53:22 PM
Thanks for the replies guys :)

I will try those. I guess i can load them as snippets as well for faster access.


Title: Re: IDA Pro helper functions
Post by: Chipburn on October 28, 2019, 03:57:54 PM
Yes, of course you can. But the whole point of the tools is to avoid having to do it via UI because GUIs suck for handling large amounts of data that is best handled by automation.

Thanks Nyet, i was doing the address naming manually etc. What i was asking about "interactive" if you can use a command in the python script that actually popup a window in IDA to define e.g. min max or load a "file"

For now i followed fluke9 guide and works marvelous.

:D


Title: Re: IDA Pro helper functions
Post by: sonflasch on October 22, 2020, 12:01:01 PM
sorry for threadjacking, dumping my hack also here:

Rudimentary damos parer which will output a python script which can be executed in the ida console,
this thing will label variables, also it will create enums for bitfields and apply them to the correct locations.

Also names the variables with repeatable comments,
your disassembly will then look something like this:
Code:
843214 loc_843214:                             ; CODE XREF: sub_842C26+46E↑j
843214                                         ; sub_842C26+47A↑j
843214                 jnb     word_FD7C.B_sa, loc_8432DC
843218                 mov     r4, ATM_bits
84321C                 and     r4, #100h
843220                 jmpa    cc_NZ, loc_8432DC
843224                 jnb     word_FD20.B_atmtpk, loc_843270
843228                 jnb     word_FD7C.B_sa, loc_843270
84322C                 extp    #206h, #1
843230                 movbz   r4, TATMSAE     ; exotherme im Schub
843234                 sub     r4, #0Ah
843238                 movbz   r5, tikatm      ; Abgastemperatur im Katalysator aus Modell
84323C                 cmp     r4, #0


script here, which will generate namebytes.py :

Code:
#!/usr/bin/python

import sys

if len(sys.argv) != 2:
    print 'please specify filename'
    exit

f = open(sys.argv[1], "r")
lines = f.readlines()
f.close()

#print 'loaded ' + sys.argv[1] + ' with ' + str(len(lines)) + ' lines'
print '# -*- coding: latin-1 -*-'

for line in lines:

    data = line.split(',')
    if len(data) > 1:
        data[1] = data[1].strip()

        if data[1].startswith('/SPZ'):
            data = line.split(',')
            varname = data[2].strip()
            varcomment = (line[line.find("{")+1 : line.find("}")] )

            temp = line[line.find("}")+1 : -1]
            aftercomment = temp[temp.find("}")+1 : -1]
            dataac = aftercomment.split(',')
            varoffset = int(dataac[2].strip()[1:], 16)

            print("set_name(" + hex(varoffset) +", \"" + varname + "\");")
            if len(varcomment):
                print("set_cmt(" + hex(varoffset) +", \"" + varcomment.replace('"', '\\"') + "\", 1);")


        if data[1].startswith('/SRC'):
            data = line.split(',')
            varname = data[2].strip()
            varcomment = (line[line.find("{")+1 : line.find("}")] )

            temp = line[line.find("}")+1 : -1]
            aftercomment = temp[temp.find("}")+1 : -1]
            dataac = aftercomment.split(',')
            varoffset = int(dataac[1].strip()[1:], 16)

            print("set_name(" + hex(varoffset) +", \"" + varname + "\");")
            if len(varcomment):
                print("set_cmt(" + hex(varoffset) +", \"" + varcomment.replace('"', '\\"') + "\", 1);")


    if line.startswith('/UMP'):
#        /UMP, {}, afnmn, {Bereichsfenster Aussetzer, minimale Drehzahl}, $3830B5, 513, 160, nmot_ub_q40, 3, $FF, K;

        data = line.split(',')

        temp = line[line.find("}")+1 : -1]
        varcomment = (temp[temp.find("{")+1 : temp.find("}")] )

        temp = line[line.find("}")+1 : -1]
        aftercomment = temp[temp.find("}")+1 : -1]
        dataac = aftercomment.split(',')

        varname = data[2].strip()
        varoffset = int(dataac[1].strip()[1:], 16)
        varmask = dataac[6].strip()[1:]

        if varmask == 'FF' or varmask == 'FFFF':
            #print(varname + " | " + hex(varoffset) + " | " + varcomment + " | " + varmask)
            print("set_name(" + hex(varoffset) +", \"" + varname + "\");")
            if len(varcomment):
                print("set_cmt(" + hex(varoffset) +", \"" + varcomment.replace('"', '\\"') + "\", 1);")
            #print(varmask)
        else:
            enumname = "enum_" + str(hex(varoffset))[2:]
            maskstr = hex(int(varmask, 16))
            print("add_enum(-1, \"" + enumname + "\", 0)")
            print("set_enum_bf(get_enum(\"" + enumname + "\"), 1)")
            print("add_enum_member(get_enum(\"" + enumname + "\"), \"" + varname + "\"," + maskstr + ", " + maskstr + ")")


run with:
parsedamos.py file.dam > namebytes.py

After generating the namebytes.py copy to your ida project dir and execute in the ida console with:
execfile("namebytes.py")



Hello

I have a little question.
everything works so far but the bit fields are not displayed to me.
Enum screen all ok but in the IDA-View i don't see a name

your example
843224                 jnb     word_FD20.B_atmtpk, loc_843270
843228                 jnb     word_FD7C.B_sa, loc_843270

me look jpg.



Title: Re: IDA Pro helper functions
Post by: locon on October 22, 2020, 09:25:55 PM
Move to address 0xFD70 and press 'M' to assign an Enum entry. Select enum_FD70.


Title: Re: IDA Pro helper functions
Post by: sonflasch on October 22, 2020, 10:17:53 PM
Move to address 0xFD70 and press 'M' to assign an Enum entry. Select enum_FD70.

Ok thanks:-)
yes but shouldn't the script do it itself?


Title: Re: IDA Pro helper functions
Post by: prj on October 23, 2020, 07:53:02 AM
Maybe you think the script should give blowjobs too?  ;D
Improve it to do that if you want it to do it, and post here the result.


Title: Re: IDA Pro helper functions
Post by: noice on October 23, 2020, 11:03:33 AM
Ok thanks:-)
yes but shouldn't the script do it itself?

op_enum(0xFD70, 0, get_enum("enum_fd70"), 0)


Title: Re: IDA Pro helper functions
Post by: browny23 on October 25, 2021, 07:27:29 AM
thread revival
hey guys im trying to load a .a2l using the script and i keep getting a line 1 nonetype error


Title: Re: IDA Pro helper functions
Post by: flamy on November 03, 2022, 08:19:25 AM
Here a short script to copy or move bytes from one address to another.

Usage:
- Load script via Alt + F7
- Execute script by function call "moveCode(eas, eae, eat, erase)" in Python console

Function description:
- eas: Start address of code
- eae: End address of code
- eat: Target address where to put code
- erase: 0 = Keep source address space as it is, 1 = Overwrite source address space with "0xFF"

Hint:
- Make sure that target address space can be overwritten. Function does not check, whether there is already code existing, or not!


Title: Re: IDA Pro helper functions
Post by: fragolas on November 07, 2022, 04:46:22 PM
small script based on prj dam loader, but written to work with ida 7.5
Code:
fp = open(r"C:\Users\XXXXXXXXX\MY.dam", errors="ignore")
lines = fp.read().split("\n")
lines.pop(0)
print("Found: %d lines" % len(lines))
for line in lines:
    if (len(line) > 0):
        l = line.split(",")
        if (len(l) > 4):
            if (l[1].strip() == "/SRC"):
                addr = l[-5].replace("$", "0x")
                idc.set_name(int(addr, 0), l[2].strip(), 1)
            elif (l[0].strip() == "/UMP"):
                addr = l[-7].replace("$", "0x")
                idc.set_name(int(addr, 0), l[2].strip(), 1)


Title: Re: IDA Pro helper functions
Post by: flamy on November 08, 2022, 02:55:35 PM
Maybe useful for those of you using Keil µVision, I wrote a script to import *.H86 HEX-Files to IDApro.

Usage:
- Go to "Hex View" or "IDA View"
- Click on the address where to put the content of your *.H86 file
- Load script via Alt + F7
- Confirm target address
- Select *.H86-file to import


Title: Re: IDA Pro helper functions
Post by: Blazius on November 08, 2022, 04:17:04 PM
Maybe useful for those of you using Keil µVision, I wrote a script to import *.H86 HEX-Files to IDApro.

Usage:
- Go to "Hex View" or "IDA View"
- Click on the address where to put the content of your *.H86 file
- Load script via Alt + F7
- Confirm target address
- Select *.H86-file to import

This might be good. Cheers.


Title: Re: IDA Pro helper functions
Post by: fragolas on April 05, 2023, 04:46:28 AM
i dont know where to put this and i didnt want to start a new thread only because of this so here it goes.

Most of the time the a2l/damos is in german, and when you import it in winols it cumbersome to manualy translate it, so i wrote a simple python script that translates a csv defenition file (from winols export) based on another csv(this could be from a similiar ecu, etc)

it needs some work but for the most part it works. Hope its usefull for someone.

Code:
import csv

de = open(r"C:\Users\me\Desktop\f30.csv")
en = open(r"C:\Users\me\Desktop\f10.csv")
out = open(r"C:\Users\me\Desktop\outputmap.csv","w", newline="")


with de as file_de, en as file_en, out as outfile:
    fieldnames = ['Name', 'IdName', 'AxisX.Name', 'AxisY.Name'] #, 'FolderName'
    writer = csv.DictWriter(outfile, fieldnames=fieldnames, delimiter=";")
    writer.writeheader()
    german = list(csv.DictReader(file_de, delimiter=';'))
    english = list(csv.DictReader(file_en, delimiter=';'))
    cont1=0
    print(len(english))
    for row_de in german:
        cont = 0
        count2 = 0
        for row_en in english:
            if row_de['IdName'].lower() != row_en['IdName'].lower():
                cont = cont + 1
                if cont == len(english): #if after running throught english file no match found print german
                   writer.writerow({'Name': row_de['Name'], 'IdName' : row_de['IdName'], 'AxisX.Name' : row_de['AxisX.Name'], 'AxisY.Name' : row_de['AxisY.Name']}) # 'FolderName' : row_de['FolderName'],
                    #print(row_de['Name'] + ';' + row_de['IdName'] + ";" + row_de["FolderName"] + ";" + row_de["AxisX.Name"] + ";" + row_de["AxisY.Name"])
            else:
                count2 = count2+1
                if count2 == 1: # in case there is more than one "idname" with the same name, this makes sure it only prints once per row of german
                   writer.writerow({'Name': row_en['Name'], 'IdName': row_de['IdName'], 'AxisX.Name': row_en['AxisX.Name'], 'AxisY.Name': row_en['AxisY.Name']}) # 'FolderName': row_de['FolderName'],
                    #print(row_en['Name'] + ';' + row_de['IdName'] + ";" + row_en["FolderName"] + ";" + row_en["AxisX.Name"] + ";" + row_en["AxisY.Name"])

        cont1 = cont1 + 1
        print("percentage = %.2f" % (cont1 / len(german) * 100), "%")
    print("done")



also for the folder name( this one i have to work a bit more)

Code:
import csv

de = open(r"C:\Users\me\Documents\Carros\ECU\mini\WinOLS rcz english.csv")
en = open(r"C:\Users\me\Documents\Carros\ECU\mini\WinOLS psa.csv")
out = open(r"C:\Users\me\Documents\Carros\ECU\mini\folder_translator.csv","w", newline="")


with de as file_de, en as file_en, out as outfile:
    fieldnames = ['FolderName']
    writer = csv.DictWriter(outfile, fieldnames=fieldnames, delimiter=";")
    writer.writeheader()
    german = list(csv.DictReader(file_de, delimiter=';'))
    english = list(csv.DictReader(file_en, delimiter=';'))
    cont1=0
    for row_de in german:
        cont = 0
        count2 = 0
        row_de1 = row_de['FolderName'].lower().split()
        row_de2 = row_de1[0]
        for row_en in english:
            row_en1=row_en['FolderName'].lower().split()
            row_en2=row_en1[0]
            if row_de2 != row_en2:
                cont = cont + 1
                if cont == len(english): #if after running throught english file no match found print german
                    #print(row_de['FolderName'])
                    writer.writerow({'FolderName': row_de['FolderName']})
            else:
                count2 = count2+1
                if count2 == 1: # in case there is more than one "idname" with the same name, this makes sure it only prints once per row of german
                    #print(row_en['FolderName'])
                    writer.writerow({'FolderName': row_en['FolderName']})
        cont1 = cont1 + 1
        print("percentage = %.2f" % (cont1 / len(german) * 100), "%")
    print("done")



Title: Re: IDA Pro helper functions
Post by: fknbrkn on February 15, 2024, 04:22:55 PM
del


Title: Re: IDA Pro helper functions
Post by: fknbrkn on February 15, 2024, 04:24:16 PM
Ive made a script to find and parse MED17 registers values / addresing and so on
IDA 7.4+ / ida_python required

Howto:
-load bin with start address, loading address = 0x80000000, tricore cpu
-make autoanalyse of pflash segment to get raw code
-file -> script file

Whats inside:
-searching for global registers values (simply assignment)
-parse em in code, converts to offset (based on prjs indirect() script)
-searching for a9 global register offset
-parse direct addressing mode (sometimes not)
-handle double pointer offset // this part might be buggy (offset applies until target register assignment with some other value or 'rets')

Initial code
Code:
PFLASH:800F0076                 st32.b          byte_D000209F, d15
PFLASH:800F007A                 ld32.bu         d15, byte_D00000CE
PFLASH:800F007E                 jnz32.t         d15:5, locret_800F00A2
PFLASH:800F0082                 ld32.a          a4, [a9]0x52C
PFLASH:800F0086                 ld32.a          a15, [a9]0x798
PFLASH:800F008A                 ld32.w          d5, [a0]-0x6DC0
PFLASH:800F008E                 lea             a4, [a4]0xBDD
PFLASH:800F0092                 ld32.bu         d4, [a15]0x150
PFLASH:800F0096                 ld32.w          d6, [a0]-0x6DF0
PFLASH:800F009A                 call32          sub_800FC9C8
PFLASH:800F009E                 st32.b          byte_D0002097, d2

After script apply
Code:
PFLASH:800F0076                 st32.b          byte_D000209F, d15
PFLASH:800F007A                 ld32.bu         d15, byte_D00000CE
PFLASH:800F007E                 jnz32.t         d15:5, locret_800F00A2
PFLASH:800F0082                 ld32.a          a4, [a9](off_80174B70 - off_80174644)
PFLASH:800F0086                 ld32.a          a15, [a9](off_80174DDC - off_80174644)
PFLASH:800F008A                 ld32.w          d5, [a0](dword_D0003B98 - word_D000A958)
PFLASH:800F008E                 lea             a4, [a4](dword_80057E58+0x1D - dword_80057298)
PFLASH:800F0092                 ld32.bu         d4, [a15](unk_80062CDE - dword_80062B8E)
PFLASH:800F0096                 ld32.w          d6, [a0](dword_D0003B68 - word_D000A958)
PFLASH:800F009A                 call32          sub_800FC9C8
PFLASH:800F009E                 st32.b          byte_D0002097, d2



Title: Re: IDA Pro helper functions
Post by: fknbrkn on March 06, 2024, 02:27:43 AM
Added a2l parser with maps / params / bitfields
Still room of imporvement ofc but no time for that

Moved to git
https://github.com/fknbrkn/IDA-PRO---MED17-python-script


Title: Re: IDA Pro helper functions
Post by: prj on March 06, 2024, 04:34:43 AM
Bitfields not very useful on tricore because the ones outside the dedicated memory it just uses shifting and extr.u to access them.
So to track them you need a full blown pseudocode generator/decompiler like hexrays or ghidra.


Title: Re: IDA Pro helper functions
Post by: fknbrkn on March 06, 2024, 07:02:23 AM
Bitfields not very useful on tricore because the ones outside the dedicated memory it just uses shifting and extr.u to access them.
So to track them you need a full blown pseudocode generator/decompiler like hexrays or ghidra.

Well i might be wrong at naming here, i mean bit params b_xxx and mapping it as enums
Code:
PFLASH:8011479A                     ld.hu           d15, mdns_w ; "Nachstartmoment"
PFLASH:8011479E                     st32.h          mdsmn_w, d1 ; "Motorverlustmoment ohne Ladungswechselarbeit"
PFLASH:801147A2                     jnz16           d15, loc_801147AC
PFLASH:801147A4                     ld32.bu         d15, byte_D0000088
PFLASH:801147A8                     jnz32.t         d15:B_stend, loc_80114850 ; "Bedingung Startende erreicht"


 enum enm_0xd0000088, mappedto_323
FFFFFFFF SWSVW_bChaElgDeb1  = 0                  ; XREF: PFLASH:800FC54A/s
FFFFFFFF                                         ; PFLASH:800FC93A/s ... ; "Fehler in Steuerkettenlдngung"
FFFFFFFF B_dlrparc        = 1                    ; XREF: PFLASH:8009C080/s
FFFFFFFF                                         ; sub_8009C140+24E/s ... ; "Bedingung: SollgrцЯensprung steht an"
FFFFFFFF B_stendrk        = 2                    ; XREF: sub_800FAADC+4/s
FFFFFFFF                                         ; sub_800FAC20+2C/s ... ; "Bedingung Umschaltung Start / Nachstart-Warmlauf fьr rk"
FFFFFFFF B_stend          = 3                    ; XREF: PFLASH:8007456C/s
FFFFFFFF                                         ; sub_8009C4C2+45C/s ... ; "Bedingung Startende erreicht"
FFFFFFFF B_wbkse          = 4                    ; XREF: PFLASH:800B6B18/s
FFFFFFFF                                         ; PFLASH:loc_800B6FD6/s ... ; "Bed. Wobbeln BKS enabled"
FFFFFFFF B_hstnl          = 6                    ; XREF: PFLASH:800EF134/s
FFFFFFFF                                         ; PFLASH:loc_800EF13A/s ... ; "Bed. HeiЯstart aus tmot-Verlauf im SG-Nachlauf"
FFFFFFFF B_dkpaw          = 7                    ; XREF: sub_800F3086+2A8/s
FFFFFFFF                                         ; sub_800F3086+30E/s ... ; "Bedingung DK-Poti-Auswahl fьr DK-Sensor-Ersatzbetrieb"
FFFFFFFF
It covers only direct access to bit, not much but something


Title: Re: IDA Pro helper functions
Post by: prj on March 06, 2024, 07:05:20 AM
It covers only direct access to bit, not much but something
Only a very small amount of memory on TriCore is bit addressable.
The rest is not.
On modern ECU's there are much more bitfields than can ever fit into the small bit addressable memory.

Because of this it needs to do a load, and then using extr.u shift and extract the result.
IDA can not follow this at all and there is no hexrays plugin for tricore.

Ghidra can with the decompiler...

It becomes even worse between two software revisions if some bitfields are moved around. Then the code to access them is different.

Of course it's still useful to load the bitfields as enums, but not as useful as it seems on first glance.


Title: Re: IDA Pro helper functions
Post by: fknbrkn on March 06, 2024, 07:54:31 AM
Only a very small amount of memory on TriCore is bit addressable.
The rest is not.
On modern ECU's there are much more bitfields than can ever fit into the small bit addressable memory.

Because of this it needs to do a load, and then using extr.u shift and extract the result.
IDA can not follow this at all and there is no hexrays plugin for tricore.

Ghidra can with the decompiler...

It becomes even worse between two software revisions if some bitfields are moved around. Then the code to access them is different.

Of course it's still useful to load the bitfields as enums, but not as useful as it seems on first glance.

Ghidra decompiler looks promising
Just a bit tricky for ida user, thanks for the input


Title: Re: IDA Pro helper functions
Post by: prj on March 06, 2024, 08:16:19 AM
For fast work IDA is still the best by far.

Ghidra is really clunky to use for many things, but in case of more complex usage, the decompiler is pretty invaluable.
Reversing headers and other stuff becomes trivial.


Title: Re: IDA Pro helper functions
Post by: prometey1982 on September 12, 2024, 04:27:42 PM
IDC function for adding indirection XRefs to memory with DPP and extp

Code:
static makexrefauto()
{
auto curaddr;
auto prevaddr;
auto from_addr;
auto is_ok = 0;
auto i;
        curaddr = ScreenEA();
prevaddr = PrevHead(curaddr, 0);
for(i = 0; i < 2; ++i) {
auto optype = get_operand_type(curaddr, i);
auto local_addr = get_operand_value(curaddr, i);
msg("local addr 0x%X, op_type %d\n", local_addr, optype);
if(optype == o_mem) {
from_addr = local_addr;
is_ok = 1;
}
else if(optype == o_displ) {
auto prev_instr = print_insn_mnem(prevaddr);
if(prev_instr == "extp") {
from_addr = get_operand_value(prevaddr, 0) * 0x4000 + local_addr;
is_ok = 1;
}
else if(local_addr & 0x8000 && local_addr & 0x4000) {
from_addr = get_sreg(curaddr, "DPP3") * 0x4000 + local_addr - 0xC000;
is_ok = 1;
}
else if(local_addr & 0x8000) {
from_addr = get_sreg(curaddr, "DPP2") * 0x4000 + local_addr - 0x8000;
is_ok = 1;
}
else if(local_addr & 0x4000) {
from_addr = get_sreg(curaddr, "DPP1") * 0x4000 + local_addr - 0x4000;
is_ok = 1;
}
else {
from_addr = get_sreg(curaddr, "DPP0") * 0x4000 + local_addr;
is_ok = 1;
}
}
if(is_ok)
break;

        }
msg("0x%X\n", from_addr);
if(!is_ok)
return;
AddCodeXref(curaddr, from_addr, XREF_USER);
        auto name = sprintf("0x%X", from_addr);
MakeComm(curaddr, name);
}



Title: Re: IDA Pro helper functions
Post by: Artemisia on September 23, 2024, 11:21:10 PM
A script that generate patterns that can help to identify variable addresses on a slightly different file

You input the segment name in which to search for the variable. The script will load all references of that variable, load 5 instructions before and after each instance. Then it applies wildcards to dynamic operands while keeping the opcode. Generated patterns / sequences are output to the console

Works for IDA 7.5, Python 3.8.2

Output example:

Code:

Clearing console...
Variable 'redist' found at address: 0xd000190c
Usage of 'redist' found at 0x800a9258: st32.b          redist, d15
Generated pattern: AB 11 ?? ?? 37 00 ?? ?? 02 F1 BF 50 ?? ?? 25 DF ?? ?? 25 DF ?? ?? 16 FF 05 D0 ?? ?? EE 04 8F 40 ?? ??

Usage of 'redist' found at 0x8010d5ca: ld32.bu         d1, redist
Generated pattern: 05 D4 ?? ?? 6D FF ?? ?? 25 D2 ?? ?? 00 90 BB 00 ?? ?? 05 D1 ?? ?? DF 01 ?? ?? 82 0F FF 51 ?? ?? 82 50

Usage of 'redist' found at 0x8010de2e: ld32.bu         d8, redist
Generated pattern: D9 0F ?? ?? A8 0F 00 90 05 DF ?? ?? 3C 51 05 D8 ?? ?? D5 D7 ?? ?? FF 58 ?? ?? D9 0F ?? ?? 82 66

Usage of 'redist' found at 0x8010e390: ld32.bu         d15, redist
Generated pattern: 00 90 D9 0F ?? ?? 05 DF ?? ?? 37 0F ?? ?? 28 0F 05 DF ?? ?? D9 0F ?? ?? 28 0F 00 90 00 90

Usage of 'redist' found at 0x801241a2: ld32.bu         d15, redist
Generated pattern: 05 DF ?? ?? 09 F0 ?? ?? 3F 0F ?? ?? 05 DF ?? ?? 6F 3F ?? ?? 05 DF ?? ?? FF 5F ?? ?? 05 D0 ?? ?? 09 CF ?? ?? 42 0F

Usage of 'redist' found at 0x80124312: ld32.bu         d15, redist
Generated pattern: 05 D0 ?? ?? 05 DF ?? ?? AB 00 ?? ?? 25 DF ?? ?? 00 90 05 DF ?? ?? 1E 55 05 DF ?? ?? 6F 3F ?? ?? D5 DA ?? ??



Title: Re: IDA Pro helper functions
Post by: prometey1982 on October 10, 2024, 12:39:07 AM
Updated script to load A2L to IDA. Also contains function to disassemble memory region instead of repeating Ctrl+U C.
Usage:
Code:
processrom(0x0, 0x80000) # try to disassemble memory from 0x0 to 0x80000
a2l('c:\my_shit\a2l\my_super_puper.a2l') # load a2l
Works with IDA 7.7. Tested on Volvo ME9 and Ford ME9 A2L and bins.


Title: Re: IDA Pro helper functions
Post by: prj on October 10, 2024, 03:28:52 AM
Updated script to load A2L to IDA. Also contains function to disassemble memory region instead of repeating Ctrl+U C.
Usage:
Code:
processrom(0x0, 0x80000) # try to disassemble memory from 0x0 to 0x80000
a2l('c:\my_shit\a2l\my_super_puper.a2l') # load a2l
Works with IDA 7.7. Tested on Volvo ME9 and Ford ME9 A2L and bins.

I am not sure what you did besides copy-pasting my script form first post into a .py file?


Title: Re: IDA Pro helper functions
Post by: prometey1982 on October 10, 2024, 06:00:07 AM
I am not sure what you did besides copy-pasting my script form first post into a .py file?
I'm maintaining this script to support new IDA versions. Also was added functionality to define enums for c167 CPUs. And function to define code and functions by one line command. And this script defines maps too instead of original function. It works well with PowerPC and c167 ECUs.