日历
网志分类
· 所有网志 (107)
· 傻伦 (54)
· 心情 (6)
· 任务 (2)
· 希望 (2)
· friends (0)
· 日记 (20)
· 技术类 (16)
· (2)
· 镜头下的缤纷世界 (2)
· 未分类 (3)
最新的评论
站内搜索
友情链接
· 我的歪酷 非非共享界
· xuan&connie's msn spaces
· connie
· rrrickey
· zorzor
· catherine 佟儿
· 风轻君 木棉林中的面包树
· suesu-阿苏
· 妹头
· 伟荣师弟
· 面包
· 桃桃

订阅 RSS

0022210

歪酷博客

猪之栏,清荷,轩


Eric @ 2007-03-25 21:23

#include "ntddk.h"

#define WINUNK        0
#define WIN2K        1
#define WINXP        2
#define WIN2003        3

#define SSTForId(x) ((x >> 12) & 0x3)

typedef NTSTATUS (NTAPI *NTPROC)() ;
typedef NTPROC *PNTPROC ;

typedef struct _SYSTEM_SERVICE_TABLE // SSD
{
    PNTPROC    ServiceTable ;    // array of entry points
    PULONG    CounterTable ;    // array of usage counters . be NULL
    ULONG    ServiceLimit ;    // number of table entries
    UCHAR*    ArgumentTable ;    // array of bytes counts

} SYSTEM_SERVICE_TABLE , *PSYSTEM_SERVICE_TABLE , **PPSYSTEM_SERVICE_TABLE ;;

typedef struct _SERVICE_DESCRIPTOR_TABLE    // SDT
{
    SYSTEM_SERVICE_TABLE    ntoskrnl ;        // ntoskrnl.exe (Nativate API)
    SYSTEM_SERVICE_TABLE    win32k ;        // win32k.sys (gdi/user support)
    SYSTEM_SERVICE_TABLE    table3 ;        // not used
    SYSTEM_SERVICE_TABLE    table4 ;        // not used

} SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE , **PPSERVICE_DESCRIPTOR_TABLE ;
   


typedef NTSTATUS (*ZWCREATEFILE)(PHANDLE FileHandle,
                                 ACCESS_MASK DesiredAccess,
                                 POBJECT_ATTRIBUTES ObjectAttributes,
                                 PIO_STATUS_BLOCK IoStatusBlock,
                                 PLARGE_INTEGER AllocationSize ,
                                 ULONG FileAttributes,
                                 ULONG ShareAccess,
                                 ULONG CreateDisposition,
                                 ULONG CreateOptions,
                                 PVOID EaBuffer ,
                                 ULONG EaLength
                                 );



//
// 函数声明
//

VOID GetVersion(VOID) ;

PVOID HookServices(PVOID pfnRealHandler, PVOID pfnHookHandler ) ;

void UnHookServices(PVOID pfnHandler , PVOID pfnRealHandler) ;

ULONG ServiceIdFromFn (PVOID pfnHandler) ;

NTSTATUS Hook_ZwCreateFile(PHANDLE FileHandle,
                         ACCESS_MASK DesiredAccess,
                         POBJECT_ATTRIBUTES ObjectAttributes,
                         PIO_STATUS_BLOCK IoStatusBlock,
                         PLARGE_INTEGER AllocationSize OPTIONAL,
                         ULONG FileAttributes,
                         ULONG ShareAccess,
                         ULONG CreateDisposition,
                         ULONG CreateOptions,
                         PVOID EaBuffer OPTIONAL,
                         ULONG EaLength) ;


#include "hooksys.h"


//
// 全局变量
//
ULONG gKernelVersion = WINUNK ;
ZWCREATEFILE gfn_RealZwCreateFile = NULL ;


//
// KeServiceDescriptorTable 由ntoskrnl.exe公开导出的数据结构
// 在NT下,只有一个服务描述符表(SDT),注意,每个SDT内都包含4个SST
// 在2K\XP,除了KeServiceDescriptorTable以外,还有一个KeServiceDescriptorTableShadow。
// 第2个SDT包含win32k.sys的入口地址,这个SDT没有被导出。
// 因为我们要HOOK的是Native API,与wink32.sys无关,因此不必考虑这个问题。
//
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;



