检测沙盒技巧二

admin 2022年6月4日12:34:14评论115 views字数 5330阅读17分46秒阅读模式

    在反跟踪中,最富贵的是它的“思想”,是它的“天马行空”、“挖空心思”、“出其不意”。


    以前有个计算指令周期的手法,对汇编的每条指令都计算周期数,然后比较发现是否被反跟踪,现在好像没见过,少见了。曾记得,学生时代,对《微机原理》里面的每条指令有几个时钟周期都了解得一清二楚。后来学着雷军的“黄玫瑰”也写了一个加密软件,里面的很多反跟踪手法都是来源于病毒的分析,提取出来,集大成。


检测沙盒技巧二

这是当年分析的多维变形病毒。顾名思义,就是每次调试加载时代码都是不同的,等于重新来过一遍,那时还没有ida之类的利器,只能纯手工的Debug,相当“考验”人,这应该就是“求伯君”精神的感召吧。

检测沙盒技巧二

检测沙盒技巧二

检测沙盒技巧二

检测沙盒技巧二

检测沙盒技巧二

这后来写入了我的杀毒软件“Pecker”中。


    当年,最想去反病毒公司,没想到进了现在这个行业,也是算是专业对口吧。

===================================

言归正传吧,每次碰到这类话题,都很有感情。


   当年,病毒最喜欢的就是截获“中断”,就是现在的“钩子”。好像,我给百货公司的带键盘的收银机时就写过一个“键盘钩子”的,好像是验证什么,忘了。


下面,我就介绍下“Hooked”的检测技巧。


二、钩子检测方法

    使用钩子来检测用户的存在或作为检查是否安装了一些不寻常的主机操作系统钩子的方法。


1.检查系统函数内是否设置了钩子

恶意软件读取特定地址的内存以检查 Windows API 函数是否已被挂钩。
这种方法基于这样一个事实,即仿真环境最有可能挂钩这些功能,以便能够在仿真期间收集数据和统计信息。


要检查的热门功能:


  • 读取文件

  • 删除文件

  • CreateProcessA/W


读取内存是通过以下函数完成的:


  • 读进程内存

  • NtReadVirtualMemory


然后可以使用不同的算法进行检查:


  • 将前两个字节与x8BxFF (mov edi, edi)进行比较——kernel32函数的典型序言开始。

  • 将前 N 个字节与xCC - 软件断点(int 3)进行比较,没有直接与钩子连接,但仍然是可疑行为。

  • 将前 N 个字节与xE9 ( call )xEB (jmp指令) 进行比较 — 用于重定向执行的典型指令。

  • 检查执行重定向的push/ret组合。

等等。


钩子检测示例

HOOK_TYPE IsHooked(LPCVOID lpFuncAddress, DWORD_PTR *dwAddressOffset) {
LPCBYTE lpBytePtr = (LPCBYTE)lpFuncAddress;
if (lpBytePtr[0] == 0xE9) {
*dwAddressOffset = 1;
return HOOK_RELATIVE; // E9 jmp is relative.
} else if (lpBytePtr[0] == 0x68 && lpBytePtr[5] == 0xC3) {
*dwAddressOffset = 1;
return HOOK_ABOLSUTE; // push/ret is absolute.
}

return HOOK_NONE; // No hook.

}

LPVOID lpFunction = ...;

DWORD_PTR dwOffset = 0;

LPVOID dwHookAddress = 0;

HOOK_TYPE ht = IsHooked(lpFunction, &dwOffset);

if (ht == HOOK_ABSOLUTE) {

// 1. Get the pointer to the address (lpFunction + dwOffset)
// 2. Cast it to a DWORD pointer
// 3. Dereference it to get the DWORD value
// 4. Cast it to a pointer

dwHookAddress = (LPVOID)(*(LPDWORD)((LPBYTE)lpFunction + dwOffset));

}

else if (ht == HOOK_RELATIVE) {

// 1. Get the pointer to the address (lpFunction + dwOffset)
// 2. Cast it to an INT pointer
// 3. Dereference it to get the INT value (this can be negative)
INT nJumpSize = (*(PINT)((LPBYTE)lpFunction + dwOffset);
// 4. E9 jmp starts from the address AFTER the jmp instruction
DWORD_PTR dwRelativeAddress = (DWORD_PTR)((LPBYTE)lpFunction + dwOffset + 4));
// 5. Add the relative address and jump size

dwHookAddress = (LPVOID)(dwRelativeAddress + nJumpSize);

}

为了对上面的代码理解,准备了下面这个图来理解:

检测沙盒技巧二


脱钩函数示例

// Parse the PE headers.

PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)lpMapping;

PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpMapping + pidh->e_lfanew);

// Walk the section headers and find the .text section.

