我对破解知识的了解实在太少,没有东西拿得出手,所以把这个东西拿出来,也不知道是不是发在了适合的版块,但这确实已经是我认为自己能拿出来的唯一有点“价值”的东西了,希望对需要的朋友有用。


//
// 特点与不足
//
我们知道当前注入最流行的做法是用 CreateRemoteThread() 在目标进程创建一个远程线程, 并将线程的过程函数指定为 LoadLibrary() 这个系统 API, 其参数为我们事先用 WriteProcessMemory() 这个系统 API 写到目标进程里的一个字符串, 而这个字符串是我们欲注入的 dll 文件的路径. 相比 Jeffrey Richter 在《Windows 核心编程》一书中提到的那数种注入方法, 此方法无疑是其中最简单最稳定最可爱的. 但遗憾的是 Windows9x 系列不支持 CreateRemoteThread() 函数, 所以此方法不能用于该版本的系统. 不过没关系, 在下面的这个代码中将提供一个间接的替代方案, 希望能给和我一样初级的朋友开阔思路, 高手就一笑置之吧( 我昨天就在论坛一个帖子里看见一位前辈一口气就说出了数种注入方法并指出各自优点与不足, 当然, 包括我这里说到的方法 ). 该代码已经经过了比较长时间的使用, 使用过程中发现的 BUG 都已逐个解决, 相对来说, 已经比较稳定. 另外, 鉴于我个人水平的浅薄, 我没有考虑任何反反注入技术, 因为我根本没接触过, 还有, Win9x 很快或者已经退出了历史舞台, 这算是此方法的两个不足吧. 好了, 我们开始吧.


//
// 解决方法概要
//
我们通过控制目标进程中任一线程的线程环境, 使其直接执行我们已经写入到目标进程中的加载我们欲注入 dll 文件的代码, 以此替代创建远程线程的方法. 听起来很不错, 但 Win9x 可能太老了, 不仅仅是不支持 CreateRemoteThread() 这一个 API 而已, 还有着相当一部分比较"好用的"、"底层的" API 它没有. 所以, 在我们的替代方案中, 我们将在真正做事之前模拟出一些该系统不支持的 API. 同时, 为了让我们的整个"系统"对外更简单, 我们将封装这些细节, 根据当前的系统版本动态的以结构体的形式提供给外部一组系统版本无关的、"好用的"、"底层的" API 函数指针.


// 具体实现 : 头文件 //////////////////////////////////////////////////////////
//
// 文件 : InjectModule.h
// 
// 作者 : 刘泽围
//
// 日期 : 2007年01月17日
//
// 描述 : 将我们的模块注入到一个正在运行的或者由我们创建的进程
//
// 致谢 : Miguel Feijao, yoda, patrick, Azorbix
//        特别的致谢送给《Windows 核心编程》作者 Jeffrey Richter
//
///////////////////////////////////////////////////////////////////////////////
#ifndef INJECT_MODULE_H
#define INJECT_MODULE_H


#include <windows.h>
#include <TLHELP32.H>


// 操作系统版本
struct OS_VER
{
    bool IsWin98;
    bool IsWinMe;
    bool IsWinXp;
};