NTSTATUS DriverDispatch(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    return Irp->IoStatus.Status;
}


VOID DriverUnload(
    IN PDRIVER_OBJECT DriverObject
    )
{   
    DbgPrint( "[hooksys.sys] DriverUnload" ) ;
    UNREFERENCED_PARAMETER(DriverObject) ;
    UnHookServices(ZwCreateFile,gfn_RealZwCreateFile);
}




NTSTATUS DriverEntry (
    __in PDRIVER_OBJECT DriverObject,
    __in PUNICODE_STRING RegistryPath)
{
    NTSTATUS status = STATUS_SUCCESS;
    UNREFERENCED_PARAMETER(RegistryPath);

   
    // 取版本
   
    GetVersion() ;


    DriverObject->MajorFunction[IRP_MJ_CREATE] =
    DriverObject->MajorFunction[IRP_MJ_CLOSE] =
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =DriverDispatch;
    DriverObject->DriverUnload = DriverUnload;


    gfn_RealZwCreateFile = HookServices(ZwCreateFile,Hook_ZwCreateFile) ;

    return status ;
}



//
// 取系统类型,仅判断 2000\XP03
//
VOID GetVersion(VOID)
{
    ULONG    major = 0 ,
            minor = 0 ,
            build = 0 ;
    if ( PsGetVersion(&major, &minor, &build, NULL) == TRUE )
    {
        switch(major)
        {

        // 98 or NT
        case 4:
            break ;

        // 2K or XP or 2003
        case 5:
            switch(minor)
            {
            case 0:
                gKernelVersion = WIN2K;
                break;

            case 1:
                gKernelVersion = WINXP;
                break;

            case 2:
                gKernelVersion = WIN2003 ;
                break;
            }
               
            break ;

        // Vista or Longhorn
        case 6:
            break;
        }
    }

    DbgPrint( "[hooksys.sys] PsGetVersion: %d\n" , gKernelVersion );   
}


//
// Hook Native API ,只能用于Native API(由ntoskerl.exe实现的API)
//
// HookServices( ZwCreateFile , Hook_ZwCreateFile ) 返回 ZwCreateFile 的真实地址
//
PVOID HookServices( PVOID pfnRealHandler, PVOID pfnHookHandler )
{
    ULONG uServiceId = ServiceIdFromFn (pfnRealHandler);
    ULONG uIndexSST = SSTForId(uServiceId) ;

    // xp sp2 ,uServiceId=25 , uIndexSST =0
    DbgPrint( "[hooksys.sys] hook %x Service , in No.%d SST " , uServiceId , uIndexSST ) ;
   

    //
    // 只hook由ntosknrl.exe导出的函数(Native API)
    //
    if ( uIndexSST == 0 )
    {       
        PSYSTEM_SERVICE_TABLE pServiceTable = &(*KeServiceDescriptorTable).ntoskrnl ;

        if ( uServiceId < pServiceTable->ServiceLimit )
        {
            PVOID pfnHandler = pServiceTable->ServiceTable[uServiceId] ;
            _asm cli
            pServiceTable->ServiceTable[uServiceId] = pfnHookHandler ;
            _asm sti
   
            DbgPrint ( "[hooksys.sys] Hook success !!!" ) ;
            return pfnHandler ;
        }
    }

    DbgPrint( "[hooksys.sys] Hook failed!!!" ) ;
    return NULL ;
}


void UnHookServices(PVOID pfnHandler , PVOID pfnRealHandler)
{   
    ULONG uServiceId = ServiceIdFromFn (pfnHandler);
    ULONG uIndexSST = SSTForId(uServiceId) ;

    if ( uIndexSST == 0 )
    {
        PSYSTEM_SERVICE_TABLE pServiceTable = &(*KeServiceDescriptorTable).ntoskrnl ;

        _asm cli
        pServiceTable->ServiceTable[uServiceId] = pfnRealHandler ;
        _asm sti

        DbgPrint ( "[hooksys.sys] Unhook success !!!" ) ;
    }
}


