找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 2569|回复: 0

qq空间老文章转载-api-hook探索

[复制链接]
发表于 2014-2-19 19:51:40 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
这两天仔细研究了下hook api,很难得,我电脑win7 64位,经过3天各种调试、终于有了眉目了,虽然还是有未知小bug,不过应该都能解决。。。
先在网上遍搜api hook相关信息和文档和代码,最后把一些看起来比较正常的代码整合到一起,写到我的代码里,同时把我逆向过的一部分Unlocker代码也弄进去了。
遇到的第一个难题:无论如何注入的代码总也运行不起来,就连xp都不行。。。后来加入各种调试输出语句,排了一些错,还是不行。。看网上有人说想在win7 64位成功必须用Unicode字符串,于是我把一些地方改了,包括Process32FirstW,然而本来很好用的Process32First改了以后,不知道为什么总获取不到信息了,最后仔细在msdn里找了一下,原来第二个参数要对一个成员初始化。。。网上的代码很不正规,图省事就直接贴上去了。。。
第二个问题困扰了我2天:注入进程后总是是目标程序崩溃。。。百思不得其解,网上的代码也是都有问题的,没发现有能用的(64位win7),xp我没装,于是没管。网上的解决办法也不对。第一天晚上,突然发现release版的居然可以用了,注入到目标程序可以显示出对话框,但是点了以后还是程序崩溃。。网上全是求助帖,没看到有真正解决的!!!好水。可是第二天早上,我才发现只有release可以,debug居然不行!!!最后最后我实在没招了用ida看了一下,原来如此啊,,debug里为了调试程序,每一个自己写的函数都是由2个函数实现的,其中一个调用另一个,我把一个函数代码写到另一个进程中后,只是把最外层那个函数调用了,而注入的目标进程肯定是没有里面那个函数的,因为我没法写到进程里,而且极难实现。。连函数在哪里都无法得知的,微软弄得很复杂的。release版由于优化了,只有一个调用函数,所以能正常注入。。。
最后我的解决办法是:利用外壳函数一个性质,外壳函数的内部汇编实现是jmp+偏移地址,这里暂且将外壳函数用func1表示,真正的函数用func2表示。那么有func1() {func2();}  汇编写法就是jmp addr   其中addr为func2函数位置相对于jmp的下一条指令的偏移;这个指令长度5字节,这条指令本身占5字节(jmp1字节),因此只需要读取func1这个函数指针偏移位置为1的地方,读取4字节即可,然后把结果加上func1所在地址,就是func2的绝对地址了。此时把func2写入即可。
做了这些以后,本以为万无一失了,谁知道还是不行,目标进程还是挂掉了。。于是我把写入到内存的那些func2函数代码看了一下,居然和直接汇编得到的(文件中的)不一样。。。,(很茫然,我觉得应该是用来调试的指令吧),总有字节被硬生生替换为0xcc...这是个特权指令,一运行程序就崩了。。。而且程序运行的时候内存里的函数居然也是这个。。。无解。最后想到的办法就是把func2硬编码了,直接编译出来,取得汇编代码相对应的16进制机器码,作为数组直接写到进程中,在执行,这样总不会弄什么猫腻了吧,结果真的可以,对话框有了。。。只有几个烦人的bug都被我调好了,现在仍然有bug,不过可以通过func2让目标进程加载dll了。

