⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 function.cpp

📁 Windows 图形编程 书籍
💻 CPP
字号:
//-----------------------------------------------------------------------------------//
//              Windows Graphics Programming: Win32 GDI and DirectDraw               //
//                             ISBN  0-13-086985-6                                   //
//                                                                                   //
//  Written            by  Yuan, Feng                             www.fengyuan.com   //
//  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
//  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
//                                                                                   //
//  FileName   : function.cpp		                                                 //
//  Description: KFuncTable class                                                    //
//  Version    : 1.00.000, May 31, 2000                                              //
//-----------------------------------------------------------------------------------//

#define NOCRYPT

#include <windows.h> 
#include <string.h>
#include <assert.h>

#include "..\..\include\Decoder.h"
#include "..\..\include\atom.h"

#include "Function.h"
#include "Format.h"
#include "Report.h"
#include "Diver.h"
#include "..\Patcher\Patcher.h"

bool HackCopy(void * pDest, void * pSource, DWORD nSize);

/*
{
#ifdef WRITE_PROCESS

	static HANDLE hCurProcess = 0;

	DWORD dwWritten;

	bool rslt;
	
	if ( hCurProcess==0 )
		hCurProcess = GetCurrentProcess();

	rslt = WriteProcessMemory(hCurProcess, pDest, pSource, nSize, & dwWritten) != 0;

	return rslt && (dwWritten==nSize);

#else

	__try
	{
		memcpy(pDest, pSource, nSize);
	}
	__except ( EXCEPTION_EXECUTE_HANDLER )
	{
		__try
		{
			MEMORY_BASIC_INFORMATION mbi;
            
			VirtualQuery(pDest, & mbi, sizeof(mbi));
			VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, & mbi.Protect);

			memcpy(pDest, pSource, nSize);
		}
		__except ( EXCEPTION_EXECUTE_HANDLER )
		{
			return false;
		}
    }

	return true;

#endif
}
*/


FARPROC KFuncTable::GetProcAddr(int funcid)
{
    int mod = m_func[funcid].f_module;

    switch ( m_func[funcid].f_kind )
	{
		case FUNC_COMMETHOD:
		{
			const unsigned * pFunc = (const unsigned *) VTable(mod);
			assert(pFunc);

			return (FARPROC) pFunc[m_func[funcid].f_methodid];
		}
		break;

		case FUNC_WIN32API:
	    {
		    HINSTANCE hModule = ModHandle(m_func[funcid].f_module);
			assert(hModule);

			FARPROC fp = GetProcAddress(hModule, GetFuncName(funcid));

//			assert(fp);

			if ( fp==NULL )
			{
				char temp[128];

				wsprintf(temp, "Not found module %d at %x, func %s at %x",
					m_func[funcid].f_module, hModule, GetFuncName(funcid), fp);

				Send(M_TEXT, 0, 0, temp);
			}

			return fp;
		}

		case FUNC_SYSCALL:
			return m_func[funcid].f_oldaddress;

		default:
			assert(false);
    }

	return NULL;
}


int KFuncTable::DefPara(const char * paratype, const char *name)
{
    if ( m_parano > MAX_PARA )
    {
        assert(0);
        return -1;
    }
    
    if ( (m_lastmodule<0) || (m_lastfunc<0) )
        return -1;
    
    m_func[m_lastfunc].f_parano ++;        
    
	int len = strlen(paratype);
	const char * pSpace = strchr(paratype, ' ');
	
	if ( pSpace )
		len = (int) pSpace - (int) paratype;

	char temp[64];

	assert(64>len);
	memcpy(temp, paratype, len);
	temp[len] = 0;

    m_para[m_parano].p_type = AddAtom(temp);
    m_para[m_parano].p_name = AddAtom(name);    
    
    return m_parano ++; 
}


void KFunction::InitStub(int index, FARPROC newaddress)
{
	f_stub[0]			      = 0x68;               // push
	*((int *)(f_stub+1))      = index;              // index
	f_stub[5]			      = 0xE9;               // jmp relative
	*((unsigned *)(f_stub+6)) = (unsigned) newaddress - (unsigned) (f_stub+10);
}


#define field_this 0

int KFuncTable::AddFunc(unsigned ord, const char *name, unsigned opt,
                        int     parano,
                        const char * paratype,
						int     kind,
						const void *  oldaddr)
{
    if ( (m_funcno > MAX_FUNC) || (m_lastmodule<0) )
    {
        assert(0);
        m_lastfunc = -1;

        return -1;
    }

	m_lastfunc = m_funcno ++;

    m_func[m_lastfunc].f_kind       = kind;
    m_func[m_lastfunc].f_module     = m_lastmodule;
    m_func[m_lastfunc].InitStub(m_lastfunc, (FARPROC) ProxyProlog);
	m_func[m_lastfunc].f_methodid   = ord;
    m_func[m_lastfunc].f_name       = AddAtom(name);
    m_func[m_lastfunc].f_parano     = 0;
    m_func[m_lastfunc].f_firstpara  = m_parano;
    m_func[m_lastfunc].f_class      = opt;
    m_func[m_lastfunc].f_hooked     = FALSE;

    m_func[m_lastfunc].f_totaltime  = 0;
    m_func[m_lastfunc].f_callno     = 0;

    for (int i=0; i<parano; i++)
	{
        DefPara(paratype);

		if ( i < (parano-1) )
		{
			paratype = strchr(paratype, ' ') + 1;

			if ( paratype==(const char *) 1 )
			{
				assert(false);

				paratype = NULL;
			}
		}
	}
    
	if ( oldaddr )
		m_func[m_lastfunc].f_oldaddress = (FARPROC) oldaddr;
	else
		m_func[m_lastfunc].f_oldaddress = GetProcAddr(m_lastfunc);
	
    return m_lastfunc;
}


