刘收获

导航

05 初识加壳脱壳

 (很久以前的学习记录,放到博客上来)
 
1.IsDebuggerPresent()函数(CheckRemoteDebuggerPresent())
    确定调用进程是否由用户模式的调试器调试.


#include "stdafx.h"
#include<windows.h>
#include<stdio.h>
 
int main()
{
if (IsDebuggerPresent())
{
printf("Debugger!\n");
}
else
{
printf("no debugger\n");
}
 
    return 0;
}

VS2015中运行:

图片 


ollydbg中运行:

 图片

 

--------------------------------------------------------------------------------------------------
2.加壳与脱壳

源代码如下:

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
 
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "$packed.exe <password>\n");
return 1;
}
if (IsDebuggerPresent()) {
 
printf("on debugger\n");
return -1;
}
else {
 
if (strcmp(argv[1], "unpacking") == 0) {
printf("correct!\n");
}
else {
printf("auth error\n");
return -1;
}
}
getchar();
return 0;

}

exe文件(未加壳)拖到IDA中反汇编:
 

.text:00411830 ; int __cdecl main(int argc, char **argv)
.text:00411830 _main           proc near               ; CODE XREF: j__mainj
.text:00411830
.text:00411830 var_C0          = byte ptr -0C0h
.text:00411830 argc            = dword ptr  8
.text:00411830 argv            = dword ptr  0Ch
.text:00411830
.text:00411830                 push    ebp
.text:00411831                 mov     ebp, esp
.text:00411833                 sub     esp, 0C0h
.text:00411839                 push    ebx
.text:0041183A                 push    esi
.text:0041183B                 push    edi
.text:0041183C                 lea     edi, [ebp+var_C0]
.text:00411842                 mov     ecx, 30h
.text:00411847                 mov     eax, 0CCCCCCCCh
.text:0041184C                 rep stosd
.text:0041184E                 cmp     [ebp+argc], 2
.text:00411852                 jge     short loc_41187D
.text:00411854                 push    offset _Format  ; "$packed.exe <password>\n"
.text:00411859                 mov     esi, esp
.text:0041185B                 push    2
.text:0041185D                 call    ds:__imp____acrt_iob_func
.text:00411863                 add     esp, 4
.text:00411866                 cmp     esi, esp
.text:00411868                 call    j___RTC_CheckEsp
.text:0041186D                 push    eax             ; _Stream
.text:0041186E                 call    j__fprintf
.text:00411873                 add     esp, 8
.text:00411876                 mov     eax, 1
.text:0041187B                 jmp     short loc_4118F6
.text:0041187D ; ---------------------------------------------------------------------------
.text:0041187D
.text:0041187D loc_41187D:                             ; CODE XREF: _main+22j
.text:0041187D                 mov     esi, esp
.text:0041187F                 call    ds:__imp__IsDebuggerPresent@0 ; IsDebuggerPresent()
.text:00411885                 cmp     esi, esp
.text:00411887                 call    j___RTC_CheckEsp
.text:0041188C                 test    eax, eax
.text:0041188E                 jz      short loc_4118A4
.text:00411890                 push    offset aOnDebugger ; "on debugger\n"
.text:00411895                 call    j__printf
.text:0041189A                 add     esp, 4
.text:0041189D                 or      eax, 0FFFFFFFFh
.text:004118A0                 jmp     short loc_4118F6
.text:004118A2 ; ---------------------------------------------------------------------------
.text:004118A2                 jmp     short loc_4118E5
.text:004118A4 ; ---------------------------------------------------------------------------
.text:004118A4
.text:004118A4 loc_4118A4:                             ; CODE XREF: _main+5Ej
.text:004118A4                 push    offset Str2     ; "unpacking"
.text:004118A9                 mov     eax, 4
.text:004118AE                 shl     eax, 0
.text:004118B1                 mov     ecx, [ebp+argv]
.text:004118B4                 mov     edx, [ecx+eax]
.text:004118B7                 push    edx             ; Str1
.text:004118B8                 call    j__strcmp
.text:004118BD                 add     esp, 8
.text:004118C0                 test    eax, eax
.text:004118C2                 jnz     short loc_4118D3
.text:004118C4                 push    offset aCorrect ; "correct!\n"
.text:004118C9                 call    j__printf
.text:004118CE                 add     esp, 4
.text:004118D1                 jmp     short loc_4118E5
.text:004118D3 ; ---------------------------------------------------------------------------
.text:004118D3
.text:004118D3 loc_4118D3:                             ; CODE XREF: _main+92j
.text:004118D3                 push    offset aAuthError ; "auth error\n"
.text:004118D8                 call    j__printf
.text:004118DD                 add     esp, 4
.text:004118E0                 or      eax, 0FFFFFFFFh
.text:004118E3                 jmp     short loc_4118F6
.text:004118E5 ; ---------------------------------------------------------------------------
.text:004118E5
.text:004118E5 loc_4118E5:                             ; CODE XREF: _main+72j
.text:004118E5                                         ; _main+A1j
.text:004118E5                 mov     esi, esp
.text:004118E7                 call    ds:__imp__getchar
.text:004118ED                 cmp     esi, esp
.text:004118EF                 call    j___RTC_CheckEsp
.text:004118F4                 xor     eax, eax
.text:004118F6
.text:004118F6 loc_4118F6:                             ; CODE XREF: _main+4Bj
.text:004118F6                                         ; _main+70j ...
.text:004118F6                 pop     edi
.text:004118F7                 pop     esi
.text:004118F8                 pop     ebx
.text:004118F9                 add     esp, 0C0h
.text:004118FF                 cmp     ebp, esp
.text:00411901                 call    j___RTC_CheckEsp
.text:00411906                 mov     esp, ebp
.text:00411908                 pop     ebp
.text:00411909                 retn

