【文章标题】: 巧用CDB解决问题
【文章作者】: kkbing
【作者声明】: 只想说明:遇到疑问,在求助他人的同时,也要自己想法解决。
--------------------------------------------------------------------------------
【详细过程】

  一.遇到疑问。一般来说,在编码dll注射,shellcode及病毒时,都不可避免要获得kernel32的基址。
  获得其基址的方法大体有三种:扫描SEH,利用hardcode及PEB法。在用PEB法时我看到两种不同的代码,如下.
  1.mov eax, dword ptr FS:[30h] 
    mov eax, dword ptr[eax+0ch]
    mov eax, dword ptr[eax+1ch]
    mov eax, dword ptr[eax]
    mov eax, [eax+8]
  2.mov eax,fs:[18h]
    mov eax,[eax+30h]
    mov eax, dword ptr[eax+0ch]
    mov eax, dword ptr[eax+1ch]
    mov eax, dword ptr[eax]
    mov eax, [eax+8]
  很明显可以看出,第2个代码比第1个代码多了一行,是不是错了?最终检验是对的!那么只有一个
  解释,mov eax,fs:[18h]就等于mov eax,fs:[0].接着就要验正了,这必然和结构有关,但无奈手
  边资料匮乏,怎么办?这时想到了CDB中的dt命令,可以用来分析结构。
  
  二.构建CDB.CDB是windbg中的一个基于命令行的工具,操作起来比较简单。另外就是安装调试符号
  尽管可以在线下载用,但如果网速不快还是下载打包文件回来默认安装的好。如我的windbg安装在
  c:\windbg目录,调试符号在c:\windows\symbols.下来为了方便,建一个批处理文件,很简单。
  @echo off
  
  set path=d:\windbg;%path%;    //设置相对路径
  set _nt_symbol_path=c:\windows\symbols  //设置符号路径
  
  echo on 
  命名为windbg.bat,存放在d:\下
  
  三.解决问题。
  1.顺便检验fs:[0]是否指向TEB.
  d:\>windbg
  d:\>cdb notepad //随便打开一个可执行文件进入调试状态
  .....
  0:000>dg @fs  //显示fs的信息,注意Base基址值
  Sel   Base    Limit     Type ....
  --- -------- -------  ---------...
  003B 7ffdf000 00000fff Data RW...
  0:000>r $teb  //显示teb的基址
  $teb=7ffdf000
  可以发现两基址是相同的,都是7ffdf000
  2.查看TEB结构
  0:000>dt ntdll!*teb*  //dt是显示数据结构的常用命令,在不知具体结构是
                             时可用* *
            ntdll!_teb
            .....
  0:000>dt ntdll!_teb
  ntdll!_TEB
     +0x000 NtTib             :_NT_TIB
     +0x01c EnvironmentPointer:Ptr32 Void
     +0x020 ClientId          :_CLIENT_ID
     +0x028 ActiveRpcHandl3   :Ptr32 Void
     +0x030 ProcessEnvironmentBlock:Ptr32 _PEB //这就是fs:[30}的来源
     ......
  那么fs:[28]从何而来呢?请看
  0:000>dt _nt_tib
  ntdll!_NT_TIB
     +0x000 ExceptionList    :Ptr32 _EXCEPTION_REGISTRATION_RECORD
     +0x004 StackBase        :Ptr32 Void
     +0x008 StackLimit       :Ptr32 Void
     +0x00c SubSystemTib     :Ptr32 Void
     +0x010 FiberData        :Ptr32 Void
     +0x010 Version          :Uint4B
     +0x014 ArbitratyUserPointer :Ptr32 Void
     +0x018 Self             :Ptr32 _NT_TIB //注意
  从TIB的结构可以看出其最后一个0x18偏移出是指向自身的。也就是说
  fs:[18]与fs:[0]尽管在逻辑地址上不一样,但最终都映射在了相同的
  物理地址。
  3.结论。通过以上分析就明白了,尽管表述上有差异,但最终结果是一样
  的,这是内在结构上的一种“巧合”吧。所以为了代码简单,明了,以后就
  可以直接用fs:[30]来获取PEB了。心中的疑惑没了,爽!
  
  以上只是简单的分析而已,如果想要枚举当前进程中的所有模块
  可以进一步不分析的,只怪自己水平有限,高手莫笑。
  
  
--------------------------------------------------------------------------------
【经验总结】
  知其然,更应知其所以然。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年05月15日 22:56:03

  • 标 题: 答复
  • 作 者:小虾
  • 时 间:2006-05-15 23:41

fs:[0]是_tib的结构开始地址,fs:[18]是一个指向_tib(fs:[0])结构的指针。