隐蔽的恶意代码启动


知识点

启动器:启动器,也称为加载器,是一种设置自身或者其他恶意代码片段以到达即时或将来秘密运行的恶意代码。启动器经常回在资源节包含要加载的恶意代码。如果资源节被压缩或者加密,则恶意代码必须在加载前对资源节进行提取操作,因此可以在代码中看到FindResourceLoadResource、以及SizeofResource等API函数。恶意代码通常需要管理员权限才能进行下面介绍的操作。

进程注入:隐藏启动行为的最流行的技术是进程注入,这是一种将代码注入到另外一个正在运行的进程中,而被注入的进程会不知不觉地运行注入地代码。执行进程注入通常用到如下API:VirtualAllocEx用来分配一块内存空间、WriteProcessMemory用来想之前分配地地址空间内写入数据。

DLL注入:DLL注入是进程注入地一种形式,它强迫一个远程进程加载DLL程序,同时它也是最常使用地的隐秘加载技术。DLL注入将代码注入到一个远程进程并让远程进程调用LoadLibrary,从而强制远程进程加载一个DLL程序到它的进程上下文,一旦被感染的进程加载了恶意DLL,系统会自动调用DLLMain函数。注入的DLL与被注入DLL的进程拥有相同的权限。

DLL注入流程:

  • CreateToolhelp32SnapshotProcess32FirstProcess32Next来查找进程列表中的目标进程。
  • 启动器提取目标进程的PID并调用OpenProcess以获取进程的句柄。
  • CreateRemoteThread函数在远程进程中创建一个新的线程(CreateRemoteThread的三个参数:hProcess进程句柄、lpStartAddress注入线程的入口点、hpparameter线程的参数)。
  • VirtualAllocEx为恶意DLL名字字符创建内存空间,或者在远程进程中分配内存空间。
  • WriteProcessMemory将DLL的名字字符串写入到分配的内存空间中。

直接注入:直接注入在远程进程的内存空间中分配和插入代码,与DLL注入不同的是这些恶意代码不是在DLL文件中而是直接写入的。直接注入比DLL注入更为灵活,且一般用于注入编译过的代码如ShellCode。在应用直接注入技术的恶意代码中,尽成灰发现如下三个函数:VirtualAllocExWriteProcessMemoryCreateRemoteThread。通常会有两次VirtualAllocExWriteProcessMemory的调用,第一次是分配内存空间并写入远程线程使用的数据。第二次分配内存空间并写入远程新城代码。CreateRemoteThread调用远程线程代码的位置lpStartAddress和数据lpParameter

进程替换:使用进程替换方法可以将一个可执行文件重写到一个运行进程的内存空间,当恶意代码编写者想要将恶意代码伪装成一个合法的进程,并不会产生DLL注入可能会让进程崩溃的危险时,他们呢会使用进程替换技术。进程替换技术的关键是以挂起状态创建一个线程,这个程序将不做任何事情,恢复主线程后才开始执行。几次呢很难过替换技术可以将一个进程载入内存并在入口点挂起它。

进程替换流程:

  • 创建一个进程。
  • 用恶意的可执行文件替换受害者进程的内存空间,使用ZwUnmapViewOfSection来释放由参数指向的所有内存。
  • 使用VirtualAllocEx为恶意代码分配新的内存。
  • 调用ResumeThread函数初始化恶意代码并执行。

钩子(Hook)注入:Hook注入使用Windows Hook加载恶意代码,恶意代码用它拦截发往某个应用程序的消息,Hook注入一般有如下作用:

  • 保证无论如何拦截到一个特殊消息,恶意代码都会被运行。
  • 保证一个特殊的DLL被载入到受害进程的内存空间。

本地Hook和远程Hook:

  • 本地Hook用来观察和操纵发往进程内部的消息。
  • 远程Hook用来观察和操纵一个发往远程进程的消息(系统中的另一个进程),有两种形式,上层和底层,上层的Hook要求Hook例程是DLL程序的一个导出函数,他被操作系统映射到被挂钩的线程或系统所有线程的进程地址空间。底层Hook则要求Hook例程被保护在安装Hook的进程中,这个例程在操作系统获得处理事件的机会前被通知。

