由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。(本文仅用于交流学习)
这个方法大概是2020年的时候国外友人提出的了,虽然不是新方法但是思路还是很有意思,值得去学习。
作者的大概思路就是利用NtDuplicateObject间接的去获取句柄,我们先来看看NtDuplicateObject函数是什么意思。
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/ddi/ntifs/nf-ntifs-zwduplicateobject
NTSYSAPI NTSTATUS ZwDuplicateObject(
[in] HANDLE SourceProcessHandle,
[in] HANDLE SourceHandle,
[in, optional] HANDLE TargetProcessHandle,
[out, optional] PHANDLE TargetHandle,
[in] ACCESS_MASK DesiredAccess,
[in] ULONG HandleAttributes,
[in] ULONG Options
);
我们着重看前三个参数
其和DuplicateHandle参数是差不多的,我们先创建两个个实例m.exe、t.exe,我们将m.exe的线程句柄复制到t.exe中,并在t.exe中将其线程终止。
m.exe
#include <iostream>
#include <windows.h>
#include <process.h>
#include <TlHelp32.h>
#include "ntdll.h"
#pragma comment(lib, "ntdll.lib")
using namespace std;
unsigned __stdcall thread(void* lpPragma)
{
while (1)
{
Sleep(500);
cout << "terminal me" << endl;
}
return 0;
}
HANDLE GetProcessHandle()
{
DWORD pid;
PROCESSENTRY32 ed;
ed.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (Process32First(snapshot, &ed) == TRUE)
{
while (Process32Next(snapshot, &ed) == TRUE)
{
if (string(ed.szExeFile) == "t.exe") {
pid = ed.th32ProcessID;
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
}
}
}
}
int main(void)
{
HANDLE hThread;
hThread = (HANDLE)_beginthreadex(NULL, 0, thread, NULL, 0, NULL);
cout << "Thread Handle: " << hThread << endl;
HANDLE hTarget;
if (NtDuplicateObject(GetCurrentProcess(), hThread, GetProcessHandle(), &hTarget,
PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ACCESS) == STATUS_SUCCESS) {
cout << "句柄复制成功, 其句柄值为:" << hTarget << endl;
}
cin.get();
return 0;
}
t.exe
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <process.h>
using namespace std;
int main(void)
{
HANDLE hRecv;
cout << "请输入复制过来的句柄:" << endl;
cin >> hRecv;
TerminateThread(hRecv, 0);
system("pause");
return 0;
}
了解了NtDuplicateObject函数,那么我们如何获得进程打开的句柄呢?我们再来看看NtQuerySystemInformation函数
https://learn.microsoft.com/zh-cn/windows/win32/api/winternl/nf-winternl-ntquerysysteminformation
__kernel_entry NTSTATUS NtQuerySystemInformation(
[in] SYSTEM_INFORMATION_CLASS SystemInformationClass,
[in, out] PVOID SystemInformation,
[in] ULONG SystemInformationLength,
[out, optional] PULONG ReturnLength
);
我们着重看一下第一个参数SystemInformationClass(官方文档给出的参数很多,我们着重看一下要使用的就行)
我们使用SystemHandleInformation参数,遍历系统句柄信息,我们来看看SYSTEM_HANDLE_INFORMATION结构体
将所以的句柄放在Handles[1]中,其总数由NumberOfHandles参数表示,我们再来看看SYSTEM_HANDLE_INFORMATION结构体
其中UniqueProcessId、HandleValue是什么意思很明了了
这个函数再熟悉不过了,我们主要看看第一个参数
https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
因为我们只是要复制句柄,因此我们不必使用PROCESS_ALL_ACCESS,我们可以使用如下
https://skelsec.medium.com/duping-av-with-handles-537ef985eb03
9 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!