当前位置: 首页 > 工具软件 > IDA PRO > 使用案例 >

IDA Pro 基础学习

南门棋
2023-12-01

IDA Pro 基础学习 (2016-09-26 )

甲: IDA 的窗口

IDA 的窗口可以通过view->open subview 中的菜单项来打开。
ctrl-1 是快捷键打开选择窗口。再选择要打开的窗口.

窗口为我们提供信息表格整理,

导航(双击),跳转,及搜索供我们找到感兴趣的东西。
跳转:
有一个菜单项search. 在jump 菜单下,有一堆快速跳转快捷键,简述几个。
- Ctrl-L: 跳转到名称,然后选择Label
- G: 跳转到地址, 可以输入Label
- X: 在Label 上输入x, 可以打开交叉参考窗口,选择跳转到你期望的地址
搜索:
- IDA 的文本搜索ALT-T,
- 二进制搜索ALT-B 及
- 其它搜索(代码搜索,数据搜索等)

1.主要数据显示窗口:

反汇编窗口,16进制窗口,names 窗口,strings窗口,函数窗口. 函数调用窗口.
菜单栏–>选项–>常规–>反汇编–>机器码字节数,填入一个数反汇编即可以显示机器码了。
1. IDA 可以有多个反汇编窗口和多个hex 窗口
对代码的注释

.plt:08048374 ; void srand(unsigned int seed)            // 已经找到了函数原型
.plt:08048374 _srand          proc near               ; CODE XREF: main+42 ▽p 该代码由main 引用, p 为procedure
.plt:08048374                 jmp     ds:off_8049940 // 跳转到一个地址,该地址在.got.plt节内存中
.plt:08048374 _srand          endp

.plt 为procedure linkage table 节

.got.plt:08049940 off_8049940     dd offset srand         ; DATA XREF: _srand ▲r 该数据由_srand 引用, r 为read, w为write
                                                        // 还有 o 偏移量交叉引用。引用的是地址而不是值,例如虚函数表只有o引用

srand 是一个外部符号地址,由连接器来确定。不在本程序内。
点击某个符号,例如_srand, 然后敲击”X”快捷键,会打开交叉引用窗口。窗口内容是交叉引用列表。
方便浏览和跳转。
2. IDA 可以把一组汇编指令折叠,方法,点击窗口标题,快捷菜单项group node
3. names 窗口:
是二进制文件的所有全局名称。名称是对一个程序的虚拟地址的符号描述。
名称有类型: F(函数-常规) L(库函数) I(导入函数) D(数据) A(字符串)
G(命名代码- IDA 在符号表中找到了一个名称,但未发现任何对它的引用,出现此情况)
IDA 自动生成的名称不会进入此窗口,它们是:
sub_xxxx //函数
loc_xxxx //位置
byte_xxxx //数据 byte, word, dword 及其它
word_xxxx
dword_xxxx
unk_xxxx //大小未知的数据块
4. strings 窗口
显示二进制文件中搜索到的字符串,窗口快捷菜单中可以设置字符串搜索选项。
配合交叉参考很重要。

IDA view 窗口中中文字符乱码,但strings 窗口中显示正常。

2.辅助窗口

导入表,导出表,结构体表,枚举表
导入表。 win程序在idata 节

3.其它窗口:

段窗口。 签名窗口,类型库窗口,问题窗口

  1. 段窗口, ctrl-s 可以快速跳转段窗口
  2. 签名窗口, 可以查看已经签名的库.
    库签名,就是把库的特征值取出来,以后通过模式匹配技术,确定某段代码是库函数的过程。
    手工加载方式: 在库签名窗口中右键关联菜单里
    如何生成自己的库签名?
    例如:

    ./pelf libgcc.a
    将会生成libgcc.a 的pat 文件 libgcc.pat
    ./sigmake libgcc.pat libgcc.sig
    将会生成签名文件

    不过这一步一般第一次不会生成.sig 文件, 而是生成一个.exc文件(冲突文件)
    冲突的产生是因为pat文件提取前32个字节, 而相近的函数前面字节完全相同,sigature 不知道该使用哪个.
    解决冲突的办法是删除冲突文件前4行说明,这样对冲突的函数就不会签名,如果想指明用莫一个,可以在其前面放一个+号, 如果只想添加某函数注释,可以在某函数前放一个-号, 加减号只能放一个.
    然后可以把.sig文件拷贝到对应目录下. 例如我的libgcc.a是arm的,我把libgcc.sig 放到了sig\arm 下.
  3. 在类型库窗口->可以查看已经加载的类型库

    类型库,记录了一些数据类型,函数原型,可以知道数据结构的名称,大小和布局,从头文件中收集,用以注释反汇编代码。

    如何生成自己的类型库? 例如,从structs.h 生成structs.til, 你可能需要修改头文件使满足tilib 要求

    tilib -c -hstructs.h structs.til

    想要查看类型库内容,可以用tilib 工具,例如

    tilib -l structs.til

    手工加载方式: 在类型库窗口中右击鼠标,在菜单中选择Load Type Library
    加载了你可能也看不到什么变化,因为structs窗口及local-type 窗口都没有什么变化, 它是作为标准的数据类型存在于idb 文件中.

    1. 你可以在函数原型中使用这些类型.
    2. 你也可以把类型导入到structs窗口中,自己摸索的, 在structs窗口中按Insert 插入条目, 点击对话框的add stardard struct. 就看到你加载的原型库内容了, 不用导入到structs窗口中也可以使用这些数据类型.