// 动态获取或模拟一组操作系统核心 API
struct OS_API
{
    HANDLE  ( WINAPI *CreateToolhelp32Snapshot )( DWORD  dwFlags, DWORD th32ProcessID );
    BOOL    ( WINAPI *Process32First )          ( HANDLE hSnapshot, LPPROCESSENTRY32 lppe ); 
    BOOL    ( WINAPI *Process32Next )           ( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
    BOOL    ( WINAPI *Module32First )           ( HANDLE hSnapshot, LPMODULEENTRY32 lpme ); 
    BOOL    ( WINAPI *Module32Next )            ( HANDLE hSnapshot, LPMODULEENTRY32 lpme );
    BOOL    ( WINAPI *Thread32First )           ( HANDLE hSnapshot, LPTHREADENTRY32 lpte );
    BOOL    ( WINAPI *Thread32Next )            ( HANDLE hSnapshot, LPTHREADENTRY32 lpte );
    HANDLE  ( WINAPI *OpenProcess )             ( DWORD dwDesiredAccess,
                                                  BOOL  bInheritHandle,
                                                  DWORD dwProcessId
                                                );
    HANDLE  ( WINAPI *OpenThread )              ( DWORD dwDesiredAccess,
                                                  BOOL  bInheritHandle,
                                                  DWORD dwThreadId
                                                );
    LPVOID  ( WINAPI *VirtualAllocEx )          ( HANDLE hProcess,
                                                  LPVOID lpAddress,
                                                  SIZE_T dwSize,
                                                  DWORD  flAllocationType,
                                                  DWORD  flProtect
                                                );
    BOOL    ( WINAPI *VirtualFreeEx )           ( HANDLE hProcess,
                                                  LPVOID lpAddress,
                                                  SIZE_T dwSize,
                                                  DWORD  dwFreeType
                                                );        
};

// 得到操作系统版本
bool GetOsVer( /*OUT*/OS_VER *osVer );

// 根据操作系统版本, 动态获取一组操作系统核心 API. 如果当前操作系统不
// 提供其中某个函数, 则会由库负责模拟一个
bool GetOsApi( /*OUT*/OS_API *osApi );

// 获取某个进程的相关数据
bool GetProcessInfo( const char *exeName, /*OUT*/PROCESS_INFORMATION *processInfo );

// 获取某个进程中某个模块的相关数据
bool GetModuleInfo( const char *exeName, const char *moduleName,
                    /*OUT*/MODULEENTRY32 *moduleEntry32 );

// 将模块注入到某个进程
bool InjectModule( const char *exeName, const char *modulePath );


#endif


// 具体实现 : 代码 ////////////////////////////////////////////////////////////
//
// 文件 : InjectModule.cpp
// 
// 作者 : 刘泽围
//
// 日期 : 2007年01月17日
//
///////////////////////////////////////////////////////////////////////////////
#include "InjectModule.h"
#include <stddef.h>


//
// 操作系统版本与对应 API 组, 给模块内部使用, 我们只需初始化
// 一次, 所以声明为全局变量
//
OS_VER OsVer;
bool IsGotOsVer = false;

OS_API OsApi;
bool IsGotOsApi = false;


// Windows9x 系统上模拟 OpenThread
HANDLE WINAPI OpenThread9x( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId );

// Windows9x 系统上模拟 VirtualAllocEx
LPVOID WINAPI VirtualAllocEx9x( HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect );

// Windows9x 系统上模拟 VirtualFreeEx
BOOL WINAPI VirtualFreeEx9x( HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType );

// 获得 Api 的地址
bool GetApiAddress( const char *dllName, const char *apiName, DWORD *apiAddress );

// 通过比较两个模块的名字判断两个模块是否为同一个模块
// 注意 : 此比较为完全忽略路径与大小写的比较
// Windows9x 系统考虑完整路径, 2000/Xp 系统仅考虑模块名
bool IsSameName( const char *targetString, const char *sourceString );


bool GetOsVer( /*OUT*/OS_VER *osVer )
{
    if ( IsGotOsVer == false )
    {
        OSVERSIONINFO OSVI;
        OSVI.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
        if ( !GetVersionEx( &OSVI ) )
            return false;

        OsVer.IsWin98 = ( OSVI.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS && OSVI.dwMajorVersion==4 && OSVI.dwMinorVersion<=10 ) ? true : false;
        OsVer.IsWinMe = ( OSVI.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS && OSVI.dwMajorVersion==4 && OSVI.dwMinorVersion>=90 ) ? true : false;
        OsVer.IsWinXp = ( OSVI.dwPlatformId==VER_PLATFORM_WIN32_NT ) ? true : false;

        IsGotOsVer = true;
    }

    // 如果是外部调用, 则将该结构拷贝一个副本给外部
    if ( osVer != NULL )
        memcpy( (void *)osVer, (const void *)&OsVer, sizeof( OS_VER ) );

    return true;
}


bool GetOsApi( /*OUT*/OS_API *osApi )
{
    if ( IsGotOsApi == false )
    {
        // 得到操作系统版本
        if ( !GetOsVer( NULL ) )
            return false;
    
        //
        // 根据操作系统版本动态得到相关的操作系统 API
        //
        if ( !GetApiAddress( "kernel32.dll", "CreateToolhelp32Snapshot",
                             (DWORD *)&OsApi.CreateToolhelp32Snapshot ) )
            return false;

        if ( !GetApiAddress( "kernel32.dll", "Process32First",
                             (DWORD *)&OsApi.Process32First ) )
            return false;

        if ( !GetApiAddress( "kernel32.dll", "Process32Next",
                             (DWORD *)&OsApi.Process32Next ) )
            return false;

        if ( !GetApiAddress( "kernel32.dll", "Module32First",
                             (DWORD *)&OsApi.Module32First ) )
            return false;

        if ( !GetApiAddress( "kernel32.dll", "Module32Next",
                             (DWORD *)&OsApi.Module32Next ) )
            return false;

        if ( !GetApiAddress( "kernel32.dll", "Thread32First",
                             (DWORD *)&OsApi.Thread32First ) )
            return false;

        if ( !GetApiAddress( "kernel32.dll", "Thread32Next",
                             (DWORD *)&OsApi.Thread32Next ) )
            return false;

        if ( !GetApiAddress( "kernel32.dll", "OpenProcess",
                             (DWORD *)&OsApi.OpenProcess ) )
            return false;

        if ( OsVer.IsWin98 )
            *(PDWORD)(&OsApi.OpenThread) = (DWORD)OpenThread9x;
        else if ( !GetApiAddress( "kernel32.dll", "OpenThread",
                                  (DWORD *)&OsApi.OpenThread ) )
            return false;
        
        if ( OsVer.IsWin98 || OsVer.IsWinMe )
            *(PDWORD)(&OsApi.VirtualAllocEx) = (DWORD)VirtualAllocEx9x;
        else if ( !GetApiAddress( "kernel32.dll", "VirtualAllocEx",
                                  (DWORD *)&OsApi.VirtualAllocEx ) )
            return false;
        
        if ( OsVer.IsWin98 || OsVer.IsWinMe )
            *(PDWORD)(&OsApi.VirtualFreeEx) = (DWORD)VirtualFreeEx9x;
        else if ( !GetApiAddress( "kernel32.dll", "VirtualFreeEx",
                                  (DWORD *)&OsApi.VirtualFreeEx ) )
            return false;

        IsGotOsApi = true;
    }

    // 如果是外部调用, 则将该结构拷贝一个副本给外部
    if ( osApi != NULL )
        memcpy( (void *)osApi, (const void *)&OsApi, sizeof( OS_API ) );
  
    return true;
}


bool GetProcessInfo( const char *exeName, /*OUT*/PROCESS_INFORMATION *processInfo )
{
    // 得到相关系统 API
    if ( !GetOsApi( NULL ) )
        return false;

    //
    // 枚举当前系统中所有进程找出目标进程
    //
    HANDLE snapshotProcess = OsApi.CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    if ( snapshotProcess == INVALID_HANDLE_VALUE )
        return false;

    PROCESSENTRY32 PE32;
    PE32.dwSize = sizeof( PROCESSENTRY32 );   

    bool isExist = false;
    if ( OsApi.Process32First( snapshotProcess, &PE32 ) )
    {
        do
        {                  
            if ( IsSameName( PE32.szExeFile, exeName ) )    
                isExist = true;                        
        } while ( isExist == false && OsApi.Process32Next( snapshotProcess, &PE32 ) );
    }
    
    CloseHandle( snapshotProcess );

    if ( isExist == false ) 
        return false;

    //
    // 枚举目标进程中所有线程找出其中任一线程
    //
    HANDLE snapshotThread = OsApi.CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
    if ( snapshotThread == INVALID_HANDLE_VALUE )
        return false;

    THREADENTRY32 TE32;
    TE32.dwSize = sizeof( THREADENTRY32 );

    isExist = false;
    if ( OsApi.Thread32First( snapshotThread, &TE32 ) )
    {
        do
        {
            if ( TE32.th32OwnerProcessID == PE32.th32ProcessID )
            {
                CloseHandle( snapshotThread );
                isExist = true;

                break;
            }
        } while ( isExist == false && OsApi.Thread32Next( snapshotThread, &TE32 ) );
    }

    CloseHandle( snapshotThread );

    if ( isExist == false )
        return false;

    //
    // 分别通过 Id 找到其句柄, 填充 processInfo, 输出结果
    //    
    PROCESS_INFORMATION PI;

    PI.dwProcessId = PE32.th32ProcessID;
    PI.hProcess = OsApi.OpenProcess( PROCESS_ALL_ACCESS, FALSE, PE32.th32ProcessID );
    if ( PI.hProcess == NULL )
        return false;

    PI.dwThreadId = TE32.th32ThreadID;
    PI.hThread = OsApi.OpenThread( THREAD_ALL_ACCESS, FALSE, TE32.th32ThreadID );
    if ( PI.hThread == NULL )
    {
        CloseHandle( PI.hProcess );

        return false;
    }

    // 如果是外部调用, 则将该结构拷贝一个副本给外部
    if ( processInfo != NULL )
        memcpy( (void *)processInfo, (const void *)&PI, sizeof( PROCESS_INFORMATION ) );

    return true;
}


bool GetModuleInfo( const char *exeName, const char *moduleName,
                           /*OUT*/MODULEENTRY32 *moduleEntry32 )
{
    // 得到相关系统 API
    if ( !GetOsApi( NULL ) )
        return false;

    PROCESS_INFORMATION processInfo;

    // 获取操作目标进程的相关数据
    if ( GetProcessInfo( exeName, &processInfo ) == false )
        return false;

    HANDLE snapshotModule = OsApi.CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, processInfo.dwProcessId );
    if ( snapshotModule == INVALID_HANDLE_VALUE )
    {
        CloseHandle( processInfo.hThread );
        CloseHandle( processInfo.hProcess );        

        return false;
    }

