这个东西是在研究Linux下屏幕抓词的时候写的,用于观察相关API的运行情况。
HookFunc 是要先执行自己的代码,再执行目标程序。
HookFuncEx 是要先执行目标API,再到自己的函数中拦截结果。
要点:编译不要时不要采用优化选项,可以写成动态库,用LD_PRELOAD方式加载。
#define LEAVE_SPACE 40
#define JMP_ORGFUNC()\
\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
__asm__ __volatile__ ("nop");\
typedef struct FUNC_INFOTag
{
void *pFunc;
void *pHookFunc;
char cFuncName[32];
unsigned int nAsm;
unsigned char cAsm[16];//
}FUNC_INFO;
void HookFunc(const FUNC_INFO *pfi)
{
int nSize = getpagesize();
if ( mprotect((void *)((unsigned int)pfi->pFunc / nSize * nSize),nSize * 2,7) < 0)
{
#ifdef _HDEBUG_
printf("mprotect error 0, %s , address=%d\n",pfi->cFuncName,(unsigned int)pfi->pFunc / nSize * nSize);
#endif
return;
}
if ( mprotect((void *)((unsigned int)pfi->pHookFunc / nSize * nSize),nSize * 2,7) < 0)
{
#ifdef _HDEBUG_
printf("mprotect error 1, %s , address=%d\n",pfi->cFuncName,(unsigned int)pfi->pHookFunc / nSize * nSize);
#endif
return;
}
unsigned char *pc0 = (unsigned char *)pfi->pFunc;
unsigned int *pn0 = (unsigned int *)(pc0+1);
if (pc0[0] == 0xe9)
{
#ifdef _HDEBUG_
printf("%s, is allready hooked!\n",pfi->cFuncName);
#endif
return;
}
memcpy((void *)pfi->cAsm,(void *)pc0,pfi->nAsm);
*pc0=0xe9;
*pn0 = (unsigned int)pfi->pHookFunc - (unsigned int)pfi->pFunc - 5 ;
unsigned char *pc1 = (unsigned char *)pfi->pHookFunc;
int i = 0;
int j;
int nFind;
while(1)
{//leave=0xc9
nFind = 1;
for (j = 0; j < LEAVE_SPACE; j++)
{
if (pc1[i+j] != 0x90)
{
nFind = 0;
break;
}
}
if ( nFind == 1)
{
break;
}
i++;
}
pc1 += i;//first nop
i = LEAVE_SPACE;
while(1)
{//leave=0xc9//pc1[i]==0xc3)
nFind = ((pc1[i]==0x55) && (pc1[i+1]==0x89) && (pc1[i+2]==0xe5));
if ( nFind != 0 )
{
break;
}
i++;
}
while (1)
{
if (pc1[i] == 0xc3)
{//
break;
}
i--;
}
int nCopyNumber = i - LEAVE_SPACE;
//
memcpy(pc1,pc1 + LEAVE_SPACE, nCopyNumber);
pc1 += nCopyNumber;
//
memcpy(pc1, pfi->cAsm,pfi->nAsm);
//add jmp
pc1 += pfi->nAsm;
*pc1 = 0xe9;
pc1++;
unsigned int *pn1 = (unsigned int *)(pc1);
pc1+=4;
*pn1 = (unsigned int)(pc0 + pfi->nAsm ) - (unsigned int)(pc1) ;
}
void HookFuncEx(const FUNC_INFO *pfi, int nParaSize)
{
int nSize = getpagesize();
if ( mprotect((void *)((unsigned int)pfi->pFunc / nSize * nSize),nSize * 2,7) < 0)
{
#ifdef _HDEBUG_
printf("mprotect error 0, %s , address=%d\n",pfi->cFuncName,(unsigned int)pfi->pFunc / nSize * nSize);
#endif
return;
}
if ( mprotect((void *)((unsigned int)pfi->pHookFunc / nSize * nSize),nSize * 2,7) < 0)
{
#ifdef _HDEBUG_
printf("mprotect error 1, %s , address=%d\n",pfi->cFuncName,(unsigned int)pfi->pHookFunc / nSize * nSize);
#endif
return;
}
unsigned char *pc0 = (unsigned char *)pfi->pFunc;
unsigned int *pn0 = (unsigned int *)(pc0+1);
if (pc0[0] == 0xe9)
{
#ifdef _HDEBUG_
printf("%s, is allready hooked!\n",pfi->cFuncName);
#endif
return;
}
memcpy((void *)pfi->cAsm,(void *)pc0,pfi->nAsm);
*pc0=0xe9;
*pn0 = (unsigned int)pfi->pHookFunc - (unsigned int)pfi->pFunc - 5 ;
unsigned char *pc1 = (unsigned char *)pfi->pHookFunc;
int i = 0;
int j;
int nFind;
while(1)
{//leave=0xc9
nFind = 1;
for (j = 0; j < LEAVE_SPACE * 10; j++)
{
if (pc1[i+j] != 0x90)
{
nFind = 0;
break;
}
}
if ( nFind == 1)
{
break;
}
i++;
}
// move my code
memcpy(pc1 + LEAVE_SPACE * 10, pc1, i);
//804f8aa: 55 push %ebp
//804f8ab: 89 e5 mov %esp,%ebp
*pc1++=(unsigned char)0x55;
*pc1++=(unsigned char)0x89;
*pc1++=(unsigned char)0xe5;
//804f8ae: 83 ec 34 sub $0x34,%esp
*pc1++=(unsigned char)0x83;
*pc1++=(unsigned char)0xec;
*pc1++=(unsigned char)nParaSize + 4;
for (i= 0 ;i < nParaSize; i++)
{
//804efee: 8a 45 01 mov 0x1(%ebp),%al
//804eff1: 88 44 24 01 mov %al,0x1(%esp)
*pc1++= (unsigned char)0x8a;
*pc1++= (unsigned char)0x45;
*pc1++= (unsigned char)(0x8 + i);
*pc1++= (unsigned char)0x88;
*pc1++= (unsigned char)0x44;
*pc1++= (unsigned char)0x24;
*pc1++= (unsigned char)(0x0 + i);
}
// 804efee: 68 ff ff ff ff push 0xffffffff
*pc1 ++= (unsigned char)0x68;
*((unsigned int *)(pc1)) = (unsigned int)(pc1 + 4 + pfi->nAsm + 5 );
pc1 += 4;
memcpy(pc1, pfi->cAsm,pfi->nAsm);
pc1+= pfi->nAsm;
//jmp XXXXXXX
*pc1 ++= (unsigned char)0xe9;
*((unsigned int *)(pc1)) = (unsigned int)(pc0 + pfi->nAsm ) - (unsigned int)(pc1 + 4);
pc1 += 4;
*pc1++=(unsigned char)0xc9;
}
下面是Hook的例子:
//先执行目标程序,拦截返回值,需要用HookFuncEx方式。
Picture XRenderCreatePictureHook (Display *dpy,
Drawable drawable,
_Xconst XRenderPictFormat *format,
unsigned long valuemask,
_Xconst XRenderPictureAttributes *attributes)
{
JMP_ORGFUNC();
JMP_ORGFUNC();
JMP_ORGFUNC();
JMP_ORGFUNC();
JMP_ORGFUNC();
JMP_ORGFUNC();
JMP_ORGFUNC();
JMP_ORGFUNC();
JMP_ORGFUNC();
JMP_ORGFUNC();
Picture picture = 0;
__asm__ __volatile__ ("mov %%eax,%0":"=g"(picture));
//your code .....
#ifdef _HDEBUG_
printf("XRenderCreatePictureHook : Picture=%x, Drawable=%x\n", picture, drawable);
#endif
return picture;
}
//先执行拦截程序,用HookFunc方式。
void XRenderFreePictureHook (Display *dpy, Picture picture)
{
#ifdef _HDEBUG_
printf("XRenderFreePictureHook: display=%x, picture=%x\n",dpy,picture);
#endif
//your code .....
JMP_ORGFUNC();
return;
}
调用:
FUNC_INFO _g_func_infos[] ={
{0,(void *)XRenderCreatePictureHook,"XRenderCreatePicture",5,""},
{0,(void *)XRenderFreePictureHook,"XRenderFreePicture",6,""}
}
HookFuncEx(&_g_func_infos[0], 20);
HookFunc(&_g_func_infos[1]);