首页
社区
课程
招聘
[旧帖] [分享][分享]重定向API总结 0.00雪花
发表于: 2012-4-24 09:47 2317

[旧帖] [分享][分享]重定向API总结 0.00雪花

2012-4-24 09:47
2317
重定向API就是修改EXE文件的PE结构中的IAT,将自己的函数地址替换原来的函数。
// 实现重定向API
// 参数pDllName:目标API所在的DLL名称
// 参数pFunName:目标API名称
// 参数dwNewProc:自定义的函数地址
BOOL WINAPI RedirectApi ( PCHAR pDllName, PCHAR pFunName, DWORD dwNewProc)
{
    // 检查参数是否合法
    if ( pDllName == NULL || pFunName == NULL || !dwNewProc || !pItem )
       return FALSE ;

    // 获取自身应用程序文件基址dwBaseImage
    char  szTempDllName[256] = {0} ;
    DWORD  dwBaseImage = (DWORD)GetModuleHandle(NULL) ;
    if ( dwBaseImage == 0 )
      return FALSE ;

    // pDosHeader指向DOS头结构
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)dwBaseImage ;

    //pNtHeader指向PE文件头结构
    PIMAGE_NT_HEADERS  pNtHeader  = (PIMAGE_NT_HEADERS)(dwBaseImage + (pDosHeader->e_lfanew)) ;

    //pOptionalHeader指向可选头结构  
    PIMAGE_OPTIONAL_HEADER32  pOptionalHeader = &(pNtHeader->OptionalHeader) ;

    //pSectionHeader指向第一个段头部结构
    PIMAGE_SECTION_HEADER  pSectionHeader = (PIMAGE_SECTION_HEADER)  
                                  ((DWORD)pNtHeader + 0x18 +
                                  pNtHeader->FileHeader.SizeOfOptionalHeader ) ;

    // 遍历导入表
    PIMAGE_THUNK_DATA pThunk, pIAT ;

    //pIID指向第一个导入DLL目录结构
    PIMAGE_IMPORT_DESCRIPTOR pIID = (PIMAGE_IMPORT_DESCRIPTOR)(dwBaseImage+pOptionalHeader->DataDirectory[1].VirtualAddress ) ;

     while ( pIID->FirstThunk )
      {
         // 找到指定的DLL导入目录
         if ( strcmp ( (PCHAR)(dwBaseImage+pIID->Name), pDllName ) )
           {
               pIID++ ;
               continue ;
           }
         //pIAT指向该导入DLL的IAT表
         pIAT = (PIMAGE_THUNK_DATA)( dwBaseImage +
                    pIID- >FirstThunk ) ;

         //pThunk指向原始的IAT表,说实话我真不清楚什么叫原始IAT表
         if ( pIID->OriginalFirstThunk )
              pThunk = (PIMAGE_THUNK_DATA)( dwBaseImage +
              pIID->OriginalFirstThunk ) ;
         else
              pThunk = pIAT ;

         // 遍历IAT
              DWORD  dwThunkValue = 0 ;
              //dwThunkValue存放原始的IAT表中函数的虚拟地址
              while ( ( dwThunkValue = *((DWORD*)pThunk) ) != 0 )
              {
                 if ( ( dwThunkValue & IMAGE_ORDINAL_FLAG32 ) == 0 )
                 {
                      // 寻找指定的函数在IAT表中的项
                      if ( strcmp ( (PCHAR)  (dwBaseImage+dwThunkValue+2),
                           pFunName ) == 0 )
                      {
   
                           // 修改IAT项
                           DWORD dwOldProtect = 0 ;
                           VirtualProtect ( pIAT, 4, PAGE_READWRITE,
                                                  &dwOldProtect ) ;

                           *((DWORD*)pIAT) = dwNewProc ;
                           VirtualProtect ( pIAT, 4, PAGE_READWRITE,
                                                  &dwOldProtect ) ;
                           return TRUE ;
                      }
                    }

                    pThunk ++ ;
                    pIAT ++ ;
                }

     pIID ++ ;
  }
return FALSE ;
}

总结:该函数就是修改了,当前可执行文件的PE结构中的IAT表,然后这个应用程序调用特定的函数,就调用自己定义的函数了

[课程]Android-CTF解题方法汇总!

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 208
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
IAT hook,good
楼主有考虑过delay IAT吗?
2012-4-24 11:36
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
      

数据目录中的IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT存放了
延迟加载DLL的信息吧,我在网上找到一篇分析delay IAT的文章http://blog.csdn.net/panda1987/article/details/5936770,可惜我汇编还没学好,看不懂哇希望对你有用