//
// 由函数的地址返回索引
// Native API 索引值的范围:0x0000 - 0x0FFF(4095)
// win32k.sys 调用的索引值:0x1000 - 0x1FFF
// 0x2000 - 0x2FFF 留给第3个表
// 0x3000 - 0x3FFF 留给第4个表
//
// 一般我们要HOOK的服务的索引值应该在0xFFF
//
ULONG ServiceIdFromFn (PVOID pfnHandler)
{
    PUCHAR    pbHandler = (PUCHAR) pfnHandler ;   
    ULONG ulService = * ((PULONG)(pbHandler + 1));       
    return ulService;
}



NTSTATUS Hook_ZwCreateFile(PHANDLE FileHandle,
                         ACCESS_MASK DesiredAccess,
                         POBJECT_ATTRIBUTES ObjectAttributes,
                         PIO_STATUS_BLOCK IoStatusBlock,
                         PLARGE_INTEGER AllocationSize OPTIONAL,
                         ULONG FileAttributes,
                         ULONG ShareAccess,
                         ULONG CreateDisposition,
                         ULONG CreateOptions,
                         PVOID EaBuffer OPTIONAL,
                         ULONG EaLength)
{   
    NTSTATUS rc;
    DbgPrint( "_ZwCreateFile : %S" , ObjectAttributes->ObjectName ? ObjectAttributes->ObjectName->Buffer : L"" ) ;
    rc= gfn_RealZwCreateFile (
        FileHandle,
        DesiredAccess,
        ObjectAttributes,
        IoStatusBlock,
        AllocationSize,
        FileAttributes,
        ShareAccess,
        CreateDisposition,
        CreateOptions,
        EaBuffer,
        EaLength);
       
    return rc;
}


 
Eric @ 2007-03-25 21:22

// HookApi_IAT.h — 使用IAT法写的一个HOOK API的类.
//
#ifndef _HOOK_API_IAT
#define _HOOK_API_IAT

class CHookApi_IAT 
{
public:
    CHookApi_IAT();
    virtual ~CHookApi_IAT();
   
public:
    PROC m_lpOldFunc;
    PROC m_lpNewFunc;

    BOOL HookAllAPI(
        PCSTR   ModuleName,
        PROC    HookAPIAddr,
        PROC    lpNewFunc);
   
    BOOL HookOneAPI(
        PCSTR   ModuleName,
        PROC    HookAPIAddr,
        PROC    lpNewFunc,
        HMODULE hmodCaller);

    BOOL HookOneAPI_OFF(
        PCSTR   ModuleName,
        HMODULE hmodCaller);
};

#endif

// HookApi_IAT.cpp:实现CHookApi_IAT类.
//
#include "stdafx.h"
#include "HookApi_IAT.h"
#include <tlhelp32.h>
#include <imagehlp.h>
#pragma comment (lib,"imagehlp.lib")

//---------------------------------------------------------------------------
CHookApi_IAT::CHookApi_IAT()
{
}

//---------------------------------------------------------------------------
CHookApi_IAT::~CHookApi_IAT()
{
}

//---------------------------------------------------------------------------
BOOL CHookApi_IAT::HookAllAPI(LPCTSTR ModuleName, PROC HookAPIAddr, PROC lpNewFunc)
{
    if (ModuleName == NULL||HookAPIAddr == NULL)
        return FALSE;

    HANDLE hSnapshot;
    MODULEENTRY32 hMod = {sizeof(hMod)};
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,NULL);
   
    // 取得所有模块列表中的指定的模块.
    BOOL bMoreMods = Module32First(hSnapshot, &hMod);
    if (bMoreMods == FALSE) return FALSE;
   
    // 循环取得想要的模块.
    for (;bMoreMods; bMoreMods = Module32Next(hSnapshot, &hMod))
    {
        MEMORY_BASIC_INFORMATION mbi;
        // 获取本模块信息.
        VirtualQuery(this,&mbi,sizeof(mbi));
        // 不在自己的模块中挂钩函数.
        if (hMod.hModule != (HMODULE)mbi.AllocationBase)
        {
            //hMod.hModule:指向当前被挂钩进程的每一个模块.
            HookOneAPI(    ModuleName,HookAPIAddr,
                lpNewFunc,hMod.hModule);
        }
    }
   
    return TRUE; 
}