Hook技术的击键记录器:Hook技术可以被用来记录按键。击键可以有WH_KEYBOARD和WH_KEYBOARD_LL的Hook例程类型来注册上层和底层Hook。

使用SetWindowsHookEx:这是用来执行远程Windows Hook的主要函数,参数如下:

  • idhook:指定要安装的Hook例程的类型。
  • lpfn:Hook例程指针。
  • hMod:对于上层的钩子,它用来标识包含lpfn定义的Hook例程的DLL句柄,对于底层Hook,他来标识包含lpfn历程的本地模块句柄。
  • dwThreadId:指定与钩子例程关联的线程标识,如果这个参数为0则挂钩例程将绑定与调用线程同在一个桌面的所有线程。

Detours:Detours时微软开打的用于拓展已有操作系统和应用程序的减淡工具,但是恶意代码编写人员使用Detours库执行对导入表,挂在DLL到已有程序文件,并向运行的进程添加钩子函数等。恶意代码修改PE结构,并创建一个名为.detour的段,它通常位于导出表与调试符号之间。.detour段在新的导入地址中包含了原始的PE头部。使用Detours库提供的setdll工具,恶意代码编写者修改PE头部,并使其指向新的导出表。

APC注入:APC为Windows异步过程调用。通过创建线程来使用远程进程中函数的方法会增加系统开销,所以调用一个现有的线程会更加高效。APC可以让一个线程在它正常执行路径运行之前执行一些其他的代码,每一个线程都有一个附加的APC队列,他们在线程处于可警告的等待状态时被处理。例如WaitForStriongObjectExWaitForMultipleObjectsExSleepEx函数等,这些函数给了线程一个处理等待APC的机会。如果应用程序在线程可警告等待状态时(未运行之前)排入一个APC队列,name线程将从调用APC函数开始,线程诸葛调用APC队列中的所有APC,当PC队列完成时,线程才继续沿着它规定的路径执行,恶意代码编写者为了让他们的代码立即执行,他们用APC抢占可警告等待状态的线程。

用户模式的APC注入:用户模式下,一个线程可以使用API函数QueueUserAPC排入一个让远程调用的函数,运行用户模式的APC要求线程必须处于可警告等待状态,因此恶意代码会查看进程中是否有可能进入这个状态的目标线程,WaitForSingleObjectEx是常用的调用。

内核模式的APC注入:使用设备驱动进行APC注入需要使用函数KeInitializeApcKeInsertQueueApc

课后练习

Lab12-1

分析恶意代码确保这些文件在同一目录下

问题

1.在你运恶意代码的可执行文件时会发生什么?

程序会每隔一分钟弹出一个MessageBox显示Press OK to reboot

2.哪个进程会被注入?

1
2
3
4
5
.text:00401095                 push    0Ch             ; size_t
.text:00401097 push offset explore_exe ; "explorer.exe"
.text:0040109C lea ecx, [ebp+var_108]
.text:004010A2 push ecx ; char *
.text:004010A3 call __strnicmp

代码会循环对比进程是否为explorer.exe,如果对比成功则进行注入。

3.你如何能够让恶意代码停止弹出窗口?

重新启动进程explorer.exe

4.这些恶意代码样本是如何工作的?

略。

Lab12-2

问题

1.这个程序的目的是什么?

隐蔽地启动另一个程序。

2.启动器代码是如何隐蔽执行的?

进程替换。

3.恶意代码的负载存储在哪里?

1
2
3
4
5
push    offset Type     ; "UNICODE"
push offset Name ; "LOCALIZATION"
mov eax, [ebp+hModule]
push eax ; hModule
call ds:FindResourceA

程序将恶意负载存储在资源节LOCALIZATION中。

4.恶意负载是如何被保护的?

通过XOR编码加密。

5.字符串列表是如何被保护的?

1
2
3
4
5
6
7
8
9
10
.text:00401016                 mov     ecx, [ebp+var_4]
.text:00401019 cmp ecx, [ebp+arg_4]
.text:0040101C jnb short loc_401033
.text:0040101E mov edx, [ebp+arg_0]
.text:00401021 add edx, [ebp+var_4]
.text:00401024 mov al, [edx]
.text:00401026 xor al, [ebp+arg_8]
.text:00401029 mov ecx, [ebp+arg_0]
.text:0040102C add ecx, [ebp+var_4]
.text:0040102F mov [ecx], al

