设为首页收藏本站
查看: 4593|回复: 2

[翻译]规避技术:全局操作系统对象

[复制链接]
  • TA的每日心情
    开心
    2022-1-9 18:41
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2021-9-12 16:43:39 | 显示全部楼层 |阅读模式
    备注
    原文地址:https://evasions.checkpoint.com/techniques/global-os-objects.html
    原文标题:Evasions: Global OS Objects
    更新日期:2021年5月19日
    此文后期:根据自身所学进行内容扩充
    因自身技术有限,只能尽自身所能翻译国外技术文章,供大家学习,若有不当或可完善的地方,希望可以指出,用于共同完善这篇文章。


    目录
    • 全局目标检测方法
    • 1.检查特定的全局互斥体
    • 2.检查特定的虚拟设备
    • 3.检查特定的全局管道
    • 4.检查特定的全局对象
    • 5.检查特定对象目录(仅限于沙盒)
    • 6.检查系统中是否存在虚拟注册表(仅限于沙盒)
    • 反制措施
    • 归功于

    全局目标检测方法
    所有全局对象检测方法的基本原理是:在通常的主机上没有这样的对象,但它们存在于特定的虚拟环境和沙盒中。如果存在这样的伪装,则可以检测虚拟环境。
    1.检查特定的全局互斥体
    此方法检查虚拟环境中存在但通常主机系统中不存在的特定互斥体。
    使用的函数:
    • CreateMutexA/W
    • OpenMutexA/W

    代码样本
    1. // usage sample:
    2. supMutexExist(L"Sandboxie_SingleInstanceMutex_Control"); // sample value from the table below


    3. BOOL supMutexExist(_In_ LPWSTR lpMutexName)
    4. {
    5.     DWORD dwError;
    6.     HANDLE hObject = NULL;
    7.     if (lpMutexName == NULL) {
    8.         return FALSE;
    9.     }

    10.     SetLastError(0);
    11.     hObject = CreateMutex(NULL, FALSE, lpMutexName); // define around A or W function version
    12.     dwError = GetLastError();

    13.     if (hObject) {
    14.         CloseHandle(hObject);
    15.     }

    16.     return (dwError == ERROR_ALREADY_EXISTS);
    17. }
    复制代码

    该代码样本归功于:VMDE project
    识别标志
    如果以下函数包含表列“名称”的第3个参数:
    • CreateMutexA/W(..., ..., registry_path)
    • OpenMutexA/W(..., ..., registry_path)

    那么这就表明应用程序试图使用规避技术。
    检测表
    检查是否存在以下全局互斥体:
    检测
    名称
    DeepFreeze
    Frz_State
    Sandboxie
    Sandboxie_SingleInstanceMutex_Control
    SBIE_BOXED_ServiceInitComplete_Mutex1
    VirtualPC
    MicrosoftVirtualPC7UserServiceMakeSureWe'reTheOnlyOneMutex

    注意:DeepFreeze是一个在每次重启时恢复系统的应用程序。
    2. 检查特定的虚拟设备
    这种方法检查特定的虚拟设备,这些设备存在于虚拟环境中,但不在常规的主机系统中。
    使用的函数:
    • NtCreateFile

    代码样本
    1. // usage sample:
    2. HANDLE hDummy = NULL;
    3. supOpenDevice(L"\\Device\\Null", GENERIC_READ, &hDummy); // sample values from the table below


    4. BOOL supOpenDevice(
    5.     _In_ LPWSTR lpDeviceName,
    6.     _In_ ACCESS_MASK DesiredAccess,
    7.     _Out_opt_ PHANDLE phDevice)
    8. {
    9.     OBJECT_ATTRIBUTES attr;
    10.     IO_STATUS_BLOCK iost;
    11.     UNICODE_STRING uDevName;
    12.     HANDLE hDevice;
    13.     NTSTATUS Status;

    14.     if (phDevice) {
    15.         *phDevice = NULL;
    16.     }
    17.     if (lpDeviceName == NULL) {
    18.         return FALSE;
    19.     }

    20.     hDevice = NULL;
    21.     RtlSecureZeroMemory(&uDevName, sizeof(uDevName));
    22.     RtlInitUnicodeString(&uDevName, lpDeviceName);
    23.     InitializeObjectAttributes(&attr, &uDevName, OBJ_CASE_INSENSITIVE, 0, NULL);

    24.     Status = NtCreateFile(&hDevice, DesiredAccess, &attr, &iost, NULL, 0,
    25.         0, FILE_OPEN, 0, NULL, 0);
    26.     if (NT_SUCCESS(Status)) {
    27.         if (phDevice != NULL) {
    28.             *phDevice = hDevice;
    29.         }
    30.     }

    31.     return NT_SUCCESS(Status);
    32. }
    复制代码

    该代码样本归功于:VMDE project
    识别标志
    如果下面的函数包含第三个参数,它的字段' ObjectName->Buffer '来自表列' 名称 ':
    • NtCreateFile(..., ..., attr, ...)

    那么这就表明应用程序试图使用规避技术。
    第三个参数的类型如下:
    1. typedef struct _OBJECT_ATTRIBUTES {
    2.     ULONG Length;
    3.     HANDLE RootDirectory;
    4.     PUNICODE_STRING ObjectName;
    5.     ULONG Attributes;
    6.     PVOID SecurityDescriptor;
    7.     PVOID SecurityQualityOfService;
    8. } OBJECT_ATTRIBUTES;
    复制代码
    检测表
    检查是否存在以下虚拟设备:
    检测
    路径
    VirtualBox
    \\.\VBoxMiniRdDN
    \\.\VBoxMiniRdrDN
    \\.\VBoxGuest
    \\.\VBoxTrayIPC
    \\.\VBoxMouse
    \\.\VBoxVideo
    VMware
    \\.\HGFS
    \\.\vmci

    3.检查特定的全局管道
    管道只是虚拟设备的一个特殊情况,请参考上一节的代码样本和识别标志。
    检测表
    检查是否存在以下全局管道:
    检测
    字符串
    VirtualBox
    \\.\pipe\VBoxMiniRdDN
    \\.\pipe\VBoxTrayIPC

    4.检查特定的全局对象

    这种方法检查特定的全局对象,这些对象存在于虚拟环境中,但不存在于常规的主机系统中。
    使用的函数:
    • NtOpenDirectoryObject
    • NtQueryDirectoryObject

    代码样本
    1. // usage sample:
    2. supIsObjectExists(L"\\Driver", L"SbieDrv"); // sample values from the table below


    3. typedef struct _OBJECT_DIRECTORY_INFORMATION {
    4.     UNICODE_STRING Name;
    5.     UNICODE_STRING TypeName;
    6. } OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;

    7. BOOL supIsObjectExists(
    8.     _In_ LPWSTR RootDirectory,
    9.     _In_ LPWSTR ObjectName)
    10. {
    11.     OBJSCANPARAM Param;
    12.     if (ObjectName == NULL) {
    13.         return FALSE;
    14.     }

    15.     Param.Buffer = ObjectName;
    16.     Param.BufferSize = (ULONG)_strlen_w(ObjectName);

    17.     return NT_SUCCESS(supEnumSystemObjects(RootDirectory, NULL, supDetectObjectCallback, &Param));
    18. }

    19. NTSTATUS NTAPI supDetectObjectCallback(
    20.     _In_ POBJECT_DIRECTORY_INFORMATION Entry,
    21.     _In_ PVOID CallbackParam)
    22. {
    23.     POBJSCANPARAM Param = (POBJSCANPARAM)CallbackParam;
    24.     if (Entry == NULL) {
    25.         return STATUS_INVALID_PARAMETER_1;
    26.     }
    27.     if (CallbackParam == NULL) {
    28.         return STATUS_INVALID_PARAMETER_2;
    29.     }
    30.     if (Param->Buffer == NULL || Param->BufferSize == 0) {
    31.         return STATUS_MEMORY_NOT_ALLOCATED;
    32.     }
    33.     if (Entry->Name.Buffer) {
    34.         if (_strcmpi_w(Entry->Name.Buffer, Param->Buffer) == 0) {
    35.             return STATUS_SUCCESS;
    36.         }
    37.     }

    38.     return STATUS_UNSUCCESSFUL;
    39. }

    40. NTSTATUS NTAPI supEnumSystemObjects(
    41.     _In_opt_ LPWSTR pwszRootDirectory,
    42.     _In_opt_ HANDLE hRootDirectory,
    43.     _In_ PENUMOBJECTSCALLBACK CallbackProc,
    44.     _In_opt_ PVOID CallbackParam)
    45. {
    46.     BOOL cond = TRUE;
    47.     ULONG ctx, rlen;
    48.     HANDLE hDirectory = NULL;
    49.     NTSTATUS status;
    50.     NTSTATUS CallbackStatus;
    51.     OBJECT_ATTRIBUTES attr;
    52.     UNICODE_STRING sname;
    53.     POBJECT_DIRECTORY_INFORMATION objinf;

    54.     if (CallbackProc == NULL) {
    55.         return STATUS_INVALID_PARAMETER_4;
    56.     }
    57.     status = STATUS_UNSUCCESSFUL;
    58.    
    59.     __try {
    60.         // We can use root directory.
    61.         if (pwszRootDirectory != NULL) {
    62.             RtlSecureZeroMemory(&sname, sizeof(sname));
    63.             RtlInitUnicodeString(&sname, pwszRootDirectory);
    64.             InitializeObjectAttributes(&attr, &sname, OBJ_CASE_INSENSITIVE, NULL, NULL);

    65.             status = NtOpenDirectoryObject(&hDirectory, DIRECTORY_QUERY, &attr);
    66.             if (!NT_SUCCESS(status)) {
    67.                 return status;
    68.             }
    69.         }
    70.         else {
    71.             if (hRootDirectory == NULL) {
    72.                 return STATUS_INVALID_PARAMETER_2;
    73.             }
    74.             hDirectory = hRootDirectory;
    75.         }

    76.         // Enumerate objects in directory.
    77.         ctx = 0;
    78.         do {
    79.             rlen = 0;
    80.             status = NtQueryDirectoryObject(hDirectory, NULL, 0, TRUE, FALSE, &ctx, &rlen);
    81.             if (status != STATUS_BUFFER_TOO_SMALL)
    82.                     break;
    83.             objinf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rlen);
    84.             if (objinf == NULL)
    85.                 break;
    86.                
    87.             status = NtQueryDirectoryObject(hDirectory, objinf, rlen, TRUE, FALSE, &ctx, &rlen);
    88.             if (!NT_SUCCESS(status)) {
    89.                 HeapFree(GetProcessHeap(), 0, objinf);
    90.                 break;
    91.             }

    92.             CallbackStatus = CallbackProc(objinf, CallbackParam);
    93.             HeapFree(GetProcessHeap(), 0, objinf);
    94.             if (NT_SUCCESS(CallbackStatus)) {
    95.                 status = STATUS_SUCCESS;
    96.                 break;
    97.             }
    98.         } while (cond);

    99.         if (hDirectory != NULL) {
    100.             NtClose(hDirectory);
    101.         }
    102.     }
    103.     __except (EXCEPTION_EXECUTE_HANDLER) {
    104.         status = STATUS_ACCESS_VIOLATION;
    105.     }

    106.     return status;
    107. }
    复制代码

    该代码样本归功于:VMDE project
    检测表
    检查是否存在以下全局对象:
    检测
    路径
    对象
    Hyper-V
    VmGenerationCounter
    \Device
    Parallels
    prl_pv
    \Device
    prl_tg
    \Device
    prl_time
    \Device
    Sandboxie
    SandboxieDriverApi
    \Device
    SbieDrv
    \Driver
    SbieSvcPort
    \RPC Control
    VirtualBox
    VBoxGuest
    \Device
    VBoxMiniRdr
    \Device
    VBoxVideo
    \Driver
    VBoxMouse
    \Driver
    VirtualPC
    VirtualMachineServices
    \Device
    1-driver-vmsrvc
    \Driver
    VMware
    vmmemctl
    \Device

    5.检查特定对象目录(仅限于沙盒)
    该方法检查特定的对象目录,该目录存在于Sandboxie虚拟环境中,但不存在于常规的主机系统中。
    使用的函数:
    • GetFileAttributes

    代码样本
    1. #define DIRECTORY_QUERY (0x0001)
    2. #define OBJ_CASE_INSENSITIVE 0x00000040L
    3. #define DIRECTORY_SANDBOXIE L"\\Sandbox"

    4. int check_if_obj_dir_present() {
    5.     OBJECT_ATTRIBUTES attr;
    6.     UNICODE_STRING ustrName;
    7.     HANDLE hObject = NULL;

    8.     RtlSecureZeroMemory(&ustrName, sizeof(ustrName));
    9.     RtlInitUnicodeString(&ustrName, DIRECTORY_SANDBOXIE);
    10.     InitializeObjectAttributes(&attr, &ustrName, OBJ_CASE_INSENSITIVE, NULL, NULL);

    11.     if (NT_SUCCESS(NtOpenDirectoryObject(&hObject, DIRECTORY_QUERY, &attr))) {
    12.         NtClose(hObject);
    13.         return TRUE;
    14.     }
    15.    
    16.     return FALSE;
    17. }
    复制代码

    该代码样本归功于:VMDE project
    识别标志
    如果下面的函数包含第3个参数,其字段 "ObjectName->Buffer "来自表列`名称`。
    • NtOpenDirectoryObject(..., ..., attr, ...)

    那么这就表明应用程序试图使用规避技术。
    第三个参数的类型如下:
    1. typedef struct _OBJECT_ATTRIBUTES {
    2.     ULONG Length;
    3.     HANDLE RootDirectory;
    4.     PUNICODE_STRING ObjectName;
    5.     ULONG Attributes;
    6.     PVOID SecurityDescriptor;
    7.     PVOID SecurityQualityOfService;
    8. } OBJECT_ATTRIBUTES;
    复制代码

    检测表
    Check if the following object directory exists:
    Detect
    Path
    Sandboxie
    \Sandbox

    6.检查系统中是否存在虚拟注册表(仅限于沙盒)
    此方法检查Sandboxie虚拟环境中存在的虚拟注册表,但在通常的主机系统中不存在。
    应用程序打开注册表项\注册表\用户。它使用以下函数来检查真实的对象名:
    1. NtQueryObject(
    2.     hUserKey,
    3.     ObjectNameInformation,
    4.     oni, // OBJECT_NAME_INFORMATION object
    5.     Size,
    6.     NULL);
    复制代码

    如果接收到的OBJECT_NAME_INFORMATION对象名称不等于“"\REGISTRY\USER",则应用程序假定它运行在沙箱环境中。
    识别标志
    如果使用以下函数来打开\REGISTRY\USER:
    • NtOpenKey

    后面是调用下面的函数,其第一个参数是 \REGISTRY\USER键的句柄:
    • NtQueryObject(hUserKey, ...)

    那么这就表明应用程序试图使用规避技术。
    反制措施
    拦截目标函数,如果指标(表格中的对象)被触发,返回适当的结果。在某些情况下,停止适当的设备可能会有帮助--但这并不是一个普遍的反击行动:不是所有的全局对象都是设备。
    归功于
    归功于开源项目,代码样本来自该项目。
    尽管Check Point工具InviZzzible已经实现了所有这些功能,但由于代码的模块化结构,需要更多的空间来展示这个工具的代码样本,以达到相同的目的。这就是为什么我们决定在整个百科全书中使用其他伟大的开源项目作为例子。

    点评

    支持一下  发表于 2024-10-3 16:42
  • TA的每日心情
    开心
    4 小时前
  • 签到天数: 576 天

    [LV.9]以坛为家II

    发表于 2024-10-3 16:43:34 | 显示全部楼层
    谢谢分享,已回复。
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    红盟社区--红客联盟 

    Processed in 0.067542 second(s), 22 queries.

    站点统计| 举报| Archiver| 手机版| 黑屋 |   

    备案号:冀ICP备20006029号-1 Powered by HUC © 2001-2021 Comsenz Inc.

    手机扫我进入移动触屏客户端

    关注我们可获取更多热点资讯

    Honor accompaniments. theme macfee

    快速回复 返回顶部 返回列表