不知为什么IDAy 把查看一下类型库信息搞得这么隐蔽呢? 希望它的新版本能改进这一点, 我现在用的是IDA68

还有一种加载数据类型的方式是file->load file->parse c header. 但我不知道它把信息到底加到哪里去了? local type 窗口是看见了一部分,但很少,
大部分都不见了, 既然类型库已经走通了, 那直接分析头文件搞不清楚也就算了, 反正这一块做的界面不够友好!

  1. 问题窗口:
    • BOUNDS: IDA 无法确定调用或跳转的目标,会发生BOUNDS 问题,例如 call eax
      当发现目标地址非法时,也会出现这种情况。(在加密段中)
    • DECISION: 一般不是问题,
      表示IDA 决定将该字节或段作为指令或作为数据来使用
      例如:switch-case 有的编译器代码中穿插数据。
    • 其它问题,SIGFNREF, ROLLBACK 可能都不是问题, 有的需要动态跟踪鉴别。

乙. 与IDA 交互:

1. 代码

### 1. 哑名更改. 

与位置有关的名称(函数名称,全局变量名称),栈帧变量名称。自动生成的名称没有多少意义。
我们难以了解它的用途,对了解程序的行为也没有帮助。
所有,需要我们更改为有意义的函数名称,正确的函数原型。(参数类型,参数名称)及有意义的局部
变量名称, 这些都是N 快捷键需要做的。
IDA 能够很好的扩散名称。

2. 注释

;可重复注释(可以很好的扩散),
shift+;(就是:) 为常规注释
IDA 的字符串是一种”虚拟”的可重复注释

3. 函数原型的修改. 由快捷菜单的edit function(Alt-p) 和 set-type(Y) 来修改

    函数原型参数会扩散到调用处。
    函数原型如果添加可重复注释,会扩散到调用处。

4. 其它:

  • 前注释,后注释要通过edit->comment 子菜单项完成,有Ins,shift+Ins 快捷键
  • option->general 中有对反汇编项的定制。确定显示或者不显示什么项。
    例如: numbers of opcode bytes 可以显示对应的操作码, 默认为0字节不显示。
    stack pointer, 可以显示每条指令对应的栈指针。默认关闭。
    另,栈指针也是可以调整的.,针对调用莫个外部函数时

  • 格式化指令中的操作数, 可以用你定义的常量来表达这些操作数,例如作为偏移值的成员变量名等。

  • 操作函数: 创建,删除,修改属性等,前面叙述过一部分,在菜单edit->function 子菜单下。

  • 代码和数据互换,需要先undef 它, 然后C->code, D->data, 重新建立分析。

2. 数据

数据类型的确定.

  1. 从已知的函数原型中确定数据类型。对应的内存可能是char,word,dword,struct 类型
  2. 通过寄存器的使用方式确定。例如向一个32位寄存器加载内容,则这是一个4字节整数或4字节指针。
  3. 从数据属性中判定大小. movb, movw, movl, mov 对应不同的数据类型。
  4. 从内存字节序列中得知。 最明显的是字符串。
  5. 数组: 往往第一个项目被直接引用,后面的项目通过索引等复杂运算计算偏移量,加上基址来引用。
    可用edit->array 来创建
  6. 栈内容或者局部变量可用通过o(%rbp), 基址+偏移来访问, 或者o(%rbp,%rax,4) (基址+偏移) + (索引 × 项长)来定位
    定义结构体及成员,替换定义若干个变量。

补充:
ida6.8 中文显示乱码问题.(反编译一个ubuntu 下的elf 文件)
这个是编码问题, 先找到
Options->ASCII String Style..。选择Change Encoding。
打开的窗口中有至少四个选项:,,UTF8,UTF16LE。
选择UTF8
选择Set Default Encoding
8-bit and multibyte string, 选择UTF8
则乱码解决!
IDA 还可以导出数据库和类型数据库为IDC文件, 这个IDC 文件可能很庞大,但也给了我们一种方法, 编辑这个IDC文件再把它导入回去,这样来完成同步.

 类似资料: