请问下大家,关于HOOK API函数时需要改变页面文件属性的有关问题

请教下大家,关于HOOK API函数时需要改变页面文件属性的问题!
最近在学HOOK,于是在网上COPY了一些代码,但发现很多都不能编译通过的`
今天在看雪上看到 小扫地僧 的代码,COPY下来编译了个DLL,是HOOOK MessageBox函数的,然后注入了自己的测试程序,发现能HOOK成功。
于是把代码改了下,想把它弄成HOOK SEND 函数的。
但是注入程序的时候,能把那个SEDN HOOK ,但是程序会崩溃。下面是代码,请大家指点下!
#include <windows.h>
#define HookModName "wsock32.dll" //HOOK的模块和API
#define HookApiName "send"

//修改API入口为 mov eax, 00400000;jmp eax是程序能跳转到自己的函数
BYTE g_btNewBytes[8] = { 0xB8, 0x0, 0x0, 0x40, 0x0, 0xFF, 0xE0, 0x0 };
//保存原API入口的8个字节
DWORD g_dwOldBytes[8] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
//API地址
void * m_AddrAPI;
//定义自己的API,参数表和原函数一致,MyHookAPI中调用的也一样
int WINAPI MyHookAPI(SOCKET, const char FAR *, int , int);
typedef int(*PFunSend)( SOCKET, const char FAR *, int , int); // send 函数指针
PFunSend pSend;
BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
  if(ul_reason_for_call==DLL_PROCESS_ATTACH)  
  {
  //找到API地址
::MessageBox(0,"sdfdsf",0,0);//这句是为了方便的知道,DLL是不是成功的被加载了。。
  HMODULE hWsock = LoadLibrary(HookModName);
  m_AddrAPI = (void *)GetProcAddress( hWsock,HookApiName);
  //保存原始字节

  ReadProcessMemory(INVALID_HANDLE_VALUE,m_AddrAPI, ( void * )g_dwOldBytes, sizeof( DWORD )*2, NULL );
  //将00400000替换为我们函数的地址
  *( DWORD* )( g_btNewBytes + 1 ) = ( DWORD )MyHookAPI;
  //改写API跳向MyHookAPI
DWORD dwOldProc;
  DWORD dwNewProc;
VirtualProtectEx(INVALID_HANDLE_VALUE,m_AddrAPI,sizeof( DWORD )*2,PAGE_READWRITE,&dwOldProc);
  WriteProcessMemory( INVALID_HANDLE_VALUE,m_AddrAPI,( void * )g_btNewBytes, sizeof( DWORD )*2, NULL ); 
  VirtualProtectEx(INVALID_HANDLE_VALUE,m_AddrAPI,sizeof( DWORD )*2,dwOldProc, &dwNewProc );
  }
  
  return TRUE;
}
int _stdcall MyHookAPI(SOCKET s, const char FAR *buf, int len, int flags)
{ int Ret;
DWORD dwOldProc;
  DWORD dwNewProc;
//恢复指令
VirtualProtectEx(INVALID_HANDLE_VALUE,m_AddrAPI,sizeof( DWORD )*2,PAGE_READWRITE,&dwOldProc);//看到网上的大能说要修改页面属性,于是我把这句代码加了进去。但是被注入的程序还是崩溃。
WriteProcessMemory( INVALID_HANDLE_VALUE,m_AddrAPI,( void * )g_dwOldBytes, sizeof( DWORD )*2, NULL );
VirtualProtectEx(INVALID_HANDLE_VALUE,m_AddrAPI,sizeof( DWORD )*2,dwOldProc, &dwNewProc );
//调用
::MessageBox(0,"HOOK了",0,0);//SEND函数入口被修改了,就弹出个窗口。问题在这里,当被注入的程序调用了SEND函数的时候,是弹出了这个窗口。接着程序就马上崩溃了。提示某个指令地址引用的内存地址不能read.
Ret=pSend(s, buf, len, flags );
VirtualProtectEx(INVALID_HANDLE_VALUE,m_AddrAPI,sizeof( DWORD )*2,PAGE_READWRITE,&dwOldProc);
//重新改写,为下次调用
WriteProcessMemory( INVALID_HANDLE_VALUE,m_AddrAPI,( void * )g_btNewBytes, sizeof( DWORD )*2, NULL );
VirtualProtectEx(INVALID_HANDLE_VALUE,m_AddrAPI,sizeof( DWORD )*2,dwOldProc, &dwNewProc );
return Ret;
}

------解决方案--------------------
你先不看,直接用看行不行,我给的接口还是很简单的