Linux下的 API Hook

 Linux下的 API Hook
2011-02-18 15:39:59
标签: linux  HOOK  api  休闲  职场

这个东西是在研究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]);

你可能感兴趣的:(Linux下的 API Hook)