-
-
[原创]分析实战读书笔记4_汇编中C代码结构
-
2020-12-18 16:31
2169
-
本章心法:

汇编中的C代码结构笔记:
全局与局部变量
全局变量:
全局变量在汇编中以mov eax,dword ptr ds:[0xXXXXXXXX]
的形式表现, 在一个立即数地址中存储.
在IDA中表现为dword_XXXXXXXX
局部变量:
局部变量在汇编中以mov eax,dword ptr ds:[EBP-X]
的形式, 存储在子程序的栈中.
在IDA中表现为var_X
算术操作
自增自减
1 2 3 4 5 6 7 | int a = 0 ;
a + + ; / a - - ;
mov [ebp - 4 ], 0
mov eax,[ebp - 4 ]
add eax, 1 / sub eax, 1
mov [ebp - 4 ],eax
|
取模
1 2 3 4 5 6 7 8 9 10 11 | int a = 10 ;
int b = 0 ;
b = a % 3 ;
mov [ebp - 4 ], 0xA
mov [ebp - 8 ], 0
mov eax,[ebp - 4 ] / / 将被除数存到eax中
cdq
mov ecx, 3 / / 将除数存到ecx中
idiv ecx
mov [ebp - 8 ],edx / / 结果会存到edx中
|
If语句
普通if else
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int x = 1 , y = 2 ;
if (x = = y){
code1
} else {
code2
}
mov [ebp - 4 ], 1
mov [ebp - 8 ], 2
mov eax,[ebp - 4 ]
cmp eax,[ebp - 8 ]
jnz code2 / / else
code1 / / if
jmp xxx / / 后续代码 可以看到两段代码只能有其中一段被执行,因此这个jmp是关键
|
ida中的图形化表示

可以看到明显的两个分支只能执行其中一个
嵌套if else
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 | int x = 0 ,y = 1 ,z = 2 ;
if (x = = y){
if (z = = 0 ){
code1
} else {
code2
}
} else {
if (z = = 0 ){
code3
} else {
code4
}
}
mov [ebp - 4 ], 0
mov [ebp - 8 ], 1
mov [ebp - c], 2
mov eax,[ebp - 4 ]
cmp eax,[ebp - 8 ] / / 外层 if
jnz FLAG2 / / 外层 else
cmp eax,[ebp - c] / / 外层 if - >内层 if
jnz FLAG1 / / 外层 if - >内层 else
code1
jmp XXX / / 跳出
FLAG1:code2
jmp xxx
FLAG2: cmp eax,[ebp - c] / / 外层 else - >内层 if
jnz code4 / / 外层 else - >内层 else
code3
|
for循环
for循环由四部分组成:初始化 比较 执行代码 递增或递减
, 汇编中分辨这四个模块可以快速判断出是一个for循环代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | for ( int i = 0 ;i< 100 ;i + + ){
code1
}
code2
mov [ebp - 4 ], 0 / / 初始化
jmp FLAG1 / / 比较
FLAG2:mov eax,[ebp - 4 ] / / 递增
add eax, 1
mov [ebp - 4 ],eax
FLAG1: cmp [ebp - 4 ], 0x64 / / 比较
jge code2 / / 跳出循环
code1 / / 执行代码
jmp FLAG2 / / 递增
|
在IDA中视图体现为:

while循环
while循环类似for循环, 仅少了递增递减的部分 : 初始化 比较 执行代码 再次比较
1 2 3 4 5 6 7 8 9 10 11 | int status = 0 ;
while (status = = 0 ){
code1
}
code2
mov [ebp - 4 ], 0 / / 初始化
FLAG: cmp [ebp - 4 ], 0 / / 比较
jnz code2 / / 跳出 while
code1 / / 执行代码同时修改status
jmp FLAG / / 无条件跳转回比较代码
|
函数调用约定:

switch语句
switch在反汇编中的体现分为两类if样式 跳转表样式
if样式

if样式下, switch语句被视为与if语句相同
跳转表样式
当switch语句的case过多时, 编译器进行了优化生成了一张跳转表

在IDA中体现为:

可以看到多个代码块共用一个jmp, 通过下标进行跳转, 这样可以节省字节空间
数组

数组的格式比较简单, 类似[ebp-x+ecx*4]
,[ebp-x]可以理解为数组首地址, ecx代表数组元素的位置, 4代表每个元素的宽度, 就像查数一样
结构体

上图是一份C代码例子,下面是汇编中的体现


可以看到结构体类似数组, 原理都是通过首地址进行成员的访问, 只是结构体的成员宽度不一定相同,因此在访问时不像数组有固定的格式
链表

链表节点指向另一个链表的首地址
章节练习:
Lab 6 - 1
由main函数调用的唯一子过程中发现的主要代码结构是什么?
main函数只调用了一个401000, 进去查看汇编

1 | 可以看到jz跳到了一个代码段, jmp跳过了这个代码段, 明显的两段代码只能执行一段, 所以是 if 结构
|
位于0x40105F的子过程是什么?
1 | 子过程是printf (答案上这么说的,而书中答案的依据是参数包含\n所以就觉得是printf, 那么恶意代码开发者是否可以自行实现高相似度的printf并在其中插入恶意代码来躲避分析呢?)
|
这个程序的目的是什么?
程序在入口时首先判断网络状态, 分支结构下执行了同一个函数sub_40105F
也就是printf

所以整个样本的功能就是判断网络连接状态后进行打印
Lab 6 - 2:
main函数调用的第一个子过程执行了什么操作?

1 | main函数第一个子过程为 401000 根据 6 - 1 的分析可以知道这个函数用于判断网络连接状态
|
位于0x40117F的子过程是什么?
被main函数调用的第二个子过程做了什么?


在这个子过程中使用了什么类型的代码结构?
在这个程序中有任何基于网络的指示吗?
1 | 有很多与网络相关的API函数,有与网络相关的提示信息,有与网络相关的url字符串
|
这个恶意代码的目的是什么?
1 | 程序首先检测本地网络状态,网络有效则访问url取网络数据,判断数据前几个字符是否符合注释文本,符合则解析并打印第五个字符,然后sleep一分钟后退出
|
6-2小结:
1 | 401040 处的局部变量没有被ida正确解析,按下Ctrl + K将bufer改为 512 长度的数组就可以解析成功了
|
Lab 6 - 3:
比较在main函数与实验6-2的main函数的调用。从main中调用的新的函数是什么?
这个新的函数使用的参数是什么?
这个函数包含的主要代码结构是什么?
这个函数能够做什么?
1 | 这个函数可以根据网页中取得的字符执行不同的功能,其中包括的功能有:创建目录,复制文件,删除文件,添加注册表自启
|
在这个恶意代码中有什么本地特征吗?
1 2 | 注册表特征 Software\Microsoft\Windows\CurrentVersion\Run
文件目录特征 C:\\Temp\\cc.exe
|
这个恶意代码的目的是什么?
Lab 6 - 4:
在实验6-3和6-4的main函数中的调用之间的区别是什么?
什么新的代码结构已经被添加到main中?
这个实验的解析HTML的函数和前面实验中的那些有什么区别?
1 | 多了一个参数,在解析html的函数中InternetOpenA函数参数是动态拼接出来的
|
这个程序会运行多久?(假设它已经连接到互联网。)
在这个恶意代码中有什么新的基于网络的迹象吗?
1 | 在解析html的函数中InternetOpenA函数参数是动态拼接出来的
|
这个恶意代码的目的是什么?
1 | 循环获取html中的字符数据执行恶意代码,具体恶意行为与 6 - 3 相同
|
[招聘] 欢迎你加入看雪团队!