Angr的力量是有极限的 所以我要转行学idaapi了!
获取二进制文件信息
获取硬件信息
inf_is_64bit() -> bool | inf_is_32bit_exactly() -> bool
判断当前IDA打开的二进制文件是64位或32位的
inf_is_be() -> bool
判断当前程序的模式是大端序(返回 True)或是小端序
inf_get_procname()[.lower()] -> str
返回程序框架名
1 | { |
idc.get_sreg(ea, reg) -> int
Thumb模式下在用户代码段处的第20个段寄存器存放的值是 1 通过这个可以判断当前ARM框架下的模式是否是Thumb模式:
1 | def is_thumb(address): |
获取内存信息
is_mapped(ea) -> bool
判断地址ea是否是有效地址(在程序内)
get_bytes(ea, size[, gmb_flags=0x01]) -> bytes | get_wide_byte(ea) -> int
分别用来以大端序获取位于地址ea处的size个字节数据和1个字节的数据 除此之外还有包括获取1字 双字等的函数 但是这两个应该够用了
[2024 长城杯] tmaze
主函数:
1 | int __fastcall __noreturn main(int argc, const char **argv, const char **envp) |
前面的逻辑不解释 总之就是选择x, y, z来选择要走分支 然后根据这个位置有没有能解引用的地址 最终目标是让mapx
到达mapy
每条分支除了要看能不能解引用还要看接下来的三个字节 为0代表对饮的分支可走
这意味着这题如果手动找解的话要不停的telescope来手绘地图 这里就可以用到get_bytes()
和get_wide_byte()
来轻松获取全部路径:
1 | import idaapi, idc |
得到result:
1 | 0x1a9f16bd830 -> ['0x0', '0x1a9f16bd880', '0x1a9f16bdc90'] |
与IDA交互
让IDA生成信息更具可操作性
get_name_value(_from, name) -> (typ, value) | get_dtype_size(dtype)
获取IDA生成信息对应的值和值的类型 例如:
1 | # test.py |
其中typ
以及后面会出现的dtype
成员代表该数据的类型 参考IDA SDK: Operand value types 如果传入的name
在程序未开始运行时不存在值时返回的value
是-1且typ
为NT_NONE(0x0)
否则value
为这个IDA名称所对应的真实值 可以用来编写汇编代码 若不确定_from
的话应该使用idc.BADADDR
占位
get_dtype_size(dtype)
返回某个dtype代号对应的数据类型长度(in bytes)
get_item_head(ea) -> int | get_item_size(ea) -> int
get_item_head
用于获取IDA中某个地址所在Item的首地址 而get_item_size
用于获取某个地址距离所在Item结尾地址的长度 例如汇编指令:
1 | import idaapi, idc |
class insn_t() | decode_insn(insn, ea) -> int
insn_t
对象实例化时不需要也不能传递任何参数 实例化出来的对象所有的成员都被初始化成一个固定的初始值(大部分是-1) 使用decode_insn()
传入已经实例化的insn_t
对象和要解析的指令的首地址 函数返回指令的长度(in bytes) 此时insn就记录了这条指令的所有信息 其中最重要的是这条指令操作数(op_t
) 操作数对象还包含了更多相关信息 介绍一下其中两个比较常用的成员
insn.ops[n].dtype
: 操作数的数据类别 参考IDA SDK: Operand value types
insn.ops[n].type
: 操作数的类别 参考IDA SDK: Operand types
insn.ops[n].value
: 如果该操作数是立即数 返回这个值
get_func_attr(ea, attr) -> any | set_func_addr(ea, attr, value) -> int
分别用于获取和设置ea地址所在的函数的attr属性 设置属性时返回1
表示成功返回0
表示失败
这些属性是:
Attribution (idc.) | Value |
---|---|
FUNCATTR_ARGSIZE | 28 |
FUNCATTR_COLOR | 36 |
FUNCATTR_END | 4 |
FUNCATTR_FLAGS | 8 |
FUNCATTR_FPD | 32 |
FUNCATTR_FRAME | 16 |
FUNCATTR_FRREGS | 24 |
FUNCATTR_FRSIZE | 20 |
FUNCATTR_OWNER | 16 |
FUNCATTR_REFQTY | 20 |
FUNCATTR_START | 0 |
FUNC_BOTTOMBP | 256 |
FUNC_FAR | 2 |
FUNC_FRAME | 16 |
FUNC_HIDDEN | 64 |
FUNC_LIB | 4 |
FUNC_LUMINA | 65536 |
FUNC_NORET | 1 |
FUNC_NORET_PENDING | 512 |
FUNC_OUTLINE | 131072 |
FUNC_PURGED_OK | 16384 |
FUNC_SP_READY | 1024 |
FUNC_STATIC | 8 |
FUNC_TAIL | 32768 |
FUNC_THUNK | 128 |
FUNC_USERFAR | 32 |
对二进制文件进行操作
patch_byte(ea, x) -> bool | patch_bytes(ea, buf) -> bool
分别用于将ea处的1个和多个字节patch成目标字节x
或目标字节串buf
返回patch的结果是否成功
用IDA去虚拟跳转混淆
之前使用Angr符号执行的方式去虚拟跳转时提到过 IDA可以直接计算出跳转的终点 可以利用这个特性来大大简化去除混淆的过程:
1 | import idaapi, idc, idautils |