首页 > 逆向调试 > 单步跟踪法手脱UPX壳

单步跟踪法手脱UPX壳

很早以前接触过免杀,不过那个时候我连汇编都不懂,所以自然是没有成功过一次;依然还记得那时候用Ollydbg、CCL之类的工具照着动画视频做,可以弄到很晚,但是一直是失败的。当然,我做这个的目的,全然是个人兴趣所向,不是拿来干坏事的,现在接触点这个,也只是兴趣,或者说以后拿来对抗病毒所用。

这里的文章算是看《杀不死的秘密》的一点笔记(个人觉得这本书上的废话太多了,很多地方感觉实在充字数。将就看下吧。)这里显示看一下单步跟踪法脱壳,这个实际过程应该很少用到,太麻烦了。

单步跟踪法就是利用OD的单条指令执行功能,从壳的入口一直执行到OEP,最终通过这个OEP将原程序dump出来。然当,在单步跟踪的时候需要跳过一些不能执行到的指令。使用单步跟踪法追踪OEP的常见步骤

  1. 用OD载入待脱壳文件,如果出现压缩提示,选择“不分析代码”;
  2. 向下单步跟踪,实现向下的跳转;
  3. 遇到程序往上跳转的时候(包括循环),在回跳的下一句代码上单击并按键盘上的“F4”键跳过回跳指令;
  4. OD中的绿色线条表示跳转没有实理,不必理会,红色线条表示跳转已经实现;
  5. 如果刚载入程序的时候,在附近有一个CALL指令,那么就要按键盘上的“F7”键跟进这个CALL内,不然程序很容易运行起来;
  6. 在跟踪的时候,如果执行某个CALL指令后就运行,一定要按键盘上的“F7”键进入这个CALL之内再单步跟踪;
  7. 遇到在popad指令下的远转移指令时,要格处注意,因为这个远转移指令的目的地很可能就是OEP。

下面做一个简单的测试。首先下载UPX,可以从UPX官方网站http://upx.sourceforge.net/下载,然后给Windows自带的记事本加一个壳,之后载入OllyDbg自己脱壳测试。按照上面所说的步骤,一路F7单步,遇到系统的API可以F8步过,遇到向上跳转的地方可以来到下一行按F4,其中有的地方如果步过了,会运行起程序,所以要单步跟进:

010141D0    8807            mov byte ptr ds:[edi],al
010141D2    47              inc edi
010141D3    49              dec ecx
010141D4  ^ 75 F7           jnz Xnotepad.010141CD
010141D6  ^ E9 63FFFFFF     jmp notepad.0101413E                     ; 需要F7进入
010141DB    90              nop                                      ; 到这里运行程序
010141DC    8B02            mov eax,dword ptr ds:[edx]

如上面的代码中如果F4执行到010141DB处,程序已经运行起来了,所以010141D6这个地方要F7跟进。之后会第二次来到这里,但程序会跳到010141DC处。之后会再次遇到一个地方,如果F4会运行程序:

0101422C    8B07            mov eax,dword ptr ds:[edi]               ; 外层循环
0101422E    09C0            or eax,eax
01014230    74 3C           je Xnotepad.0101426E                     ; 外层循环结束
01014232    8B5F 04         mov ebx,dword ptr ds:[edi+0x4]
01014235    8D8430 14AE0100 lea eax,dword ptr ds:[eax+esi+0x1AE14]
0101423C    01F3            add ebx,esi
0101423E    50              push eax
0101423F    83C7 08         add edi,0x8
01014242    FF96 DCAE0100   call dword ptr ds:[esi+0x1AEDC]          ; kernel32.LoadLibraryA
01014248    95              xchg eax,ebp
01014249    8A07            mov al,byte ptr ds:[edi]                 ; 内层循环
0101424B    47              inc edi
0101424C    08C0            or al,al
0101424E >^ 74 DC           je Xnotepad.0101422C                     ; 内层循环结束
01014250    89F9            mov ecx,edi
01014252    57              push edi
01014253    48              dec eax
01014254    F2:AE           repne scas byte ptr es:[edi]
01014256    55              push ebp
01014257    FF96 E0AE0100   call dword ptr ds:[esi+0x1AEE0]          ; kernel32.GetProcAddress
0101425D    09C0            or eax,eax
0101425F    74 07           je Xnotepad.01014268
01014261    8903            mov dword ptr ds:[ebx],eax
01014263    83C3 04         add ebx,0x4
01014266  ^ EB E1           jmp Xnotepad.01014249
01014268    FF96 F0AE0100   call dword ptr ds:[esi+0x1AEF0]          ; 如执行到这里则运行程序
0101426E    8BAE E4AE0100   mov ebp,dword ptr ds:[esi+0x1AEE4]

