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_string
Where 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 idaapi
import idc
ea = 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 idaapi
import idc
import idautils
ea = 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)
......