IDA编译头文件
打开菜单中Options ->Compiler…
按 Ctrl+F9 载入头文件(例如jni.h)
IDA拍摄快照
拍摄快照:快捷键Ctrl + Shift + W
管理快照:快捷键Ctrl + Shift + T
IDA创建结构体
参考:https://thinkycx.me/2019-07-15-how-to-create-structs-in-IDA.html
方式1:通过Structures Subview手动创建
(感觉不是很方便,还是编译头文件更好用)
选择Structures选项卡
按Insert新建结构体(对ROG而言是Fn+Delete)
第一个复选框:决定新结构体在结构体窗口中的显示位置
第二个复选框:是否在窗口中显示新结构体
第三个复选框:是否创建联合体
创建完成后:
方式2:通过头文件
IDA还原结构体
参考:https://blog.seeflower.dev/archives/173/
IDA中,32位的指针类型是int*,64位的指针类型是__int64*
__int64如果看着不太顺眼,可以使用int64_t来代替。IDA中没法直接找到int64_t这个类型,但是如果使用了这个写法IDA会自动关联
示例:
struct nameserver {
int socket;
int64_t *connection;
_BYTE address[128];
socklen_t addrlen;
int failed_times;
int timedout;
_BYTE event[200];
};
IDA修改函数声明
右键函数名 → Set item type
IDA修改函数调用处的函数定义
右键函数名 → Set call type
IDA修改函数参数类型
右键参数 → Set Ivar type
IDA 处理伪代码JUMPOUT指令
函数被IDA错误合并
IDA分析so时,可能会遇到反编译结果不准确的情况,如下:
这里的两个JUMPOUT其实解析有问题,如下:
例如loc_18B27B0被解析成了HEN_WriteBlock函数的一个分支中的代码:
Tab查看结果如下:
但是其实loc_18B27B0处是一个独立的函数。
函数重新识别
Undefine HEN_WriteBlock函数(找到HEN_WriteBlock函数的函数名,按U)
然后再回到HEN_ReadBlock函数,进而找到loc_18B27B0:
在loc_18B27B0处create function(右键→Create Function,或者按p):
回到HEN_ReadBlock
按F5,发现loc_18B27B0处的函数已经被识别出来了:
同法处理另一个函数loc_18B2868后:
(如果伪代码更新不过来,就先进入sub_18B2868的伪代码,然后再重新进入HEN_ReadBlock的伪代码,再按F5)
(如果更上层的函数的伪代码更新不过来,也是同法,先进入下层函数伪代码,再回到上层函数伪代码并按F5)
IDA 处理 positive sp value has been detected
TAB看伪代码时出现这种报错:
positive sp value has been detected, the output may be wrong!
这是因为IDA认为函数栈帧不平衡,满堆栈递减情况下SP超出了栈顶
解决办法参考:
https://bbs.kanxue.com/thread-158896.htm
https://blog.csdn.net/xiangshangbashaonian/article/details/81950110
https://d0nuts33.github.io/2023/02/21/%E9%9D%9E%E5%B9%B3%E5%9D%A6%E5%8C%96%E6%B7%B7%E6%B7%86%E6%80%BB%E7%BB%93/index.html
https://blog.csdn.net/weixin_52369224/article/details/121086041
IDA中Options → General → 把Stack pointer勾选上
这之后汇编代码左侧会出现一列值,(我理解)代表的是 栈顶地址减去当前SP值
如果是负数,就说明运行到该位置时SP越界了
在某行代码处按ALT+K(或者在代码处右键→“Change stack pointer”),可以看到该行代码对SP的修改情况(新SP 减去 旧SP)
比如这里的ADD SP, SP, #0x50
,就会将SP值增加0x50:
显然这里增加0x50之后,SP就越界了。
一种解决思路是将该指令NOP掉,因为它可能是花指令;
另一种思路是强行控制SP的变化情况,比如我们强制让SP的变化量为0x0:
这之后栈帧就平衡了,但仍可能存在其他问题影响反编译
Win IDA 命令行 使用
例如要反汇编JDJRMobile这个macho文件,得到.asm和.i64文件:
ida64 -B JDJRMobile
或者
ida64 -B JDJRMobile | more
IDA字符串搜素
Alt+T
IDA运行IDC脚本
打开i64文件后,File → Script command
点击Import导入写好的idc文件,点击Run运行
参考:https://blog.csdn.net/mandiheyanyu/article/details/125997818
IDA复制汇编代码
使用此IDC脚本,输出在当前打开的i64文件目录下,文件名由i64的文件名加"Part" 组成
#include "idc.idc"
static ElementExist(arrayid,size,val)
{
auto i,v;
for(i=0;i<size;i++)
{
v=GetArrayElement(AR_LONG,arrayid,i);
if(v==val)
return 1;
}
return 0;
}
static GenFuncIns(st,arrayid,size)
{
auto start,end,i,ins,x,xt,funcend;
start=st;
end=FindFuncEnd(start);
for(i=start;i<end;)
{
ins=GetDisasm(i);
for(x=Rfirst(i);x!=BADADDR;x=Rnext(i,x))
{
xt=XrefType();
if(xt == fl_CN && !ElementExist(arrayid,size,x))
{
SetArrayLong(arrayid,size,x);
size++;
}
}
i=ItemEnd(i);/*FindCode(i,1);*/
//Message(form("%s\r\n",ins));
}
return size;
}
static main()
{
auto arrayid,size,pos,st,file,funcend,path;
st=ScreenEA();
path = GetIdbPath();
path = substr(path, 0, strlen(path) - 4) + "Part.asm";
file=fopen(path,"w+");
if(st==BADADDR)
{
Warning("您需要选中一个函数起始地址!");
return;
}
arrayid=CreateArray("gen_func_ins");
if(arrayid<0)
{
arrayid=GetArrayId("gen_func_ins");
}
pos=0;
SetArrayLong(arrayid,pos,st);
size=1;
for(pos=0;pos<size;pos++)
{
st=GetArrayElement(AR_LONG,arrayid,pos);
Message(form("proc:%8.8x\r\n",st));
funcend=FindFuncEnd(st);
if (funcend!=BADADDR)
{
Message("正在将这个函数代码写入 %s \n",path);
GenerateFile(OFILE_ASM,file, st,funcend, 0);
}
else
{
Message(form("proc:%8.8x Write false\r\n",st));
}
size=GenFuncIns(st,arrayid,size);
}
DeleteArray(arrayid);
fclose(file);
Message("All done, exiting...\n");
}
修改基地址
修改IDA显示二进制文件的基地址
Edit–>Segments–>Rebase Program
左下角的AC
据豆包说:
在 IDA Pro 中,左下角的 AC:xxxx 通常指的是 Analysis Coverage(分析覆盖度),xxxx 代表具体的百分比数值 。它表示 IDA Pro 对当前分析文件的代码和数据的分析覆盖程度。比如 AC:90% 意味着 IDA Pro 已经对该文件 90% 的内容完成了分析,还有 10% 的部分未被充分分析或识别,这可能包括一些复杂的代码结构、未识别的数据类型等未被完全解析的内容。通过这个指标,用户可以大致了解 IDA Pro 对文件的分析进展和完整性。
C++ this指针
在 C++ 的底层实现中,当通过指针调用类的成员函数时,隐式的 this 指针会被编译器自动插入为第一个参数。因此,编译后的代码中,参数列表会比源代码中多一个 this 参数,导致在反汇编工具(如 IDA)中看到的参数数量可能比源代码多一个。
比如源代码:
m_registry->callNativeMethod(call.moduleId, call.methodId, std::move(call.arguments), call.callId);
IDA看到的:
sub_100347FE4(*(a1 + 1), *v9, *(v9 + 4), v9 + 8, *(v9 + 56));