    MODULEENTRY32 ME32;
    ME32.dwSize = sizeof( MODULEENTRY32 );
    if ( OsApi.Module32First( snapshotModule, &ME32 ) )
    {
        do
        {            
            if ( IsSameName( ME32.szExePath, moduleName ) )
            {    
                // 如果是外部调用, 则将该结构拷贝一个副本给外部
                if ( moduleEntry32 != NULL )
                    memcpy( (void *)moduleEntry32, (const void *)&ME32,
                            sizeof( MODULEENTRY32 ) );

                CloseHandle( processInfo.hThread );
                CloseHandle( processInfo.hProcess );
                CloseHandle( snapshotModule );
                
                return true;
            }
        } while ( OsApi.Module32Next( snapshotModule, &ME32 ) );
    }

    CloseHandle( processInfo.hThread );
    CloseHandle( processInfo.hProcess );
    CloseHandle( snapshotModule );

    return false;
}


bool InjectModule( const char *exeName, const char *modulePath )
{
    PROCESS_INFORMATION processInfo;
    DWORD beginAddress = 0, endAddress = 0;
    BYTE injectCode[512];
        
    // 得到系统版本
    if ( !GetOsVer( NULL ) )
        return false;

    // 得到相关系统 API
    if ( !GetOsApi( NULL ) )
        return false;    

    // 检查待注入模块是否已经被加载
    if ( GetModuleInfo( exeName, modulePath, NULL )  )
        return true;

    // 获取操作目标进程的相关数据
    if ( !GetProcessInfo( exeName, &processInfo ) )
        return false;

    //
    // 注入目标进程
    //
    DWORD loadLibraryAddress = 0;
    if ( !GetApiAddress( "kernel32.dll", "LoadLibraryA", &loadLibraryAddress ) )
    {
        CloseHandle( processInfo.hThread );
        CloseHandle( processInfo.hProcess );

        return false;
    }
      
    beginAddress = (DWORD)OsApi.VirtualAllocEx( processInfo.hProcess, NULL, 512,
                                                MEM_COMMIT, PAGE_EXECUTE_READWRITE );
    if ( beginAddress == 0 )
    {
        CloseHandle( processInfo.hThread );
        CloseHandle( processInfo.hProcess );

        return false;
    }   
    
    // 根据操作系统版本填充相应注入代码结构体
    // 从分配的内存的第4号字节开始填充, 防止堆中垃圾数据对填充后
    // 的第一条代码的影响
    // 这里请高手指点 : 堆中垃圾数据是否真的会影响我们的第一条代码, 不知我这样做是否多余
    injectCode[0] = 0x90;
    injectCode[1] = 0x90;
    injectCode[2] = 0x90;
    injectCode[3] = 0x90;
    injectCode[4] = 0x68;
    *(DWORD *)( injectCode + 5 ) = beginAddress + 16;
    injectCode[9] = 0xE8;
    *(DWORD *)( injectCode + 10 ) = loadLibraryAddress - beginAddress - 14;
    if ( OsVer.IsWin98 || OsVer.IsWinMe )
    {        
        injectCode[14] = 0xEB;
        injectCode[15] = 0xFE; // 0xEBFE 是跳转到当前行, 也就是原地循环
    }
    else
    {
        injectCode[14] = 0xC3; // 0xC3 是返回
        injectCode[15] = 0x90;
    }
    strcpy( (char *)&injectCode[16], modulePath );

    endAddress = beginAddress + 14;

    // 向目标进程写入注入代码
    if ( !WriteProcessMemory( processInfo.hProcess, (void *)beginAddress, (void *)injectCode, 512, NULL ) )
    {
        OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
        CloseHandle( processInfo.hThread );
        CloseHandle( processInfo.hProcess );

        return false;
    }

    // 根据操作系统版本用相应的方式运行已写入的注入代码
    if ( OsVer.IsWin98 || OsVer.IsWinMe )
    {
        // 检查目标进程是否已经启动并初始化好, 这里以目标进程加载了 Kernel32.dll 为
        // 其启动成功的标志, 且判断后再 Sleep() 给其启动时间, 或许还有其他更好更稳
        // 健的方法
        /* 这里请高手指点 : 此处的判断是多余的吗, 需不需要及如何判断一个进程是否已经完全启动好^^
        if ( !GetModuleInfo( exeName, "kernel32.dll", NULL ) )
        {
            OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
            CloseHandle( processInfo.hThread );
            CloseHandle( processInfo.hProcess );

            return false;
        }
        Sleep( 50 );
        */                      
        
        //
        // 通过修改目标进程中某一线程的线程环境的方法, 使目标进程执行我们写入的代码
        // 注意: 下面的代码写得很烦琐, 我仅仅是想让其尽可能稳定, 你大可简单的跳过不看 ^^
        //       因为以下任一句 ResumeThread() 函数调用失败, 目标线程都将被永久挂起, 必
        //       造成目标进程不可预计的严重错误, 建议的做法是重新启动目标进程.
        //
        INT countSuspend;
        CONTEXT orgContext, runContext;

        if ( SuspendThread( processInfo.hThread ) == 0xFFFFFFFF )
            return false;

        countSuspend = 1;
        
        orgContext.ContextFlags = CONTEXT_FULL;
        if ( !GetThreadContext( processInfo.hThread, &orgContext ) )
        {
            ResumeThread( processInfo.hThread );      
            OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
            CloseHandle( processInfo.hThread );
            CloseHandle( processInfo.hProcess );

            return false;
        }
        
        runContext = orgContext;
        runContext.Eip = beginAddress + 4;
        if ( !SetThreadContext( processInfo.hThread, &runContext ) )
        {               
            ResumeThread( processInfo.hThread );
            OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
            CloseHandle( processInfo.hThread );
            CloseHandle( processInfo.hProcess );

            return false;
        }
        
        while ( runContext.Eip != endAddress )
        {
            // 确保并调整该线程到运行状态
            while ( true )
            {
                DWORD returnValue = ResumeThread( processInfo.hThread );
            
                if ( returnValue <= 1 )
                {
                    if ( returnValue == 1 )
                        countSuspend--;

                    break;
                }
                else if ( returnValue < 0xFFFFFFFF )
                {
                    countSuspend--;
                }
                else if ( returnValue == 0xFFFFFFFF )
                {
                    OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
                    CloseHandle( processInfo.hThread );
                    CloseHandle( processInfo.hProcess );

                    return false;
                }
            }
            
            // 让线程运行我们注入的代码
            Sleep( 50 );

            // 确保并调整该线程到暂停状态
            if ( SuspendThread( processInfo.hThread ) == 0xFFFFFFFF )
            {
                OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
                CloseHandle( processInfo.hThread );
                CloseHandle( processInfo.hProcess );

                return false;        
            }
            countSuspend++;

            if ( !GetThreadContext( processInfo.hThread, &runContext ) )
            {            
                if ( countSuspend > 0 )
                    while ( countSuspend-- > 0 && ResumeThread( processInfo.hThread ) != 0xFFFFFFFF );
                else if ( countSuspend < 0 )
                    while ( countSuspend++ < 0 && SuspendThread( processInfo.hThread ) != 0xFFFFFFFF );
            
                OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
                CloseHandle( processInfo.hThread );
                CloseHandle( processInfo.hProcess );

                return false;        
            }            
        }

        if ( !SetThreadContext( processInfo.hThread, &orgContext ) )
        {
            if ( countSuspend > 0 )
                while ( countSuspend-- > 0 && ResumeThread( processInfo.hThread ) != 0xFFFFFFFF );
            else if ( countSuspend < 0 )
                while ( countSuspend++ < 0 && SuspendThread( processInfo.hThread ) != 0xFFFFFFFF );
        
            OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
            CloseHandle( processInfo.hThread );
            CloseHandle( processInfo.hProcess );

            return false;
        }

        //
        // 操作成功, 恢复线程到初始状态
        //
        if ( countSuspend > 0 )
            while ( countSuspend-- > 0 && ResumeThread( processInfo.hThread ) != 0xFFFFFFFF );
        else if ( countSuspend < 0 )
            while ( countSuspend++ < 0 && SuspendThread( processInfo.hThread ) != 0xFFFFFFFF );
    }
    else // Windows2000, WindowsXP 采用创建远程线程的方法运行注入代码
    {
        HANDLE remoteThread = CreateRemoteThread( processInfo.hProcess, NULL, 0,
            (LPTHREAD_START_ROUTINE)( beginAddress + 4 ), NULL, 0, NULL );
        if ( remoteThread == NULL )
        {
            OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
            CloseHandle( processInfo.hThread );
            CloseHandle( processInfo.hProcess );

            return false;
        }

        WaitForSingleObject( remoteThread, INFINITE );

        DWORD moduleBase;
        if ( !GetExitCodeThread( remoteThread, &moduleBase ) || !moduleBase )
        {
            OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
            CloseHandle( processInfo.hThread );
            CloseHandle( processInfo.hProcess );

            return false;
        }  
    }
    
    OsApi.VirtualFreeEx( processInfo.hProcess, (void *)beginAddress, 512, MEM_DECOMMIT );
    CloseHandle( processInfo.hThread );
    CloseHandle( processInfo.hProcess );
    
    return true;
}


