一丶遠程線程注入的講解
遠程線程注入的原理,我會寫一個遠程線程開發的例子
我們總共需要幾步
/*1.查找窗口,獲取窗口句柄*/ /*2.根據窗口句柄,獲得進程的PID*/ /*3.根據進程的PID,獲得進程的句柄*/ /*4.根據進程的句柄,給進程申請額外內存空間*/ /*5.調用WriteProcessMemory,給進程寫入DLL的路徑*/ /*6.創建遠程線程,執行我們的代碼*/ /*7.調用退出代碼,釋放遠程線程的dll*/
每一步單獨講解
我們新建一個MFC 對話框程序,添加一個按鈕,這個按鈕專門響應注入的實現
第一步: 查找窗口,獲得窗口句柄(采用WindowsAPI FindWindow,傳入窗口名稱,然后找到則返回對應的窗口句柄)
HWND hWnd = FindWindow("","計算器"); if(NULL == hWnd) { return; //失敗則返回 }
第二步: 根據窗口句柄,查找進程PID (調用 GetWindowThreadProcessId API,傳入窗口句柄,然后通過第二個參數把進程的PID給我們的參數)
/*2.根據窗口句柄,獲得進程的PID*/ DWORD DwPid = 0; GetWindowThreadProcessId(hWnd,&DwPid); //這個函數會返回線程的ID,但是我們不關心,所以沒有加返回值
第三步: 根據進程PID,返回進程的句柄(OpenProcess,參數一,權限 參數二,句柄是否繼承,參數三,進程的pid)
/*3.根據進程的PID,獲得進程的句柄*/ HANDLE hProHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,DwPid); //參數一,選擇所有權限,參數二,不繼承給false,參數三,給我們上面獲得的pid的值 if(NULL == hProHandle) { return; }
第四步: 給遠程進程申請空間,並且返回空間的首地址(調用的API 是VirtualAllocEx)
/*4.根據進程的句柄,給進程申請額外內存空間*/ LPVOID lpAddr = VirtualAllocEx(hProHandle,NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE); if(NULL == lpAddr) { return ; }
VirtualAllocEx說明:
第一個參數: 進程的句柄
第二個參數: 指定位置分配內存,給NULL為默認幫我們找塊地方申請內存(不過這個地址會返回,所以不關心)
第三個參數: 內存分配多大,我們給了4096個字節大小,也就是一個分頁(1000H)
第四個參數: 是否立即申請,還是保留這塊內存,只能給我們用,但是還沒申請,我們選擇立即申請
第五個參數: 權限,你申請的這塊內存是什么內存,只能讀,還是只能寫,還是只能執行,我們選擇全部,可讀可寫可執行
第五步:調用WriteProcessMemory將我們的Dll路徑,寫入到遠程進程中
/*5.調用WriteProcessMemory,給進程寫入DLL的路徑*/ char szBuf[MAX_PATH] = {NULL}; GetCurrentDirectory(sizeof(szBuf),szBuf); //這三行代碼主要是拼接我們的DLL,DLL是我們自己寫的 strcat(szBuf,"StaticDll.dll"); //DLL這里就不寫了,用我的吧,我會發上去的
BOOL bRet = WriteProcessMemory(hProHandle,lpAddr,szBuf,strlen(szBuf)+1,NULL); if(!bRet) { return; }
WriteProcessMemory講解:
第一個參數: 進程的句柄,可以用我們上面的OpenProcess返回的
第二個參數: 你要寫入的地址,地址使我們VirtualAllocEx申請之后返回的(就是你要往哪個地址寫內容)
第三個參數: 你寫入的內容是什么,寫入的內容使我們的Dll路徑,上面已經拼接好了
第四個參數: 你寫入的內容的大小是多大,這里我們用strlen求出來了
第五個參數: 實際寫入的個數,我們不關心,如果你想知道,則定義一個變量,然后 取地址傳入即可,因為是個指針
第六步: 遠程進程開辟線程,調用LoadLibrary,加載我們的dll,而你們知道,當dll被加載的時候,會有信息
所以我們在我們的dll里面寫入我們自己的代碼,比如這個dll被加載的時候,我們執行我們的代碼,
這里我的代碼就是找到計算器,然后給它加個菜單,並且響應消息
HANDLE hThreadHandle = CreateRemoteThread(hProHandle, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, lpAddr, 0, NULL);
核心代碼就在這里,我們必須要知道,我們現在加載我們的DLL,而我們的DLL被加載的時候,就要執行自己的代碼
所以這個時候就可以執行代碼了
CreateRemoteThread講解:
第一個參數: 進程的句柄(你要往哪個進程開辟線程)
第二個參數: 安全屬性,句柄可否繼承,不需要給NULL
第三個參數: 棧的大小,給0則默認
第四個參數: 函數執行,我們要開辟線程,開辟的線程叫做loadLibrary
第五個參數: 開辟線程傳入的參數,我們知道,線程只有一個參數,而現在正好load也是一個參數,所以加載的參數就是我們的
寫入遠程進程內存的dll路徑,而dll路徑一旦啟動,則會執行自己的代碼(核心,一定掌握)
第六個參數: 創建的標志,默認給0
第七個參數: 線程的ID,不需要知道,給NULL
我們嘗試一下是否可以成功注入計算器,並且加入菜單
已經成功注入了.對於完整的代碼,我會放到課堂資料中,但是這幾步,一定要親自手動弄明白
(備注: 我是使用VC++6.0編寫代碼,是MFC程序,當然你也可以用高版本,參考我這個,是一樣的
對於DLL,我也會發,你們可以自己去寫自己的DLL,比如一個空DLL會有DLL main,也就是dll的入口點
當第一次加載的時候會來信息什么的,所以可以在里面寫代碼.dll靠自己,這里只提供思路)