班门弄斧一次VC++.NET 2008写的HOOK RECV代码

学习资料:

 

班门弄斧一次VC++.NET 2008写的HOOK RECV代码

 

确实是班门弄斧,因为我是学VB的,虽然VB6和.NET都算入门吧,可真正拿VC++写程序还是第一次。学B/C/D的就莫看了。

由于是用上两篇写的远线程调用,所以很多参数等等都是传入的,而不是直接获取的。

 

下面就一个用VB的人能理解为目标做简单说明和注释:

1、VC里面声明变量和VB不一样:类型在前,名称在后,例如:

BYTE B ;

等同于:

dim B as byte

VC用分号来识别行结束,而VB用回车;VB用圆括号表示数组,VC用方括号……不多说了,我也不是很清楚,总之习惯就好

2、VC里面的函数、变量等等区分大小写,VB不区分,这个一定要注意!

3、类型转换:VB有显式或隐式的,而VC必须用显式的——即时内存里面存的就是那个东东你也不能直接拿来用,够严格,不过指针够灵活也够太灵活……转换时使用的方法就是在圆括号里面写入你要的类型,后面跟着你的参数就可以。例如:

(DWORD)LEN;就是把LEN转换成DWORD类型,据我理解要么是UINTEGER,要么是INTEGER,可能不同API要求不同,我一直都是按INTEGER处理的,也就是说,前面那句相当于CTYPE(LEN,INTEGER)了。

4、&将会吧后面的变量变为指针,*将会把指针变成相应的数据……说的不确切,应该是转换吧

5、其他看看就知道了,VC用API、常数等根本不声明……而是导入.H文件吧(头文件,而且里面可以用宏来改变API书写的名称,就像VB声明API时那个别名吧),反正这个工程里没用到。

 

以上言论如有误导,请尽快指出………………以免造孽更深…………谢谢………………

 

 

//自定义APIHOOK结构

typedef struct

{

   FARPROC funcaddr;  //RECV函数所在地址

 BYTE   olddata[8];      //RECV函数开头的8个字节原始数据

 BYTE   newdata[8];    //我们要写入的数据,汇编代码在下面,利用了EAX存储要跳转的地址,并且FF E0这个操作是绝对地址的

}HOOKSTRUCT;

//0-4 : move eax 0x00000000 //绝对地址,避免了一个换算,其实这个换算也简单,ADDRESS-MFUNADDRESS-5即是

//5-7 : jmp eax

HWND _fHandle ;  //接收消息窗口句柄

DWORD _dwIdNew ;  //PID

HANDLE hProc;  //进程内核句柄,就是OPENPROCESS打开PID得到的那个东东——读写内存用到

DWORD _ws2_RecvIndex = 1 ;  //ws2_32.dll RECVHOOK标志,实际和HOOK没关系,但是当你HOOK的函数多起来,你得区分是哪个函数发来的消息啊!

HOOKSTRUCT _ws2_RecvHook; //ws2_32.dll HOOK结构

//这下面的这些家伙,就是一个定义,和下面写的函数实体一样声明即可,VB里不用这么干编译器也能识别都有哪些函数,可VC不成

int WINAPI m_ws2_recv(SOCKET s, char FAR*buf, int len, int flags);

void SendMsg(char *buf,DWORD len,DWORDIndex);

void HookOnOne(HOOKSTRUCT *hookfunc);

void HookOffOne(HOOKSTRUCT *hookfunc);

bool HOOKAPI(DWORD Address,HOOKSTRUCT*hookfunc,DWORD mFncAddress);

//下面传入了一些参数:被注入进程PID,要接收返回信息窗口的句柄

extern "C" _declspec(dllexport)void __stdcall Init(DWORD PID ,HWND FormHandle)

{

 AFX_MANAGE_STATE(AfxGetStaticModuleState());   //这个……VC里叫宏吧,哎……说来话长,这句去掉也无所谓的

 _dwIdNew = PID ;            //备份PID,其实后面代码没用到,主要是为了识别注入了多个程序的话,是哪个程序发回来的信息呢

 _fHandle = FormHandle ;  //接收消息的窗口句柄,SendMsg函数用到

 hProc = OpenProcess(PROCESS_ALL_ACCESS, 0,_dwIdNew);   //打开进程,进一步操作他

}

//下面这个用来:记录被HOOK函数前8字节原始数据、构建新的8字节代码、将新代码替换RECV函数原来代码的

//说明全部都是以RECV函数为例,其实这个函数是一个通用函数

bool HOOKAPI(DWORD Address,HOOKSTRUCT*hookfunc,DWORD mFncAddress)

{

 hookfunc->funcaddr = (FARPROC)Address;  //这个地方用了一个转换,把传入值转换成何结构当中声明的一样

   memcpy(hookfunc->olddata, hookfunc->funcaddr, 8); //记录RECV函数前8字节原始数据

 //下面开始构建汇编代码{0xB8,0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00 }

 hookfunc->newdata[0]=0xB8;   //MOVE EAX (EAX后面的数就是下面4字节了)

 hookfunc->newdata[1]=0x00;

 hookfunc->newdata[2]=0x00;

 hookfunc->newdata[3]=0x00;

 hookfunc->newdata[4]=0x00; //到这里是 MOVE EAX00000000 ,这里的地址,将会在下面被替换(注意是绝对地址)

 hookfunc->newdata[5]=0xFF;

 hookfunc->newdata[6]=0xE0;//到这里是 JMP EAX

 hookfunc->newdata[7]=0xCC;//填充一个INT3 ,其实NOP(&h90)啥的也行,换句话说这个不改、不理他都可以,不过翻看帖子时看到一些人说CPU识别错代码,谁知道真假,还是放个显眼的比较保险……

 memcpy(&hookfunc->newdata[1],&mFncAddress, 4);  //这里替换了上面提到的00000000 为我们用来代替RECV的函数的地址

 HookOnOne(hookfunc);  //将RECV函数前8字节替换为我们构建的代码——开始HOOK RECV

 returntrue;

}

 

 