//---------------------------------------------------------------------------
BOOL CHookApi_IAT::HookOneAPI(PCSTR   ModuleName, PROC HookAPIAddr,
                              PROC    lpNewFunc, HMODULE hmodCaller)
{
    DWORD size;
   
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
        (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
        hmodCaller,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
   
    if(pImportDesc == NULL) return FALSE;
   
    for (;pImportDesc->Name;pImportDesc++)
    {
        LPSTR pszDllName = (LPSTR)((PBYTE)hmodCaller + pImportDesc->Name);
        if(lstrcmpiA(pszDllName,ModuleName) == 0) break;
    }
   
    if(pImportDesc->Name == NULL) return FALSE;
    PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
        ((PBYTE)hmodCaller + pImportDesc->FirstThunk);//IAT

    for(;pThunk->u1.Function;pThunk++)
    {
        PROC * ppfn= (PROC *)&pThunk->u1.Function;
       
        m_lpOldFunc = (PROC)pThunk->u1.Function;
        m_lpNewFunc =lpNewFunc;

        if (*ppfn == HookAPIAddr)
        {
            MEMORY_BASIC_INFORMATION mbi;
            ZeroMemory(&mbi, sizeof(MEMORY_BASIC_INFORMATION));
            VirtualQuery(ppfn,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
            VirtualProtect(mbi.BaseAddress,mbi.RegionSize,
                                       PAGE_READWRITE,&mbi.Protect);
            *ppfn = *lpNewFunc;
            DWORD dwOldProtect;
            VirtualProtect(mbi.BaseAddress,mbi.RegionSize,
                                mbi.Protect,&dwOldProtect);
            return TRUE;
        }
    }
   
    return FALSE;
}

//---------------------------------------------------------------------------
BOOL CHookApi_IAT::HookOneAPI_OFF(PCSTR ModuleName, HMODULE hmodCaller)
{
    return  HookOneAPI(ModuleName, m_lpNewFunc,m_lpOldFunc,hmodCaller);
}


 
Eric @ 2007-03-25 21:21

// HookApi_JMP.cpp.
#include "stdafx.h"
#include "HookApi_JMP.h"

// 直接跳转.
//---------------------------------------------------------------------------
CHookApi_Jmp::CHookApi_Jmp(void)
{
}

//---------------------------------------------------------------------------
CHookApi_Jmp::~CHookApi_Jmp()
{
    CloseHandle(m_hProc);
}

//---------------------------------------------------------------------------
void CHookApi_Jmp::SetHookOn()
{
    DWORD dwOldFlag;
    WriteProcessMemory(m_hProc, (void *)m_lpHookFunc,
                       (void *)m_NewFunc, 5, &dwOldFlag);
}

//---------------------------------------------------------------------------
void CHookApi_Jmp::SetHookOff()
{
    DWORD dwOldFlag;
    WriteProcessMemory(m_hProc, (void *)m_lpHookFunc,
                  (void *)m_OldFunc, 5, &dwOldFlag);
}

//---------------------------------------------------------------------------
void CHookApi_Jmp::HookOneAPI(LPCTSTR ModuleName,
                             LPCTSTR ApiName, FARPROC lpNewFunc)
{
    m_lpHookFunc = GetProcAddress(GetModuleHandle(ModuleName),ApiName);
    m_hProc = GetCurrentProcess();
    m_NewFunc[0]=0xe9;   

    // 复制m_lpHookFunc前5个字节代码到m_OldFunc.
    memcpy(m_OldFunc,(char *)m_lpHookFunc,5);

    DWORD*pNewFuncAddress;   
    pNewFuncAddress=(DWORD*)&m_NewFunc[1];   
    *pNewFuncAddress=(DWORD)lpNewFunc-(DWORD)m_lpHookFunc-5;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 间接跳转.
CHookApi_Jmp2::CHookApi_Jmp2()
{
    BYTE str[8] = { 0x0B8, 0x0, 0x0, 0x40, 0x0, 0x0FF, 0x0E0,0};
    memcpy(m_NewFunc,str,8);
}

//---------------------------------------------------------------------------
CHookApi_Jmp2::~CHookApi_Jmp2()
{
    CloseHandle(m_hProc);
}

//---------------------------------------------------------------------------
void CHookApi_Jmp2::SetHookOn()
{
    DWORD dwOldFlag;
    WriteProcessMemory(m_hProc, (void *)m_lpHookFunc,
                       (void *)m_NewFunc, 8, &dwOldFlag);
}

//---------------------------------------------------------------------------
void CHookApi_Jmp2::SetHookOff()
{
    DWORD dwOldFlag;
    WriteProcessMemory(m_hProc, (void *)m_lpHookFunc,
                  (void *)m_OldFunc, 8, &dwOldFlag);
}

//---------------------------------------------------------------------------
void CHookApi_Jmp2::HookOneAPI
      (LPCTSTR ModuleName, LPCTSTR ApiName, FARPROC lpNewFunc)
{
    m_lpHookFunc = GetProcAddress(GetModuleHandle(ModuleName),ApiName);
    m_hProc = GetCurrentProcess();

    // 复制m_lpHookFunc前8个字节代码到m_OldFunc.
    memcpy(m_OldFunc,(char *)m_lpHookFunc,8);
    *(DWORD *)( m_NewFunc + 1 ) = (DWORD)lpNewFunc;
}


// HookApi_JMP.h:使用JMP法写的一个HOOK API的类.
//
#ifndef _HOOK_API_JMP
#define _HOOK_API_JMP

// 直接跳转类.
class CHookApi_Jmp 
{
public:
    CHookApi_Jmp();
    virtual ~CHookApi_Jmp();

public:
    void HookOneAPI(LPCTSTR ModuleName, LPCTSTR ApiName, FARPROC lpNewFunc);
    void SetHookOn();
    void SetHookOff();
   
protected:
    HANDLE m_hProc;
    BYTE m_OldFunc[8];
    BYTE m_NewFunc[8];
    PROC m_lpHookFunc;
};

// 间接跳转类.
class CHookApi_Jmp2 
{
public:
    CHookApi_Jmp2();
    virtual ~CHookApi_Jmp2();

public:
    void HookOneAPI(LPCTSTR ModuleName,LPCTSTR ApiName,FARPROC lpNewFunc);
    void SetHookOn();
    void SetHookOff();

protected:
    HANDLE m_hProc;
    BYTE m_OldFunc[8];
    BYTE m_NewFunc[8];
    PROC m_lpHookFunc;
};
#endif

// HookJmp.cpp:使用JMP法进行挂钩.
//
#include "stdafx.h"
#include <afxdllx.h>
#include "HookApi_Jmp.h"

void WINAPI ExampleJmp();
CHookApi_Jmp myJmp;

static AFX_EXTENSION_MODULE HookJmpDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    // Remove this if you use lpReserved
    UNREFERENCED_PARAMETER(lpReserved);

    if (dwReason == DLL_PROCESS_ATTACH)
    {
        ExampleJmp();
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        myJmp.SetHookOff();
        TRACE0("HOOKJMP.DLL Terminating!\n");
        // Terminate the library before destructors are called
        AfxTermExtensionModule(HookJmpDLL);
    }
    return 1;
}

//---------------------------------------------------------------------------
// 首先关闭拦截,然后才能调用被拦截的Api 函数.
int WINAPI JmpMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType )
{
    int nReturn=0;
    myJmp.SetHookOff();
    nReturn=MessageBoxA(hWnd,"Hooking MessageBox by Jmp",lpCaption,uType);
    myJmp.SetHookOn();
    return(nReturn);
}

//---------------------------------------------------------------------------
void WINAPI ExampleJmp()
{
    myJmp.HookOneAPI("user32.dll","MessageBoxA",(FARPROC)JmpMessageBoxA);
    myJmp.SetHookOn();
}


 
Eric @ 2007-03-25 21:18

// HookRemote.h : main header file for the HOOKREMOTE application
//

#if !defined(AFX_HOOKREMOTE_H__14BDB60A_90EA_48A2_BB9A_75E4E6860FC5__INCLUDED_)
#define AFX_HOOKREMOTE_H__14BDB60A_90EA_48A2_BB9A_75E4E6860FC5__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
    #error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h"        // main symbols

/////////////////////////////////////////////////////////////////////////////
// CHookRemoteApp:
// See HookRemote.cpp for the implementation of this class
//

class CHookRemoteApp : public CWinApp
{
public:
    CHookRemoteApp();

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CHookRemoteApp)
    public:
    virtual BOOL InitInstance();
    //}}AFX_VIRTUAL

// Implementation

    //{{AFX_MSG(CHookRemoteApp)
        // NOTE - the ClassWizard will add and remove member functions here.
        //    DO NOT EDIT what you see in these blocks of generated code !
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};