void KFuncTable::Initialize(void)
{
    KModuleTable::Initialize();
    
    m_funcno  = 0;
    m_parano  = 0;
        
    Initialize_API();
}


FARPROC KFuncTable::LookupInterceptedAPI(FARPROC address, int & id)
{
    for (int i=0; i<m_funcno; i++)
    {
        if ( (m_func[i].f_kind==FUNC_WIN32API) && !m_func[i].f_hooked )
        if ( m_func[i].f_oldaddress == address )
        {
            id = i;
            return m_func[i].f_newaddress();
        }
    }

/*
    // If it's Chicago, and the app is being debugged (as this app is)
    // the loader doesn't fix up the calls to point directly at the
    // DLL's entry point.  Instead, the address in the .idata section
    // points to a PUSH xxxxxxxx / JMP yyyyyyyy stub.  The address in
    // xxxxxxxx points to another stub: PUSH aaaaaaaa / JMP bbbbbbbb.
    // The address in aaaaaaaa is the real address of the function in the
    // DLL.  This ugly code verifies we're looking at this stub setup,
    // and if so, grabs the real DLL entry point, and scans through
    // the InterceptedAPIArray list of addresses again.
    // ***WARNING*** ***WARNING*** ***WARNING*** ***WARNING*** 
    // This code is subject to change, and is current only as of 9/94.

	if ((GetVersion() & 0xC0000000) == 0xC0000000)
    {
        if ( (unsigned) address < 0x80000000 )  // Only shared, system DLLs
            return NULL;                        // have stubs
        
        if ( IsBadReadPtr(address, 9) || (*(PBYTE)address != 0x68)
             || (*((PBYTE)address+5) != 0xE9) )
            return NULL;

        FARPROC stubAddress = * (FARPROC *)((PBYTE) address+1);

        for (int i=0; i<m_funcno; i++ )
            if (!m_func[i].f_isvfunc)
            {
                FARPROC lunacy = m_func[i].f_oldaddress;
            
                if ( lunacy == stubAddress )
                    return m_func[i].f_newaddress();
            
                if ( !IsBadReadPtr(lunacy, 9) && 
				     (*(PBYTE)lunacy == 0x68) && 
				     (*((PBYTE)lunacy+5) == 0xE9) )
                {
                    lunacy = * (FARPROC *)( ((PBYTE)lunacy)+1);
                
				    if ( lunacy == stubAddress )
                        return m_func[i].f_newaddress();
                }
            }
    }
*/

    return NULL;
}

_declspec(naked) void SysCall_00(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret
}

_declspec(naked) void SysCall_04(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	4
}

_declspec(naked) void SysCall_08(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	8
}

_declspec(naked) void SysCall_0C(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x0c
}

_declspec(naked) void SysCall_10(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x10
}

_declspec(naked) void SysCall_14(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x14
}

_declspec(naked) void SysCall_18(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x18
}

_declspec(naked) void SysCall_1C(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x1C
}

_declspec(naked) void SysCall_20(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x20
}

_declspec(naked) void SysCall_24(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x24
}

_declspec(naked) void SysCall_28(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x28
}

_declspec(naked) void SysCall_2C(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x2C
}

_declspec(naked) void SysCall_30(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x30
}

_declspec(naked) void SysCall_34(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x34
}

_declspec(naked) void SysCall_38(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x38
}

_declspec(naked) void SysCall_3C(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x3C
}

_declspec(naked) void SysCall_40(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x40
}
_declspec(naked) void SysCall_44(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x44
}

_declspec(naked) void SysCall_48(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x48
}

_declspec(naked) void SysCall_4C(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x4C
}

_declspec(naked) void SysCall_50(void)
{
	__asm lea	edx, [esp+4]
	__asm int	0x2E
	__asm ret	0x50
}

const void * SysCall_Stub [] =
{
	SysCall_00,
	SysCall_04,
	SysCall_08,
	SysCall_0C,

	SysCall_10,
	SysCall_14,
	SysCall_18,
	SysCall_1C,

	SysCall_20,
	SysCall_24,
	SysCall_28,
	SysCall_2C,

	SysCall_30,
	SysCall_34,
	SysCall_38,
	SysCall_3C,

	SysCall_40,
	SysCall_44,
	SysCall_48,
	SysCall_4C,
	
	SysCall_50
};