通过XOR加密。

Lab12-3

问题

1.这个恶意负载的目的是什么?

其实看到这些跟键盘相关的字符串就能差不多猜出这是一个键盘监听器:

通过分析函数sub_4010C7也可以看出这是一个键盘窃听器。

2.恶意负载时如何注入自身的?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int __cdecl main(int argc, const char **argv, const char **envp)
{
HMODULE v3; // eax
HWND hWnd; // [esp+0h] [ebp-8h]
HHOOK hhk; // [esp+4h] [ebp-4h]

AllocConsole();
hWnd = FindWindowA(ClassName, 0);
if ( hWnd )
ShowWindow(hWnd, 0);
memset(byte_405350, 1, 0x400u);
v3 = GetModuleHandleA(0);
hhk = SetWindowsHookExA(13, fn, v3, 0);
while ( GetMessageA(0, 0, 0, 0) )
;
return UnhookWindowsHookEx(hhk);
}

此程序通过设置挂钩注入来实现键盘监听。

3.这个程序还创建了哪些其他文件?

practicalmalwareanalysis.log

Lab12-4

问题

1.位置0x401000的代码完成了什么功能?

这个代码跟上面分析的函数流程相似,在系统内搜索所有进程,验证进程名称是否为winlogon.exe

2.代码注入了哪个进程?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __cdecl sub_401174(DWORD dwProcessId)
{
HMODULE v2; // eax
HANDLE hProcess; // [esp+4h] [ebp-8h]

if ( sub_4010FC(aSedebugprivile) ) // SeDebugPrivilege
return 0;
v2 = LoadLibraryA(LibFileName); // sfc_os.dll
lpStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(v2, (LPCSTR)2);
hProcess = OpenProcess(0x1F0FFFu, 0, dwProcessId);
if ( !hProcess )
return 0;
CreateRemoteThread(hProcess, 0, 0, lpStartAddress, 0, 0, 0);
return 1;
}

参数dwProcessIdwinlogon.exeProcessId

winlogon.exe

3.使用LoadLibraryA装载了哪个DLL程序?

1
2
3
4
5
6
7
8
9
10
.text:004011A3                 push    offset LibFileName ; "sfc_os.dll"
.text:004011A8 call ds:LoadLibraryA
.text:004011AE push eax ; hModule
.text:004011AF call ds:GetProcAddress
.text:004011B5 mov lpStartAddress, eax
.text:004011BA mov eax, [ebp+dwProcessId]
.text:004011BD push eax ; dwProcessId
.text:004011BE push 0 ; bInheritHandle
.text:004011C0 push 1F0FFFh ; dwDesiredAccess
.text:004011C5 call ds:OpenProcess

sfc_os.dll

4.传递个CreateRemoteThread调用的第四个参数是什么?

1
2
3
4
5
6
7
8
9
10
.text:004011D8                 push    0               ; lpThreadId
.text:004011DA push 0 ; dwCreationFlags
.text:004011DC push 0 ; lpParameter
.text:004011DE mov ecx, lpStartAddress
.text:004011E4 push ecx ; lpStartAddress
.text:004011E5 push 0 ; dwStackSize
.text:004011E7 push 0 ; lpThreadAttributes
.text:004011E9 mov edx, [ebp+hProcess]
.text:004011EC push edx ; hProcess
.text:004011ED call ds:CreateRemoteThread

sfc_os.dll的地址。

5.二进制主程序释放出了哪个恶意代码?

在函数sub_4011FC()中可以看到如下代码:

1
2
3
4
5
6
.text:004012A7                 mov     [ebp+hModule], eax
.text:004012AA push offset Type ; "BIN"
.text:004012AF push offset Name ; "#101"
.text:004012B4 mov eax, [ebp+hModule]
.text:004012B7 push eax ; hModule
.text:004012B8 call ds:FindResourceA

于是在ResourceHacker中看一下资源节发现确实有一个PE文件:

释放的文件名为\system32\wupdmgr.exe

6.释放出恶意代码的目的是什么?

恶意代码使用这个程序进行自我更新。


本章结束🎊

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×