/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_HOOKREMOTE_H__14BDB60A_90EA_48A2_BB9A_75E4E6860FC5__INCLUDED_)

// HookRemote.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "HookRemote.h"
#include "HookRemoteDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CHookRemoteApp

BEGIN_MESSAGE_MAP(CHookRemoteApp, CWinApp)
    //{{AFX_MSG_MAP(CHookRemoteApp)
        // NOTE - the ClassWizard will add and remove mapping macros here.
        //    DO NOT EDIT what you see in these blocks of generated code!
    //}}AFX_MSG
    ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHookRemoteApp construction

CHookRemoteApp::CHookRemoteApp()
{
    // TODO: add construction code here,
    // Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CHookRemoteApp object

CHookRemoteApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CHookRemoteApp initialization

BOOL CHookRemoteApp::InitInstance()
{
    AfxEnableControlContainer();

    // Standard initialization
    // If you are not using these features and wish to reduce the size
    //  of your final executable, you should remove from the following
    //  the specific initialization routines you do not need.

#ifdef _AFXDLL
    Enable3dControls();            // Call this when using MFC in a shared DLL
#else
    Enable3dControlsStatic();    // Call this when linking to MFC statically
#endif

    CHookRemoteDlg dlg;
    m_pMainWnd = &dlg;
    int nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO: Place code here to handle when the dialog is
        //  dismissed with OK
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: Place code here to handle when the dialog is
        //  dismissed with Cancel
    }

    // Since the dialog has been closed, return FALSE so that we exit the
    //  application, rather than start the application's message pump.
    return FALSE;
}


 
Eric @ 2007-03-25 21:17

