WIN32 SDKには、セキュリティ実装のサンク

//thunk 的安全实现, 废话我就少说可,下面用代码说明吧

//WinX.h
#ifndef _WINX_H_
#define _WINX_H_

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

//此代码在XP到Win7系统测试可正常执行

//函数模版用到的标记宏
#ifndef FUN_END_FLAG

    //函数结束标记
    #define FUN_END_FLAG(X) \
    DWORD WINAPI X##_END() \
    {\
        return (DWORD)X##_END;\
    }

    //头部声明使用
    #define DEF_END_FUN(X) DWORD WINAPI X##_END();

    //数组使用
    #define ITEM_FUN(X) X##_END,

    //根据函数名获取结束函数名
    #define GET_END_FUN(X) X##_END

    // 局部变量的宏定义
    #define DEF_THIS_VAL 0x00000000
    #define VAR_LOCAL(TYPE,NAME,VALUE) TYPE NAME; __asm{MOV NAME,VALUE};
#endif


//如果定义此宏
//则使用   TemplateWinProcCode[] 作为函数模版, 其内容是通过反汇编TemplateWndProc获得
//否则根据 TemplateWndProc       生成函数模版, TemplateWndProc 是编译器生成的代码
#define USE_CODE_ARRAY


#ifdef _DEBUG
#ifndef USE_CODE_ARRAY
    #define USE_CODE_ARRAY //在调试模式下,强制使用USE_CODE_ARRAY宏
#endif
#endif

//动态分配一个TemplateWndProc函数,并让函数内部变量指针指向pThis
LPVOID NewTemplateWndProc(DWORD pThis);

const unsigned char TemplateWinProcCode[]={
0x55,0x8B,0xEC,0x51,0x56,0xC7,0x45,0xFC,0x00,0x00,0x00,0x00,0x8B,0x75,0x14,0x8B,
0x4D,0xFC,0x8B,0x45,0x08,0x56,0x8B,0x75,0x10,0x89,0x41,0x04,0x8B,0x11,0x56,0x8B,
0x75,0x0C,0x56,0x50,0xFF,0x52,0x04,0x5E,0x8B,0xE5,0x5D,0xC2,0x10,0x00,0x90,0x90,
};

class CThunk
{
public:
    HWND      m_hWnd;
    LPVOID    m_WndProc;

    CThunk()
    {
        m_hWnd=NULL;
        m_WndProc=NewTemplateWndProc((DWORD)this);
    }

    virtual ~CThunk()
    {
        if (m_WndProc)
        {
            VirtualFree(m_WndProc,NULL,MEM_RELEASE);
        }
    }

    virtual LRESULT WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)=0;
};

class CWinX : public CThunk
{
public:

    WNDPROC   m_SubclassProc;
private:

    char szclass[16];

public:

	CWinX(HWND hWnd = NULL)
	{
		m_hWnd = hWnd;
        m_SubclassProc=NULL;

        szclass[0]=NULL;
	}

    virtual ~CWinX()
    {
        if (szclass[0] && m_hWnd)
        {
            UnregisterClass(szclass,GetModuleHandle(NULL));
        }
    }

	CWinX& operator=(HWND hWnd)
	{
		m_hWnd = hWnd;
		return *this;
	}

	inline operator HWND() const { return m_hWnd; }

    inline HWND GetSafeHwnd()
    {
        return m_hWnd;
    }

	void Attach(HWND hWndNew)
	{
		m_hWnd = hWndNew;
	}

	HWND Detach()
	{
		HWND hWnd = m_hWnd;
		m_hWnd = NULL;
		return hWnd;
	}

    virtual LRESULT WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
        if (Msg==WM_DESTROY)
        {
            ::PostQuitMessage(0);
            return 0;
        }

