I'm analyzing an obfuscated code which splits its code into multiple blocks seperated by many, many unconditional jmps. Here is a picture of what the obfuscation looks like:
I wrote an IDAPython algorithm for this a few weeks ago, but it misplaces labels and does not place code in the correct location for most larger functions. I could not get it to work in the end.
visted_blocks = list() f = open("myfile.txt", "w+") def RemoveJumps(FuncAddress): while 1: if FuncAddress in visted_blocks: return mnem = idc.GetMnem(FuncAddress) if mnem == 'nop': FuncAddress = idc.next_head(FuncAddress, -1) continue if len(list(CodeRefsTo(FuncAddress, 0))) > 0: if FuncAddress in visted_blocks: return visted_blocks.append(FuncAddress) f.write("loc_%02X: \n" % FuncAddress) if len(mnem) == 0 or mnem == 'retn' or mnem == 'int': return if mnem == 'j': # ^if this is a jump/branch JmpOperand = get_operand_value(FuncAddress, 0) if mnem == 'jmp': visted_blocks.append(FuncAddress) FuncAddress = JmpOperand # advance to next code continue else: # ^else it is a branch, explore recursively visted_blocks.append(FuncAddress) f.write(" %s \n" % idc.GetDisasm(FuncAddress)) RemoveJumps(idc.next_head(FuncAddress, -1)) FuncAddress = JmpOperand # advance to next code continue else: # ^default condition, just print the instruction OpHex(FuncAddress, -1) f.write(" %s \n" % idc.GetDisasm(FuncAddress)) FuncAddress = idc.next_head(FuncAddress, -1) myFuncAddress = 0x774D8 RemoveJumps(myFuncAddress) f.close()
My script recursively explores every code path, prints the code, and jumps to the next block while omitting the
jmp instruction when an unconditional
jmp is encountered, and the destination block has no other cross references. This works perfectly well on small functions, however it fails on most other functions. I spent many hours trying to fix the issues when I used my script on larger functions but I could not get it to work. I would like to know about better methods for connecting basic blocks separated by unconditional jumps in a function. In the end, I want to be able to have a disassembly graph that is easily readable.
How can I stitch together those blocks?