首页
社区
课程
招聘
[求助]这句代码不能理解
发表于: 2008-5-2 09:54 4493

[求助]这句代码不能理解

2008-5-2 09:54
4493
代码来自于

char ResetApiName[APICOUT][255] =
{
        "ZwCreateFile",
        "ZwOpenFile",
        "ZwCreateProcess",
        "ZwCreateProcessEx"
};
#define NONEHOOK 0
#define ANTIHOOKFAILD 1
#define ANTIHOOKTRUE  2
//恢复原来的代码
int ResetCode(HANDLE theHandle)
{
        BYTE code[5] = {0};
        BYTE Newcode[5] = {0};
        DWORD dwReadnum;
        DWORD oldpro;
        BOOL ret = NONEHOOK;
        for(int i = 0; i < APICOUT; i++)
        {
                DWORD ApiAddr = (DWORD)GetProcAddress(GetModuleHandle("NTDLL.DLL"),ResetApiName[i]);
                if( ApiAddr )
                {
                        VirtualProtectEx(theHandle,(LPVOID)ApiAddr,5,PAGE_EXECUTE_READWRITE,&oldpro);
                        ReadProcessMemory(theHandle,(LPVOID)ApiAddr,code,5,&dwReadnum);
                        if( dwReadnum != 0)
                        {
                                if( 0xE8 == code[0] )//if Hook
                                {
                                        DWORD NewAddr = ApiAddr + *(DWORD*)&code[1] + 5;//这句代码不知道为什么要这么做?
                                        VirtualProtectEx(theHandle,(LPVOID)NewAddr,5,PAGE_EXECUTE_READWRITE,&oldpro);
                                        ReadProcessMemory(theHandle,(LPVOID)NewAddr,Newcode,5,&dwReadnum);
                                        if( dwReadnum != 0)
                                        {
                                                //restore hook
                                                if( !WriteProcessMemory(theHandle,(LPVOID)ApiAddr,Newcode,5,&dwReadnum) )
                                                {
                                                        ret = ANTIHOOKFAILD;
                                                }
                                                else
                                                {
                                                        ret = ANTIHOOKTRUE;
                                                }
                                        }
                                }
                        }
                }
        }
        return ret;
}

这段代码是来自珠海金山2007逆向分析挑战赛里面的代码用于恢复被hook的函数的

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 2384
活跃值: (766)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
2
那一句作用是取得HOOK API函数的执行地址。然后从HOOK API函数头中读取头5个字节,再写回原API头中恢复原API代码。
2008-5-2 11:08
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
哪位大虾有时间,能给这段代码加上详细的注视呢?

俺越看越蒙了
2008-5-2 14:17
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
4
char ResetApiName[APICOUT][255] =
{
  "ZwCreateFile",
  "ZwOpenFile",
  "ZwCreateProcess",
  "ZwCreateProcessEx"
};//这里是需要被恢复的四个函数的名称
#define NONEHOOK 0
#define ANTIHOOKFAILD 1
#define ANTIHOOKTRUE  2
//恢复原来的代码
int ResetCode(HANDLE theHandle)//恢复进程的API HOOK。theHandle为进程句柄。
{
  BYTE code[5] = {0};
  BYTE Newcode[5] = {0};
  DWORD dwReadnum;
  DWORD oldpro;
  BOOL ret = NONEHOOK;
  for(int i = 0; i < APICOUT; i++)//对每个函数进行恢复hook操作。
  {
    DWORD ApiAddr = (DWORD)GetProcAddress(GetModuleHandle("NTDLL.DLL"),ResetApiName[i]);//得到API地址
    if( ApiAddr )
    {
      VirtualProtectEx(theHandle,(LPVOID)ApiAddr,5,PAGE_EXECUTE_READWRITE,&oldpro);//修改内存地址属性为RWE
      ReadProcessMemory(theHandle,(LPVOID)ApiAddr,code,5,&dwReadnum);//从API开头读5字节
      if( dwReadnum != 0)
      {
        if( 0xE8 == code[0] )//if Hook,即开头是一个jmp
        {
          DWORD NewAddr = ApiAddr + *(DWORD*)&code[1] + 5;//相对jmp地址计算,计算出jmp到的代码位置
          VirtualProtectEx(theHandle,(LPVOID)NewAddr,5,PAGE_EXECUTE_READWRITE,&oldpro);
          ReadProcessMemory(theHandle,(LPVOID)NewAddr,Newcode,5,&dwReadnum);//将此处的5字节读出
          if( dwReadnum != 0)
          {
            //restore hook
            if( !WriteProcessMemory(theHandle,(LPVOID)ApiAddr,Newcode,5,&dwReadnum) )//将读出的5字节内容写回原API函数开头
            {
              ret = ANTIHOOKFAILD;
            }
            else
            {
              ret = ANTIHOOKTRUE;
            }
          }
        }
      }
    }
  }
  return ret;
}
2008-5-2 23:49
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
5
如上,我觉得这份代码已经十分简明了。楼主不能理解代码,我看还是对INLINE HOOK的细节以及汇编中相对jmp代码的机器码不了解。