// HookWProc.cpp.
#include "stdafx.h"
#include <stdio.h>

//---------------------------------------------------------------------
typedef LONG    (WINAPI *SETWINDOWLONG)     (HWND,int,LONG);
typedef BOOL    (WINAPI *SETWINDOWTEXT)     (HWND,LPCSTR);
typedef LRESULT    (WINAPI *CALLWINDOWPROC) (WNDPROC,HWND,UINT,WPARAM,LPARAM);

typedef struct {
    SETWINDOWLONG    fnSetWindowLong;
    CALLWINDOWPROC    fnCallWindowProc;   
    SETWINDOWTEXT    fnSetWindowText;
    HWND            hwnd;
    WNDPROC            fnNewProc;
    char            pszStr[20];
    WNDPROC         fnOldProc;   
} INJDATA, *PINJDATA;

//---------------------------------------------------------------------
DWORD WINAPI InjectFunc (INJDATA *pData)
{
    pData->fnOldProc = (WNDPROC)pData->fnSetWindowLong
        ( pData->hwnd, GWL_WNDPROC,(long)pData->fnNewProc );

    return (pData->fnOldProc != NULL);
}

//---------------------------------------------------------------------
// 新的Windows过程函数.
static LRESULT CALLBACK NewProc(HWND hwnd,
                                UINT uMsg,
                                WPARAM wParam,
                                LPARAM lParam ) 
{   
    // 计算INJDATA的位置,注意在远进程中INJDATA紧放在NewProc前.
    INJDATA* pData;

    _asm {               
        call    dummy
    dummy:
        pop        ecx            // 此时ECX 指向当前 EIP (指示指针).
        sub        ecx,   14    // 此时ECX 指向 NewProc的地址.
        mov        pData, ecx
    }

    pData--;

    switch (uMsg)
    {
        case WM_LBUTTONDOWN:
            break;
        case WM_PAINT:
            pData->fnSetWindowText(hwnd,pData->pszStr);
            break;
    }

    return pData->fnCallWindowProc
         (pData->fnOldProc, hwnd,uMsg,wParam,lParam );       
}

