I'm trying to figure out a way to automatically decrypt certain strings in a binary called by a function several times.The function takes three arguments and is a simple xor decryption. However it uses a different key for each unique string it wants to decrypt.char* decrypt(char* string_to_decrypt, uint string_len, char xor_byte)What I'm attempting to do is get a list of the xrefsTo this function (This is as far as I got) and read in the current string it wants to decrypt in the binary, and grab the xor key and length, then patch the binary to display the plaintext strings.The function is called like this.text:0040168A push    83h.text:0040168F push    9.text:00401691 mov     eax, esi.text:00401693 mov     edx, offset unk_406D58.text:00401698 call    decrypt_stringWhere EDX, always holds the address of the encrypted string, and the two pushes are the key and length (9 length, 0x83 key)The mov eax, esi isn't always present. Is there a way to read the disassembly and get this function and then just dynamically decrypt all the strings in the database? For completeness this is where I started.import idaapiimport idcea = here()print hex(ea)xrefs = CodeRefsTo(ea,0)    for xref in xrefs:    print Ref Addr: {}.format(hex(xref))# for all xrefs, get string offset, length and key,# decrypt that string, and patch or rename it to display decrypted string)Thank you.EDIT:w-s response got me in the right direction. Here is what I came up with. It's rough, I know :)import idaapiimport idcimport idautilsea = here()xrefs = CodeRefsTo(ea,0)data = []decrypted = []for xref in xrefs:    current_x = xref    d = {}    d['addr'] = hex(current_x)    n_pushes = 0    n_movedx = 0    for i in xrange(6):        if n_pushes == 2 and n_movedx == 1:            break        current_x = idc.PrevHead(current_x)        instr = idautils.DecodeInstruction(current_x)        if instr.itype == idaapi.NN_push:            if n_pushes < 1:                d['len'] = int(GetOperandValue(current_x, 0))            if n_pushes == 1:                d['key'] = int( hex(GetOperandValue(current_x, 0)), 16)            n_pushes += 1        if instr.itype == idaapi.NN_mov:            if GetOpnd(current_x, 0) == 'edx':                d['string_offset'] = GetOperandValue(current_x, 1)    data.append(d)......
Automating a Decryption function call in IDA Python
ida;idapython
When I did something similar I used idc.PrevHead(ea)to iterate back from the call site, so it was something similar to this:# Not tested, even not runned even once# expect errors, use on your own risk # probably parsing and analysing disassembly is not best way to do itimport idcimport idautilsea = idc.ScreenEA()xrefs = CodeRefsTo(ea,0)for xref in xrefs:    current = xref    numOfPushes = 0    numOfEdx = 0    edxes = []    pushes = []    for i in range(10): # taking 10 instructions back        if numOfEdx == 1 and numOfPushes == 2:            break        current = idc.PrevHead(current)        s = idc.GetDisasm(current)        if s.find(mov edx) != -1: #copy-paste exact string here, tabulation expected            edxes.append(s)            numOfEdx += 1        if s.find(push)!= -1:             pushes.append(s)            numOfPushes += 1    if len(edxes) > 0:        print %08x : EDX instruction  % xref, edxes[0]    else:        print %08x : EDX mov not found % xref    if len(pushes) >= 2:        print %08x : Push[0]  % xref, pushes[0]        print %08x : Push[1]  % xref, pushes[1]    else:        print %08x : can not find appropriate push instructions %  xrefWhen you have your instructions, all the rest should be obvious.Good luck.