int KFuncTable::InterceptSysCall(void)
{
	int no = 0;

	for (int i=0; i<m_funcno; i++)
        if ( (m_func[i].f_kind==FUNC_SYSCALL) && !m_func[i].f_hooked )
        {            
			unsigned char * p = (unsigned char *) m_func[i].f_oldaddress;

			// B8 DB 10 00 00     mov         eax,10DBh
			// 8D 54 24 04        lea         edx,[esp+4]
			// CD 2E              int         2Eh
			// C3                 ret

			// verify that the destination follows a system call pattern
			if ( ! IsBadReadPtr(p, 12) )
			if ( (p[0]==0xB8) && 
				 (p[5]==0x8D) && (p[6]==0x54) && (p[7]==0x24) && (p[8]==0x04) &&
				 (p[9]==0xCD) && (p[10]==0x2E) )
            {
				// let ProxyProlog return control to our SysCall_xx routines
				// f_parano counts return type, so decrease by 1
				m_func[i].f_oldaddress = (FARPROC) SysCall_Stub[m_func[i].f_parano-1];

				unsigned char Link[6];

				            Link[0] = 0xE9;
			* (unsigned *) (Link+1)	= (unsigned) m_func[i].f_newaddress() - 
									  (unsigned) ( p +10);
							Link[5] = 0x90;

				HackCopy(p+5, Link, 6);

                m_func[i].f_hooked = TRUE;
                no ++;
            }

        }

	return no;
}


int KFuncTable::InterceptCom(void)
{
    int no = 0;
    
    for (int i=0; i<m_funcno; i++)
        if ( (m_func[i].f_kind==FUNC_COMMETHOD) && !m_func[i].f_hooked )
        {            
            if ( HackMethod(VTable(m_func[i].f_module), 
				            m_func[i].f_methodid, 
							m_func[i].f_newaddress()) )
            {
                m_func[i].f_hooked = TRUE;
                no ++;
            }

        }

    return no;
}


int KFuncTable::InterceptWin32(const char        *Caller,
                               const char        *Callee,
                               PIMAGE_THUNK_DATA  pName,
                               PIMAGE_THUNK_DATA  pThunk,
                               const char        *baseAddress)
{
    int no = 0;
    
    // if module not added to module table, quit
    if (LookupModule(Caller, Callee) == -1)
        return 0;

    
    while ( pThunk->u1.Function )
    {
        int id;

        PBYTE   pFunctionName        = (PBYTE) ( baseAddress + (unsigned) pName->u1.ForwarderString + 2);
        FARPROC pInterceptedFunction = LookupInterceptedAPI((FARPROC) pThunk->u1.Function, id);

        if ( pInterceptedFunction )
			if ( HackCopy(& pThunk->u1.Function, & pInterceptedFunction, sizeof(FARPROC)) )
			{
				m_func[id].f_hooked = TRUE;
				no ++;
			}	
            
        pName ++;
        pThunk++;
    }

    return no;
}


int KFuncTable::InterceptWin32(const char *ModuleName, const char * baseAddress)
{
	int no = 0;

    PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) baseAddress;
    
    if ( IsBadReadPtr(baseAddress, sizeof(PIMAGE_NT_HEADERS)) )
        return 0;
    
    if ( pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE )
        return 0;

    PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS) ( baseAddress + pDOSHeader->e_lfanew);
    if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
        return 0;
    
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 
		(PIMAGE_IMPORT_DESCRIPTOR) ( baseAddress + 
		pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress );
                        
    // Bail out if the RVA of the imports section is 0 (it doesn't exist)
    if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR) pNTHeader )
        return 0;

    while ( pImportDesc->Name )
    {
        no += InterceptWin32(ModuleName,
                             (const char *) ( baseAddress + pImportDesc->Name ),
                             (PIMAGE_THUNK_DATA) ( baseAddress + (unsigned) pImportDesc->OriginalFirstThunk),
                             (PIMAGE_THUNK_DATA) ( baseAddress + (unsigned) pImportDesc->FirstThunk),
                             baseAddress);
        pImportDesc++;
    }
    
    return no;
}


KPatcher directpatcher;

int KFuncTable::InterceptWin32(void)
{
    int no = 0;

//	DebugBreak();

    for (int i=0; i<m_funcno; i++)
        if ( (m_func[i].f_kind==FUNC_WIN32API) & !m_func[i].f_hooked )
        // if there is an unhooked win32 function
		{
			int module = m_func[i].f_module;

			// if caller and callee are the same module, patch function target
			if ( strcmp(CallerName(module), CalleeName(module))==0 )
			{
				if ( directpatcher.Patch(ModHandle(module), GetFuncName(i), 
										 i, ProxyProlog,
										 (unsigned long *) &  m_func[i].f_oldaddress) )
					no ++;
			}
			else
			{
				const char *caller  = CallerName(module);
				const char *address = (const char *) ModHandle(module);

				// if caller module is loaded into current process, hack in it.
				if (address)
					no += InterceptWin32(caller, address);
			}
		}

    return no;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -