地址跳转g
交叉引用x
伪C跳到对应汇编代码Tab
IDA默认显示十进制数,按H转成十六进制
IDA中的MD5
搜索立即数 search->immediate value
F5识别出来有时候会把无符号数识别成有符号数,右键invert sign
define里定义的函数在反编译的时候不会出现这个函数,在编译的时候就被替换进汇编代码了,这就是之前MD5的C代码反汇编的时候看不出来里面的FF等函数
_ROR4_
在IDA里是循环右移的函数,对于32位数据来讲,循环右移27位等于循环左移5位
数据类型转换,DCD代表两个字节的数据,DCB代表一个字节的数据,按D可以切换解析方式,还有DCW和DCQ
右键,rename var修改变量名便于分析
__int8 一般就是char类型
函数参数没识别出来,点进去再返回,或者选择tab看汇编
手上有源码,可以把函数复制到IDA里取辅助识别,右键函数,选set item type
IDA算法识别插件
github下载代码,把py和规则文件复制到IDA/plugin目录下,重启IDA,在edit->plugin下选择,如果没有,在日志中看一下是不是python的依赖库没装好
插件:Findcrypt3 Signsrch
检测不到算法的原因:打开options->general->number of opcode bytes,改为8,查看汇编代码对应的机器指令;有时候IDA会对指令进行优化,有些看着是一条指令,实际上是两条指令(64位so一般是arm指令,32位一般是thumb指令,两种指令字节数不同),一些插件搜索的是hex内容,因此有可能IDA里看到有常量而插件搜不到
其他插件:findhash trace_natives
findhash 会自动生成frida的hook代码
trace_natives 会生成frida-trace的hook代码,这个代码里有函数的相对地址,可以结合findhash生成的hook代码再去hook对应地址的函数,因为trace_natives的hook只能打印函数栈,不能看参数和返回值
修改之后的traceNatives.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 import osfrom idaapi import plugin_tfrom idaapi import PLUGIN_PROCfrom idaapi import PLUGIN_OKimport ida_naltimport idaapiimport idautilsimport idcimport timedef getSoPathAndName (): fullpath = ida_nalt.get_input_file_path() filepath,filename = os.path.split(fullpath) return filepath,filename def getSegAddr (): textStart = [] textEnd = [] for seg in idautils.Segments(): if (idc.get_segm_name(seg)).lower() == '.text' or ( idc.get_segm_name(seg)).lower() == 'text' : tempStart = idc.get_segm_start(seg) tempEnd = idc.get_segm_end(seg) textStart.append(tempStart) textEnd.append(tempEnd) return min (textStart), max (textEnd) class traceNatives (plugin_t ): flags = PLUGIN_PROC comment = "traceNatives" help = "" wanted_name = "traceNatives" wanted_hotkey = "" def init (self ): print ("traceNatives(v0.1) plugin has been loaded." ) return PLUGIN_OK def run (self, arg ): ea, ed = getSegAddr() search_result = [] for func in idautils.Functions(ea, ed): try : functionName = str (idaapi.ida_funcs.get_func_name(func)) if len (list (idautils.FuncItems(func))) > 10 : arm_or_thumb = idc.get_sreg(func, "T" ) if arm_or_thumb: func += 1 search_result.append(hex (func)) except : pass so_path, so_name = getSoPathAndName() search_result = [f"'{offset} '" for offset in search_result] search_result = ", " .join(search_result) search_result = "[" + search_result + "]" script_name = so_name.split("." )[0 ] + "_" + str (int (time.time())) +".txt" save_path = os.path.join(so_path, script_name) with open (save_path, "w" , encoding="utf-8" )as F: F.write(search_result) print ("使用方法如下:" ) print (f"frida-trace -UF -O {save_path} " ) def term (self ): pass def PLUGIN_ENTRY (): return traceNatives()
会生成一个txt,里面只有地址
findhash生成的hook代码再改一下,这里的地址就是上述的地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 function hook_suspected_function(targetSo) { const funcs = ['0x152c' , '0x16c4' , '0x16fc' , '0x1734' , '0x177c' , '0x187c' , '0x18b4' , '0x18f4' , '0x193c' , '0x1974' , '0x19a8' , '0x1b60' , '0x1c5c' , '0x1e04' , '0x1ecc' , '0x1f14' , '0x1fb0' , '0x1ff0' , '0x21c4' , '0x2380' , '0x25ac' , '0x25ec' , '0x262c' , '0x2854' , '0x2a1c' , '0x2a8c' , '0x2d04' , '0x4264' , '0x4360' , '0x449c' ]; for (var i in funcs) { let relativePtr = funcs[i]; let funcPtr = targetSo.add(relativePtr); hook_native_addr(funcPtr); } } function main() { var targetSo = Module.findBaseAddress('libxiaojianbang.so' ); hook_suspected_function(targetSo); } setImmediate(main); function print_arg(addr){ var module = Process.findRangeByAddress(addr); if (module != null){ return hexdump(addr) + "\n" ; }else { return ptr(addr) + "\n" ; } } function hook_native_addr(funcPtr){ var module = Process.findModuleByAddress(funcPtr); Interceptor.attach(funcPtr, { onEnter: function(args){ this.args0 = args[0 ]; this.args1 = args[1 ]; this.args2 = args[2 ]; this.args3 = args[3 ]; this.logs = []; this.logs.push("call " + module.name + "!" + ptr(funcPtr).sub(module.base) + "\n" ); this.logs.push("this.args0 onEnter: " + print_arg(this.args0)); this.logs.push("this.args1 onEnter: " + print_arg(this.args1)); this.logs.push("this.args2 onEnter: " + print_arg(this.args2)); this.logs.push("this.args3 onEnter: " + print_arg(this.args3)); }, onLeave: function(retval){ this.logs.push("this.args0 onLeave: " + print_arg(this.args0)); this.logs.push("this.args1 onLeave: " + print_arg(this.args1)); this.logs.push("this.args2 onLeave: " + print_arg(this.args2)); this.logs.push("this.args3 onLeave: " + print_arg(this.args3)); this.logs.push("retval onLeave: " + retval + "\n" ); console.log(this.logs); } }); }