【文章标题】: 看figo的冰点破解文章,一波三折
【文章作者】: hpxpj
【作者邮箱】: qwhp6891@163.com
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  刚看到figo的冰点破解文章的是时候,兴奋与佩服都让自己粗心起来,只看到牛。。。
  今天再看这篇文章的是时候,突然晕了。。
  copy
  ********************************************************************************************************
  VOID RtlRunDecodeUnicodeString(  UCHAR  Seed,  PUNICODE_STRING String  )
    
    第一个参数是 :
    字节类型, 加密的种子的值.
    
    第二个参数是:
    是个 PUNICODE_STRING 数据类型
    指向被解密的数据的地址(注意了,是双重指针)
    
    好了,通过上面的分析,我们开始对 RtlRunDecodeUnicodeString  下断点,点击 OK 按纽,程序被中断在如下代码:
    
    
    EAX=0000002A   EBX=00000006   ECX=7C822E07   EDX=00140608   ESI=0014C2A8        
    EDI=0014CDB0   EBP=0012F088   ESP=0012F06C   EIP=7C94EF8B   o d I s Z a P c     
    CS=001B   DS=0023   SS=0023   ES=0023   FS=003B   GS=0000                       
    --------------------------------------------------byte--------------PROT---(0)--
    0023:00E20034 B0 CD 14 00 03 00 00 00-28 CF 14 00 68 00 E2 00  ........(...h.? 
    0023:00E20044 00 00 00 00 03 00 01 00-90 A5 15 00 03 00 01 00  .............. 
    0023:00E20054 B0 65 17 00 03 00 01 00-D0 25 19 00 03 00 01 00  .e.......%...... 
    0023:00E20064 F0 E5 1A 00 70 00 E2 00-00 00 00 00 78 00 E2 00  .?.p.?....x.? 
    ------ntdll!RtlRunEncodeUnicodeString+004D-------------------------------PROT32-
    ntdll!RtlRunDecodeUnicodeString                                                 
    001B:7C94EF8B  8BFF                MOV       EDI,EDI                            
    001B:7C94EF8D  55                  PUSH      EBP                                
    001B:7C94EF8E  8BEC                MOV       EBP,ESP                            
    
    刚才我们了解到 RtlRunDecodeUnicodeString  的第二个参数是指向密文的双重指针,输入:
    D *(ESP - 08)                                                               
    这时,密文的地址如上面DATA 窗口所示,为 14CDB0H.
    不要急着下断点,要等到它解密完毕.
  ********************************************************************************************************
  我认为有问题的关键两行:
  ***************************************************************************************
  *   刚才我们了解到 RtlRunDecodeUnicodeString  的第二个参数是指向密文的双重指针,输入:  * 
  *   D *(ESP - 08)                                                                     *
  *                                                                                     *
  ***************************************************************************************
  
  我们知道stack是向底地址增长,按他说的应该是d *(esp+8)才是啊
  刚开始我还以为figo是笔误,就按这自己的想法去做实验,很奇怪的是居然不对,然后就按figo写的那样,
  又成功了,顺间晕了。。
  然后我就去问了下figo,他告诉我是他写错了,那我就更不明白了,没方法,只有自己去搞明白
  当我成功断下,来到
  ntdll!RtlRunDecodeUnicodeString                                                 
    001B:7C94EF8B  8BFF                MOV       EDI,EDI                            
    001B:7C94EF8D  55                  PUSH      EBP                                
    001B:7C94EF8E  8BEC                MOV       EBP,ESP                            
  stack应该是这样像这样子
  
  按figo的意思,ESP-8就是保存着指向加密字符的地址,我们知道那里保存信息显然是不安全的,
  只要RtlRunDecodeUnicodeString函数push几下就被改了,所以我们只能在刚断下来的时候用d *(esp-8)去看这里的信息,
  如果p ret之后再用d *(esp-12)去看,显然是不一定正确。事实上肯定会被改,看下RtlRunDecodeUnicodeString反汇编代码就知道了! 
  我们用IDA看下RtlRunDecodeUnicodeString函数,我添加了注释
  .text:7C94EF8B ; __stdcall RtlRunDecodeUnicodeString(x, x)
  .text:7C94EF8B                 public _RtlRunDecodeUnicodeString@8
  .text:7C94EF8B _RtlRunDecodeUnicodeString@8 proc near
  .text:7C94EF8B
  .text:7C94EF8B arg_0           = byte ptr  8  //它是一个指向byte的指针,这个byte数据就是加密种子
  .text:7C94EF8B arg_4           = dword ptr  0Ch //一个指向dword的指针
  .text:7C94EF8B
  .text:7C94EF8B                 mov     edi, edi
  .text:7C94EF8D                 push    ebp
  .text:7C94EF8E                 mov     ebp, esp
  .text:7C94EF90                 mov     cl, [ebp+arg_0]
  .text:7C94EF93                 push    esi
  .text:7C94EF94                 mov     esi, [ebp+arg_4]
  .text:7C94EF97                 push    edi
  .text:7C94EF98                 movzx   edi, word ptr [esi] //获得输入字符的个数
  .text:7C94EF9B
  .text:7C94EF9B loc_7C94EF9B:                           ; CODE XREF: RtlRunDecodeUnicodeString(x,x)+26j
  .text:7C94EF9B                 cmp     edi, 1 
  .text:7C94EF9E                 jbe     short loc_7C94EFB3
  .text:7C94EFA0                 mov     eax, [esi+4] //这里是关键,获得指向加密字符的地址
  .text:7C94EFA3                 add     eax, edi //eax指向字符串最后一个字符的下一个位置
  .text:7C94EFA5                 mov     dl, [eax-2] //第一次循环获得字符串倒数第二个字符
  .text:7C94EFA8                 xor     dl, [eax-1] //第一次循环与最后一个字符异或
  .text:7C94EFAB                 xor     dl, cl //与加密种子异或,dl就是明码了
  .text:7C94EFAD                 mov     [eax-1], dl //解密完一个字符
  .text:7C94EFB0                 dec     edi
  .text:7C94EFB1                 jmp     short loc_7C94EF9B
  .text:7C94EFB3 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
  .text:7C94EFB3
  .text:7C94EFB3 loc_7C94EFB3:                           ; CODE XREF: RtlRunDecodeUnicodeString(x,x)+13j
  .text:7C94EFB3                 cmp     word ptr [esi], 1
  .text:7C94EFB7                 jb      short loc_7C94EFC1
  .text:7C94EFB9                 mov     esi, [esi+4]
  .text:7C94EFBC                 or      cl, 43h
  .text:7C94EFBF                 xor     [esi], cl
  .text:7C94EFC1
  .text:7C94EFC1 loc_7C94EFC1:                           ; CODE XREF: RtlRunDecodeUnicodeString(x,x)+2Cj
  .text:7C94EFC1                 pop     edi
  .text:7C94EFC2                 pop     esi
  .text:7C94EFC3                 pop     ebp
  .text:7C94EFC4                 retn    8
  .text:7C94EFC4 _RtlRunDecodeUnicodeString@8 endp
  现在明白了吧,其实问题就是我们没有搞清楚RtlRunDecodeUnicodeString参数意思
  void RtlRunDecodeUnicodeString(x,y)
  x 它是一个指向byte的指针,这个byte数据就是加密种子
  y 它指向一个dword,这个dword指针指一个数据结构
  这数据结构是这样子的
  struct{
  int count;
  dword *decodedata;
  }
  现在我们破解冰点:
  一:start softice,这一定要第一步,如果先CTRL + ALT + SHIFT + F6 激活冰点,冰点有可能会自动退出
  当我用CTRL + ALT + SHIFT + F6 激活冰点,因为我没有为softice建立桌面快捷方式,准备从开始菜单中打开softice
  的时候,由于冰点的窗口前置,不能打开softice,我只有关掉冰点窗口(这下我能打开softice了吧,哈哈:)),启动
  softice,可是当我再次CTRL + ALT + SHIFT + F6时,冰点自动退出了,试了好几次,都这样,实验证明我们只有第一步
  先打开softice
  二:CTRL + ALT + SHIFT + F6调出冰点,输入密码,如123456789
  三:CTRL+D调出softice,对RtlRunDecodeUnicodeString下断点,bpx RtlRunDecodeUnicodeString
  四:CTRL+D退出softice,按下冰点的ok,成功断下
  五:d *(esp+8)
  六:看到比如00 09 00 09 A8 CF 14 00
  七:0014CFA8就是指向解密字符串,d 0014CFA8
  八:p ret
  九:在数据窗口就可以看到我们输入的字符串了,如:这里是123456789
  十。。。以后就按figo步骤了。。。
  
  
  注:由于本人表达方面不是很好,希望大家谅解!本来想用IceExt 7.0来输出文章的,
  可惜一用!dumpscreen \\??\c:\screen.bin就蓝屏,郁闷,只有靠自己拙劣的表词了,呵呵。。。
  
--------------------------------------------------------------------------------
【经验总结】
  仔细学习才是真..
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年03月12日 21:23:27

  • 标 题:答复
  • 作 者:kanxue
  • 时 间:2008-03-12 21:23

引用:
最初由 hpxpj发布 查看帖子
可惜一用!dumpscreen \\??\c:\screen.bin就蓝屏,郁闷,只有靠自己拙劣的表词了,呵呵。。。
这样试试,运行Symbol Loader后,将历史缓冲区(history buffer)调大些(默认为256,不能存放足够多的缓冲数据);然后切换到SoftICE调试画面下,转到需要抓取的地方,反汇编这些代码,比如:U CS:EIP L 100;立即按Ctrl+D返回Windows环境,再次转到symbol loader程序,选择“File/Save SoftICE History As…”,反汇编代码保存在*.log文件里。