.text:00411909 _main           endp 

这段汇编代码开起来简明清晰。 


接下来用UPX为exe文件加壳(用cmd命令行执行的时候被“拒绝访问”了,最后直接拿exe文件往upx.exe里拖,压缩成功了): 

压缩过的exe文件在IDA中的流程视图:

图片

图片
 

里面的代码也变成这样的了(截取) :

UPX1:004204C0 ; ---------------------------------------------------------------------------
UPX1:004204C2                 align 8
UPX1:004204C8
UPX1:004204C8 loc_4204C8:                             ; CODE XREF: start:loc_4204D9j
UPX1:004204C8                 mov     al, [esi]
UPX1:004204CA                 inc     esi
UPX1:004204CB                 mov     [edi], al
UPX1:004204CD                 inc     edi
UPX1:004204CE
UPX1:004204CE loc_4204CE:                             ; CODE XREF: start+B6j
UPX1:004204CE                                         ; start+CDj
UPX1:004204CE                 add     ebx, ebx
UPX1:004204D0                 jnz     short loc_4204D9
UPX1:004204D2
UPX1:004204D2 loc_4204D2:                             ; CODE XREF: start+10j
UPX1:004204D2                 mov     ebx, [esi]
UPX1:004204D4                 sub     esi, 0FFFFFFFCh
UPX1:004204D7                 adc     ebx, ebx
UPX1:004204D9
UPX1:004204D9 loc_4204D9:                             ; CODE XREF: start+20j
UPX1:004204D9                 jb      short loc_4204C8
UPX1:004204DB                 mov     eax, 1
UPX1:004204E0
UPX1:004204E0 loc_4204E0:                             ; CODE XREF: start+3Fj
UPX1:004204E0                                         ; start+4Aj
UPX1:004204E0                 add     ebx, ebx
UPX1:004204E2                 jnz     short loc_4204EB
UPX1:004204E4                 mov     ebx, [esi]
UPX1:004204E6                 sub     esi, 0FFFFFFFCh
UPX1:004204E9                 adc     ebx, ebx
UPX1:004204EB
UPX1:004204EB loc_4204EB:                             ; CODE XREF: start+32j
UPX1:004204EB                 adc     eax, eax
UPX1:004204ED                 add     ebx, ebx
UPX1:004204EF                 jnb     short loc_4204E0
UPX1:004204F1                 jnz     short loc_4204FC
UPX1:004204F3                 mov     ebx, [esi]
UPX1:004204F5                 sub     esi, 0FFFFFFFCh
UPX1:004204F8                 adc     ebx, ebx
UPX1:004204FA                 jnb     short loc_4204E0

 (现在想要去解压缩,因为upx命令行输入总是被拒绝访问,解决无果,无奈发现好像存在带有窗口界面的upx,按百度排序的第一个下载——全是一群流氓,捆绑一堆软件安装,百度流氓头子!最后下载的upx还总是error,最后在360上查了下,发现360竟然有这款软件,UPX Easy GUI,今天感谢360的良心!)

Depreess脱壳后的exe文件不如原来那样清晰直观了:
流程试图:

图片