        if (m_SubclassProc)
        {
            return CallWindowProc(m_SubclassProc, hWnd,Msg,wParam,lParam);
        }else{
            return ::DefWindowProc(hWnd,Msg,wParam,lParam);
        }
    }

	HWND Create(LPCTSTR lpszWndClass, HWND hWndParent, int x, int y, int cx, int cy, LPCTSTR lpszWindowName = NULL, DWORD dwCsStyle=0, DWORD dwStyle = WS_OVERLAPPEDWINDOW, DWORD dwExStyle = 0,  LPCTSTR lpIcon=NULL, UINT nID = 0, LPVOID lpCreateParam = NULL)
	{

        HINSTANCE   hInstance=GetModuleHandle(NULL);

        if (lpszWndClass==NULL)
        {
            WNDCLASSEX wceClass = {0};

            wceClass.lpfnWndProc = (WNDPROC)(void *)m_WndProc; 

            wceClass.cbSize = sizeof(WNDCLASSEX);
            wceClass.style = dwCsStyle;
            wceClass.hInstance = hInstance;
            wceClass.lpszMenuName=LPCSTR((dwStyle&WS_CHILD)?0:nID);

            if (lpIcon) wceClass.hIcon = (HICON)LoadImage(hInstance, lpIcon, IMAGE_ICON, 32, 32, LR_CREATEDIBSECTION);

            wceClass.hCursor = LoadCursor(NULL, IDC_ARROW);
            wceClass.hbrBackground = (HBRUSH) COLOR_BTNSHADOW;

            if (lpIcon) wceClass.hIconSm = (HICON)LoadImage(hInstance, lpIcon, IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);

            sprintf(szclass,"WinX:%08X", wceClass.lpfnWndProc);
            wceClass.lpszClassName = szclass;

            ATOM atm=RegisterClassEx(&wceClass);

            if (atm)
            {
                m_hWnd=CreateWindowEx(dwExStyle, szclass, _T(lpszWindowName), dwStyle, x, y, cx, cy, hWndParent, HMENU((dwStyle&WS_CHILD)?nID:0), hInstance , NULL);
            }else{

                szclass[0]=NULL;
            }

        }else{

            m_hWnd=CreateWindowEx(dwExStyle, _T(lpszWndClass), _T(lpszWindowName), dwStyle, x, y, cx, cy, hWndParent, HMENU((dwStyle&WS_CHILD)?nID:0), hInstance , NULL);
            /*
            if (SubclassWindow(m_hWnd))
            {
                ModifyStyle(0,dwStyle);
                ModifyStyleEx(0,dwExStyle);
                OnCreate(NULL);
            }
            */
        }

        return m_hWnd;
	}

    static int MessageLoop(UINT AccelID=NULL)
    {
        HACCEL hAccelTable = ::LoadAccelerators(::GetModuleHandle(NULL), (LPCTSTR)AccelID);

        MSG msg;
        while (::GetMessage(&msg, NULL, 0, 0))
        {

            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                ::TranslateMessage(&msg);
                ::DispatchMessage(&msg);
            }

        }

        return msg.wParam;
    }
};


//窗口函数模版
LRESULT CALLBACK TemplateWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    VAR_LOCAL(CThunk *, pThunk, DEF_THIS_VAL)
    pThunk->m_hWnd=hWnd;
    return pThunk->WindowProc(hWnd,message,wParam,lParam);

}
FUN_END_FLAG(TemplateWndProc) //函数结束标记


//设置函数局部变量值
BOOL SetLocalVar(void *lpFun, unsigned int size, unsigned int val, unsigned int new_val)
{
    if (lpFun==NULL || size<5) return -1;

    unsigned char *ptr=(unsigned char *)lpFun;

    for (unsigned int i=0;i<size-4;i++)
    {
        if ( ptr[i]==0xC7 && ptr[i+1]==0x45 )
        {
            if ( *(unsigned int*)(ptr+i+3) == val )
            {
                
                *(unsigned int*)(ptr+i+3)=new_val;
                return TRUE;
            }
        }
    }

    return FALSE;
}

//判断第一个函数是否跳转
DWORD GetFunTrueAddress(LPVOID pFun)
{
    unsigned char *ptr=(unsigned char *)pFun;

    while ( *ptr == 0xE9 )
    {
        int add=*(int *)(ptr+1);
        ptr+=5;
        ptr+=add;
    }

    return (DWORD)ptr;
}


//动态分配一个TemplateWndProc函数,并让函数内部变量指针指向pThis
LPVOID NewTemplateWndProc(DWORD pThis)
{

#ifdef USE_CODE_ARRAY
    DWORD AllocSize=sizeof(TemplateWinProcCode);
#else
    DWORD AddressStart = GetFunTrueAddress(TemplateWndProc);
    DWORD AddressEnd   = GetFunTrueAddress(GET_END_FUN(TemplateWndProc));
    DWORD AllocSize=AddressEnd-AddressStart;
#endif

    LPVOID m_WndProc=VirtualAlloc(NULL,AllocSize,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    if (m_WndProc)
    {
#ifdef USE_CODE_ARRAY
        memcpy(m_WndProc, TemplateWinProcCode, AllocSize);
        *(DWORD *)((char *)m_WndProc+8)=pThis;
        ::FlushInstructionCache(NULL,m_WndProc,AllocSize);
        return m_WndProc;
#else
        memcpy(m_WndProc, (void *)AddressStart, AllocSize);
        if (SetLocalVar(m_WndProc,AllocSize,DEF_THIS_VAL,pThis))  
        {
            ::FlushInstructionCache(NULL,m_WndProc,AllocSize);  
            return m_WndProc;  
        }
#endif

    }
    return NULL;
}

#endif //(_WINX_H_)

/*
//测试代码

#include "stdafx.h"
#include "WinX.h"

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    CWinX win;

    if (win.Create(NULL,NULL,0,0,500,500,"hello"))
    {
        ShowWindow(win,SW_SHOW);

        win.MessageLoop(IDC_MY);
    }

    return 0;
}
*/


 

84元記事公開 ウォン称賛15 ビューに14万+を

おすすめ

転載: blog.csdn.net/TDGX2004/article/details/6955077