DLL注入程式碼(C函式)的編寫
阿新 • • 發佈:2019-01-10
attachdlltoprocess.cpp
// attachdlltoprocess.cpp : Defines the entry point for the application. // #include <WINDOWS.H> #include <TCHAR.H> #define CODE_SIZE 1024 BYTE remotecode[CODE_SIZE]; //定義被注入程式碼所需引數的結構體 typedef struct REMOTE_INFO { //API 地址 DWORD ccall_LoadLibraryA; DWORD ccall_GetProcAddress; DWORD ccall_VirtualFree; DWORD ccall_ExitThread; DWORD ccall_MessageBoxA; //引數地址 DWORD cdword_rpfun; char *csz_dllname; char *csz_InitModule; char *csz_msgtitle; char *csz_msgerrorload; char *csz_msgerrorinitmodule; }REMOTE_INFO, *PREMOTE_INFO; #define PARAM_START 0x80000000 #define call_LoadLibraryA PARAM_START + 1 #define call_GetProcAddress PARAM_START + 2 #define call_VirtualFree PARAM_START + 3 #define call_ExitThread PARAM_START + 4 #define call_MessageBoxA PARAM_START + 5 #define sz_InitModule PARAM_START + 6 #define sz_dllname PARAM_START + 7 #define sz_msgtitle PARAM_START + 8 #define sz_msgerrorload PARAM_START + 9 #define sz_msgerrorinitmodule PARAM_START + 10 #define dword_rpfun PARAM_START + 11 //在緩衝區code查詢DWORD值finddata,如果找到替換成setdata int SetPoint(BYTE *code, DWORD finddata, DWORD setdata) { for(int i = 0; i < CODE_SIZE; i++) { if(*(DWORD*)&code[i] == finddata) {//找到了,替換 *(DWORD*)&code[i] = setdata; return TRUE; } } return FALSE; } BOOL AttachDllToProcess(HANDLE hprocess, char *szdll) { DWORD codestart, codeend, codesize; _asm { jmp CODE_END; CODE_START: //被注入的程式碼起始地址 int 3; //LoadLibraryA(sz_dllname); push sz_dllname; mov eax, call_LoadLibraryA; call eax; test eax, eax; jnz GETPROC; //MessageBoxA(NULL, "載入[sz_dllname]失敗", "錯誤", MB_OK); push MB_OK; push sz_msgtitle; push sz_msgerrorload; push NULL; mov eax, call_MessageBoxA; call eax; jmp CLEAR; GETPROC: push eax; push sz_InitModule; push eax; mov eax, call_GetProcAddress; call eax; test eax, eax; jnz CALLINIT; //MessageBoxA(NULL, "獲取函式[InitModule]地址失敗", "錯誤", MB_OK); push MB_OK; push sz_msgtitle; push sz_msgerrorinitmodule; push NULL; mov eax, call_MessageBoxA; call eax; jmp CLEAR; CALLINIT: //InitModule(hinstance); call eax; CLEAR: //VirtualFree(dword_rpfun, 0, MEM_RELEASE); //ExitThread(0); //以下程式碼將在堆疊中執行,原因為呼叫VirtualFree後所在的記憶體就無效了 push 0; push MEM_RELEASE; push 0; push dword_rpfun; push call_ExitThread; push call_VirtualFree; ret; //被注入的程式碼結束地址 CODE_END: //獲取被注入程式碼的首地址和結束地址 lea eax, CODE_START; mov codestart, eax; lea eax, CODE_END; mov codeend, eax; } codesize = codeend - codestart; //被注入的程式碼長度 RtlCopyMemory(remotecode, (LPVOID)codestart, codesize); //複製被注入的程式碼到緩衝區 DWORD dataoffset = codesize; DWORD oldprotect, sztmp; //在目標程序中申請記憶體 LPVOID lpcode = VirtualAllocEx(hprocess, NULL, CODE_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); DWORD addrlocal = (DWORD)remotecode, addrremote = (DWORD)lpcode; //修改緩衝區記憶體屬性為可執行 VirtualProtectEx(GetCurrentProcess(), remotecode, CODE_SIZE, PAGE_EXECUTE_READWRITE, &oldprotect); //修正被注入程式碼的API引數地址 SetPoint(remotecode, call_LoadLibraryA, (DWORD)LoadLibraryA); SetPoint(remotecode, call_GetProcAddress, (DWORD)GetProcAddress); SetPoint(remotecode, call_VirtualFree, (DWORD)VirtualFree); SetPoint(remotecode, call_ExitThread, (DWORD)ExitThread); SetPoint(remotecode, call_MessageBoxA, (DWORD)MessageBoxA); SetPoint(remotecode, dword_rpfun, (DWORD)lpcode); SetPoint(remotecode, sz_dllname, addrremote + dataoffset); lstrcpyA((char*)(addrlocal + dataoffset), szdll); dataoffset += lstrlenA(szdll) + 1; SetPoint(remotecode, sz_InitModule, addrremote + dataoffset); lstrcpyA((char*)(addrlocal + dataoffset), "InitModule"); sztmp = addrlocal + dataoffset; dataoffset += lstrlenA((char*)(addrlocal + dataoffset)) + 1; SetPoint(remotecode, sz_msgtitle, addrremote + dataoffset); lstrcpyA((char*)(addrlocal + dataoffset), "錯誤"); dataoffset += lstrlenA((char*)(addrlocal + dataoffset)) + 1; SetPoint(remotecode, sz_msgerrorload, addrremote + dataoffset); wsprintfA((char*)(addrlocal + dataoffset), "載入[%s]失敗", szdll); dataoffset += lstrlenA((char*)(addrlocal + dataoffset)) + 1; SetPoint(remotecode, sz_msgerrorinitmodule, addrremote + dataoffset); wsprintfA((char*)(addrlocal + dataoffset), "獲取函式[%s]地址失敗", sztmp); dataoffset += lstrlenA((char*)(addrlocal + dataoffset)) + 1; WriteProcessMemory(hprocess, lpcode, remotecode, CODE_SIZE, &oldprotect); /* _asm { mov eax, lpcode; jmp eax; } */ CreateRemoteThread(hprocess, NULL, NULL, (LPTHREAD_START_ROUTINE)lpcode, 0, NULL, NULL); return TRUE; } //被注入到遠端程序的C函式 DWORD WINAPI RemoteCode(PREMOTE_INFO pri) { DWORD codeend; //LoadLibraryA; if(pri->cdword_rpfun) { //_asm int 3; typedef HMODULE (WINAPI *tLoadLibraryA)(LPCSTR lpLibFileName); tLoadLibraryA sysLoadLibraryA; sysLoadLibraryA = (tLoadLibraryA)pri->ccall_LoadLibraryA; HMODULE hmodule = sysLoadLibraryA(pri->csz_dllname);//載入DLL typedef int (WINAPI *tMessageBoxA)(HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType); tMessageBoxA sysMessageBoxA; sysMessageBoxA = (tMessageBoxA)pri->ccall_MessageBoxA; DWORD rpfun = pri->cdword_rpfun; DWORD ccall_ExitThread = pri->ccall_ExitThread; DWORD ccall_VirtualFree = pri->ccall_VirtualFree; if(NULL != hmodule) { typedef FARPROC (WINAPI *tGetProcAddress)(HMODULE hModule, LPCSTR lpProcName); tGetProcAddress sysGetProcAddress; sysGetProcAddress = (tGetProcAddress)pri->ccall_GetProcAddress; FARPROC pinitmodule = (FARPROC)sysGetProcAddress(hmodule, pri->csz_InitModule); if(NULL != pinitmodule) {//呼叫InitModule typedef void (WINAPI *tInitModule)(HMODULE hModule); tInitModule sysInitModule; sysInitModule = (tInitModule)pinitmodule; sysInitModule(hmodule); } else {//獲取InitModule失敗 sysMessageBoxA(NULL, pri->csz_msgerrorinitmodule, pri->csz_msgtitle, MB_OK); } } else {//載入DLL失敗 sysMessageBoxA(NULL, pri->csz_msgerrorload, pri->csz_msgtitle, MB_OK); } _asm {//釋放記憶體,退出執行緒 push 0; push MEM_RELEASE; push 0; push rpfun; push ccall_ExitThread; push ccall_VirtualFree; ret; } } _asm { call GET_ENDADDR; GET_ENDADDR: pop codeend; } codeend += 50; return codeend; } BOOL AttachDllToProcessC(HANDLE hprocess, char *szdll) { DWORD codestart, codeend, codesize; PREMOTE_INFO pri = (PREMOTE_INFO)remotecode; if(0xe9 == *(BYTE*)RemoteCode) { codestart = (DWORD)RemoteCode + *(DWORD*)((DWORD)RemoteCode + 1) + 5; } else codestart = (DWORD)RemoteCode; RtlZeroMemory(remotecode, CODE_SIZE); codeend = RemoteCode(pri); codesize = codeend - codestart; //被注入的程式碼長度 pri = (PREMOTE_INFO)&remotecode[codesize]; RtlCopyMemory(remotecode, (LPVOID)codestart, codesize); //複製被注入的程式碼到緩衝區 DWORD dataoffset = codesize + sizeof(REMOTE_INFO) + 1; DWORD oldprotect, sztmp; //在目標程序中申請記憶體 LPVOID lpcode = VirtualAllocEx(hprocess, NULL, CODE_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); DWORD addrlocal = (DWORD)remotecode, addrremote = (DWORD)lpcode; //修改緩衝區記憶體屬性為可執行 VirtualProtectEx(GetCurrentProcess(), remotecode, CODE_SIZE, PAGE_EXECUTE_READWRITE, &oldprotect); //修正被注入程式碼的API引數地址 pri->ccall_LoadLibraryA = (DWORD)LoadLibraryA; pri->ccall_GetProcAddress = (DWORD)GetProcAddress; pri->ccall_VirtualFree = (DWORD)VirtualFree; pri->ccall_ExitThread = (DWORD)ExitThread; pri->ccall_MessageBoxA = (DWORD)MessageBoxA; pri->cdword_rpfun = (DWORD)lpcode; pri->csz_dllname = (char*)(addrremote + dataoffset); lstrcpyA((char*)(addrlocal + dataoffset), szdll); dataoffset += lstrlenA(szdll) + 1; pri->csz_InitModule = (char*)(addrremote + dataoffset); lstrcpyA((char*)(addrlocal + dataoffset), "InitModule"); sztmp = addrlocal + dataoffset; dataoffset += lstrlenA((char*)(addrlocal + dataoffset)) + 1; pri->csz_msgtitle = (char*)(addrremote + dataoffset); lstrcpyA((char*)(addrlocal + dataoffset), "錯誤"); dataoffset += lstrlenA((char*)(addrlocal + dataoffset)) + 1; pri->csz_msgerrorload = (char*)(addrremote + dataoffset); wsprintfA((char*)(addrlocal + dataoffset), "載入[%s]失敗", szdll); dataoffset += lstrlenA((char*)(addrlocal + dataoffset)) + 1; pri->csz_msgerrorinitmodule = (char*)(addrremote + dataoffset); wsprintfA((char*)(addrlocal + dataoffset), "獲取函式[%s]地址失敗", sztmp); dataoffset += lstrlenA((char*)(addrlocal + dataoffset)) + 1; WriteProcessMemory(hprocess, lpcode, remotecode, CODE_SIZE, &oldprotect); /* _asm { mov eax, lpcode; jmp eax; } */ CreateRemoteThread(hprocess, NULL, NULL, (LPTHREAD_START_ROUTINE)lpcode, (LPVOID)((DWORD)lpcode + codesize), NULL, NULL); return TRUE; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. DWORD pid = 0; //測試時的目標(包含標題為"注入測試 - 記事本"的程式) HWND hwnd = FindWindow(NULL, _T("注入測試.txt - 記事本")); if(NULL == hwnd) return TRUE; GetWindowThreadProcessId(hwnd, &pid); //pid = GetCurrentProcessId();//首先在本程序內測試 if(0 == pid) return TRUE; HANDLE hins = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, NULL, pid); if(NULL != hins) { char *szdll = "F:\\temp\\buildtmp\\testdll\\testdll.dll"; AttachDllToProcessC(hins, szdll); CloseHandle(hins); } //while(TRUE) Sleep(5000); return 0; }