//---------------------------------------------------------------------
int InjectCode (HWND hWnd, char *pszText)
{
    HANDLE    hProcess;
    HANDLE    hThread;   
    DWORD   dwPID;
    BYTE    *pCodeRemote;
    BYTE    *pDataRemote;
    BYTE    *pNewProcRemote;
    DWORD    dwThreadId;
    DWORD   dwNumBytes;
    int        nSuccess    = 0;
    int     nNewProc    = 250;
    int     nInjectFunc = 1024;

    __try {
        GetWindowThreadProcessId( hWnd, &dwPID );
        hProcess = OpenProcess(    PROCESS_ALL_ACCESS, FALSE, dwPID);
        if (hProcess == NULL)
            __leave;       
        int size = sizeof(INJDATA) + nNewProc;
       
        pDataRemote = (BYTE*) VirtualAllocEx( hProcess, 0,
            size, MEM_COMMIT, PAGE_EXECUTE_READWRITE );       

        if ( pDataRemote == NULL )
            __leave;       


        pNewProcRemote = pDataRemote + sizeof(INJDATA);
        WriteProcessMemory( hProcess, pNewProcRemote,
                             NewProc, nNewProc, &dwNumBytes);
       
        // 初始化INJDATA结构.
        HMODULE hUser32 = GetModuleHandle("user32");
        INJDATA DataLocal = {
                (SETWINDOWLONG) GetProcAddress(hUser32, "SetWindowLongA"),
                (CALLWINDOWPROC)GetProcAddress(hUser32, "CallWindowProcA"),
                (SETWINDOWTEXT) GetProcAddress(hUser32, "SetWindowTextA"),
                hWnd,
                (WNDPROC) (pNewProcRemote)
        };
       
        strcpy(DataLocal.pszStr,pszText);

        if (DataLocal.fnSetWindowLong  == NULL ||            
            DataLocal.fnCallWindowProc == NULL ||
            DataLocal.fnSetWindowText  == NULL)
            __leave;       
       
        // 把初始化的INJDATA拷贝到远进程中.
        WriteProcessMemory( hProcess,pDataRemote,
             &DataLocal, sizeof(INJDATA), &dwNumBytes);
       
        pCodeRemote = (BYTE*) VirtualAllocEx(
            hProcess, 0, nInjectFunc, MEM_COMMIT, PAGE_EXECUTE_READWRITE );

        if ( pCodeRemote == 0 )
            __leave;

        WriteProcessMemory( hProcess, pCodeRemote,
                      InjectFunc, nInjectFunc, &dwNumBytes);

        // Start execution of remote InjectFunc
        hThread = CreateRemoteThread(hProcess, NULL, 0,
                (LPTHREAD_START_ROUTINE) pCodeRemote,
                pDataRemote, 0 , &dwThreadId);
        if ( hThread == 0 )
            __leave;

        WaitForSingleObject(hThread, INFINITE);
        GetExitCodeThread(hThread, (PDWORD) &nSuccess);
    }
    __finally {
        if( !nSuccess )       
            VirtualFreeEx( hProcess, pDataRemote, 0, MEM_RELEASE );

        if ( pCodeRemote != NULL )
            VirtualFreeEx( hProcess, pCodeRemote, 0, MEM_RELEASE );

        if ( hThread != NULL )           
            CloseHandle(hThread);

        if ( hProcess != NULL )           
            CloseHandle( hProcess );
    }

    return nSuccess;
}

void NewProcCode()
{
// 定义最大代码长度.
#define Max_Sc_Len     45  
   
    char buffer[Max_Sc_Len];
    // 复制代码到buffer.
    memcpy(buffer,(char *)NewProc,Max_Sc_Len);
   
    // 显示代码.
    for(int i=0;i<Max_Sc_Len;i++){
        printf("  %02x", buffer[i]&0xff);
    }

    getchar();
}

void main()
{
//  调用显示NewProc()函数代码的函数.
//    NewProcCode();

    HWND hWnd;
    hWnd = FindWindow (NULL,TEXT("HookMsgbx"));
    if(!hWnd) return;
    hWnd = FindWindowEx (hWnd, NULL,TEXT("BUTTON"),"确定");   
    if(!hWnd) return;
    InjectCode(hWnd,"Hello!");
}