反汇编代码(截取): 
.text:0041104B ; [00000005 BYTES: COLLAPSED FUNCTION start. PRESS CTRL-NUMPAD+ TO EXPAND]
.text:00411050 ; [00000005 BYTES: COLLAPSED FUNCTION j_wcscpy_s. PRESS CTRL-NUMPAD+ TO EXPAND]
.text:00411055 ; ---------------------------------------------------------------------------
.text:00411055                 jmp     sub_414E40
.text:0041105A
.text:0041105A ; =============== S U B R O U T I N E =======================================
.text:0041105A
.text:0041105A ; Attributes: thunk
.text:0041105A
.text:0041105A sub_41105A      proc near               ; CODE XREF: .text:00411C1Ap
.text:0041105A                                         ; .text:00411C4Ap
.text:0041105A                 jmp     sub_411BF0
.text:0041105A sub_41105A      endp
.text:0041105A
.text:0041105F
.text:0041105F ; =============== S U B R O U T I N E =======================================
.text:0041105F
.text:0041105F ; Attributes: thunk
.text:0041105F
.text:0041105F sub_41105F      proc near               ; CODE XREF: .text:00411CA1p
.text:0041105F                                         ; .text:00411CC5p ...
.text:0041105F                 jmp     sub_413650
.text:0041105F sub_41105F      endp
.text:0041105F
.text:00411064
.text:00411064 ; =============== S U B R O U T I N E =======================================
.text:00411064
.text:00411064 ; Attributes: thunk
.text:00411064
.text:00411064 sub_411064      proc near               ; CODE XREF: sub_412D00+6p
.text:00411064                                         ; .text:00412D63p ...
.text:00411064                 jmp     sub_414820
.text:00411064 sub_411064      endp
.text:00411064
.text:00411069
.text:00411069 ; =============== S U B R O U T I N E =======================================
.text:00411069
.text:00411069 ; Attributes: thunk
.text:00411069
.text:00411069 sub_411069      proc near               ; CODE XREF: sub_411BA0+1Ap
.text:00411069                 jmp     sub_4123C0
.text:00411069 sub_411069      endp
.text:00411069 

--------------------------------------------------------------------------------------------------------
3.尝试手动脱壳
 
在ollydbg中打开upx加壳过的exe文件,开头是这样的:

00FC03F0 > $ 60             PUSHAD
00FC03F1   . BE 00E0FB00    MOV ESI,Pack.00FBE000
00FC03F6   . 8DBE 0030FEFF  LEA EDI,DWORD PTR DS:[ESI+FFFE3000]
00FC03FC   . 57             PUSH EDI
00FC03FD   . 83CD FF        OR EBP,FFFFFFFF
00FC0400   > EB 10          JMP SHORT Pack.00FC0412

首先PUSHAD将所有寄存器的值复制都栈中,F8单步执行,不远处进入了一个人循环:
(PUSHAD指令在堆栈中按顺序压入下列寄存器:EAX,ECX,EDX,EBX,ESP,EBP,ESI和EDI.
POPAD指令则是PUSHAD指令的逆操作。POPAD指令按照与上面相反的顺序依次弹出寄存器的值。
顺序为 EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX.)


00FC0408   > 8A06           MOV AL,BYTE PTR DS:[ESI]
00FC040A   . 46             INC ESI
00FC040B   . 8807           MOV BYTE PTR DS:[EDI],AL
00FC040D   . 47             INC EDI
00FC040E   > 01DB           ADD EBX,EBX
00FC0410   . 75 07          JNZ SHORT Pack.00FC0419
00FC0412   > 8B1E           MOV EBX,DWORD PTR DS:[ESI]
00FC0414   . 83EE FC        SUB ESI,-4
00FC0417   . 11DB           ADC EBX,EBX
00FC0419   >^72 ED          JB SHORT Pack.00FC0408

这里的逻辑就是从esi中向edi中拷贝数据,
还可以从窗口中看到edi的地址是从00FC03F0开始的。

向下找到 POPAD命令,F2设置断点,F9执行到断点处。

 00FC056B   . 61             POPAD
 00FC056C   . 8D4424 80      LEA EAX,DWORD PTR SS:[ESP-80]
 00FC0570   > 6A 00          PUSH 0
 00FC0572   . 39C4           CMP ESP,EAX
 00FC0574   .^75 FA          JNZ SHORT Pack.00FC0570
 00FC0576   . 83EC 80        SUB ESP,-80
 00FC0579   .-E9 CD0AFFFF    JMP Pack.00FB104B

执行到JMP Pack.00FB104B,
跳转到了:
00FB104B   E9 50100000      JMP Pack.00FB20A0
00FB1050   E9 553D0000      JMP Pack.00FB4DAA                        ; JMP to ucrtbase.wcscpy_s
 
 
这时打开菜单栏上Plug_in   >   OllyDump   >   Dump debugged process,进行脱壳,但是......多歧路今安在啊!总是无法读内存,显示“Bad DOS Signature”,我也很无奈,尚未解决。
图片

按道理, pushad和popad之间的代码就是解压缩,在解压缩之前,先将寄存器状态保存到栈,解压缩结束之后在从栈中读取,恢复寄存器状态,从而运行真正的代码。
所以手动脱壳,关键在于找到 解压结束,程序开始的瞬间。

 

posted on 2017-11-19 10:53  沉疴  阅读(1318)  评论(0编辑  收藏  举报