对API函数的INLINE HOOK,将API函数开头的5字节替换为
jmp hookfunction

这5个字节的代码,变成机器码,第一个字节为0xE8,后面四个字节为一个DWORD值。
这个相对jmp的DWORD值的计算方法是:
目标代码地址-jmp命令位置-jmp命令长度(5字节)

当API函数开头jmp入hookfunction开头时,hookfunction的开头:
实现原API函数开头的5个字节代码,然后跳回原API函数5个字节后的代码。

以上就是楼主的代码所要面对的现实情况,这样你才可以理解这个代码是在干什么:
从API函数头部5字节的jmp中,找到跳转到的hookfunction的地址
从hookfunction处拷贝5个字节的内容,也即是API函数前5字节的原始内容
将这5字节内容覆盖回原API函数头部
这样就解除了INLINE HOOK

不知道楼主现在明白没有。
2008-5-2 23:58
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
谢谢楼上的两位,我明白了
2008-5-4 15:41
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
7
是吗? 我怎么感觉你们的解释都怪怪的 ?

第一点. E8 是 call , 不是 jmp

第二点. 他前面写的四个api是 Zw开头的, 显然是 ntdll.dll
        以 ZwCreateFile 为例, 入点为 :
                  B820000000 mov eax,20h
                  8d542404   lea edx,[esp+04]
                  cd2e       int 2Eh

        注意: 是B8开头, 不是 E8 开头.
        所以, 他已经自我预设为, 被人用Call的方式 Hook, 而不是以 jmp 的方式 Hook

        ZwCreateFile:
                  E8xxxxxxxx call NewAddr
                  8d542404   lea edx,[esp+04]
                  cd2e       int 2Eh

        当然了. 在他的Hook函式(NewAddr)在返回前会还原 EAX 的值 再 ret

  接下来, 他写: 
      NewAddr = ApiAddr + *(DWORD*)&code[1] + 5   (这是算出 Hook 函数的入点没错)

  最后他读NewAddr函数的前5个byte, 填入(还原) ZwCreateFile 的开头.

      关于这一点. 他又自我预设了Hook函数(NewAddr)的前5个byte为原API的5个byte
      亦即他预设了, 
           NewAddr:
                   B820000000 mov eax,20h
                   .....
                   .....

由于我没看到整个Project, (这里只贴上这 ResetCode 函数而己)
除非 Hook 函式也是作者自己写的, 否则...这根本不能用. 更谈不上
"这段代码是来自珠海金山2007逆向分析挑战赛里面的代码用于恢复被hook的函数的"
(取自于楼主的话)

刚接触破解, 若有错误请指教.
2008-5-4 16:34
0
游客
登录 | 注册 方可回帖
返回
//