在上面的代码中,如果在01014268地址处按下F4,则会运行程序。实际上可以看到之前的代码是一个双重循环,外层循环通过LoadLibrary来获取DLL的句柄,内层循环通过GetProcAddress来获取函数的指针,这里实际上是在填充IAT。当外层循环结束时,会跳到0101426E地址处,也就是上面的代码中的最后一行。

再跟一段距离,就可以看到如下代码了:

01014298    53              push ebx
01014299    57              push edi
0101429A    FFD5            call ebp
0101429C    58              pop eax
0101429D    61              popad                                    ; 看到popad了
0101429E    8D4424 80       lea eax,dword ptr ss:[esp-0x80]
010142A2    6A 00           push 0x0
010142A4    39C4            cmp esp,eax
010142A6  ^ 75 FA           jnz Xnotepad.010142A2
010142A8    83EC 80         sub esp,-0x80
010142AB  - E9 ED30FFFF     jmp notepad.0100739D                     ; 跳转到OEP
010142B0    48              dec eax


看到popad,就应该知道OEP马上要到了(这里又牵扯到ESP定律脱壳了,ESP脱壳原理:广义ESP定律),继续往下就会看到一个jmp远眺,经验表明,F7来到jmp的目标地址,那就是程序的OEP,这里OEP的RVA是739D。之后就可以直接用Ollydbg的插件把内存dump出来,也可以用LordPE进行dump,用ImportREC修复导入表。脱壳后的程序可以正常运行。

用PEiD查看没有加壳的原始程序,发现OEP也是739D。
Ollydbg单步跟踪法手脱UPX壳
P.S.
传了一份《杀不死的秘密》PDF版本到DBank,比较清晰,排版也还好,比以前找的好多了:http://dl.dbank.com/c09oiogcl4
看雪论坛《UPX脱壳详细分析》:http://bbs.pediy.com/showthread.php?p=843702


觉得文章还不错?点击此处对作者进行打赏!


本文地址: 程序人生 >> 单步跟踪法手脱UPX壳
作者:代码疯子(Wins0n) 本站内容如无声明均属原创,转载请保留作者信息与原文链接,谢谢!


更多



分类: 逆向调试 标签: , , ,
  1. 2011年11月29日20:24 | #1

    很不错呀,写的很细致了,估计在学了很多底层的东西之后,再来看这些东西是不是很清晰呀。

    [回复]

    代码疯子 回复:

    @胡阳, 估计是吧,虽然现在我还在菜鸟阶段徘徊……我看的东西很乱,感觉就是个实在的码农,你看的东西属于上层了,感觉更加利于发展。光是编码感觉还是不够,要懂设计、懂管理、懂用户体验之类的,呵呵,要向你学习

    [回复]

    代码疯子 回复:

    @胡阳, 不管是什么东西,看多了就熟悉了。熟能生巧

    [回复]

  2. 2011年12月1日11:02 | #2

    额。。。。看个人兴趣和客观因素了,其实我也想深入底层研究一番,但是工作了,没有足够的时间来做这些东西,研究底层的东西需要花费较多的时间吧,并且需要较强的毅力。所以现在根据自己的状况了解一些产品设计的东西,学习这些东西都不用高度集中精力,只需要多思考就行。 [em009]

    [回复]

  3. zihuo
    2013年11月1日13:58 | #3

    我这边有个程序,用peid查壳 显示什么都没有 但是他的section里有 upx0 upx1 upx2 现在就是脱不了这个壳 能不能加下好友 指教一番 qq179325637

    [回复]