-
如果不知道汇编指令操纵的数据是什么意义, 那么你必定分析不出汇编指令在完成何种功能.
-
想要知道被汇编指令操纵的数据是什么意义, 那么你必须找到这个数据的值的来源(任何一个数据,它的初始值的来源有两种: 一. 随机值, 二. 人为赋值).
-
一个数据的来源一般有以下几种:
-
来自直接给出的常量(比如:
mov [0x403000], 0x12345678
) -
来自函数返回值:
call GetDlgItemTextInt mov [0x12345678] , eax
-
来自函数内部的赋值:
1 lea eax, [ebp-20h] 2 push eax 3 call sacnf 4 add esp , 4
-
数据来源未必就只有以上三种
总结: 要分析汇编指令, 必先分析其操纵的数据
代码结构
需分析代码结构的场景: 如果数据的来源是一个敏感函数的返回值,或输出值. 或者数据的来源是一串常量字符串, 那么数据的意义就很明显. 但是大多数情况下, 即使你已经找到了数据的来源, 你仍然猜测不出数据的意义何在.
我们在使用高级语言编写代码时, 一般都会在函数中使用局部变量. 局部变量的使用场景无外乎以下几种:
-
保存函数的返回值
-
保存函数的输出内容
-
用于计数的变量
-
数据交换时用到的临时变量
-
仅仅用于保存另一个变量的值的临时变量
只要能够识别出局部变量的使用场景,那么分析时就能够知道局部变量所保存的值的意义.
大多数临时变量都可以直接识别出来, 但仍然有一些变量不能轻易识别出. 好消息是这些不能轻易识别出来的变量一般都会在特定的代码结构中出现.
一个循环的代码结构:
1 mov [ebp-14h] , 0 2 _loop: 3 cmp [ebp-14h], 100h 4 jge _exit 5 mov eax, [ebp-14] 6 inc eax 7 mov eax, [ebp-14] 8 jmp _loop 9 _exit: 10 ret
在这种结构的代码下, [ebo-14]
它的初始值是0 , 在随后的代码中, 它的值不断产生变化, 变动的值来自于它本身.
如果不了解循环结构 , 那么你可能就意识不到, [ebo-14]
是一个循环结构中的计数器.
除了循环结构, 还有一些其它的代码结构:
-
if
...else if
...else
结构 -
switch
...case
结构
总结: 识别出代码的结构有助于提升数据来源的分析效率.
数据交叉引用
程序结构有助于分析出局部变量的数据来源, 但对于一些全局变量, 就失灵了. 在碰到全局变量时, 你可能在整个函数中都找不到其初始来源, 这是因为全局变量一般情况下在任何函数都可以被赋值, 如果想要分析其数据来源, 就需要挨个挨个函数地去找被赋值的地方.
IDA
中提供了数据交叉引用
, 能够快速查看整个程序代码中, 使用了全局变量的代码. 使用这个功能, 我们就能够快速找到全局变量被赋值的地方.
OD
中提供了查找参考
功能, 这个功能和IDA
的数据交叉引用类似, 也能够快速查找到所有使用全局变量的代码.
如果全局变量的值来自于一个局部变量, 那么, 我们就可以用局部变量的分析方法分析出局部变量的数据来源.
总结:
-
全局变量可以使用
IDA
的数据交叉引用,OD
中的查找参考功能快速找到全局变量被赋值的地方 -