CN103077332A - 一种运行含有自校验的加壳程序的方法和装置 - Google Patents

一种运行含有自校验的加壳程序的方法和装置 Download PDF

Info

Publication number
CN103077332A
CN103077332A CN2012105872089A CN201210587208A CN103077332A CN 103077332 A CN103077332 A CN 103077332A CN 2012105872089 A CN2012105872089 A CN 2012105872089A CN 201210587208 A CN201210587208 A CN 201210587208A CN 103077332 A CN103077332 A CN 103077332A
Authority
CN
China
Prior art keywords
function
hook function
original program
file
instruction
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
CN2012105872089A
Other languages
English (en)
Other versions
CN103077332B (zh
Inventor
陆舟
于华章
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Feitian Technologies Co Ltd
Original Assignee
Feitian Technologies Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Feitian Technologies Co Ltd filed Critical Feitian Technologies Co Ltd
Priority to CN201210587208.9A priority Critical patent/CN103077332B/zh
Publication of CN103077332A publication Critical patent/CN103077332A/zh
Application granted granted Critical
Publication of CN103077332B publication Critical patent/CN103077332B/zh
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Images

Landscapes

  • Storage Device Security (AREA)

Abstract

本发明公开一种运行含有自校验的加壳程序的方法和装置,该方法包括:壳将原程序加载到内存中,钩子函数等待被调用,当钩子函数被调用时,执行相应操作,将结果返回给原程序。本发明公开的一种运行含有自校验的加壳程序的方法和装置,在加壳程序运行时,使加壳程序通过自校验,保证了加壳后的程序的安全性。

Description

一种运行含有自校验的加壳程序的方法和装置
技术领域
本发明涉及软件保护领域,尤其涉及一种运行含有自校验的加壳程序的方法和装置。
背景技术
自校验是一种用于在软件运行时检查软件自身是否被修改的方法。例如,CRC(Cyclic Redundancy Check,循环冗余校验码)就是数据通信领域中最常用的一种差错校验码,可以用来判断软件自身是否被破解或者破坏。当软件被修改后,校验出的CRC值就和原来的CRC值不同,从而判断出软件被改动。因为CRC校验的实现简单,相对比较安全,所以这种方法广泛的应用在软件行业。加壳就是对可执行程序进行代码段、数据段加密和压缩,是一种保护可执行文件的常用手段。加壳的目的是阻止对软件的反汇编分析或者动态分析,这种技术常用来保护软件,防止软件被破解。而对于含有自校验的加壳程序,加壳后的软件由于对软件进行加密和压缩,校验出来的值就和以前的不同,因此无法通过自校验。
现有技术运行含有自校验的加壳程序的方法是:在运行期间,壳把原程序释放到硬盘上,再通过创建新的进程或系统内存加载技术运行原程序。这种技术的缺点是:原程序被释放到了硬盘上,原程序可以通过一些工具被找到原程序,在以后的使用过程直接使用原程序即可,加壳技术没有起到保护原程序的作用。
发明内容
本发明的目的是为了克服现有技术的不足,提供一种运行含有自校验的加壳程序的方法和装置,提高了加壳程序的安全性。
本发明提供的一种运行含有自校验的加壳程序的方法,包括:
步骤S1:壳获取指定接口函数的内存地址;
步骤S2:所述壳将所述指定接口函数中的部分指令替换为跳转到对应的钩子函数的跳转指令,将所述指定接口函数的所述部分指令保存到与所述指定接口函数对应的钩子函数的代码存储区中,再加入跳转回对应的所述接口函数的跳转指令,所述壳获取加壳程序在存储设备上的访问路径,将加密后的原程序解密到内存中;
步骤S3:所述壳将控制权交给所述原程序的入口点;
步骤S4:所述钩子函数等待被调用;
当第一钩子函数被调用时,所述第一钩子函数调用访问文件函数,返回调用结果,判断所述访问文件函数的位置参数是否与所述加壳程序在所述存储设备上的访问路径一致,若一致则判断所述调用结果是否包含第一句柄,是则保存所述第一句柄,所述第一钩子函数结束,否则所述第一钩子函数结束;若不一致则所述第一钩子函数结束;
当第二钩子函数被调用时,所述第二钩子函数读取获取文件大小函数中的句柄参数,判断所述句柄参数是否为保存的所述第一句柄,是则所述第二钩子函数调用获取文件大小函数,获取第一文件大小,对所述第一文件大小进行计算得到第二文件大小,将所述第二文件大小返回给所述原程序,所述第二钩子函数结束;否则,所述第二钩子函数调用所述获取文件大小函数,返回调用结果,所述第二钩子函数结束;
当第三钩子函数被调用时,所述第三钩子函数读取读文件函数中的句柄参数,判断所述句柄参数是否为保存的所述第一句柄,是则执行步骤S5,否则,所述第三钩子函数调用所述读文件函数读取相应内容,将读取到的内容返回给所述原程序,所述第三钩子函数结束;
当第四钩子函数被调用时,
所述第四钩子函数调用创建文件映射函数,返回调用结果,判断创建文件映射函数的句柄参数是否与保存的所述第一句柄一致,若一致则判断所述调用结果是否包含映射文件句柄,是则保存所述映射文件句柄,所述第四钩子函数结束,否则所述第四钩子函数结束;若不一致则所述第四钩子函数结束;
当第五钩子函数被调用时,所述第五钩子函数读取所述映射文件函数中的句柄参数,判断所述句柄参数是否为保存的所述映射文件句柄,是则所述第五钩子函数调用所述映射文件函数,根据壳的长度和加密头的大小将所述原程序中的与所述句柄参数对应的内容映射到所述内存,对所述内存中映射到的内容进行解密,将解密后的内容返回给所述原程序,所述第五钩子函数结束;否则,所述第五钩子函数将与所述句柄参数对应的内容映射到所述内存,返回所述映射的内容,所述第五钩子函数结束;
步骤S5:所述第三钩子函数判断将要读取的内容的大小是否在所述加密后的原程序的大小范围内,是则所述第三钩子函数调用读文件函数,根据壳的长度和加密头的大小读取所述原程序中的相应内容,对读取到的内容进行解密,并将解密后的内容返回给所述原程序,所述第三钩子函数结束;否则,所述第三钩子函数调用读文件函数,读取相应内容,对所述读取到的内容进行解密,并将解密后的内容返回给所述原程序,所述第三钩子函数结束。
所述步骤S1中所述指定接口函数为所述访问文件函数或所述获取文件大小函数或所述读文件函数或所述创建文件映射函数或所述映射文件函数。
所述步骤S2包括:
步骤S2-1:所述壳获取所述跳转到对应的钩子函数的指令的长度;
步骤S2-2:所述壳从所述指定接口函数中的第一条指令中解析出完整的汇编指令,并将所述汇编指令的长度作为当前指令长度;
步骤S2-3:所述壳判断当前指令长度是否小于所述跳转到对应的钩子函数的指令的长度,是则执行步骤S2-4,否则执行步骤S2-5;
步骤S2-4:所述壳将所述指定接口函数中的下一条指令解析出完整的汇编指令,用所述汇编指令的长度与当前指令长度的和更新当前指令长度,执行步骤S2-3;
步骤S2-5:所述壳读取所有的汇编指令并将其存储到所述钩子函数的代码存储区,并在所述代码存储区的指令后加入一条跳转指令,所述跳转指令用于跳转到与所述指定接口函数中被读取的指令相邻的指令,并把所述代码存储区的属性设置为可执行可读;
步骤S2-6:所述壳将所述接口的代码属性修改为可写,将所述指定接口函数中被读取的指令替换为跳转到所述对应的钩子函数指令,并恢复所述接口的代码属性;
步骤S2-7:所述壳获取所述加壳程序在存储设备上的访问路径;
步骤S2-8:所述壳根据第一偏移地址读取加密头,获取所述加密头的大小和加密原程序所使用的密钥;
步骤S2-9:所述壳使用所述密钥对加密后的原程序进行解密;
步骤S2-10:所述壳读取并存储所述原程序的关键数据;所述关键数据包括所述原程序中节的数目、原程序入口点、原程序基址、指向引入表和重定位表的数据目录、节表数据结构;
步骤S2-11:所述壳读取所述关键数据中的所述节表数据结构,获取所述原程序的各个节在所述内存中的布局,并按照所述布局将所述原程序的各个节加载到所述内存中;
步骤S2-12:所述壳读取所述关键数据中的所述引入表,获取所述原程序各个节所需的动态链接库和所需动态链接库中的函数;
步骤S2-13:所述壳将所述动态链接库加载到所述内存中,获取所述关键数据中各个节所需动态链接库中的函数在所述内存中的地址,将所述地址写入相应的节中;
步骤S2-14:所述壳比较所述原程序加载到所述内存后的程序基址与所述关键数据中的所述原程序基址是否相同,是则执行步骤S2-16,否则执行步骤S2-15;
步骤S2-15:所述壳找到需要被重新定位的地址,根据所述原程序加载到所述内存后的所述程序基址与所述原程序基址对需要被重新定位的地址进行重定位,顺序执行步骤S2-16;
步骤S2-16:所述壳修改所述内存中节的属性。
所述步骤S4还包括:当第六钩子函数被调用时,所述第六钩子函数修改所述接口代码属性,将所述钩子函数代码存储区内的指定接口函数的指令写回到对应的所述接口函数中的相应位置,删除所述指定接口函数中所述跳转到钩子函数指令,并恢复所述接口代码属性,调用退出进程函数,所述第六钩子函数结束。
所述步骤S4中当第五钩子函数被调用时,具体包括:
步骤S4-1:所述第五钩子函数获取所述映射文件函数中的句柄参数,判断所述句柄参数是否为所述映射文件句柄,是则执行步骤S4-3,否则执行步骤S4-2;
步骤S4-2:所述第五钩子函数调用所述第五钩子函数的代码存储区中的映射文件函数,将与所述句柄参数对应的内容映射到内存,所述第五钩子函数结束;
步骤S4-3:所述第五钩子函数用所述映射文件偏移地址加上所述壳的长度更新映射文件的偏移地址,用映射文件大小加上加密头的长度更新映射文件大小;
步骤S4-4:所述第五钩子函数调用所述第五钩子函数的代码存储区内的所述映射文件函数,根据更新后的映射文件偏移地址和更新后的映射文件大小读取相应内容并将其映射到所述内存;
步骤S4-5:所述第五钩子函数读取所述加密头并对其进行校验,获取加密原程序的密钥;
步骤S4-6:所述第五钩子函数对映射到所述内存中的内容进行解密,将解密后的内容返回给所述原程序,所述第五钩子函数结束。
所述步骤S5包括:
步骤S5-1:所述第三钩子函数判断所述将要读取的内容的大小是否在所述加密后的原程序的大小范围内,是则执行步骤S5-3,否则执行步骤S5-2;
步骤S5-2:所述第三钩子函数调用所述第三钩子函数的代码存储区内的读文件函数,读取相应内容,对读取到的内容进行解密,并将解密后的内容返回给所述原程序,所述第三钩子函数结束;
步骤S5-3:所述第三钩子函数把待读取位置偏移加上所述壳的长度;
步骤S5-4:所述第三钩子函数调用所述代码存储区中的读文件函数读取加密头并对其进行校验,并获得加密原程序的密钥,同时获得所述加密头的大小,将待读取位置偏移加上加密头的大小;
步骤S5-5: 所述第三钩子函数根据待读取位置偏移读取加密后的原程序;
步骤S5-6:所述第三钩子函数对读取到的内容进行解密,并将解密后的内容返回给原程序,所述第三钩子函数结束。
一种运行含有自校验的加壳程序的装置,所述装置包括获取模块,修改模块,解密模块,加载模块,转交模块,访问文件模块,获取文件大小模块,读文件模块,创建文件映射模块,映射文件模块;
所述获取模块,用于获取指定接口函数的内存地址;
所述修改模块,用于修改所述指定接口函数中的指令,修改对应的钩子函数的代码存储区中的指令;
所述解密模块,用于获取加壳程序在存储设备上的访问路径,将加密后的原程序解密到内存中;
所述加载模块,用于将所述解密后的原程序加载到所述内存中;
所述转交模块,用于将控制权交给所述原程序的入口点;
所述访问文件模块,用于
当第一钩子函数被调用时,所述第一钩子函数调用访问文件函数,返回调用结果,判断所述访问文件函数的位置参数是否与所述加壳程序在所述存储设备上的访问路径一致,若一致则判断所述调用结果是否包含第一句柄,是则保存所述第一句柄,所述第一钩子函数结束,否则所述第一钩子函数结束;若不一致则所述第一钩子函数结束;
所述获取文件大小模块,用于当第二钩子函数被调用时,第二钩子函数读取获取文件大小函数中的句柄参数,判断所述句柄参数是否为保存的所述第一句柄,是则所述第二钩子函数调用获取文件大小函数,获取第一文件大小,对所述第一文件大小进行计算得到第二文件大小,将所述第二文件大小返回给所述原程序,所述第二钩子函数结束;否则,所述第二钩子函数调用所述获取文件大小函数,返回调用结果,所述第二钩子函数结束;
所述读文件模块,用于当第三钩子函数被调用时,第三钩子函数读取读文件函数中的句柄参数,判断所述句柄参数是否为保存的所述第一句柄,是则所述第三钩子函数调用读文件函数,读取相应内容,对读取到的内容进行解密,并将解密后的内容返回给所述原程序,所述第三钩子函数结束,否则,所述第三钩子函数调用所述读文件函数读取相应内容,将读取到的内容返回给所述原程序,所述第三钩子函数结束;
所述创建文件映射模块,当第四钩子函数被调用时,所述第四钩子函数调用创建文件映射函数,返回调用结果,判断创建文件映射函数的句柄参数是否与保存的所述第一句柄一致,若一致则判断所述调用结果是否包含映射文件句柄,是则保存所述映射文件句柄,所述第四钩子函数结束,否则所述第四钩子函数结束;若不一致则所述第四钩子函数结束;
所述映射文件模块,用于当第五钩子函数被调用时,所述第五钩子函数读取所述映射文件函数中的句柄参数,判断所述句柄参数是否为保存的所述映射文件句柄,是则所述第五钩子函数调用所述映射文件函数,根据壳的长度和加密头的大小将所述原程序中的与所述句柄参数对应的内容映射到所述内存,对所述内存中映射到的内容进行解密,将解密后的内容返回给所述原程序,所述第五钩子函数结束;否则,所述第五钩子函数将与所述句柄参数对应的内容映射到所述内存,返回所述映射的内容,所述第五钩子函数结束。
所述装置包括退出进程模块;
所述退出进程模块,用于当第六钩子函数被调用时,第六钩子函数修改所述接口代码属性,将所述钩子函数代码存储区内的指定接口函数的指令写回到对应的所述接口函数中的相应位置,删除所述指定接口函数中所述跳转到钩子函数指令,并恢复所述接口代码属性,调用退出进程函数,所述第六钩子函数结束。
所述修改模块包括第一获取单元,解析单元,第一判断单元,更新单元,读取单元,写指令单元,属性设置单元;
所述第一获取单元,用于获取所述跳转到对应的钩子函数指令的长度;
所述解析单元,用于从所述指定接口函数中的第一条指令中解析出完整的汇编指令,并将所述汇编指令的长度作为当前指令长度;
所述第一判断单元,用于判断所述当前指令长度是否小于所述跳转到对应的钩子函数指令的长度;
所述更新单元,用于将解析出的下一条汇编指令的长度与当前指令长度的和更新当前指令长度;
所述读取单元,用于读取所有的汇编指令并将其存储到对应的钩子函数的代码存储区;
所述写指令单元,用于在所述钩子函数的代码存储区的指令后写入一个跳转指令,跳转到与所述指定接口函数中被读取的指令相邻的指令,还用于将所述指定接口函数中被读取的指令替换为所述跳转到对应的钩子函数的指令;
所述属性设置单元,用于将所述代码存储区内的属性设置为可执行可读。
所述解密模块包括第二获取单元,解密单元;
所述第二获取单元,用于获取所述加壳程序在存储设备上的访问路径,根据第一偏移地址获取加密头,获取所述加密头的大小和加密原程序所使用的密钥;
所述解密单元,用于使用所述第三获取单元获取的密钥将加密后的原程序解密到所述内存中。
所述加载模块包括存储单元,加载单元,第三获取单元,第二判断单元,重定位单元,属性单元;
所述存储单元,用于读取并存储所述原程序的关键数据;
所述加载单元,用于读取节表数据结构,获取所述原程序的各个节在所述内存中的布局,并按照所述布局将所述原程序的各个节加载到所述内存中,还用于根据引入表获取所述原程序各个节所需的动态链接库和所需动态链接库中的函数;
所述第三获取单元,用于将动态链接库加载到所述内存中,获取关键数据中各个节所需动态链接库中的函数在所述内存中的地址,将所述地址写入相应的节中;
所述第二判断单元,用于比较所述原程序加载到所述内存后的程序基址与原程序基址是否相同;
所述重定位单元,用于找到需要被重新定位的地址,根据所述原程序加载到所述内存后的所述程序基址与存储在头部的所述原程序基址对需要被重新定位的地址进行重定位;
所述属性单元,用于修改所述内存中节的属性。
所述读文件模块包括第三判断单元,读文件单元和第一解密单元;
所述第三判断单元,用于读取读文件函数中的句柄参数,判断句柄参数是否为所述第一句柄,还用于判断将要读取的内容的大小是否在加密后的原程序的大小范围内;
所述读文件单元,用于读取相应内容,将读取到的内容返回给所述原程序;
所述第一解密单元,用于对读取到的内容进行解密。
所述映射文件模块包括第四判断单元,映射文件单元和第二解密单元;
所述第四判断单元,用于获取所述映射文件函数中的句柄参数,判断所述句柄参数是否为所述映射文件句柄;
所述映射文件单元,用于将原程序中的相应内容映射到所述内存,返回所述原程序中的相应内容;
所述第二解密单元,用于对映射到的内容进行解密,返回解密后的内容。本发明与现有技术相比,具有以下优点:
在加壳程序运行时,使加壳程序通过自校验,保证了加壳后的程序的安全性。
附图说明
图1是本发明实施例1提供的一种运行含有自校验的加壳程序的方法流程图;
图2和图3是本发明实施例2提供的一种运行含有自校验的加壳程序的方法流程图;
图4是本发明实施例3提供的一种运行含有自校验的加壳程序的装置方框图。
具体实施方式
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
实施例1
本发明的实施例1提供一种运行含有自校验的加壳程序的方法,如图1所示,本实施例中,加壳后程序由壳、加密头部和加密后的原程序顺序组成,本方法包括:
步骤101:壳获取指定接口函数的内存地址;
步骤102:壳将指定接口函数中的部分指令替换为跳转到对应的钩子函数的跳转指令,将指定接口函数中的部分指令保存到与指定接口函数对应的钩子函数的代码存储区中,再加入跳转回对应的接口函数的跳转指令,壳获取加壳程序在存储设备上的访问路径,将加密后的原程序解密到内存中;
步骤103:壳将控制权交给原程序的入口点;
步骤104:钩子函数等待被调用;
当第一钩子函数被调用时,第一钩子函数调用访问文件函数,返回调用结果,判断访问文件函数的位置参数是否与加壳程序在存储设备上的访问路径一致,若一致则判断调用结果是否包含第一句柄,是则保存第一句柄,第一钩子函数结束,否则第一钩子函数结束;若不一致则第一钩子函数结束;
当第二钩子函数被调用时,第二钩子函数读取获取文件大小函数中的句柄参数,判断该句柄参数是否为保存的第一句柄,是则调用第二钩子函数的代码存储区中的获取文件大小函数,获取第一文件大小,对第一文件大小进行计算得到第二文件大小,将第二文件大小返回给原程序,第二钩子函数结束;否则,第二钩子函数调用获取文件大小函数,返回调用结果,第二钩子函数结束;
当第三钩子函数被调用时,第三钩子函数读取读文件函数中的句柄参数,判断该句柄参数是否为保存的第一句柄,是则执行步骤105,否则,第三钩子函数调用第三钩子函数的代码存储区中的读文件函数,读取相应内容,将读取到的内容返回给原程序,第三钩子函数结束;
当第四钩子函数被调用时,第四钩子函数调用创建文件映射函数,返回调用结果,判断创建文件映射函数的句柄参数是否与保存的第一句柄一致,若一致则判断调用结果是否包含映射文件句柄,是则保存映射文件句柄,第四钩子函数结束,否则第四钩子函数结束;若不一致则第四钩子函数结束;
当第五钩子函数被调用时,第五钩子函数读取映射文件函数中的句柄参数,判断该句柄参数是否为保存的映射文件句柄,是则调用第五钩子函数的代码存储区内的映射文件函数,根据壳的长度和加密头的大小将原程序中的相应内容映射到内存,对映射到的内容进行解密,将解密后的内容返回给原程序,第五钩子函数结束;否则,第五钩子函数调用第五钩子函数的代码存储区中的映射文件函数,将原程序中的相应内容映射到内存,返回映射的内容,第五钩子函数结束;
本实施例中的钩子函数还包括第六钩子函数,当第六钩子函数被调用时,第六钩子函数修改接口代码属性,将第六钩子函数的代码存储区内的指定接口函数的指令写回到对应的接口函数中的相应位置,删除指定接口函数中跳转到钩子函数的指令,并恢复接口代码属性,调用第六钩子函数的代码存储区中的退出进程函数,第六钩子函数结束。
步骤105:第三钩子函数判断将要读取的内容的大小是否在加密后的原程序的大小范围内,是则调用第三钩子函数的代码存储区内的读文件函数,根据壳的长度和加密头的大小读取原程序中的相应内容,对读取到的内容进行解密,并将解密后的内容返回给原程序,第三钩子函数结束;否则,第三钩子函数调用第三钩子函数的代码存储区内的读文件函数,读取相应内容,对读取到的内容进行解密,并将解密后的内容返回给原程序,第三钩子函数结束;
实施例2
本发明的实施例2提供一种运行含有自校验的加壳程序的方法,如图2和图3所示,本实施例中,加壳后程序由壳、加密头部和加密后的原程序顺序组成,本方法包括:
步骤201:壳获取指定的API函数的内存地址;
具体地,本实施例中,步骤201包括:
步骤201-1:壳加载含有需要被修改的API的系统动态库 kernel32.dll;
具体地,本步骤通过调用系统接口LoadLibray完成;
步骤201-2:壳从系统动态库获取需要被修改的API函数的访问地址;
具体地,本步骤通过调用系统接口GetProcAddress完成,根据预定的接口名称检索访问地址;预定接口包括:用于访问文件的函数CreateFile,用于获得文件在硬盘上的大小的函数GetFileSize,用于读文件的函数ReadFile,用于创建文件映射的函数CreateFileMapping,用于把映射文件映射到内存的函数MapViewOfFile;进一步地,预定接口还包括用于退出进程的函数ExitProcess;
例如,以CreateFile函数为例,CreateFile函数对应的内存地址为0x7C810800,如下:
7C810800   mov    edi,edi
7C810802   push    ebp
7C810803   mov    ebp, esp
7C810805   sub     esp,58
7C810808   mov    eax,dword ptr[ebp+18]
7C81080B   dec     eax
……
步骤202:壳判断内存地址是否获取成功,是则执行步骤203,否则壳返回Hook函数初始化失败的信息,结束;
步骤203:壳获取跳转到Hook函数指令的长度;
例如,本实施例中,CreateFile函数跳转到第一Hook函数的汇编指令为jmp    test.00639f20,指令长度为5个字节;
步骤204:壳将API中指定接口函数的第一条指令解析出完整的汇编指令,并将该汇编指令长度作为当前指令长度;
步骤205:壳判断当前指令长度是否小于跳转到Hook函数的汇编指令的长度,是则执行步骤206,否则执行步骤207;
步骤206:壳将API中指定接口函数的下一条指令解析出完整的汇编指令,用该汇编指令长度与当前指令长度的和更新当前指令长度,返回步骤205;
例如,本实施例中,壳共解析出CreateFile函数中的三条指令,如:
7C810800   mov    edi,edi
7C810802   push    ebp
7C810803   mov    ebp, esp
步骤207:壳读取解析出的所有汇编指令到Hook函数的代码存储区,并在此代码存储区的汇编指令后加入一条跳转指令,跳转到API中的指定函数的被读取指令之后相邻的指令,并把此代码存储区内的属性置为可执行可读;
例如,本实施例中,将CreateFile函数的三条指令存储在地址为0x001638EA的内存上,如:
001638EA   mov    edi,edi
001638EC   push    ebp
001638ED   mov    ebp, esp
在三条指令后加入一个跳转指令,跳转到API中CreateFile函数的内存地址为0x7C810805的指令,如:
001638EA   mov    edi,edi
001638EC   push    ebp
001638ED   mov    ebp, esp
001638EF   jmp     dword ptr[1638F5]
001638F5   add     eax, 7C8108
步骤208:壳将API代码属性修改为可写,将API中指定函数的被读取的指令替换为跳转到Hook函数指令,并恢复原API代码属性;
例如:
7C810800   jmp     text.00639F20
7C810805   sub     esp,58
7C810808   mov    eax,dword ptr[ebp+18]
7C81080B   dec     eax
……
步骤209:壳获取加壳程序在存储设备上的访问路径;
具体地,本实施例中,壳通过调用GetModuleFileName函数获得加壳程序在存储设备上的位置;
步骤210:壳根据第一偏移地址读取加密头,获取加密头的大小和加密原程序所使用的密钥;
本实施例中,第一偏移地址为加密头在加壳程序中的文件偏移地址;
具体地,本实施例中,第一偏移地址为0x1000;
具体地,本实施例中,加密头的大小为0x100,即地址0x1000到0x1100的内容;
步骤211:壳使用密钥将加密后的原程序解密到内存中;
步骤212:壳检查内存中原程序的头部是否正确,是则执行步骤213,否则返回错误信息;
具体地,本实施例中,步骤212包括:
步骤212-1:壳读取内存中原程序头部中的DOS头,检查DOS头的前两个字节是否是MZ标识,是则执行步骤212-2,否则返回错误信息;
例如,本实施例中,DOS头如下:
4D  5A  90  00  03  00  00  00  04  0000  00  FF  FF  00  00
BB  00  00  00  00  00  00  00  40  0000  00  00  00  00  00
0000  00  00  00  00  00  00  00  00  0000  00  00  00  00
00  00  00  00  00  00  00  00  00  0000  00  E0  00  00  00
其中,MZ标识为:4D  5A;
步骤212-2:壳读取DOS头的尾部中指向PE头的文件偏移地址,根据该文件偏移地址获得PE头;
步骤212-3:壳读取内存中原程序头部中的PE头,检查PE头的前两个字节是否是PE标识,是则执行步骤213,否则返回错误信息;
例如,本实施例中,PE头如下:
50  45  00  00  4C  01  05  00  CA  B739  4F  00  00  00  00
00  00  00  00  E0  00  02  01
其中,PE标识为:50  45;
步骤213:壳读取并存储原程序头部中的关键数据;
本实施例中,关键数据存储在原程序头部的PE头中;
本实施例中,关键数据包括:原程序中节的数目、原程序入口点、原程序基址、用于指向引入表和重定位表的数据目录,例如:
0007DD37   EntryPoint(rva)
0007D137   EntryPoint(raw)
00400000   ImageBase
004C2000   Size of Image
00001000   Sections Alignment
00000200   File Alignment
0005       Number of sections
步骤214:壳读取关键数据中的节表数据结构,获取原程序的各个节在内存中的布局,并按照该布局将原程序的各个节加载到内存中;
例如,本实施例中,代码节从地址0x501000开始加载,共加载0x1000个字节;
步骤215:壳根据数据目录读取关键数据中的引入表,获取原程序各个节所需的动态链接库和所需动态链接库中的函数;
例如,需加载到内存中的动态链接库中的函数包括:WS2_32.dll、MPR.dll、COMCTL32.dll、VERSION.dll、credui.dll、SETUPAPI.dll、KERNEL.dll、USER32.dll、GDI32.dll、COMDLG32.dll;
步骤216:壳将动态链接库加载到内存中,获取关键数据中各个节所需动态链接库中的函数在内存中的地址,将地址写入相应的节中;
步骤217:壳比较原程序加载到内存后的程序基址与关键数据中的的原程序基址是否相同,是则执行步骤219,否则执行步骤218;
具体地,本实施例中,存储在头部的原程序基址为0x400000,原程序加载到内存后的程序基址为0x500000;
步骤218:壳根据重定位表找到需要被重新定位的地址,根据原程序加载到内存后的程序基址与存储在头部的原程序基址对需要被重新定位的地址进行重定位,执行步骤219;
本实施例中,重定位表指向关于重定位地址的结构,根据此结构找到需要被重新定位的地址;
具体地,在本实施例中,两个基址相差0x100000,则将需要被重新定位的地址加上0x100000,作为重定位后的地址;
步骤219:壳根据节表数据结构中的节属性,修改内存中节的属性;
例如,每个节的节属性如下:
Figure BDA0000267585551
一个节对应的信息如下:
Figure BDA0000267585552
Figure BDA0000267585553
步骤220:壳将控制权交给原程序入口点;
步骤221:Hook函数等待被调用,当第一Hook函数被调用时执行步骤222,当第二Hook函数被调用时执行步骤225,当第三Hook函数被调用时执行步骤228,当第四Hook函数被调用时执行步骤233,当第五Hook函数被调用时执行步骤236,当第六Hook函数被调用时执行步骤239;
步骤222:第一Hook函数调用CreateFile函数,返回调用结果,判断CreateFile函数中的位置参数是否与加壳程序在存储设备上的访问路径一致,是则执行步骤223,否则第一Hook函数结束;
本实施例中,若CreateFile函数中的位置参数为相对路径,则第一Hook函数调用GetCurrentDirectory函数获得当前路径,将其与相对路径进行组合,得到绝对路径;
本实施例中,CreateFile函数中包含跳转到第一Hook函数的跳转指令,所以当CreateFile函数被调用时,第一Hook函数被调用;
本实施例中,CreateFile函数参数包括位置参数,返回值为第一句柄;
步骤223:第一Hook函数判断调用结果是否包含第一句柄,是则执行步骤224,否则第一钩子函数结束;
例如,本实施例中,第一句柄为0xfec;
步骤224:第一Hook函数保存第一句柄,第一Hook函数结束;
步骤225:第二Hook函数获取GetFileSize函数中的句柄参数,判断该句柄参数是否为第一句柄,是则执行步骤226,否则第二Hook函数调用GetFileSize函数,返回调用结果,第二Hook函数结束;
本实施例中,GetFileSize函数中包含跳转到第二Hook函数的跳转指令,所以当GetFileSize函数被调用时,第二Hook函数被调用;
步骤226:第二Hook函数执行代码存储区中的GetFileSize函数的部分指令,跳转到系统的GetFileSize函数的剩余指令并执行剩余指令,获取第一文件大小,对第一文件大小进行计算,得到第二文件大小;
具体地,本实施例中,第二Hook函数将第一文件大小减去壳的长度和加密头的长度,得到第二文件大小;
步骤227:第二Hook函数将第二文件大小返回给原程序,第二Hook函数结束;
步骤228:第三Hook函数获取ReadFile函数中的句柄参数,判断该句柄参数是否为第一句柄,是则执行步骤230,否则执行步骤229;
本实施例中,ReadFile函数中包含跳转到第三Hook函数的跳转指令,所以当ReadFile函数被调用时,第三Hook函数被调用;
具体地,本实施例中,实际进行自校验需要读取的内容的文件偏移地址为0x0到0x3000,原程序的大小为0x3000字节;
本实施例中,ReadFile函数的参数包括:句柄参数、用于接收读取数据的外部缓冲区和读取文件的大小;
本实施例中,第三Hook函数通过调用SetFilePointer函数获得被读取文件的偏移地址;
步骤229:第三Hook函数执行代码存储区中的ReadFile函数的部分指令,跳转到系统的ReadFile函数的剩余指令并执行剩余指令,读取相应内容,将读取到的内容返回给原程序,第三Hook函数结束;
步骤230:第三Hook函数判断将要读取的内容的大小是否在加密后的原程序的大小范围内,是则执行步骤231,否则执行步骤232;
步骤231:第三Hook执行代码存储区内的ReadFile函数的部分指令,跳转到系统的ReadFile函数的剩余指令并执行剩余指令,根据壳的长度和加密头的大小读取原程序的相应内容,对读取到的内容进行解密,并将解密后的内容返回给原程序,第三Hook函数结束;
具体地,本实施例中,该步骤包括:
步骤231-1:第三Hook函数调用SetFilePointer函数把待读取位置偏移加上壳的长度;
本实施例中,壳的长度为0x1000字节;
步骤231-2:第三Hook函数执行代码存储区中的ReadFile函数的部分指令,跳转到系统的ReadFile函数的剩余指令并执行剩余指令,读取加密头,校验加密头有效性并获得加密原程序的密钥,同时获得加密头的大小,将待读取位置偏移加上加密头的大小;
本实施例中,加密头大小为0x100字节;
步骤231-3: 第三Hook函数执行代码存储区内的ReadFile函数的部分指令,跳转到系统的ReadFile函数的剩余指令并执行剩余指令,根据待读取位置偏移读取加密后的原程序;
具体地,本实施例中,第三Hook函数读取的是地址0x1100到地址0x4100之间的内容,此内容在加壳程序中加密的原程序数据文件大小范围内;
步骤231-4:第三Hook函数使用密钥对读取到的内容进行解密,并将解密后的内容返回给原程序,第三Hook函数结束;
步骤232:第三Hook执行代码存储区内的ReadFile函数的部分指令,跳转到系统的ReadFile函数的剩余指令并执行剩余指令,读取相应内容,对读取到的内容进行解密,并将解密后的内容返回给原程序,第三Hook函数结束;
步骤233:第四Hook函数调用CreateFileMapping函数,返回调用结果,判断CreateFileMapping函数中的句柄参数是否与第一句柄一致,是则执行步骤234,否则,第四Hook函数结束;
本实施例中,CreateFileMapping函数中包含跳转到第四Hook函数的跳转指令,所以当CreateFileMapping函数被调用时,第四Hook函数被调用;
本实施例中,CreateFileMapping函数的参数包括句柄参数,返回值为映射文件的句柄;
步骤234:第四Hook函数判断调用结果是否包含映射文件句柄,是则执行步骤235,否则第四Hook函数结束;
例如,本实施例中,映射文件句柄为0xfed;
步骤235:第四Hook函数保存映射文件句柄,第四Hook函数结束;
步骤236:第五Hook函数获取MapViewOfFile函数中的句柄参数,判断该句柄参数是否为映射文件句柄,是则执行步骤238,否则执行步骤237;
本实施例中,MapViewOfFile函数中包含跳转到第五Hook函数的跳转指令,所以当MapViewOfFile函数被调用时,第五Hook函数被调用;
步骤237:第五Hook函数执行代码存储区中的MapViewOfFile函数的部分指令,跳转到系统的MapViewOfFile函数的剩余指令并执行剩余指令,将原程序中的相应内容映射到内存,将映射的内容返回给原程序,第五Hook函数结束;
步骤238:第五Hook函数执行代码存储区内的MapViewOfFile函数的部分指令,跳转执行系统的MapViewOfFile函数的剩余指令,将原程序的相应内容映射到内存,对映射到的内容进行解密,将解密后的内容返回给原程序,第五Hook函数结束;
具体地,本实施例中,该步骤包括:
步骤238-1:第五Hook函数用映射文件偏移地址加上壳的长度更新映射文件的偏移地址,用映射文件大小加上加密头的长度更新映射文件大小;
步骤238-2:第五Hook函数执行代码存储区内的MapViewOfFile函数的部分指令,跳转执行系统的MapViewOfFile函数的剩余指令,根据更新后的映射文件偏移地址和更新后的映射文件大小将相应内容映射到内存;
步骤238-3:第五Hook函数读取加密头并对其进行校验,并获取加密原程序的密钥;
步骤238-4:第五Hook函数对映射到的内容进行解密,将解密后的内容返回给原程序,第五Hook函数结束;
步骤239:第六Hook函数将API代码属性修改为可写,将指定接口函数的代码存储区内中的指令写回到API中的接口函数的相应位置,删除跳转到对应的Hook函数的指令,并恢复API代码属性;
本实施例中,ExitProcess函数中包含跳转到第六Hook函数的跳转指令,所以当ExitProcess函数被调用时,第六Hook函数被调用;
例如,以CreateFile函数为例,API中当前CreateFile函数为:
7C810800   jmp     text.00639F20
7C810805   sub     esp,58
7C810808   mov    eax,dword ptr[ebp+18]
7C81080B   dec     eax
……
当前内存为:
001638EA   mov    edi,edi
001638EC   push    ebp
001638ED   mov    ebp, esp
001638EF   jmp     dword ptr[1638F5]
001638F5   add     eax, 7C8108
第六Hook函数将写入内存中的三条指令,即从0x001638EA开始的三条指令,写回0x7C810800中,并删除jmp  text.00639F20指令,API中当前CreateFile函数变为:
7C810800   mov    edi,edi
7C810802   push    ebp
7C810803   mov    ebp, esp
7C810805   sub     esp,58
7C810808   mov    eax,dword ptr[ebp+18]
7C81080B   dec     eax
……
步骤240:第六Hook函数执行代码存储区中的ExitProcess函数的部分指令,跳转执行系统的ExitProcess函数的剩余指令,第六Hook函数结束。
实施例3
本发明的实施例3提供一种运行含有自校验的加壳程序的装置,如图4所示,包括:获取模块301,修改模块302,解密模块303,加载模块304,转交模块305,访问文件模块306,获取文件大小模块307,读文件模块308,创建文件映射模块309,映射文件模块310;
获取模块301,用于获取指定接口函数的内存地址;
修改模块302,用于修改指定接口函数中的指令,修改对应的钩子函数的代码存储区中的指令;
解密模块303,用于获取加壳程序在存储设备上的访问路径,将加密后的原程序解密到内存中;
加载模块304,用于将解密后的原程序加载到内存中;
转交模块305,用于将控制权交给原程序的入口点;
访问文件模块306,当第一钩子函数被调用时,第一钩子函数调用访问文件函数,返回调用结果,判断访问文件函数的位置参数是否与加壳程序在存储设备上的访问路径一致,若一致则判断调用结果是否包含第一句柄,是则保存第一句柄,第一钩子函数结束,否则第一钩子函数结束;若不一致则第一钩子函数结束;
获取文件大小模块307,用于当第二钩子函数被调用时,第二钩子函数读取获取文件大小函数中的句柄参数,判断句柄参数是否为保存的第一句柄,是则第二钩子函数调用获取文件大小函数,获取第一文件大小,对第一文件大小进行计算得到第二文件大小,将第二文件大小返回给原程序,第二钩子函数结束;否则,第二钩子函数调用获取文件大小函数,返回调用结果,第二钩子函数结束;
读文件模块308,用于当第三钩子函数被调用时,第三钩子函数读取读文件函数中的句柄参数,判断句柄参数是否为保存的第一句柄,是则第三钩子函数调用读文件函数,读取相应内容,对读取到的内容进行解密,并将解密后的内容返回给原程序,第三钩子函数结束,否则,第三钩子函数调用读文件函数读取相应内容,将读取到的内容返回给原程序,第三钩子函数结束;
创建文件映射模块309,用于当第四钩子函数被调用时,第四钩子函数调用创建文件映射函数,返回调用结果,判断创建文件映射函数的句柄参数是否与保存的第一句柄一致,若一致则判断调用结果是否包含映射文件句柄,是则保存映射文件句柄,第四钩子函数结束,否则第四钩子函数结束;若不一致则第四钩子函数结束;
映射文件模块310,用于当第五钩子函数被调用时,第五钩子函数读取映射文件函数中的句柄参数,判断句柄参数是否为保存的映射文件句柄,是则第五钩子函数调用映射文件函数,根据壳的长度和加密头的大小将原程序中的与句柄参数对应的内容映射到内存,对内存中映射到的内容进行解密,将解密后的内容返回给原程序,第五钩子函数结束;否则,第五钩子函数将与句柄参数对应的内容映射到内存,返回映射的内容,第五钩子函数结束。
装置包括退出进程模块311;
退出进程模块311,用于当第六钩子函数被调用时,第六钩子函数修改接口代码属性,将钩子函数代码存储区内的指定接口函数的指令写回到对应的接口函数中的相应位置,删除指定接口函数中跳转到钩子函数指令,并恢复接口代码属性,调用退出进程函数,第六钩子函数结束。
修改模块302包括第一获取单元3021,解析单元3022,第一判断单元3023,更新单元3024,读取单元3025,写指令单元3026,属性设置单元3027;
第一获取单元3021,用于获取跳转到对应的钩子函数指令的长度;
解析单元3022,用于从指定接口函数中的第一条指令中解析出完整的汇编指令,并将汇编指令的长度作为当前指令长度;
第一判断单元3023,用于判断当前指令长度是否小于跳转到对应的钩子函数指令的长度;
更新单元3024,用于将解析出的下一条汇编指令的长度与当前指令长度的和更新当前指令长度;
读取单元3025,用于读取所有的汇编指令并将其存储到对应的钩子函数的代码存储区;
写指令单元3026,用于在钩子函数的代码存储区的指令后写入一个跳转指令,跳转到与指定接口函数中被读取的指令相邻的指令,还用于将指定接口函数中被读取的指令替换为跳转到对应的钩子函数的指令;
属性设置单元3027,用于将代码存储区内的属性设置为可执行可读。
解密模块303包括第二获取单元3031,解密单元3032;
第二获取单元3031,用于获取加壳程序在存储设备上的访问路径,根据第一偏移地址获取加密头,获取加密头的大小和加密原程序所使用的密钥;
解密单元3032,用于使用第三获取单元获取的密钥将加密后的原程序解密到内存中。
加载模块304包括存储单元3041,加载单元3042,第三获取单元3043,第二判断单元3044,重定位单元3045,属性单元3046;
存储单元3041,用于读取并存储原程序的关键数据;
加载单元3042,用于读取节表数据结构,获取原程序的各个节在内存中的布局,并按照布局将原程序的各个节加载到内存中,还用于根据引入表获取原程序各个节所需的动态链接库和所需动态链接库中的函数;
第三获取单元3043,用于将动态链接库加载到内存中,获取关键数据中各个节所需动态链接库中的函数在内存中的地址,将地址写入相应的节中;
第二判断单元3044,用于比较原程序加载到内存后的程序基址与原程序基址是否相同;
重定位单元3045,用于找到需要被重新定位的地址,根据原程序加载到内存后的程序基址与存储在头部的原程序基址对需要被重新定位的地址进行重定位;
属性单元3046,用于修改内存中节的属性。
读文件模块308包括第三判断单元3081,读文件单元3082和第一解密单元3083;
第三判断单元3081,用于读取读文件函数中的句柄参数,判断句柄参数是否为第一句柄,还用于判断将要读取的内容的大小是否在加密后的原程序的大小范围内;
读文件单元3082,用于读取相应内容,将读取到的内容返回给原程序;
第一解密单元3083,用于对读取到的内容进行解密。
映射文件310模块包括第四判断单元3101,映射文件单元3102和第二解密单元3103;
第四判断单元3101,用于获取映射文件函数中的句柄参数,判断句柄参数是否为映射文件句柄;
映射文件单元3102,用于将原程序中的相应内容映射到内存,返回原程序中的相应内容;
第二解密单元3103,用于对映射到的内容进行解密,返回解密后的内容。
以上所述,仅为本发明较佳的具体实施方式,但本发明的保护范围并不局限于此,任何熟悉本技术领域的技术人员在本发明公开的技术范围内,可轻易想到的变化或替换,都应涵盖在本发明的保护范围之内。因此,本发明的保护范围应该以权利要求的保护范围为准。

Claims (13)

1.一种运行含有自校验的加壳程序的方法,其特征在于,所述方法包括:
步骤S1:壳获取指定接口函数的内存地址;
步骤S2:所述壳将所述指定接口函数中的部分指令替换为跳转到对应的钩子函数的跳转指令,将所述指定接口函数的所述部分指令保存到与所述指定接口函数对应的钩子函数的代码存储区中,再加入跳转回对应的所述接口函数的跳转指令,所述壳获取加壳程序在存储设备上的访问路径,将加密后的原程序解密到内存中;
步骤S3:所述壳将控制权交给所述原程序的入口点;
步骤S4:所述钩子函数等待被调用;
当第一钩子函数被调用时,所述第一钩子函数调用访问文件函数,返回调用结果,判断所述访问文件函数的位置参数是否与所述加壳程序在所述存储设备上的访问路径一致,若一致则判断所述调用结果是否包含第一句柄,是则保存所述第一句柄,所述第一钩子函数结束,否则所述第一钩子函数结束;若不一致则所述第一钩子函数结束;
当第二钩子函数被调用时,所述第二钩子函数读取获取文件大小函数中的句柄参数,判断所述句柄参数是否为保存的所述第一句柄,是则所述第二钩子函数调用获取文件大小函数,获取第一文件大小,对所述第一文件大小进行计算得到第二文件大小,将所述第二文件大小返回给所述原程序,所述第二钩子函数结束;否则,所述第二钩子函数调用所述获取文件大小函数,返回调用结果,所述第二钩子函数结束;
当第三钩子函数被调用时,所述第三钩子函数读取读文件函数中的句柄参数,判断所述句柄参数是否为保存的所述第一句柄,是则执行步骤S5,否则,所述第三钩子函数调用所述读文件函数读取相应内容,将读取到的内容返回给所述原程序,所述第三钩子函数结束;
当第四钩子函数被调用时,所述第四钩子函数调用创建文件映射函数,返回调用结果,判断所述创建文件映射函数的句柄参数是否与保存的所述第一句柄一致,若一致则判断所述调用结果是否包含映射文件句柄,是则保存所述映射文件句柄,所述第四钩子函数结束,否则所述第四钩子函数结束;若不一致则所述第四钩子函数结束;
当第五钩子函数被调用时,所述第五钩子函数读取所述映射文件函数中的句柄参数,判断所述句柄参数是否为保存的所述映射文件句柄,是则所述第五钩子函数调用所述映射文件函数,根据所述壳的长度和加密头的大小将所述原程序中的与所述句柄参数对应的内容映射到所述内存中,对所述内存中的映射到的内容进行解密,将解密后的内容返回给所述原程序,所述第五钩子函数结束;否则,所述第五钩子函数将与所述句柄参数对应的内容映射到所述内存,返回所述映射的内容,所述第五钩子函数结束;
步骤S5:所述第三钩子函数判断将要读取的内容的大小是否在所述加密后的原程序的大小范围内,是则所述第三钩子函数调用所述读文件函数,根据所述壳的长度和加密头的大小读取所述原程序中的相应内容,对读取到的内容进行解密,并将解密后的内容返回给所述原程序,所述第三钩子函数结束;否则,所述第三钩子函数调用所述读文件函数,读取相应内容,对所述读取到的内容进行解密,并将解密后的内容返回给所述原程序,所述第三钩子函数结束。
2.根据权利要求1所述的方法,其特征在于,所述步骤S1中所述指定接口函数为所述访问文件函数或所述获取文件大小函数或所述读文件函数或所述创建文件映射函数或所述映射文件函数。
3.根据权利要求2所述的方法,其特征在于,所述步骤S2包括:
步骤S2-1:所述壳获取所述跳转到对应的钩子函数的指令的长度;
步骤S2-2:所述壳从所述指定接口函数中的第一条指令中解析出完整的汇编指令,并将所述汇编指令的长度作为当前指令长度;
步骤S2-3:所述壳判断当前指令长度是否小于所述跳转到对应的钩子函数的指令的长度,是则执行步骤S2-4,否则执行步骤S2-5;
步骤S2-4:所述壳将所述指定接口函数中的下一条指令解析出完整的汇编指令,用所述汇编指令的长度与当前指令长度的和更新当前指令长度,执行步骤S2-3;
步骤S2-5:所述壳读取所有的汇编指令并将其存储到所述钩子函数的代码存储区,并在所述代码存储区的指令后加入一条跳转指令,所述跳转指令用于跳转到与所述指定接口函数中被读取的指令相邻的指令,并把所述代码存储区的属性设置为可执行可读;
步骤S2-6:所述壳将所述接口的代码属性修改为可写,将所述指定接口函数中被读取的指令替换为跳转到所述对应的钩子函数指令,并恢复所述接口的代码属性;
步骤S2-7:所述壳获取所述加壳程序在存储设备上的访问路径;
步骤S2-8:所述壳根据第一偏移地址读取加密头,获取所述加密头的大小和加密原程序所使用的密钥;
步骤S2-9:所述壳使用所述密钥对加密后的原程序进行解密;
步骤S2-10:所述壳读取并存储所述原程序的关键数据;所述关键数据包括所述原程序中节的数目、原程序入口点、原程序基址、指向引入表和重定位表的数据目录、节表数据结构;
步骤S2-11:所述壳读取所述关键数据中的所述节表数据结构,获取所述原程序的各个节在所述内存中的布局,并按照所述布局将所述原程序的各个节加载到所述内存中;
步骤S2-12:所述壳读取所述关键数据中的所述引入表,获取所述原程序各个节所需的动态链接库和所需动态链接库中的函数;
步骤S2-13:所述壳将所述动态链接库加载到所述内存中,获取所述关键数据中各个节所需动态链接库中的函数在所述内存中的地址,将所述地址写入相应的节中;
步骤S2-14:所述壳比较所述原程序加载到所述内存后的程序基址与所述关键数据中的所述原程序基址是否相同,是则执行步骤S2-16,否则执行步骤S2-15;
步骤S2-15:所述壳找到需要被重新定位的地址,根据所述原程序加载到所述内存后的所述程序基址与所述原程序基址对需要被重新定位的地址进行重定位,顺序执行步骤S2-16;
步骤S2-16:所述壳修改所述内存中节的属性。
4.根据权利要求3所述的方法,其特征在于,所述步骤S4还包括:当第六钩子函数被调用时,所述第六钩子函数修改所述接口代码属性,将所述钩子函数代码存储区内的指定接口函数的指令写回到对应的所述接口函数中的相应位置,删除所述指定接口函数中所述跳转到钩子函数指令,并恢复所述接口代码属性,调用退出进程函数,所述第六钩子函数结束。
5.根据权利要求1所述的方法,其特征在于,所述步骤S4中当第五钩子函数被调用时,具体包括:
步骤S4-1:所述第五钩子函数获取所述映射文件函数中的句柄参数,判断所述句柄参数是否为所述映射文件句柄,是则执行步骤S4-3,否则执行步骤S4-2;
步骤S4-2:所述第五钩子函数调用所述第五钩子函数的代码存储区中的映射文件函数,将与所述句柄参数对应的内容映射到内存,所述第五钩子函数结束;
步骤S4-3:所述第五钩子函数用所述映射文件偏移地址加上所述壳的长度更新映射文件的偏移地址,用映射文件大小加上加密头的长度更新映射文件大小;
步骤S4-4:所述第五钩子函数调用所述第五钩子函数的代码存储区内的所述映射文件函数,根据更新后的映射文件偏移地址和更新后的映射文件大小读取相应内容并将其映射到所述内存;
步骤S4-5:所述第五钩子函数读取所述加密头并对其进行校验,获取加密原程序的密钥;
步骤S4-6:所述第五钩子函数对映射到所述内存中的内容进行解密,将解密后的内容返回给所述原程序,所述第五钩子函数结束。
6.根据权利要求1所述的方法,其特征在于,所述步骤S5包括:
步骤S5-1:所述第三钩子函数判断所述将要读取的内容的大小是否在所述加密后的原程序的大小范围内,是则执行步骤S5-3,否则执行步骤S5-2;
步骤S5-2:所述第三钩子函数调用所述第三钩子函数的代码存储区内的读文件函数,读取相应内容,对读取到的内容进行解密,并将解密后的内容返回给所述原程序,所述第三钩子函数结束;
步骤S5-3:所述第三钩子函数把待读取位置偏移加上所述壳的长度;
步骤S5-4:所述第三钩子函数调用所述代码存储区中的读文件函数读取加密头并对其进行校验,并获得加密原程序的密钥,同时获得所述加密头的大小,将待读取位置偏移加上加密头的大小;
步骤S5-5: 所述第三钩子函数根据待读取位置偏移读取加密后的原程序;
步骤S5-6:所述第三钩子函数对读取到的内容进行解密,并将解密后的内容返回给原程序,所述第三钩子函数结束。
7.一种运行含有自校验的加壳程序的装置,其特征在于,所述装置包括获取模块,修改模块,解密模块,加载模块,转交模块,访问文件模块,获取文件大小模块,读文件模块,创建文件映射模块,映射文件模块;
所述获取模块,用于获取指定接口函数的内存地址;
所述修改模块,用于修改所述指定接口函数中的指令,修改对应的钩子函数的代码存储区中的指令;
所述解密模块,用于获取加壳程序在存储设备上的访问路径,将加密后的原程序解密到内存中;
所述加载模块,用于将所述解密后的原程序加载到所述内存中;
所述转交模块,用于将控制权交给所述原程序的入口点;
所述访问文件模块,用于当第一钩子函数被调用时,所述第一钩子函数调用访问文件函数,返回调用结果,判断所述访问文件函数的位置参数是否与所述加壳程序在所述存储设备上的访问路径一致,若一致则判断所述调用结果是否包含第一句柄,是则保存所述第一句柄,所述第一钩子函数结束,否则所述第一钩子函数结束;若不一致则所述第一钩子函数结束;
所述获取文件大小模块,用于当第二钩子函数被调用时,第二钩子函数读取获取文件大小函数中的句柄参数,判断所述句柄参数是否为保存的所述第一句柄,是则所述第二钩子函数调用获取文件大小函数,获取第一文件大小,对所述第一文件大小进行计算得到第二文件大小,将所述第二文件大小返回给所述原程序,所述第二钩子函数结束;否则,所述第二钩子函数调用所述获取文件大小函数,返回调用结果,所述第二钩子函数结束;
所述读文件模块,用于当第三钩子函数被调用时,第三钩子函数读取读文件函数中的句柄参数,判断所述句柄参数是否为保存的所述第一句柄,是则所述第三钩子函数调用读文件函数,读取相应内容,对读取到的内容进行解密,并将解密后的内容返回给所述原程序,所述第三钩子函数结束,否则,所述第三钩子函数调用所述读文件函数读取相应内容,将读取到的内容返回给所述原程序,所述第三钩子函数结束;
所述创建文件映射模块,用于当第四钩子函数被调用时,所述第四钩子函数调用创建文件映射函数,返回调用结果,判断创建文件映射函数的句柄参数是否与保存的所述第一句柄一致,若一致则判断所述调用结果是否包含映射文件句柄,是则保存所述映射文件句柄,所述第四钩子函数结束,否则所述第四钩子函数结束;若不一致则所述第四钩子函数结束;
所述映射文件模块,用于当第五钩子函数被调用时,所述第五钩子函数读取所述映射文件函数中的句柄参数,判断所述句柄参数是否为保存的所述映射文件句柄,是则所述第五钩子函数调用所述映射文件函数,根据壳的长度和加密头的大小将所述原程序中的与所述句柄参数对应的内容映射到所述内存,对所述内存中映射到的内容进行解密,将解密后的内容返回给所述原程序,所述第五钩子函数结束;否则,所述第五钩子函数将与所述句柄参数对应的内容映射到所述内存,返回所述映射的内容,所述第五钩子函数结束。
8.根据权利要求7所述的方法,其特征在于,所述装置包括退出进程模块;
所述退出进程模块,用于当第六钩子函数被调用时,第六钩子函数修改所述接口代码属性,将所述钩子函数代码存储区内的指定接口函数的指令写回到对应的所述接口函数中的相应位置,删除所述指定接口函数中所述跳转到钩子函数指令,并恢复所述接口代码属性,调用退出进程函数,所述第六钩子函数结束。
9.根据权利要求7所述的方法,其特征在于,所述修改模块包括第一获取单元,解析单元,第一判断单元,更新单元,读取单元,写指令单元,属性设置单元;
所述第一获取单元,用于获取所述跳转到对应的钩子函数指令的长度;
所述解析单元,用于从所述指定接口函数中的第一条指令中解析出完整的汇编指令,并将所述汇编指令的长度作为当前指令长度;
所述第一判断单元,用于判断所述当前指令长度是否小于所述跳转到对应的钩子函数指令的长度;
所述更新单元,用于将解析出的下一条汇编指令的长度与当前指令长度的和更新当前指令长度;
所述读取单元,用于读取所有的汇编指令并将其存储到对应的钩子函数的代码存储区;
所述写指令单元,用于在所述钩子函数的代码存储区的指令后写入一个跳转指令,跳转到与所述指定接口函数中被读取的指令相邻的指令,还用于将所述指定接口函数中被读取的指令替换为所述跳转到对应的钩子函数的指令;
所述属性设置单元,用于将所述代码存储区内的属性设置为可执行可读。
10.根据权利要求7所述的方法,其特征在于,所述解密模块包括第二获取单元,解密单元;
所述第二获取单元,用于获取所述加壳程序在存储设备上的访问路径,根据第一偏移地址获取加密头,获取所述加密头的大小和加密原程序所使用的密钥;
所述解密单元,用于使用所述第三获取单元获取的密钥将加密后的原程序解密到所述内存中。
11.根据权利要求7所述的方法,其特征在于,所述加载模块包括存储单元,加载单元,第三获取单元,第二判断单元,重定位单元,属性单元;
所述存储单元,用于读取并存储所述原程序的关键数据;
所述加载单元,用于读取节表数据结构,获取所述原程序的各个节在所述内存中的布局,并按照所述布局将所述原程序的各个节加载到所述内存中,还用于根据引入表获取所述原程序各个节所需的动态链接库和所需动态链接库中的函数;
所述第三获取单元,用于将动态链接库加载到所述内存中,获取关键数据中各个节所需动态链接库中的函数在所述内存中的地址,将所述地址写入相应的节中;
所述第二判断单元,用于比较所述原程序加载到所述内存后的程序基址与原程序基址是否相同;
所述重定位单元,用于找到需要被重新定位的地址,根据所述原程序加载到所述内存后的所述程序基址与存储在头部的所述原程序基址对需要被重新定位的地址进行重定位;
所述属性单元,用于修改所述内存中节的属性。
12.根据权利要求7所述的方法,其特征在于,所述读文件模块包括第三判断单元,读文件单元和第一解密单元;
所述第三判断单元,用于读取读文件函数中的句柄参数,判断句柄参数是否为所述第一句柄,还用于判断将要读取的内容的大小是否在加密后的原程序的大小范围内;
所述读文件单元,用于读取相应内容,将读取到的内容返回给所述原程序;
所述第一解密单元,用于对读取到的内容进行解密。
13.根据权利要求7所述的方法,其特征在于,所述映射文件模块包括第四判断单元,映射文件单元和第二解密单元;
所述第四判断单元,用于获取所述映射文件函数中的句柄参数,判断所述句柄参数是否为所述映射文件句柄;
所述映射文件单元,用于将原程序中的相应内容映射到所述内存,返回所述原程序中的相应内容;
所述第二解密单元,用于对映射到的内容进行解密,返回解密后的内容。
CN201210587208.9A 2012-12-28 2012-12-28 一种运行含有自校验的加壳程序的方法和装置 Active CN103077332B (zh)

Priority Applications (1)

Application Number Priority Date Filing Date Title
CN201210587208.9A CN103077332B (zh) 2012-12-28 2012-12-28 一种运行含有自校验的加壳程序的方法和装置

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN201210587208.9A CN103077332B (zh) 2012-12-28 2012-12-28 一种运行含有自校验的加壳程序的方法和装置

Publications (2)

Publication Number Publication Date
CN103077332A true CN103077332A (zh) 2013-05-01
CN103077332B CN103077332B (zh) 2015-08-26

Family

ID=48153861

Family Applications (1)

Application Number Title Priority Date Filing Date
CN201210587208.9A Active CN103077332B (zh) 2012-12-28 2012-12-28 一种运行含有自校验的加壳程序的方法和装置

Country Status (1)

Country Link
CN (1) CN103077332B (zh)

Cited By (21)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN104077523A (zh) * 2014-06-25 2014-10-01 珠海市君天电子科技有限公司 对软件进行处理的方法和装置
CN104239786A (zh) * 2014-10-13 2014-12-24 北京奇虎科技有限公司 免root主动防御配置方法及装置
CN106325927A (zh) * 2016-08-19 2017-01-11 北京金山安全管理系统技术有限公司 一种应用于Linux系统中动态库API的拦截方法及装置
CN106547580A (zh) * 2015-09-22 2017-03-29 腾讯科技(深圳)有限公司 挂钩函数的方法和装置
CN106789051A (zh) * 2017-03-24 2017-05-31 北京奇虎科技有限公司 一种保护文件的方法、装置和计算设备
CN107133169A (zh) * 2017-04-26 2017-09-05 腾讯科技(深圳)有限公司 应用测试包生成方法及生成装置
CN107291485A (zh) * 2016-04-11 2017-10-24 北京京东尚科信息技术有限公司 动态链接库的加固方法、运行方法、加固装置和安全系统
CN107329978A (zh) * 2017-05-31 2017-11-07 北京京东尚科信息技术有限公司 多平台融合的路由方法和装置
CN107480029A (zh) * 2017-08-02 2017-12-15 北京深思数盾科技股份有限公司 一种函数调用时间的监控方法及装置
CN107908444A (zh) * 2017-10-26 2018-04-13 北京奇虎科技有限公司 终端应用的挂钩方法及装置
CN107944233A (zh) * 2017-12-11 2018-04-20 北京深思数盾科技股份有限公司 一种可执行文件的保护方法和装置
CN108415739A (zh) * 2018-02-28 2018-08-17 腾讯科技(深圳)有限公司 一种动态链接库函数的钩挂方法、装置和存储介质
CN109460640A (zh) * 2018-11-13 2019-03-12 杭州涂鸦信息技术有限公司 一种Java程序保护方法、装置、设备及可读存储介质
CN109657493A (zh) * 2018-12-17 2019-04-19 郑州云海信息技术有限公司 一种信息处理方法和装置
CN109766141A (zh) * 2018-12-26 2019-05-17 北京思源互联科技有限公司 一种基于动态链接库的数据动态更新方法及其装置
CN110673899A (zh) * 2018-07-03 2020-01-10 武汉斗鱼网络科技有限公司 一种程序处理方法及相关设备
CN111209225A (zh) * 2020-01-03 2020-05-29 北京字节跳动网络技术有限公司 获取实际地址的方法、装置、介质和电子设备
CN112527672A (zh) * 2020-12-21 2021-03-19 北京深思数盾科技股份有限公司 一种针对加壳工具的检测方法及设备
CN113741946A (zh) * 2021-08-25 2021-12-03 烽火通信科技股份有限公司 公共接口函数库的裁剪方法、装置、设备及可读存储介质
CN113987471A (zh) * 2021-10-29 2022-01-28 山西大鲲智联科技有限公司 可执行文件执行方法、装置、电子设备和计算机可读介质
CN112818359B (zh) * 2020-12-31 2022-06-03 北京深思数盾科技股份有限公司 一种文件保护方法及装置

Citations (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US20070091377A1 (en) * 2005-05-18 2007-04-26 Patrick Smith Real-time auditing of covert data marks
CN101154259A (zh) * 2007-08-27 2008-04-02 电子科技大学 通用自动化脱壳引擎与方法

Patent Citations (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US20070091377A1 (en) * 2005-05-18 2007-04-26 Patrick Smith Real-time auditing of covert data marks
CN101154259A (zh) * 2007-08-27 2008-04-02 电子科技大学 通用自动化脱壳引擎与方法

Cited By (31)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN104077523A (zh) * 2014-06-25 2014-10-01 珠海市君天电子科技有限公司 对软件进行处理的方法和装置
CN104077523B (zh) * 2014-06-25 2018-10-16 珠海市君天电子科技有限公司 对软件进行处理的方法和装置
CN104239786A (zh) * 2014-10-13 2014-12-24 北京奇虎科技有限公司 免root主动防御配置方法及装置
CN104239786B (zh) * 2014-10-13 2017-08-04 北京奇虎科技有限公司 免root主动防御配置方法及装置
CN106547580A (zh) * 2015-09-22 2017-03-29 腾讯科技(深圳)有限公司 挂钩函数的方法和装置
CN107291485A (zh) * 2016-04-11 2017-10-24 北京京东尚科信息技术有限公司 动态链接库的加固方法、运行方法、加固装置和安全系统
CN106325927A (zh) * 2016-08-19 2017-01-11 北京金山安全管理系统技术有限公司 一种应用于Linux系统中动态库API的拦截方法及装置
CN106325927B (zh) * 2016-08-19 2019-12-17 北京金山安全管理系统技术有限公司 一种应用于linux系统中动态库API的拦截方法及装置
CN106789051B (zh) * 2017-03-24 2020-01-31 北京奇虎科技有限公司 一种保护文件的方法、装置和计算设备
CN106789051A (zh) * 2017-03-24 2017-05-31 北京奇虎科技有限公司 一种保护文件的方法、装置和计算设备
CN107133169A (zh) * 2017-04-26 2017-09-05 腾讯科技(深圳)有限公司 应用测试包生成方法及生成装置
CN107133169B (zh) * 2017-04-26 2021-03-23 腾讯科技(深圳)有限公司 应用测试包生成方法及生成装置
CN107329978A (zh) * 2017-05-31 2017-11-07 北京京东尚科信息技术有限公司 多平台融合的路由方法和装置
CN107480029A (zh) * 2017-08-02 2017-12-15 北京深思数盾科技股份有限公司 一种函数调用时间的监控方法及装置
CN107908444A (zh) * 2017-10-26 2018-04-13 北京奇虎科技有限公司 终端应用的挂钩方法及装置
CN107908444B (zh) * 2017-10-26 2021-07-13 北京奇虎科技有限公司 终端应用的挂钩方法及装置
CN107944233A (zh) * 2017-12-11 2018-04-20 北京深思数盾科技股份有限公司 一种可执行文件的保护方法和装置
CN108415739A (zh) * 2018-02-28 2018-08-17 腾讯科技(深圳)有限公司 一种动态链接库函数的钩挂方法、装置和存储介质
CN108415739B (zh) * 2018-02-28 2020-04-14 腾讯科技(深圳)有限公司 一种动态链接库函数的钩挂方法、装置和存储介质
CN110673899B (zh) * 2018-07-03 2022-06-21 武汉斗鱼网络科技有限公司 一种程序处理方法及相关设备
CN110673899A (zh) * 2018-07-03 2020-01-10 武汉斗鱼网络科技有限公司 一种程序处理方法及相关设备
CN109460640A (zh) * 2018-11-13 2019-03-12 杭州涂鸦信息技术有限公司 一种Java程序保护方法、装置、设备及可读存储介质
CN109657493A (zh) * 2018-12-17 2019-04-19 郑州云海信息技术有限公司 一种信息处理方法和装置
CN109766141A (zh) * 2018-12-26 2019-05-17 北京思源互联科技有限公司 一种基于动态链接库的数据动态更新方法及其装置
CN111209225A (zh) * 2020-01-03 2020-05-29 北京字节跳动网络技术有限公司 获取实际地址的方法、装置、介质和电子设备
CN111209225B (zh) * 2020-01-03 2022-04-22 北京字节跳动网络技术有限公司 获取实际地址的方法、装置、介质和电子设备
CN112527672A (zh) * 2020-12-21 2021-03-19 北京深思数盾科技股份有限公司 一种针对加壳工具的检测方法及设备
CN112818359B (zh) * 2020-12-31 2022-06-03 北京深思数盾科技股份有限公司 一种文件保护方法及装置
CN113741946A (zh) * 2021-08-25 2021-12-03 烽火通信科技股份有限公司 公共接口函数库的裁剪方法、装置、设备及可读存储介质
CN113741946B (zh) * 2021-08-25 2023-06-09 烽火通信科技股份有限公司 公共接口函数库的裁剪方法、装置、设备及可读存储介质
CN113987471A (zh) * 2021-10-29 2022-01-28 山西大鲲智联科技有限公司 可执行文件执行方法、装置、电子设备和计算机可读介质

Also Published As

Publication number Publication date
CN103077332B (zh) 2015-08-26

Similar Documents

Publication Publication Date Title
CN103077332B (zh) 一种运行含有自校验的加壳程序的方法和装置
KR101471589B1 (ko) 공통중간언어 기반 프로그램을 위한 보안 제공 방법
WO2016078130A1 (zh) 一种防逆向apk文件的动态加载方法
CN103827880B (zh) 保护非本机代码安全的方法
KR101518420B1 (ko) 안드로이드 플랫폼에서의 apk 파일 관리 장치 및 방법
CN104573416B (zh) 一种生成应用安装包、执行应用的方法及装置
CN108229112B (zh) 一种保护应用程序、应用程序的运行方法以及装置
CN106203006A (zh) 基于dex与so文件动态执行的Android应用加固方法
CN101346727A (zh) 程序运行控制方法、其设备以及运行控制程序
CN104408337A (zh) 一种apk文件防逆向的加固方法
JP5733789B2 (ja) データ保護処理プログラム
CN107070656B (zh) 一种应用程序中so文件的加密方法、解密方法和系统
CN105022936A (zh) 一种类class文件加密解密方法和装置
CN109062582A (zh) 一种应用安装包的加密方法及装置
CN102222196A (zh) 验证自修改的计算机代码校验和的方法、装置及程序载体
CN104834838B (zh) 防止dex文件从内存中转存的方法及装置
CN106845167A (zh) 一种apk的加固方法和装置,及动态加载方法和装置
CN105512548B (zh) 基于隐藏可执行镜像并注入dll保护镜像代码的方法
CN110309630B (zh) 一种Java代码加密方法及装置
CN105335151A (zh) 安装文件的保护方法及装置
CN102317948A (zh) 芯片的安全保护方法及芯片
CN103246848A (zh) 保护软件安全的方法和设备
CN102280134B (zh) 一种用于提高移动存储设备中数据安全的方法
KR102459774B1 (ko) Dll 파일 암호화 방법, 이를 수행하는 dll 파일 암호화 시스템, 및 이를 저장하는 기록매체
CN108170433A (zh) 一种Java代码的混淆方法、恢复方法及其装置

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
C14 Grant of patent or utility model
GR01 Patent grant
CP03 Change of name, title or address
CP03 Change of name, title or address

Address after: 17th floor, building B, Huizhi building, No.9, Xueqing Road, Haidian District, Beijing 100085

Patentee after: Feitian Technologies Co.,Ltd.

Country or region after: China

Address before: 100085 17th floor, block B, Huizhi building, No.9 Xueqing Road, Haidian District, Beijing

Patentee before: Feitian Technologies Co.,Ltd.

Country or region before: China