for (WORD i = 0; i < pinh->FileHeader.NumberOfSections; i++) {

PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pinh) +
((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));
if (!strcmp(pish->Name, ".text")) {
// Deprotect the module's memory region for write permissions.
DWORD flProtect = ProtectMemory(
(LPVOID)((DWORD_PTR)hModule + (DWORD_PTR)pish->VirtualAddress), // Address to protect.

pish->Misc.VirtualSize,

// Size to protect.

PAGE_EXECUTE_READWRITE

// Desired protection.

);
// Replace the hooked module's .text section with the newly mapped module's.
memcpy(
(LPVOID)((DWORD_PTR)hModule + (DWORD_PTR)pish->VirtualAddress),
(LPVOID)((DWORD_PTR)lpMapping + (DWORD_PTR)pish->VirtualAddress),
pish->Misc.VirtualSize
);
// Reprotect the module's memory region.
flProtect = ProtectMemory(
(LPVOID)((DWORD_PTR)hModule + (DWORD_PTR)pish->VirtualAddress), // Address to protect.

pish->Misc.VirtualSize,

// Size to protect.

flProtect

// Revert to old protection.

);
}}




2.通过鼠标钩子检查用户点击

此链接描述了此技术(第 4 页,第 7 页)。


恶意软件设置鼠标钩子以检测点击(或更多)是否发生。如果是这种情况,恶意软件会将主机视为通常的主机,即最终用户位于屏幕后面,而不是虚拟环境。如果没有检测到鼠标点击,那么它很可能是一个虚拟环境。


使用的功能:


  • SetWindowsHookExA/W (WH_MOUSE_LL, ...)

  • GetAsyncKeyState


代码示例 ( SetWindowsHookExA )

HHOOK g_hhkMouseHook = NULL;

LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam){

switch (wParam)
{
case WM_MOUSEMOVE:
// ...
break;
case WM_NCLBUTTONDOWN:
// ...
break;
case WM_LBUTTONUP:
UnhookWindowsHookEx(g_hhkMouseHook);
CallMaliciousCode();
ExitProcess(0);
}
return CallNextHookEx(g_hhkMouseHook, nCode, wParam, lParam);}g_hhkMouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, GetModuleHandleA(NULL), NULL);


代码示例 ( GetAsyncKeyState )

std::thread t([](){
int count = 0;
while (true)
{
if (GetAsyncKeyState(VK_LBUTTON) || GetAsyncKeyState(VK_RBUTTON) || GetAsyncKeyState(VK_MBUTTON))
{
if (++count == 2)
break;
}
Sleep(100);
}

CallMaliciousCode();});

t.join();


3.检查错误钩子函数

    ntdll.dll中有400 多个 Native API 函数(或 Nt 函数),这些函数通常挂在沙箱中。在如此庞大的列表中,有足够的空间容纳不同类型的错误。我们检查了流行沙箱中的挂钩 Nt 函数,发现了几个问题。其中之一是对挂钩函数中的参数缺乏必要的检查。


我们发现的另一个问题是挂钩函数和原始函数中的参数数量存在差异。如果一个函数被错误地挂钩,在内核模式下,这可能会导致操作系统崩溃。不正确的用户模式挂钩并不那么重要。但是,它们可能会导致分析的应用程序崩溃或很容易被检测到。例如,让我们看一下
NtLoadKeyEx函数。它最初是在 Windows Server 2003 中引入的,只有 4 个参数。从 Windows Vista 到最新版本的 Windows 10,它有 8 个参数:

; Exported entry 318. NtLoadKeyEx;

Exported entry 1450. ZwLoadKeyEx;

__stdcall NtLoadKeyEx(x, x, x, x, x, x, x, x)

public _NtLoadKeyEx@32

但是,在 Cuckoo监控中,NtLoadKeyEx声明仍然只有 4 个参数

* POBJECT_ATTRIBUTES TargetKey

* POBJECT_ATTRIBUTES SourceFile

** ULONG Flags flags

** HANDLE TrustClassKey trust_class_key

因此,如果沙盒使用任何最新的 Windows 操作系统,则此功能会被错误地挂钩。调用错误挂钩的函数后,堆栈指针值变为无效。因此,对调用NtLoadKeyExRegLoadAppKeyW函数的完全“合法”调用 会导致异常。只需调用一次 RegLoadAppKeyW函数,就可以利用这一事实来规避 Cuckoo 沙箱。

RegLoadAppKeyW(L"storage.dat", &hKey, KEY_ALL_ACCESS, 0, 0);

// If the application is running in a sandbox an exception will occur// and the code below will not be executed.// Some legitimate code that works with hKey to distract attention goes here// ...

RegCloseKey(hKey);// Malicious code goes here// ...

我们可以不使用RegLoadAppKeyW,而是直接调用NtLoadKeyEx函数并在调用后检查 ESP 值。

代码示例

__try{
_asm mov old_esp, esp
NtLoadKeyEx(&TargetKey, &SourceFile, 0, 0, 0, KEY_ALL_ACCESS, &hKey, &ioStatus);
_asm mov new_esp, esp
_asm mov esp, old_esp
if (old_esp != new_esp)

printf("Sandbox detected!");}

__except (EXCEPTION_EXECUTE_HANDLER){

printf("Sandbox detected!");}

其实,这里介绍的三种方法,还是很普通和常见的,我记得“MJ”大神好像说过:每款产品都在挂钩,看哪个挂的点让别人“生无可恋”才是最高境界吧。



 

原文始发于微信公众号(MicroPest):检测沙盒技巧二

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月4日12:34:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   检测沙盒技巧二https://cn-sec.com/archives/1085235.html

发表评论

匿名网友 填写信息