BOOL WriteProcessMemory( HANDLE hProcess, // handle to process whose memory is written to LPVOID lpBaseAddress, // address to start writing to VirtualAllocEx分配了内存返回的 LPVOID lpBuffer, // pointer to buffer to write data to 你的函数地址 DWORD nSize, // number of bytes to write LPDWORD lpNumberOfBytesWritten // actual number of bytes written );有些人在函数后面加一个没用的函数用来计算大小, 这种方法必须工程全部重新编译才正确大小一般是自己估计, 大些没关系
先分清楚是哪种!改exe, 用IDA, hiew 手动改, 新函数超出原函数大小就比较麻烦, 需要新建段, 或者用空余动态改代码
VirtualAllocEx 分配内存, Write代码过去
在原函数的头改成一个Jmp 指令, jmp偏移根据当前地址 和VirtualAllocEx 得到的地址计算出来
不用改动原文件本身如果改动原文件本身,如果原文件更新了,原文件可能就废了,假设这是个网络游戏Hook DLL只要再改变地址
用注入DLL的方式,可以直接修改输入地址表里Thunk保存的函数地址exe文件没有地址表保存函数地址知道原函数地址的情况下,除了用汇编reject外,还有办法把这个函数替换成我自己的函数吗?就像改输入表里的函数一样
里面的函数处理跟你的要求很相似,你可以下载源代码看看.
最后一个问题
VirtualAllocEx分配了内存后,怎么才能把我的函数write进这个地址?
在高级语言里,不是reject
HANDLE hProcess, // handle to process whose memory is written to
LPVOID lpBaseAddress,
// address to start writing to VirtualAllocEx分配了内存返回的
LPVOID lpBuffer, // pointer to buffer to write data to 你的函数地址
DWORD nSize, // number of bytes to write
LPDWORD lpNumberOfBytesWritten
// actual number of bytes written
);有些人在函数后面加一个没用的函数用来计算大小, 这种方法必须工程全部重新编译才正确大小一般是自己估计, 大些没关系
{
_asm
{
pushad
}
//定义参数
_asm
{
//读出参数
}
DWORD dCallAddress = 0x5c8340;
::AfxMessageBox("OK");
_asm
{
popad
call dCallAddress
}
} pAddress = VirtualAlloc(NULL, nSize, MEM_RESERVE|MEM_TOP_DOWN|MEM_COMMIT , PAGE_READWRITE );
if( NULL == pAddress)
return FALSE;
itoa((DWORD)pAddress, szAddress, 16);
//这里函数地址的写法有问题吗?写进去的内容不是我想要的
if(FALSE == WriteProcessMemory(hSoul,pAddress, HookDisplay, nSize, NULL))
return FALSE;
::AfxMessageBox(szAddress); return TRUE;
{
PBYTE pCode;
DWORD dwAddress = 0;
DWORD dwOffset;
pCode = (PBYTE)pFun;
if (pCode == NULL)
{
return NULL;
} dwAddress = (DWORD)pFun;
if(pCode[0] == 0xFF && pCode[1] == 0x25) // jmp [+imm32]
{
dwOffset = *(DWORD *)*(DWORD *)(&pCode[1]);
dwAddress = (DWORD)pCode + 5 + dwOffset;
}
else if(pCode[0] == 0xE9) // jmp +imm32
{
dwOffset = *(DWORD *)(&pCode[1]);
dwAddress = (DWORD)pCode + 5 + dwOffset;
}
else if(pCode[0] == 0xEB) // jmps (short)
{
} return dwAddress;
}
建议楼主还是务实点,从路边旧书摊上面随便买本关于windows编程的书瞅上几眼.
windows程序设计,windows核心编程,黑客反汇编,win32汇编,加密与解密第二版
我看了这些
请问还要再看什么?
你觉得这是入门?那你给我个答案,不用汇编改原文件,给我个答案,这100分给yofoo,再送你200分
可以用了
过一会我就结贴
能不能跟我讲讲原理?
或者推荐我看个贴子
为什么我把原exe文件的call
替换成我分配后的地址然后call
跑不到我的地址,直接跳到异常处理程序了
是分配空间位置问题么?还是访问权限问题?还是作用域问题?还是
//-----------------------------ULHook.h-------------------------------//
// Write by Sunline 2003.04, [email protected]#ifndef __ULHOOKM__H_
#define __ULHOOKM__H_
#include "windows.h"
/*典型的代码替换法API Hook
经典的代码替换法API Hook过程中如果要实现原来API的功能的时候要将改写的部分还原,再调用,在多线程中可能存在线程切换时的错误
改进的办法是将原API头部的适当长度的代码保存为一个buffer,需要原API功能时,调用这个buffer,
例:
原来Messagebox: 修改后: Messagebox: myMsg: ProceHead:
8BFF mov edi,edi E9xxxxxxxx jmp myMsg ... 8BFF mov edi,edi
55 push ebp 55 push ebp
8BEC mov ebp,esp 8BEC mov ebp,esp
(theNcode): E9xxxxxxxx jmp theNcode
833D1C04D77700 cmp [77D7041Ch],0 833D1C04D77700 cmp [77D7041Ch],0
...
力求克服代码替换法的不足
*/
class CULHook
{
public:
CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnNew);
CULHook(PROC pfnOrig, PROC pfnNew);
virtual ~CULHook();
public:
bool Hook(bool bHook);
PROC OrigFunc(void);
PROC operator()();
private:
int GetOpLen(unsigned char *buffer, int buflen);
protected:
byte m_bProcHead[32];
PROC m_pfnOrig; //目标API函数的地址
PROC m_pfnNew; //替代函数地址
BYTE m_bNewHead[5]; //新构建的5个字节
HMODULE m_hModule;
};#endif //__ULHOOKM__H_
//-----------------------------ULHook.h-------------------------------//
// Write by Sunline 2003.04, [email protected]#ifndef __ULHOOKM__H_
#define __ULHOOKM__H_
#include "windows.h"
/*典型的代码替换法API Hook
经典的代码替换法API Hook过程中如果要实现原来API的功能的时候要将改写的部分还原,再调用,在多线程中可能存在线程切换时的错误
改进的办法是将原API头部的适当长度的代码保存为一个buffer,需要原API功能时,调用这个buffer,
例:
原来Messagebox: 修改后: Messagebox: myMsg: ProceHead:
8BFF mov edi,edi E9xxxxxxxx jmp myMsg ... 8BFF mov edi,edi
55 push ebp 55 push ebp
8BEC mov ebp,esp 8BEC mov ebp,esp
(theNcode): E9xxxxxxxx jmp theNcode
833D1C04D77700 cmp [77D7041Ch],0 833D1C04D77700 cmp [77D7041Ch],0
...
力求克服代码替换法的不足
*/
class CULHook
{
public:
CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnNew);
CULHook(PROC pfnOrig, PROC pfnNew);
virtual ~CULHook();
public:
bool Hook(bool bHook);
PROC OrigFunc(void);
PROC operator()();
private:
int GetOpLen(unsigned char *buffer, int buflen);
protected:
byte m_bProcHead[32];
PROC m_pfnOrig; //目标API函数的地址
PROC m_pfnNew; //替代函数地址
BYTE m_bNewHead[5]; //新构建的5个字节
HMODULE m_hModule;
};#endif //__ULHOOKM__H_
// 改进的代码替换法Hook。
#include "ULHook.h"CULHook::CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnNew)
{
m_hModule = ::LoadLibrary(pszModName);
m_pfnOrig = ::GetProcAddress(m_hModule, pszFuncName);
m_pfnNew = pfnNew;
//构建jmp xxxxxxxx
m_bNewHead[0] = 0xE9;
*(DWORD *)(m_bNewHead + 1) = (DWORD)( 0 - sizeof(m_bNewHead) + (unsigned int )m_pfnNew - (unsigned int )m_pfnOrig);//offset = desAddr - nextOPAddr
for(int i = sizeof(m_bProcHead)-1; i>=0; i--) m_bProcHead[i] = 0x90;
}CULHook::CULHook(PROC pfnOrig, PROC pfnNew)
{
m_hModule = NULL;
m_pfnOrig = pfnOrig;
m_pfnNew = pfnNew;
m_bNewHead[0] = 0xE9;
*(PDWORD)(m_bNewHead + 1) = (DWORD)( 0 - sizeof(m_bNewHead) + (unsigned int )m_pfnNew - (unsigned int )m_pfnOrig);
for(int i = sizeof(m_bProcHead)-1; i >= 0; i--) m_bProcHead[i] = 0x90;
}CULHook::~CULHook()
{
Hook(FALSE);
if(m_hModule != NULL) ::FreeLibrary(m_hModule);
}bool CULHook::Hook(bool bHook)
{
if(m_pfnOrig != NULL && m_pfnNew != NULL) //原函数和新的函数地址均有效
{
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION memInfo;
::VirtualQuery(m_pfnOrig,&memInfo,sizeof(memInfo));
if((memInfo.State == MEM_COMMIT) && (memInfo.Protect != PAGE_NOACCESS)) //目标函数在内存中
{
if(bHook) //hook the Api
{
unsigned char* p = (unsigned char *)m_pfnOrig;
int length = 0;
int offset = 0;
do
{
offset = GetOpLen(p, 20);
length += offset;
p += offset;
}while((length < sizeof(m_bNewHead)) && (offset != 0) );
if(length < sizeof(m_bNewHead))
{
return false; //原函数的头部不适合用jmp dword ptr[xxxxxxx]代换
}
::VirtualProtect(m_pfnOrig, length, PAGE_READWRITE, &dwOldProtect);
//保存原来的执行代码,并构建供OrigFunc使用的执行代码头
memcpy(m_bProcHead, m_pfnOrig, length);
m_bProcHead[length] = 0xE9; //在尾部跳到原代码的执行部份
*(DWORD *)(1 + length + m_bProcHead)= (DWORD)((unsigned int)m_pfnOrig + length -((unsigned int)&m_bProcHead + length + sizeof(m_bNewHead)));
//改写成新的执行代码
::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, m_bNewHead, sizeof(m_bNewHead), NULL);
::VirtualProtect(m_pfnOrig, length, memInfo.Protect, 0);
return true;
}
else //unHook the Api
{
::VirtualProtect(m_pfnOrig, sizeof(m_bNewHead), PAGE_READWRITE, &dwOldProtect);
if(memcmp(m_pfnOrig, m_bNewHead, sizeof(m_bNewHead)) == 0)
{ //写入原来的函数头
::WriteProcessMemory(::GetCurrentProcess(),(void *)m_pfnOrig,m_bProcHead, sizeof(m_bNewHead), NULL);
::VirtualProtect(m_pfnOrig, sizeof(m_bNewHead), memInfo.Protect, 0);
return true;
}
::VirtualProtect(m_pfnOrig, sizeof(m_bNewHead), memInfo.Protect, 0);
return false;
}
}
}
return false;
}PROC CULHook::OrigFunc()
{
return (PROC)&m_bProcHead[0];
}PROC CULHook::operator()()
{
return (PROC)&m_bProcHead[0];
}
extern byte LenTab[];
extern byte _FFTab[];
extern byte _0FTab[];
/*
这个函数仅用于反汇编一个机器代码的长度
比如"\x6A\x00\x68\x00\x30\x40\x00\xC3\xFF\x25\x00\x20\x40\x00";
6A00 push 0 //返回 2
6800304000 push 00403000 //返回 5
C3 ret //返回 1
FF2500204000 jmp DWORD ptr 00402000 //返回 6
*/int CULHook::GetOpLen(unsigned char *data, int buflen)
{
int length = 0;
int asize = 0;
int wsize = 0;
//Scan for prefixes.
for (;;) {
if (*data == 0xF3 || *data == 0xF2 || *data == 0xF0 ||
*data == 0x2E || *data == 0x36 || *data == 0x3E ||
*data == 0x26 || *data == 0x64 || *data == 0x65)
{
length++;
data++;
}
else if (*data == 0x66 || *data == 0x67)
{
asize = 2;
data++;
length++;
}
else
break;
}
//Scan for opration code
switch(*data)
{
case 0x0F:
data++;
length += _FFTab[*data];
break;
case 0xFF:
data++;
length += _0FTab[*data];
break;
default:
length += LenTab[*data];
}
length++;
if(LenTab[*data] == (byte)-1)
{
return 0;
}
return length - wsize * asize;
}
byte _0FTab[] =
{// MOV 0F20 0F21 0F22 0F23
//
/*
0 1 2 3 4 5 6 7 8 9 A B C D E F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//0
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//1
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//2
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//3
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//4
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//5
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//6
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//7
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//8
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//9
0, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1,//A
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//B
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//C
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//D
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//E
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//F
};
byte _FFTab[] =
{/*
0 1 2 3 4 5 6 7 8 9 A B C D E F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//0
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//1
-1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//2
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//3
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//4
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//5
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//6
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//7
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//8
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//9
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//A
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//B
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//C
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//D
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//E
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//F
};byte LenTab[] =
{//the table will list the instruct:
// mov: C6, C7, 88, 89, 8A, 8B, 8C, 8D, 8E,
// A0, A1, A2, A3,
//NOT RID 0F20, 0F21, 0F22, 0F23, it's operate on CR0-CR7
// push: 06, 16, 1E, 50, 6A, 68, 0FA0, 0FA8
// pushad: 60
// popad: 61
// cmp: 38, 39, 3A, 3B, 3C, 3D, 80, 81, 83
// Jump DWORD ptr [absolute]:
// call DWORD ptr [absolute]:
/*
0 1 2 3 4 5 6 7 8 9 A B C D E F */
-1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1,//0
-1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1,//1
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//2
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 4, -1, -1,//3
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//4
0, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//5
0, 0, -1, -1, -1, -1, -1, -1, 4, -1, 1, -1, -1, -1, -1, -1,//6
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//7
2, 5, 2, 2, -1, -1, -1, -1, 1, 1, 1, 1, 5, 5, 5, -1,//8
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//9
4, 4, 4, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//A
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//B
-1, -1, -1, -1, -1, -1, 2, 5, -1, -1, -1, -1, -1, -1, -1, -1,//C
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//D
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//E
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,//F
};