恶意代码分析———识别汇编中的C代码结构

C语言是最基础的高级编程语言,许多恶意代码都是有C编写的

识别汇编中的C代码结构

全局与局部变量

全局变量可以被一个程序中的任意函数访问和使用,局部变量只能在它被定义的函数中访问和使用.例如:

1
2
3
4
5
6
7
#include<stdio.h>
int x=1, y=3;
void main()
{
x = x + y;
printf("Total = %d\n",x);
}


1
2
3
4
5
6
7
#include<stdio.h>
void main()
{
int x = 1, y = 3;
x = x + y;
printf("Total = %d\n",x);
}

汇编结构:

全局变量通过内存地址引用,而局部变量通过栈地址引用.

各种结构体

if-else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
void main()
{
int x = 1, y = 3,x1=0,y1=2;
if (x==y) {
if(y1==x1){
printf("y == x\n and y1==x1\n");
}
else {
printf("y == x and y1!=x1\n");
}
}
else {
if (y1==x1) {
printf("y1== x1 and x!=y\n");
}
else {
printf("y1!= x1 and x!=y\n");
}
}
}

汇编窗口

视图

逻辑是一样的,判断后跳转

switch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
void main()
{
int i=0;
switch (i)
{
case 1:
printf("i == 1");
break;
case 2:
printf("i == 2");
break;
case 3:
printf("i == 3");
break;
}
}

汇编窗口

视图

for

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
void main()
{
int i;
for ( i = 0; i < 10; i++)
{
printf("i equals %d\n",i);
}
}

汇编窗口

while

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
void main()
{
int i=0;
while(i>10){
printf("i equals %d\n",i);
i++;
}
}

汇编窗口

数组

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>
int b[5] = {5,6,7,8,9};
void main()
{
int i=0;
int a[5];
for (i = 0; i < 5; i++)
{
a[i] = i;
b[i] = i;
}
}

汇编窗口

视图

结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<stdio.h>
struct my_struct {
int x[5];
char y;
double z;
};
struct my_struct *gms;
void test(struct my_struct *q)
{
int i;
q->y = 'a';
q->z = 15.6;
for (i = 0; i < 5; i++)
{
q->x[i] = i;
}
}
void main()
{
gms = (struct my_struct *)malloc(sizeof(struct my_struct));
test(gms);
}

汇编窗口

遍历列表

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
#include<stdio.h>
struct node {
int x;
struct node *next;
};
typedef struct node pnode;
void main()
{
pnode *curr, *head;
int i;
head = NULL;
for (i = 0; i <= 10;i++)
{
curr = (pnode *)malloc(sizeof(pnode));
curr->x = i;
curr->next = head;
head = curr;
}
curr = head;
while (curr)
{
printf("%d\n",curr->x);
curr == curr->next;
}
}

汇编窗口

函数调用约定

cdecl

C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。

stdcall

调用约定用于调用 Win32 API 函数。其参数都是从右向左通过堆栈传递的, 被调用方将清理堆栈

fastcall

规定将前两个参数由寄存器ecx和edx来传递(x86),其余参数还是通过堆栈传递(从右到左)。函数调用结束后由被调用函数清除栈内数据

实践

lab06-01

1、由main函数调用的唯一子过程中发现的主要代码结构是什么?
有一个if-else结构体
2、位于0x40105f的子过程是什么?
一个结构体,输出函数
3、这个程序的目的是什么?
判断网络连接状态

lab06-2

1、main函数调用的第一个子过程执行什么操作?
判断网络连接状态
2、位于0x40117F的子过程是什么?
一个结构体,输出函数
3、被main函数调用的第二个子过程做了什么?

一个连接网络的函数
4、在这个子过程中使用了什么类型的代码结构?
使用了if-else和结构体
5、在这个子过程中使用了什么类型的代码结构?
指定连接这个域名 http://www.practicalmalwareanalysis.com
6、这个恶意代码的目的是什么?
判断是否有网络并且连接这个域名 http://www.practicalmalwareanalysis.com

Donate
-------------本文结束感谢您的阅读-------------