• 菜鸟脱壳之脱壳的基础知识(一)


    脱壳技术

    一、基础知识
    壳的定义:在一些计算机软件里也有一段专门负责保护软件不被非法修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。由于这段程序和自然界的壳在功能上有很多相同的地方,基于命名的规则,大家就把这样的程序称为“壳”了,无非是保护、隐蔽壳内的东西。而从技术的角度出发,壳是一段执行于原始程序前的代码。原始程序的代码在加壳的过程中可能被压缩、加密……。当加壳后的文件执行时,壳-这段代码先于原始程序运行,他把压缩、加密后的代码还原成原始程序代码,然后再把执行权交还给原始代码。 软件的壳分为加密壳、压缩壳、伪装壳、多层壳等类,目的都是为了隐藏程序真正的OEP(入口点,防止被破解)。
    1.1.1  壳的加载过程
    1.保存入口函数
    加壳的程序首先会初始化所有寄存器的值,在外壳执行完毕后,会恢复各个寄存器的内容,再跳到OEP去执行程序!通常加壳程序会用pushad / pushfd进行保存现场,用popad / popfd来恢复现场,例如:我用delphi7.0程序加了一个UPX的壳!他的入口就是利用Pushad来保存的现场!
    004629D0 >  60                     pushad    //利用pushad来进行保存现场
    004629D1    BE 00F04300           mov     esi, 0043F000
    004629D6    8DBE 0020FCFF        lea     edi, dword ptr [esi+FFFC2000]
    004629DC    C787 9CC00400 7>     mov    dword ptr [edi+4C09C], 46CD167B
    004629E6    57                     push    edi
    004629E7    83CD FF               or      ebp, FFFFFFFF
    004629EA    EB 0E                 jmp     short 004629FA
    在UPX的外壳结尾:
    00462B5F    8D87 1F020000         lea     eax, dword ptr [edi+21F]
    00462B65    8020 7F                and     byte ptr [eax], 7F
    00462B68    8060 28 7F             and     byte ptr [eax+28], 7F
    00462B6C    58                     pop     eax
    00462B6D    50                     push    eax
    00462B6E    54                     push    esp
    00462B6F    50                     push    eax
    00462B70    53                     push    ebx
    00462B71    57                     push    edi
    00462B72    FFD5                  call    ebp
    00462B74    58                     pop     eax
    00462B75    61                     popad //利用popad把所有的寄存器都恢复!
    2.获取壳自己所需要的函数
    一般外壳的输入表都只有GetMoudleHandleA、GetProcAddress和LoadLibrary这几个API函数!有的甚至只有Kernel32.dll以及GetProcAddress,如果壳程序需要加载其他的函数,就可以调用LoadLibrary将DLL映射到调用进程的地址空间中,函数返回的hinstance值用于标识文件映像映射到虚拟内存地址:我们查看MSDN,找到LoadLibrary函数的原型:
    HINSTANCE LoadLibrary(   LPCTSTR lpLibFileName   // address of filename of executable module);
    当DLL文件已经被映射到调用进程的地址空间中,就可以掉用GetMoudleHandleA了,调用此函数可以活的DLL模块的句柄,GetMoudleHandleA的函数原型是:
    HMODULE GetModuleHandle (
      LPCTSTR lpModuleName); 
    当Dll模块被加载后,就可以调用GetProcAddress函数来获取输入函数的地址,GetProcAddress函数的原型是:
    FARPROC GetProcAddress(   HMODULE hModule,   // handle to DLL module      LPCSTR lpProcName   // name of function );
    经过这三个函数的调用,就可以获得想要的函数API,外壳中所用到的其他的API基本都是利用这三个函数的搭配来进行调用的!但是有的高强度的加密壳,作者可能连最基本的GetProcAddress都不用,而是自己编写一个类似与GetProcAddress函数的函数来进行替换,这样可以使函数使用的隐蔽性大大提高!
    举个例子,我用Delphi7.0加的UPX的壳,我们来看看他的外壳是不是用的我们上文提到的几个函数:

    UPX的外壳用到了LoadLibrary、GetProcAddresss等函数,和我们上文提到的函数差不多!
    3.解密各个加壳软件的区段的数据
    壳会保护被加壳程序的区块的数据和代码,会加密被加壳程序的各个区块,在程序执行时,外壳会对这些被加密的数据进行解密,从而能够让被加密的程序可以正常运行!壳会按照被加密的区块的顺序进行解密,把解密的区块的数据按照区块的定义放在合适的内存位置!
    4.初始化IAT
    程序在加壳的时候,加壳程序自己构造了一个输入表,并把PE头中的输入表的指针指向了自己构造了的输入表,所以,PE装载器会对自己建立的输入表进行了填写,那么原来的IAT是通过PE装载器来实现的,可是现在就只能依靠外壳来填写PE输入表,外壳只需要对新输入表结构从头到尾扫描一遍,对每个DLL的引入的所有函数重新获取地址,并填写IAT!
    5.跳到OEP
    当外壳的执行完毕后,会跳到原来的程序的入口点,即Entry Point,也可以称作OEP!当一般加密强度不是很大的壳,会在壳的末尾有一个大的跨段,跳向OEP,类似一个壳与程序入口点的“分界线”!例如:
    00462B74    58                 pop     eax
    00462B75    61                 popad
    00462B76    8D4424 80         lea     eax, dword ptr [esp-80]
    00462B7A    6A 00              push    0
    00462B7C    39C4              cmp     esp, eax
    00462B7E  ^ 75 FA              jnz     short 00462B7A
    00462B80    83EC 80           sub     esp, -80
    00462B83  ^ E9 109FFEFF       jmp     0044CA98  //大的跨段,此时的EIP是00462B83,而将要跳到的是0044CA98,说明这里是一个大的跨段,是个分界点!
    有的加密壳会把程序的入口点挪到壳段,并把这段代码给清除掉,就是我们称作的“Stolen Code”,这样壳与程序就部分彼此,加大了对脱壳的难度。(当然,我们可以把清除掉的OEP补回来!然后再进行脱壳!有的壳可能会利用虚拟机将入口出给VM掉,都是需要我们手动修复的!)

    总结:
    4.壳的加载过程:首先是保存现场 ==》获取壳程序自己所需要的函数(请记住这几个函数) ==》解密数据 ==》初始化IAT ==》跳到OEP ==》进行脱壳、修复




    提供一份附件,可以直接观看

    http://www.2cto.com/uploadfile/2012/1202/20121202071728354.zip

  • 相关阅读:
    实现一个简易版的react
    浅学virtualDom和diff算法
    148. 排序链表 归并排序 | 快速排序
    OC中的NSDictionary和NSMutableDictionary
    OC中的block
    OC中的category&Extension
    OC中判断方法是否实现
    OC的分组导航标记
    OC中程序的内存分布&类加载
    OC中的@property和@synthesize
  • 原文地址:https://www.cnblogs.com/Fightingbirds/p/3172892.html
Copyright © 2020-2023  润新知