// 通过特征串搜索到该串在内存中的起始地址( 线性地址 )
bool GetSigAddress( DWORD start, DWORD length, BYTE *pattern, CHAR *mask,
                    /*OUT*/DWORD *sigAddress )
{
    BYTE *currentAddress;
    BYTE *currentPattern;
    CHAR *currentMask;
    
    for ( DWORD i=0; i<length; i++ )
    {
        currentAddress = (BYTE*)(start+i);
        currentPattern = pattern;
        currentMask    = mask;
        for ( ; *currentMask; currentAddress++,currentPattern++,currentMask++ )
        {
            if ( *currentMask=='x' && *currentAddress!=*currentPattern )
                break;
        }

        if ( *currentMask == 0x0 )
        {
            *sigAddress = start + i;
            return true;
        }
    }
    
    return false;
}


HANDLE WINAPI OpenThread9x( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
{
    //
    // 说明 : 来自 Miguel Feijao
    //
    // 1> 系统 API OpenProcess() 做了什么?
    //    1、检查目标是否真的是一个进程
    //    2、调用微软未公开的一个系统函数 GetHandle()
    //
    // 2> 我们的 OpenThread9x() 做了什么?
    //    直接得到线程的 TDB, 然后调用 OpenProcess() 调用的 GetHandle() 得到线程句柄
    // 
    static DWORD *pThreadDataBase = NULL;
    static HANDLE ( WINAPI *pInternalOpenProcess )( DWORD, BOOL, DWORD ) = NULL;
    
    if ( pThreadDataBase == NULL || pInternalOpenProcess == NULL )
    {
        DWORD processID, obsfucator;

        processID = GetCurrentProcessId();
        __asm mov eax,fs:[0x30];
        __asm xor eax,processID;
        __asm mov obsfucator,eax;
    
        pThreadDataBase = ( DWORD* ) ( dwThreadId ^ obsfucator );
        if ( IsBadReadPtr( pThreadDataBase, sizeof(DWORD) ) || ( ( *pThreadDataBase & 0x7 ) != 0x7 ) )
            return NULL;
    
        if ( !GetSigAddress( (DWORD)OpenProcess, 0xFF,
                                    (BYTE*)"\xB9\x00\x00\x00\x00", "xxxxx",
                                    (DWORD *)&pInternalOpenProcess )
           )
           return NULL;
    }

    HANDLE hThread;

    __asm mov   eax, pThreadDataBase;
    __asm push  dwThreadId;
    __asm push  bInheritHandle;
    __asm push  dwDesiredAccess;
    __asm call  pInternalOpenProcess;
    __asm mov   hThread, eax;
      
    return hThread;
}


LPVOID WINAPI VirtualAllocEx9x( HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect )
{
    static LPVOID ( WINAPI *pVirtualAlloc )( LPVOID, SIZE_T, DWORD, DWORD ) = NULL;
    
    if ( pVirtualAlloc == NULL )
        GetApiAddress( "kernel32.dll", "VirtualAlloc", (DWORD *)&pVirtualAlloc );
    
    return pVirtualAlloc( lpAddress, dwSize, flAllocationType|0x8000000, flProtect );          
}


BOOL WINAPI VirtualFreeEx9x( HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
{
    static BOOL ( WINAPI *pVirtualFree )( LPVOID, SIZE_T, DWORD ) = NULL;

    if ( pVirtualFree == NULL )
        GetApiAddress( "kernel32.dll", "VirtualFree", (DWORD *)&pVirtualFree );
    
    return pVirtualFree( lpAddress, dwSize, dwFreeType );
}


bool GetApiAddress( const char *dllName, const char *apiName, DWORD *apiAddress )
{
    HMODULE dllHandle = GetModuleHandle( dllName );
    if ( dllHandle == NULL )
    {
        dllHandle = LoadLibrary( dllName );
        if ( dllHandle == NULL )
            return false;
    }

    *apiAddress = (DWORD)GetProcAddress( dllHandle, apiName );
    if ( *apiAddress == NULL )
        return false;

    return true;
}


bool IsSameName( const char *targetString, const char *sourceString )
{
    const char *index, *i, *j;
   
    for( index=i=targetString; *index; index++ )
        if ( *index == '\\' )
            i = index+1;
        
    for( index=j=sourceString; *index; index++ )
        if ( *index == '\\' )
            j = index+1;

    int length = 0;   
    
    for ( ; *i && *j; i++,j++ )
    {
        if ( tolower( *i ) != tolower( *j ) )
            break;

        length++;
    }
            
    return ( ( ( *i == 0 ) && ( *j == 0 ) )
             /*下面是为了匹配长度超过 8 位的文件名有时会变为 proces~1.exe 类似这样的名字*/
             || ( length >= 6 && (*i) == '~' ) );
}


// 一个简单的例子 : Loader.exe ////////////////////////////////////////////////
//
// 文件 : Loader.cpp
// 
// 作者 : 刘泽围
//
// 日期 : 2007年01月17日
//
// 描述 : 将我们的 Dll 加载到宿主程序进程地址空间
//
///////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include "InjectModule.h"
#pragma comment( lib, "user32.lib" )
#pragma comment( lib, "shell32.lib" )


//
// 宿主程序与我们 Dll 的文件名
//
const char exeName[32] = "NotePad.exe";
const char moduleName[32] = "Module.dll";


//
// 托盘提示信息
//
const char appName[256] = "Loader.exe";
const char running[256] = "准备就绪, 运行中...";
const char monitor[256] = "等待宿主进程启动...";

#define IDI_LOADER 101
#define WM_TRAY    ( WM_USER + 1 )
HWND appHwnd;
NOTIFYICONDATA trayIcon;


//
// 注入线程与主窗口的过程函数
//
DWORD WINAPI InjectThread( LPVOID param );
LRESULT CALLBACK WinProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );


INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nShowCmd )
{
    // 防止程序重复加载
    HANDLE handle = CreateMutex( NULL, TRUE, appName );
    if ( GetLastError() != ERROR_SUCCESS )
    {
        MessageBox( 0, "程序已经在运行!", appName, MB_OK | MB_ICONINFORMATION );
        return 0;
    }
    
    // 创建注入线程  
    CreateThread( NULL, 0, InjectThread, NULL, 0, new DWORD );
           
    //
    // 创建应用程序窗口
    //
    WNDCLASS appWndCls;
    ZeroMemory( (void *)&appWndCls, sizeof( WNDCLASS ) );
    appWndCls.lpfnWndProc = WinProc;
    appWndCls.lpszClassName = appName;  
    appWndCls.hInstance = hInstance;    
    if ( !RegisterClass( &appWndCls ) )     
        MessageBox( NULL, "初始化失败!", "提示", MB_OK | MB_ICONINFORMATION );

    appHwnd = CreateWindow( appName, appName, 0, 0, 0, 0, 0,
                            NULL, NULL, hInstance, 0 );  
    if ( !appHwnd )
        MessageBox( NULL, "初始化失败!", appName, MB_OK | MB_ICONINFORMATION );

    HICON iconLoader = LoadIcon( hInstance, (LPCTSTR)IDI_LOADER );

    //
    // 创建托盘图标
    //
    trayIcon.cbSize = sizeof( NOTIFYICONDATA ); 
    trayIcon.uCallbackMessage = WM_TRAY; 
    trayIcon.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; 
    trayIcon.uID = 8696; 
    trayIcon.hIcon = iconLoader;
    trayIcon.hWnd = appHwnd;
    strcpy( trayIcon.szTip, appName ); 

    Shell_NotifyIcon( NIM_ADD, &trayIcon );

    // 消息循环
    MSG message;
    while ( GetMessage( &message, NULL, 0, 0 ) )
    {
        TranslateMessage( &message );
        DispatchMessage( &message );
    } 

    return 0;
}


