原理介绍
代码注入是一种向目标进程插入独立运行的代码并运行的技术,可以通过调用CreateRemoteThread进行实现;
这种方式进行代码注入有点类似DLL注入,只不过这是把要执行的函数和参数一起写入到目标进程中,然后通过CreateRemoteThread进行调用,参数比较多的话,可以用结构体来装
代码注入相比DLL注入:
- 占用内存更小
- 痕迹留下的更少
- 不需要另外的dll文件,也可以进行无文件dll注入
代码注入用于代码量小且简单的情况下,dll注入用在代码量大且复杂的时候
代码示例
目标是向一个进程注入代码,使其弹出hello world消息框,这一块没啥好说的,话都在代码里
用一个结构体来填装需要用到的东西,比如函数地址,参数等
然后开始写线程函数,线程函数一定全部都要用参数里提供的内容
注入函数呢,基本上就是申请空间,写参数进去,申请空间,写函数进去,然后远程线程创建即可
注意啊,写函数进去之前申请空间的最后一个参数是PAGE_EXECUTE_READWRITE
源代码
codeinjection.h
#pragma once
#include<stdio.h>
#include<windows.h>
//Thread Parameter
typedef struct _THREAD_PARAM {
FARPROC pFunc[2];
char szBuf[4][32];//user32.dll MessageBoxA helloworld error
}THREAD_PARAM,*PTHREAD_PARAM;
//LoadlibraryA()
typedef HMODULE(WINAPI* PFLOADLIBRARYA)(LPCSTR lpLibFileName);
//GetProcAddress()
typedef FARPROC(WINAPI* PFGETPROCADDRESS)(HMODULE hModule, LPCSTR lpProcName);
//MessageBoxA
typedef int (WINAPI* PFMESSAGEBOXA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
//Thread Procedure
DWORD WINAPI ThreadProc(LPVOID lParam);
BOOL InjectCode(DWORD dwPid);
codeinjection.cpp
#include "codeinjection.h"
DWORD __stdcall ThreadProc(LPVOID lParam)
{
PTHREAD_PARAM pParam = (PTHREAD_PARAM)lParam;
//LoadLibraryA("user32.ldd")
HMODULE hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);
//GetProcAddress("MessageBoxA")
FARPROC pFunc = ((PFGETPROCADDRESS)pParam->pFunc[1])(hMod,pParam->szBuf[1]);
//MessageBoxA(NULL,"helloworld","error",MB_OK)
((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
return 0;
}
BOOL InjectCode(DWORD dwPid)
{
HMODULE hMod = GetModuleHandleA("kernel32.dll");
THREAD_PARAM param = { 0, };//括号里这种写法是什么意思?
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], "hello world");
strcpy_s(param.szBuf[3], "TMD_ERROR");
//Open Process
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPid);
//Allocation for THREAD_PARAM
DWORD dwWrittenSize = 0;
DWORD dwSize = sizeof(THREAD_PARAM);
LPVOID pRemoteBuf[2] = { 0, };
pRemoteBuf[0] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess,pRemoteBuf[0],¶m,dwSize,&dwWrittenSize);
//Allocation for ThreadFunc
dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
pRemoteBuf[1] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, pRemoteBuf[1],(LPVOID)ThreadProc, dwSize, &dwWrittenSize);
//code injection
HANDLE hThread = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)pRemoteBuf[1],pRemoteBuf[0],0,NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
main.cpp
#include"codeinjection.h"
int main(int argc, char* argv[]) {
//DWORD dwPid = (DWORD)atol(argv[1]);
DWORD dwPid = 19976;
InjectCode(dwPid);
}