//recv,这个函数将实现RECV函数的替换:只需执行一次即可

extern "C" _declspec(dllexport)bool __stdcall Hook_ws2_Recv(DWORD RecvAddress)

{

 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 HOOKAPI(RecvAddress,&_ws2_RecvHook,(DWORD)m_ws2_recv);//这里,(DWORD)m_ws2_recv的返回值就是m_ws2_recv函数的地址!你看人家VC多方便……

   return true;

}

//显然了,这个事解除RECV HOOK的

extern "C" _declspec(dllexport)bool __stdcall UnHook_ws2_Recv()

{

 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 HookOffOne(&_ws2_RecvHook);

   return true;

}

//---------------------------------------------------------------------------

//这个函数,就是我们用来替换RECV函数的家伙了,必须让这个家伙和RECV函数声明相同,这么相同呢,很简单,VC++.NET也有类似VB的代码提示(虽然少点),找一个适当的地方打上recv(小写)然后打圆括号……看到了?

int WINAPI m_ws2_recv(SOCKET s, char FAR*buf, int len, int flags)

{

   int nReturn = 0;  //这个家伙记录了RECV的返回值,-1为错误,我们不处理,0为断开,其他嘛,就是实际从SOCKET缓冲区复制了多少字节到RECV缓冲区。简单的说,-1,0都不处理,其他值就是我们要从BUF里面读多少字节了!

 HookOffOne(&_ws2_RecvHook); //先关闭HOOK,因为已经进入我们的函数了

   nReturn = recv(s, buf, len, flags); //先运行原来的RECV,否则我们不能得到或不能得到全部被复制的内容

 HookOnOne(&_ws2_RecvHook); //继续HOOK

 //sndmsg((DWORD)len,(DWORD)nReturn);

 if (nReturn == SOCKET_ERROR )

 return -1 ;

 

 SendMsg(buf ,nReturn,_ws2_RecvIndex); //发送BUF里面NRETURN个字节到接收窗体

 

   return(nReturn);

}

/

//WSARECV

 

/

//将原来的函数内容写回——关闭HOOK

void HookOffOne(HOOKSTRUCT *hookfunc)

{

 WriteProcessMemory(hProc,hookfunc->funcaddr, hookfunc->olddata, 8, 0);

}

//---------------------------------------------------------------------------

//将我们构建的代码写入——打开HOOK

void HookOnOne(HOOKSTRUCT *hookfunc)

{

 WriteProcessMemory(hProc,hookfunc->funcaddr, hookfunc->newdata, 8, 0);

}

//发送WM_COPYDATA消息到指定窗口

void SendMsg(char *buf,DWORD len,DWORDIndex)

{

         COPYDATASTRUCT cds;  

         cds.dwData = 0;//sizeof(COPYDATASTRUCT);    //有的说这个参数影响发送,还没用到,本来是存PID的,个人觉得应该不会影响

         cds.cbData = len;    //LPDATA里面的字节数

         cds.lpData = buf;   //实际数据

         SendMessage(_fHandle,WM_COPYDATA,(WPARAM)Index,(LPARAM)&cds);  //发到INIT里面指定的那个窗口

}

在Android中,应用程序被卸载时会触发一个ACTION_PACKAGE_REMOVED的广播,因此您可以使用hook代码来拦截和修改这个广播,以防止用户卸载您的应用程序。以下是一个使用Xposed框架编的示例hook代码: ```java import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class UninstallBlocker implements IXposedHookLoadPackage { public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { // 检查是否为系统应用程序 if ((lpparam.appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { // 查找PackageManagerService类 Class<?> packageManagerServiceClass = XposedHelpers.findClass("com.android.server.pm.PackageManagerService", lpparam.classLoader); // 查找deletePackage方法 Method deletePackageMethod = XposedHelpers.findMethodExact(packageManagerServiceClass, "deletePackage", String.class, IPackageDeleteObserver.class, int.class, int.class); // 创建一个新的IPackageDeleteObserver对象,用于拦截卸载广播 Object packageDeleteObserver = XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.content.pm.IPackageDeleteObserver$Stub", null), "asInterface", new Object[]{null}); // 创建一个新的BroadcastReceiver对象,用于拦截卸载广播 BroadcastReceiver uninstallReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 阻止广播传递给其他接收器 abortBroadcast(); // 显示一个Toast消息,告诉用户应用程序不能被卸载 Toast.makeText(context, "该应用程序不能被卸载", Toast.LENGTH_SHORT).show(); } }; // 注册拦截卸载广播的BroadcastReceiver IntentFilter uninstallFilter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED); uninstallFilter.addDataScheme("package"); XposedHelpers.findAndHookMethod(packageManagerServiceClass, "deletePackage", String.class, IPackageDeleteObserver.class, int.class, int.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // 拦截广播 Intent uninstallIntent = new Intent(Intent.ACTION_PACKAGE_REMOVED); uninstallIntent.setData(Uri.parse("package:" + (String) param.args[0])); uninstallReceiver.onReceive((Context) param.thisObject, uninstallIntent); // 取消卸载操作 XposedBridge.invokeOriginalMethod(deletePackageMethod, param.thisObject, param.args); } }); } } } ``` 这个示例代码使用Xposed框架来拦截卸载广播,并显示一个Toast消息,告诉用户应用程序不能被卸载。请注意,这个示例代码只是为了演示如何使用hook代码拦截卸载广播,实际上阻止用户卸载应用程序可能会违反用户隐私和安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值