DWORD WINAPI InjectThread( LPVOID param )
{
    // 得到当前路径
    char modulePath[MAX_PATH];
    GetModuleFileName( NULL, modulePath, MAX_PATH );
    char* index = strrchr( modulePath, '\\' );
    modulePath[ index - modulePath + 1 ] = 0;
    strcat( modulePath, moduleName );
    
    // 检查待注入的模块是否存在
    WIN32_FIND_DATA WFD;
    if ( FindFirstFile( modulePath, &WFD ) == INVALID_HANDLE_VALUE )
    {
        char msg[512];
        strcpy( msg, "文件 " );
        strcat( msg, moduleName );
        strcat( msg, " 不存在!" );
        
        MessageBox( NULL, msg, appName, MB_OK | MB_ICONINFORMATION );
        
        PostMessage( appHwnd, WM_CLOSE, 0, 0 );
    }
    
    // 监视目标进程, 注入模块
    while ( true )
    {
        int interval = 0;
        int returnValue = 0;
        
        if ( InjectModule( exeName, modulePath ) == true )
        {
            interval = 1000;

            if ( strcmp( trayIcon.szTip, running ) != 0 )
            {    
                strcpy( trayIcon.szTip, running );

                Shell_NotifyIcon( NIM_MODIFY, &trayIcon ); 
            }
        }
        else
        {
            interval = 10;

            if ( strcmp( trayIcon.szTip, monitor ) != 0 )
            {
                 strcpy( trayIcon.szTip, monitor );

                Shell_NotifyIcon( NIM_MODIFY, &trayIcon ); 
            }
        }
        
        Sleep( interval );
    }
    
    return 0;
}