func2由于是注入函数,不能有任何直接的东西,比如这个程序自身的指针,字符串,api统统不能用,想用都要传到参数中才行。而且下断点发现func2无法被断下来,,,估计微软没考虑到要为注入程序提供调试了,这个函数里外来的东西都不能直接用,现在仍有一处崩溃,还在查,不过release版倒是可以随便运行了。。呵呵
相关代码:
  1. [/align][align=left]DWORD RemoteInject(PROCESSENTRY32W* pInfo,DWORD len)
  2. {
  3. HMODULE hMod=GetModuleHandle("kernel32.dll");
  4. ASSERT(hMod != NULL);
  5. HANDLE hRemoteProcess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_OPERATION |
  6.   PROCESS_CREATE_THREAD,FALSE,pInfo->th32ProcessID);
  7. #ifdef _DEBUG
  8. TRACE("hRemoteProcess=%d\n",hRemoteProcess);
  9. #endif
  10. if(hRemoteProcess)
  11. {
  12. #ifdef _DEBUG
  13.   unsigned char codedata[] = //Debug版FuncToInject的字节码,随着FuncToInject函数变化而变化
  14.   {
  15.    0x55, 0x8B, 0xEC, 0x81, 0xEC, 0xC0, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x8B, 0xE5,
  16.    0x5D, 0xC2, 0x04, 0x00
  17.   };[/align][align=left]  LPVOID pfnStartAddr=VirtualAllocEx(hRemoteProcess,NULL,sizeof(codedata),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  18.   TRACE("pfnStartAddr=%d\n",pfnStartAddr);
  19. #else
  20.   LPVOID pfnStartAddr=VirtualAllocEx(hRemoteProcess,NULL,len,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  21. #endif[/align][align=left]  if(pfnStartAddr)
  22.   {
  23.    SIZE_T NumberOfBytesWritten=0;[/align][align=left]#ifdef _DEBUG
  24.    WriteProcessMemory(hRemoteProcess,pfnStartAddr,(LPVOID)codedata,sizeof(codedata),&NumberOfBytesWritten);
  25. #else
  26.    WriteProcessMemory(hRemoteProcess,pfnStartAddr,(LPVOID)&FuncToInject,len,&NumberOfBytesWritten);
  27. #endif[/align][align=left]
  28.    LPVOID ParamBuffer=VirtualAllocEx(hRemoteProcess,NULL,sizeof(InjectStruct),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  29. #ifdef _DEBUG
  30.    TRACE("ParamBuffer=%d\n",ParamBuffer);
  31. #endif
  32.    if(ParamBuffer && hMod)
  33.    {
  34.     InjectStruct RemoteFunc;
  35.     RemoteFunc.MyLoadLibraryW=(MYLOADLIBRARYW)GetProcAddress(hMod,"LoadLibraryW");
  36.     RemoteFunc.MyGetModuleHandleW=(MYGETMODULEHANDLEW)GetProcAddress(hMod,"GetModuleHandleW");
  37.     RemoteFunc.MyGetProcAddress=(MYGETPROCADDRESS)GetProcAddress(hMod,"GetProcAddress");
  38. #ifdef TEST1
  39.      HMODULE userhandle=GetModuleHandleA("user32.dll");
  40.      RemoteFunc.MyMessageBoxW=(MYMESSAGEBOXW)GetProcAddress(userhandle,"MessageBoxW");
  41.      ASSERT(RemoteFunc.MyMessageBoxW != NULL);
  42. #endif
  43.     memcpy(&RemoteFunc.ProcInfo,pInfo,sizeof(PROCESSENTRY32W));
  44.     ASSERT(RemoteFunc.MyLoadLibraryW != NULL);
  45.     ASSERT(RemoteFunc.MyGetModuleHandleW != NULL);
  46.     ASSERT(RemoteFunc.MyGetProcAddress != NULL);
  47.     lstrcpyW(RemoteFunc.DllFullPath,L"C:\\Users\\Administrator\\Desktop\\TransParentEnDeSrc\\Debug\\TransParentEnDeSrc.dll");//打算做成软件包,路径写到注册表中[/align][align=left]    WriteProcessMemory(hRemoteProcess,ParamBuffer,(LPVOID)&RemoteFunc,sizeof(InjectStruct),&NumberOfBytesWritten);[/align][align=left]    //HANDLE NewThread=CreateRemoteThread(hRemoteProcess,NULL,1024,(LPTHREAD_START_ROUTINE)pfnStartAddr,ParamBuffer,0,NULL);
  48.     HANDLE NewThread=MyCreateRemoteThread(hRemoteProcess,(LPTHREAD_START_ROUTINE)pfnStartAddr,ParamBuffer);
  49. #ifdef _DEBUG
  50. //    TRACE("%S CreateRemoteThread:Getlasterror:%d\n",pInfo->szExeFile,GetLastError());
  51. #endif
  52.     if(NewThread)
  53.      WaitForSingleObject(NewThread,INFINITE);
  54.     VirtualFreeEx(hRemoteProcess,ParamBuffer,0,MEM_RELEASE);
  55.     CloseHandle(NewThread);
  56.    }
  57.    VirtualFreeEx(hRemoteProcess,pfnStartAddr,0,MEM_RELEASE);
  58.   }
  59. #ifdef _DEBUG
  60.   else
  61.   {
  62.    TRACE("失败:%d\n",GetLastError());
  63.   }
  64. #endif[/align][align=left]  CloseHandle(hRemoteProcess);
  65. }
  66. return 0;
  67. }[/align]
  68. [align=left]
  69. BOOL WINAPI FuncToInject(InjectStruct* INJECT)//此代码在拦截createprocess时也要用到
  70. {//注入函数中不能有任何内部指针,字符串,函数也最好作为指针存到参数中   注入函数无法调试。。。。
  71.   if(INJECT->MyGetModuleHandleW(INJECT->DllFullPath)) return TRUE;//DLL已经加载直接返回
  72.   HMODULE hMod=INJECT->MyLoadLibraryW(INJECT->DllFullPath);
  73.   if(hMod == NULL)
  74.    return FALSE;
  75. SETINFO setinfo=(SETINFO)INJECT->MyGetProcAddress(hMod,(const char*)MAKELONG(1,0));//获取第一个函数
  76.   setinfo(&INJECT->ProcInfo);
  77. return TRUE;
  78. } [/align][align=left]
复制代码


回复

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-12-23 06:19 , Processed in 0.030457 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表