对于originalfirstthunk,firstthunk,绑定输入表,DLL时间戳还是不懂,先去学汇编,再继续研究了
2012-4-24 14:15
0
雪    币: 208
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
多谢了。
刚初步看了一下csdn上的这篇帖子,写的还是挺好的,应该给转载到看雪和upk上来。
2012-4-24 14:49
0
雪    币: 615
活跃值: (172)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
5
看了一下代码,写的还不错,
但是有一个地方写错了,

 
                           // 修改IAT项
                           DWORD dwOldProtect = 0 ;
                           VirtualProtect ( pIAT, 4, PAGE_READWRITE, 
                                                  &dwOldProtect ) ;
 
                           *((DWORD*)pIAT) = dwNewProc ;
                           VirtualProtect ( pIAT, 4, PAGE_READWRITE, 
                                                  &dwOldProtect ) ;


应改为:
 
                           // 修改IAT项
                           DWORD dwOldProtect = 0 ;
                           VirtualProtect ( pIAT, 4, PAGE_READWRITE, 
                                                  &dwOldProtect ) ;
 
                           *((DWORD*)pIAT) = dwNewProc ;
                           VirtualProtect ( pIAT, 4, dwOldProtect, 
                                                  &dwOldProtect ) ;


其它没发现什么问题 。
2012-4-24 21:53
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
谢谢指正,,,其实这段代码是我抄《windows编程循序渐进》上面的例子
2012-4-25 08:33
0
雪    币: 615
活跃值: (172)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
7
《windows编程循序渐进》这本书我没有看过,
但是书上的东西不一定是对的。

代码我再看了一遍,
         //pThunk指向原始的IAT表,说实话我真不清楚什么叫原始IAT表
         if ( pIID->OriginalFirstThunk )
              pThunk = (PIMAGE_THUNK_DATA)( dwBaseImage + 
              pIID->OriginalFirstThunk ) ;
         else
              pThunk = pIAT ;
 
         // 遍历IAT
              DWORD  dwThunkValue = 0 ;
              //dwThunkValue存放原始的IAT表中函数的虚拟地址
              while ( ( dwThunkValue = *((DWORD*)pThunk) ) != 0 )
              {
                 if ( ( dwThunkValue & IMAGE_ORDINAL_FLAG32 ) == 0 )
                 {



这几句代码可能很多人不太明白,我讲解一下吧。

PE导入表中OriginalFirstThunk和FirstThunk都是指向PIMAGE_THUNK_DATA一个结构数组。
FirstThunk的PIMAGE_THUNK_DATA是iat,位于 _IMAGE_IMPORT_DESCRIPTOR结构前面,
OriginalFirstThunk的PIMAGE_THUNK_DATA是int,位于 _IMAGE_IMPORT_DESCRIPTOR结构后面面,

一开始iat和int数据内容是相同的,
PE加载到内存后系统会根据int和dll名找到相应dll模块加载的基址计算出int里的实际虚拟地址并
填写到iat结构。如果int为空系统没有找到要导入的名称表,不会填充iat地址表,
这样地址表iat就保存了初始状态的int内容。

也就是这里为什么有:

         if ( pIID->OriginalFirstThunk )
              pThunk = (PIMAGE_THUNK_DATA)( dwBaseImage +
              pIID->OriginalFirstThunk ) ;
         else
              pThunk = pIAT ;

这几句代码。

if ( ( dwThunkValue & IMAGE_ORDINAL_FLAG32 ) == 0 )

这句条件判断也就是判断每个 _IMAGE_THUNK_DATA 结构最高二进制位和1进行与运算,
如果结果等于0,那最高位是0,说明导入表是以函数名称方式导入的,
如果结果等于1则表示以序号的方式导入,这里是iat hook, 故判断等于0,

如果 if ( ( dwThunkValue & IMAGE_ORDINAL_FLAG32 ) == 0 )

这句不太理解,
可以这么写或许更容易懂:

if(  IMAGE_SNAP_BY_ORDINAL32( pThunk->u1.Ordinal )  )

希望对大家有帮助!
2012-4-25 16:03
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
十分感谢,获益匪浅,呵呵
2012-4-26 07:52
0
雪    币: 615
活跃值: (172)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
9
不用谢!
2012-4-28 17:16
0
雪    币: 77
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
mark
2014-1-18 12:29
0
游客
登录 | 注册 方可回帖
返回
//