LRESULT CALLBACK WinProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    switch ( message )
    {
    case WM_TRAY:
    
        if ( (UINT)lParam == WM_RBUTTONUP )
            PostMessage( appHwnd, WM_CLOSE, 0, 0 );  
    
        break;

    case WM_CLOSE:       

        Shell_NotifyIcon( NIM_DELETE, &trayIcon );
        
        PostMessage( appHwnd, WM_QUIT, 0, 0 ); 

        break;

    default:
        return DefWindowProc( hwnd, message, wParam, lParam );
    }

    return 0;
}


// 一个简单的例子 : Module.dll ////////////////////////////////////////////////
//
// 文件 : Module.cpp
// 
// 作者 : 刘泽围
//
// 日期 : 2007年01月17日
//
// 描述 : 被我们用来注入的模块
//
///////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#pragma comment( lib, "user32.lib" )
#pragma comment( linker, "/base:0x20000000" ) // 将 Dll 加载到一个非默认的地址可以防止
                                              // 首选地址加载失败对程序性能产生的影响


int WINAPI DllMain( HANDLE module, DWORD reason, LPVOID reserved )
{
    if ( reason == DLL_PROCESS_ATTACH )
        MessageBox( NULL, "Hello Pediy!", "Module.dll", MB_OK );
    
    return true;
}




Have fun!