注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

且行且记录

点滴记录,行的更远!

 
 
 

日志

 
 

测试API HOOK  

2015-06-01 08:42:25|  分类: 一些练习 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
在家无聊,就测试一下api hook。之前已经对iat hook以及inline hook做过测试,但是对api hook没有测试过。
我发觉api hook估计更通用,类似于调试器里下断点输出内容这类操作。
其实也是一种inline hook,就是改写api的开头5字节为一个跳转语句,跳到新函数,新函数跟原api的原型要一样,
但是原api开头被破坏了,如果要用原api咋办?所以就要构造一个旧函数,开头三句的汇编就是原api一样,
后续再跟一个跳转语句,跳到原api后面没有被破坏的部分,就可以了。

先用记事本的“关于记事本”做测试,这个会调用shell32!ShellAboutW这个API。
用这个先体验一下hook效果,一般我先要用调试脚本验证过功能后,才开始编程,避免做无用功。
***api.x****
***********api hook***************
r @$t0=0c0c0000
.dvalloc /b @$t0 4000
r @$t1=SHELL32!ShellAboutW
****old fun***
eb @$t0 8b ff 55 8b ec e9
ed @$t0+6 (@$t1+5)-(@$t0+0xa)
**************
r @$t2=0c0c1000
****new fun***
a @$t2
mov @edi,@edi
push @ebp
mov @ebp,@esp
call USER32!LockWorkStation
push [@ebp+14]
push [@ebp+10]
push [@ebp+c]
push [@ebp+8]
call 0x0c0c0000
pop @ebp
ret 0x10

****patch api****
eb @$t1 e9
ed @$t1+1 @$t2-(@$t1+5)
******************
*qd

之后用以前的iat hook的一个样例,修改而成api hook的样例。
用一个注入程序注入改dll到记事本、计算器等,就可以看到效果了。
//apihook.cpp
// 编译 cl /LD apihook.cpp user32.lib
#include <windows.h>
#include <stdio.h>

#define NAKED   __declspec( naked )

BOOL ISHOOK=FALSE;
HINSTANCE hDll;

BYTE Code[]={0x8b, 0xff, 0x55, 0x8b, 0xec};
LPBYTE next5byte;
LPBYTE Addr;

void Output(char *fmt, ...)
{
   char Buff[1024];

   va_list arg_ptr;
   va_start(arg_ptr, fmt); 
   vsprintf(Buff, fmt, arg_ptr);
   va_end(arg_ptr);
   OutputDebugString(Buff);
}

NAKED int WINAPI oldfun(DWORD a1, DWORD a2, DWORD a3, DWORD a4)
__asm{
mov edi, edi
push ebp
mov ebp, esp
jmp next5byte
}
}

int WINAPI newfun(DWORD a1, DWORD a2, DWORD a3, DWORD a4)
{
MessageBox(NULL, "Hello", "Test", MB_OK);
oldfun(a1,a2,a3,a4);
//DebugBreak();
return 0;
}

int hook(void)
{
HINSTANCE ntdll;
DWORD flOldProtect;

ntdll=LoadLibrary("shell32.dll");
if (ntdll==NULL)
{
Output("LoadLibrary Failed!\n");
return 0;
}

Addr=(PBYTE)GetProcAddress(ntdll,"ShellAboutW");
if (Addr==NULL) return 0;
Output("SHELL32!ShellAboutW=0x%08X\n",Addr);
if ( memcmp(Addr, Code, 5)!=0 ) return 0;

VirtualProtect((LPVOID)Addr,5,PAGE_EXECUTE_READWRITE,&flOldProtect);
*Addr = 0xe9; //jmp
*(PDWORD)(Addr+1) = (DWORD)newfun - (DWORD)Addr - 5; //delta
VirtualProtect((LPVOID)Addr,5,flOldProtect,&flOldProtect);

next5byte = Addr+5;

ISHOOK=TRUE;
//FreeLibrary(ntdll);

return 0;
}

void unhook(void)
{
DWORD flOldProtect;

VirtualProtect((LPVOID)Addr,5,PAGE_EXECUTE_READWRITE,&flOldProtect);
memcpy(Addr, Code, 5);
VirtualProtect((LPVOID)Addr,5,flOldProtect,&flOldProtect);

ISHOOK=FALSE;
}

DWORD WINAPI ClientThread(LPVOID lpParam)
{
OutputDebugString("[*] Sleep 30s ...\n");
Sleep(30000); // 测试用

OutputDebugString("[*] FreeLibraryAndExitThread\n");
FreeLibraryAndExitThread(hDll,0);
return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad)
{
HANDLE hThread;
DWORD dwThreadId;

hDll=hinstDll;

   if (fdwReason == DLL_PROCESS_ATTACH)
{
if (!ISHOOK)
{
hook();

hThread = CreateThread(NULL, 0, ClientThread, NULL, 0, &dwThreadId);
if (hThread == NULL)
{
return TRUE;
}
CloseHandle(hThread);
}


   }

   if (fdwReason == DLL_PROCESS_DETACH)
{
if (ISHOOK)
{
unhook();
}
}

   return(TRUE);
}
  评论这张
 
阅读(64)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017