《Windows图形编程》的pe文件类的实现代码:
#include "StdAfx.h"
#include "KPEFile.h"KPEFile::KPEFile(HMODULE hModule)
{
m_pModule = (LPBYTE)hModule;
if (::IsBadReadPtr(m_pModule,sizeof(IMAGE_DOS_HEADER)))
{
m_pDosHeader = NULL;
m_pNTHeader = NULL;
}
else
{
m_pDosHeader = (PIMAGE_DOS_HEADER)m_pModule;
if (::IsBadReadPtr(RVA2Ptr(m_pDosHeader->e_lfanew),sizeof(IMAGE_NT_HEADERS)))
{
m_pNTHeader = NULL;
}
else
m_pNTHeader = (PIMAGE_NT_HEADERS)RVA2Ptr(m_pDosHeader->e_lfanew); }
}KPEFile::~KPEFile(void)
{
}const void* KPEFile::GetDirectory( int id )
{
return RVA2Ptr(m_pNTHeader->OptionalHeader.DataDirectory[id].VirtualAddress);
}PIMAGE_IMPORT_DESCRIPTOR KPEFile::GetImportDescriptor( LPTSTR pDllName )
{
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)GetDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT);
if (pImport==NULL)
return NULL; while (pImport->FirstThunk)
{ LPCSTR szDllName = static_cast<LPCSTR>(RVA2Ptr(pImport->Name));
TCHAR szwszDllName[MAX_PATH];
::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szDllName,-1,szwszDllName,MAX_PATH); if (_tcsicmp(pDllName,szwszDllName)==0)
{
return pImport;
} pImport++;
}
return NULL;
}const unsigned long* KPEFile::GetFunctionPtr( PIMAGE_IMPORT_DESCRIPTOR pImport,LPTSTR pProcName )
{
PIMAGE_THUNK_DATA32 pThunk;
pThunk = (PIMAGE_THUNK_DATA32)RVA2Ptr(pImport->OriginalFirstThunk);
// pThunk = (PIMAGE_THUNK_DATA32)RVA2Ptr(pImport->FirstThunk);
for (int i = 0;pThunk->u1.Function;i++)
{
bool match;
if (pThunk->u1.Ordinal&IMAGE_ORDINAL_FLAG32)
{
match = ((pThunk->u1.Ordinal&0xFFFF)==((DWORD)pProcName));
}
else
{
// LPCSTR szFunctionName = static_cast<LPCSTR>(RVA2Ptr((unsigned long)pThunk->u1.AddressOfData));
PIMAGE_IMPORT_BY_NAME pFuncName =static_cast<PIMAGE_IMPORT_BY_NAME>(RVA2Ptr((unsigned long)pThunk->u1.AddressOfData));
TCHAR szwFunctionName[MAX_PATH];
::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,reinterpret_cast<LPCSTR>(pFuncName->Name),-1,szwFunctionName,MAX_PATH);
match = ((_tcsicmp(pProcName,szwFunctionName))==0);
} if (match)
return (unsigned long*)RVA2Ptr(pImport->FirstThunk)+i; pThunk++;
} return NULL;
}FARPROC KPEFile::SetImportAddress( LPTSTR pDllName,LPTSTR pProcName,FARPROC pNewProc )
{
PIMAGE_IMPORT_DESCRIPTOR pImport = GetImportDescriptor(pDllName);
if (NULL!=pImport)
{
const unsigned long* pfn = GetFunctionPtr(pImport,pProcName);
if(::IsBadReadPtr(pfn,sizeof(DWORD)))
return NULL; // 读取原来的地址
FARPROC oldproc = (FARPROC)*pfn;
DWORD dwWritten; BOOL bRet = WriteProcessMemory(GetCurrentProcess(),(void*)pfn,&pNewProc,sizeof(DWORD),&dwWritten);
return oldproc;
}
else
return NULL;
}FARPROC KPEFile::SetExportAddress( LPTSTR pProcName,FARPROC pNewProc )
{
PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)GetDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT); if (NULL==pExport)
return NULL; unsigned ord =0;
if ((unsigned)pProcName<0xFFFF) //ordinal
{
ord = (unsigned)pProcName;
}
else
{
const DWORD* pNames = (const DWORD*)RVA2Ptr(pExport->AddressOfNames);
const WORD *pOrds = (const WORD*)RVA2Ptr(pExport->AddressOfNameOrdinals); for (unsigned i =0;i<pExport->AddressOfNames;i++)
{
if(_tcsicmp(pProcName,static_cast<TCHAR*>(RVA2Ptr(pNames[i])))==0)
{
ord = pExport->Base + pOrds[i];
break;
}
}
} if ((ord<pExport->Base)||(ord>pExport->NumberOfFunctions))
return NULL; DWORD dwWritten = 0;
DWORD *pRVA = (DWORD*)RVA2Ptr(pExport->AddressOfFunctions)+ord-pExport->Base;
DWORD rslt = *pRVA;
DWORD newRVA = (DWORD)pNewProc-(DWORD)m_pModule;
WriteProcessMemory(GetCurrentProcess(),pRVA,&newRVA,sizeof(DWORD),&dwWritten); return (FARPROC)RVA2Ptr(rslt);
}
外部调用这个类的接口的代码:
int WINAPI MyMessageBox(HWND hWnd,LPCTSTR pText,LPCTSTR pCaption,UINT nType)
{
TCHAR szText[MAX_PATH];
TCHAR szCaption[MAX_PATH];
_tcscat(szText,_T("intercepted"));
_tcscat(szCaption,_T("intercepted"));
return ::MessageBox(hWnd,pText,pCaption,nType);
}int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 KPEFile pe(hInstance);
pe.SetImportAddress(_T("user32.dll"),_T("MessageBoxW"),(FARPROC)MyMessageBox);
::MessageBox(NULL,_T("Test"),_T("SetImportaddress"),MB_OK); return 0;
}
这个程序要实现的功能是将该进程导入的user32.dll中的MessageBoxW函数动态替换为我编写的MyMessageBox,程序编译环境为VS C++2005,unicode字符集。经过调试进入 KPEFile::SetImportAddress后能找到MessageBoxW函数的地址,WriteProcessMemory函数的返回值也是正确的,但是运行完::MessageBox(NULL,_T("Test"),_T("SetImportaddress"),MB_OK);这一步后却出现写入冲突,错误图片如下:
#include "StdAfx.h"
#include "KPEFile.h"KPEFile::KPEFile(HMODULE hModule)
{
m_pModule = (LPBYTE)hModule;
if (::IsBadReadPtr(m_pModule,sizeof(IMAGE_DOS_HEADER)))
{
m_pDosHeader = NULL;
m_pNTHeader = NULL;
}
else
{
m_pDosHeader = (PIMAGE_DOS_HEADER)m_pModule;
if (::IsBadReadPtr(RVA2Ptr(m_pDosHeader->e_lfanew),sizeof(IMAGE_NT_HEADERS)))
{
m_pNTHeader = NULL;
}
else
m_pNTHeader = (PIMAGE_NT_HEADERS)RVA2Ptr(m_pDosHeader->e_lfanew); }
}KPEFile::~KPEFile(void)
{
}const void* KPEFile::GetDirectory( int id )
{
return RVA2Ptr(m_pNTHeader->OptionalHeader.DataDirectory[id].VirtualAddress);
}PIMAGE_IMPORT_DESCRIPTOR KPEFile::GetImportDescriptor( LPTSTR pDllName )
{
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)GetDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT);
if (pImport==NULL)
return NULL; while (pImport->FirstThunk)
{ LPCSTR szDllName = static_cast<LPCSTR>(RVA2Ptr(pImport->Name));
TCHAR szwszDllName[MAX_PATH];
::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szDllName,-1,szwszDllName,MAX_PATH); if (_tcsicmp(pDllName,szwszDllName)==0)
{
return pImport;
} pImport++;
}
return NULL;
}const unsigned long* KPEFile::GetFunctionPtr( PIMAGE_IMPORT_DESCRIPTOR pImport,LPTSTR pProcName )
{
PIMAGE_THUNK_DATA32 pThunk;
pThunk = (PIMAGE_THUNK_DATA32)RVA2Ptr(pImport->OriginalFirstThunk);
// pThunk = (PIMAGE_THUNK_DATA32)RVA2Ptr(pImport->FirstThunk);
for (int i = 0;pThunk->u1.Function;i++)
{
bool match;
if (pThunk->u1.Ordinal&IMAGE_ORDINAL_FLAG32)
{
match = ((pThunk->u1.Ordinal&0xFFFF)==((DWORD)pProcName));
}
else
{
// LPCSTR szFunctionName = static_cast<LPCSTR>(RVA2Ptr((unsigned long)pThunk->u1.AddressOfData));
PIMAGE_IMPORT_BY_NAME pFuncName =static_cast<PIMAGE_IMPORT_BY_NAME>(RVA2Ptr((unsigned long)pThunk->u1.AddressOfData));
TCHAR szwFunctionName[MAX_PATH];
::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,reinterpret_cast<LPCSTR>(pFuncName->Name),-1,szwFunctionName,MAX_PATH);
match = ((_tcsicmp(pProcName,szwFunctionName))==0);
} if (match)
return (unsigned long*)RVA2Ptr(pImport->FirstThunk)+i; pThunk++;
} return NULL;
}FARPROC KPEFile::SetImportAddress( LPTSTR pDllName,LPTSTR pProcName,FARPROC pNewProc )
{
PIMAGE_IMPORT_DESCRIPTOR pImport = GetImportDescriptor(pDllName);
if (NULL!=pImport)
{
const unsigned long* pfn = GetFunctionPtr(pImport,pProcName);
if(::IsBadReadPtr(pfn,sizeof(DWORD)))
return NULL; // 读取原来的地址
FARPROC oldproc = (FARPROC)*pfn;
DWORD dwWritten; BOOL bRet = WriteProcessMemory(GetCurrentProcess(),(void*)pfn,&pNewProc,sizeof(DWORD),&dwWritten);
return oldproc;
}
else
return NULL;
}FARPROC KPEFile::SetExportAddress( LPTSTR pProcName,FARPROC pNewProc )
{
PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)GetDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT); if (NULL==pExport)
return NULL; unsigned ord =0;
if ((unsigned)pProcName<0xFFFF) //ordinal
{
ord = (unsigned)pProcName;
}
else
{
const DWORD* pNames = (const DWORD*)RVA2Ptr(pExport->AddressOfNames);
const WORD *pOrds = (const WORD*)RVA2Ptr(pExport->AddressOfNameOrdinals); for (unsigned i =0;i<pExport->AddressOfNames;i++)
{
if(_tcsicmp(pProcName,static_cast<TCHAR*>(RVA2Ptr(pNames[i])))==0)
{
ord = pExport->Base + pOrds[i];
break;
}
}
} if ((ord<pExport->Base)||(ord>pExport->NumberOfFunctions))
return NULL; DWORD dwWritten = 0;
DWORD *pRVA = (DWORD*)RVA2Ptr(pExport->AddressOfFunctions)+ord-pExport->Base;
DWORD rslt = *pRVA;
DWORD newRVA = (DWORD)pNewProc-(DWORD)m_pModule;
WriteProcessMemory(GetCurrentProcess(),pRVA,&newRVA,sizeof(DWORD),&dwWritten); return (FARPROC)RVA2Ptr(rslt);
}
外部调用这个类的接口的代码:
int WINAPI MyMessageBox(HWND hWnd,LPCTSTR pText,LPCTSTR pCaption,UINT nType)
{
TCHAR szText[MAX_PATH];
TCHAR szCaption[MAX_PATH];
_tcscat(szText,_T("intercepted"));
_tcscat(szCaption,_T("intercepted"));
return ::MessageBox(hWnd,pText,pCaption,nType);
}int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 KPEFile pe(hInstance);
pe.SetImportAddress(_T("user32.dll"),_T("MessageBoxW"),(FARPROC)MyMessageBox);
::MessageBox(NULL,_T("Test"),_T("SetImportaddress"),MB_OK); return 0;
}
这个程序要实现的功能是将该进程导入的user32.dll中的MessageBoxW函数动态替换为我编写的MyMessageBox,程序编译环境为VS C++2005,unicode字符集。经过调试进入 KPEFile::SetImportAddress后能找到MessageBoxW函数的地址,WriteProcessMemory函数的返回值也是正确的,但是运行完::MessageBox(NULL,_T("Test"),_T("SetImportaddress"),MB_OK);这一步后却出现写入冲突,错误图片如下:
解决方案 »
- 有用过win2003-64bit+vs2005+sql2005的吗?
- 求类似csdn的国外技术网站
- 知道应用程序名,怎样判断其进程是否存在?
- 散分,我怕谁
- DirectSound播放多路声音流时出现声音的断续!
- 如何让父窗口来处理子窗口的消息
- 如何用MFC做一个demo,显示树。急急急!
- 神啊! 救救我吧
- Visual Studio 6.0 Service Pack 4在什么地方可以下载,有多大?
- 关于图象文件保存格式问题,求教高手???
- 添加消息响应函数时的出错
- 运行《windows程序设计98》(Petzold)书中第四章的程序SYSMETS1.C出现错误提示:SM_MOUSEWHEELPRESENT'
MyMessageBox自己调用自己,估计是栈溢出了,楼主可以调试一下,看MyMessageBox被调用了多少层