演示版保护技术
演示版保护技术
本文将介绍一些常用的软件保护技术,对其优缺点进行分析,并给出软件保护的一般性建议 。
序列号保护 首先来看看常见的序列号(又称注册码)保护的工作原理。从网上下载的共享软件(Shareware)一般都有使用时间或功能上的限制,如果超过了共享软件的试用期,就必须到这个软件的公司去注册方能继续使用。注册过程一般是用户把自己的信息(例如用户名、电子邮件地址、机器特征码等)告诉软件公司,软件公司根据用户的信息,利用预先编写的一个用于计算注册码的程序(称为注册机,KeyGen)算出一个序列号,并以电子邮件等形式将其发给用户。用户得到序列号后,在软件中输入注册信息和序列号。当注册信息验证通过后,软件就会取消各种限制,例如时间限制、功能限制等,从而成为完全正式版本。软件每次启动时,会从磁盘文件或系统注册表中读取注册信息并对其进行检查。如果注册信息正确,则以完全正式版的模式运行,否则将作为有功能限制或时间限制的版本来运行。注册用户可以根据所拥有的注册信息得到相应的售后服务。当软件推出新版本后,注册用户还可以向软件作者提供自己的注册信息,以获得版本升级服务。这种保护实现起来比较简单 ...
逆向分析技术
逆向分析技术
将可执行程序反汇编,通过分析反汇编代码来理獬其代码功能(例如各接口的数据结构等),然后用高级语言重新描述这段代码,逆向分析原始软件的思路,这个过程就称作逆向工程(ReverseEngineering),有时也简单地称作逆向(Reversing)。这是一项很重要的技能,需要扎实的编程功底和汇编知识。逆向分析的首选工具是IDA,它的插件Hex-Rays Decompiler能完成许多代码反编译工作,在逆向时可以作为一款辅助工具使用。 逆向工程可以让我们了解程序的结构及程序的逻辑,因此,利用逆向工程可以洞察程序的运行过程。一般的所谓“软件破解”只是逆向工程中非常初级的部分.
一、32位软件逆向技术 示例使用的是vc6.0编译的32位程序
启动函数
在编写Win32应用程序时,都必须在源码里实现一个WinMain函数。但Windows程序的执行并不是从WinMain函数开始的,首先被执行的是启动函数的相关代码,这段代码是由编译器生成的。在启动代码初始化进程完成后,才会调用WinMain函数。
对Visual C++程序来说,它调用的是C/C+运行时 ...
静态分析技术
用高级语言编写的程序有两种形式。一种程序是被编译成机器语言在CPU上执行的,例如VisualC++。机器语言与汇编语言几乎是对应的,因此,可以将机器语言转化成汇编语言,这个过程称为反汇编(Disassembler)。例如,在x86系统中,机器码“EB”对应的汇编语句是“jmp short xx’”。另一种程序是一边解释一边执行的,编写这种程序的语言称为解释性语言,例如Visual Basic3.0/4.0、Java。这类语言的编译后程序可以被还原成高级语言的原始结构,这个过程称为反编译(Decompiler)。
所谓静态分析,是指通过反汇编、反编译手段获得程序汇编代码或源代码,然后根据程序清单分析程序的流程,了解模块所完成的功能。
一、文件类型分析 逆向分析程序的第一步就是分析程序的类型,了解程序是用什么语言编写的或用什么编译器编译的,以及程序是否被某种加密程序处理过,然后才能有的放矢,进行下一步工作。这个分析过程需要文件分析工具的辅助。常见的文件分析工具有PEiD、Exeinfo PE等。此类工具可以检测大多数编译语言、病毒和加密软件,本节以PEiD为例简单讲解它 ...
动态分析技术
动态分析技术中最重要的工具是调试器,分为用户模式和内核模式两种类型。用户模式调试器是指用来调试用户模式应用程序的调试器,工作在Ring3级,例如OllyDbg、x64dbg、Visual C++等编译器自带的调试器。内核模式调试器是指能调试操作系统内核的调试器,例如WinDbg。
一、OllyDbg
OllyDbg调试器
OllyDbg结合了动态调试和静态分析,具有GUI界面,非常容易上手,对异常的跟踪处理相当灵活。它的反汇编引擎很强大,可识别数千个被G和Windows烦繁使用的函数,并能将其参数注释出来。它会自动分析函数过程、循环语句、代码中的字符串等。此外,开放式的设计给了这个软件很强的生命力。通过爱好者们的不断修改和扩充,OllyDg的脚本执行能力和开放插件接口使其变得越来越强大。
OllyDbg界面
具体各面板功能请参考OllyDbg的帮助文档。
基本操作
此处以(TraceMe.exe)为例。
分析一个Windows程序要比分析一个DOS程序容易得多,因为在Windows中,只要API函数被使用了,再想对要寻找蛛丝马迹的人隐藏一些信息就比较因难了。因 ...
熊猫烧香病毒分析
一,查壳
无壳
采用Delphi Borland Delphi 6.0-7.0编写
Delphi编译器倾向于使用寄存器传递前几个参数,寄存器传递可以比堆栈传递更快。
而C++的参数传递方式是在进行函数调用之前,会使用PUSH指令将参数按顺序推入堆栈,然后通过CALL指令调用函数。函数执行完毕后,通过调整堆栈指针来清理堆栈。
二,病毒样本分析自校验打开od,载入病毒样本,查看程序入口点
第一个函数00404E8,步入查看
通过调用GetModuleHandleA()获得程序基地址(及程序实例句柄)
接下来第二个函数004049E8,这个函数被连续调用了两次,每次调用之前都传递了两个参数
在内存窗口中看到传递的为字符串
进入函数查看,
内部又调用了三个函数,发现第二个调用的函数的功能为字符串的复制
在内存中查看
这是调用一次这个函数,复制了一部分字符串,总共调用了两次,全部调用完后是这样的(ps:重新启动了一下,存储地址发生变化了)
继续往下看,发现两端相似的代码,但是传递的参数不同,调用的函数相同
先分析405360
两个参数分别指向两个字符串
连个字符串经过如下算法加 ...
OD之断点一步到胃
常用的断点有INT3断点、硬件断点、内存断点、消息断点等。在调试时,合理使用断点能大大提高效率。
INT3断点
这是一个常用的断点。在OllyDbg中可以使用bp命令或者“F2”快捷键来设置/取消断点。当执行一个INT3断点时,该地址处的内容被调试器用INT3指令替换了,此时OllyDbg将INT3隐藏,显示出来的仍是中断前的指令。
这个INT3指令,因其机器码是0xCC,也常被称为“CC指令”。当被调试进程执行INT3指令导致一个异常时,调试器就会捕捉这个异常,从而停在断点处,然后将断点处的指令恢复成原来的指令。当然,如果自己编写调试器,也可用其他指令代替INT3来触发异常。
使用NT3断点的优点是可以设置无数个断点,缺点是改变了原程序机器码,容易被软件检测到。例如,为了防范API被下断,一些软件会检测API的首地址是否为0xCC(以此判断是否被下断)。用C语言来实现这个检测,方法是取得检测函数的地址,然后读取它的第1个字节,判断它是否等于“CC”。下面这段代码就是对MessageBoxA函数进行的断点检测。
程序编译后,对MessageBoxA函数 ...
32位下函数分析要点一步到"胃"
程序都是由具有不同功能的函数组成的,因此在逆向分析中将重点放在函数的识别及参数的传递上是明智的,这样做可以将注意力集中在某一段代码上。函数是一个程序模块,用来实现一个特定的功能。一个函数包括函数名、入口参数、返回值、函数功能等部分。
函数的识别:程序通过调用程序来调用函数,在函数执行后又返回调用程序继续执行。函数如何知道要返回的地址呢?实际上,调用函数的代码中保存了一个返回地址,该地址会与参数一起传递给被调用的函数。有多种方法可以实现这个功能,在绝大多数情况下,编译器都使用call和ret指令来调用函数及返回调用位置。
call指令与跳转指令功能类似。不同的是,call指令保存返回信息,即将其之后的指令地址压入栈的顶部,当遇到ret指令时返回这个地址。也就是说,call指令给出的地址就是被调用函数的起始地址。ret指令则用于结束函数的执行(当然,不是所有的ret指令都标志着函数的结束)。通过这一机制可以很容易地把函数调用和其他跳转指令区别开来。 因此,可以通过定位call机器指令或利用ret指令结束的标志来识别函数。call指令的操作数就是所调用函数的首地址。看一个例子, ...
常见数据类型分析要点一步到"胃"
数据结构是计算机存储、组织数据的方式。在进行逆向分析时,确定数据结构以后,算法就很容易得到了。有些时候,事情也会反过来,即根据特定算法来判断数据结构。本节将讨论常见的数据结构及它们在汇编语言中的实现方式。
局部变量:局部变量(Local Variables)是函数内部定义的一个变量,其作用域和生命周期局限于所在函数内。使用局部变量使程序模块化封装成为可能。从汇编的角度来看,局部变量分配空间时通常会使用栈和寄存器。
(1)利用栈存放局部变量
局部变量在栈中进行分配,函数执行后会释放这些栈,程序用“sub esp,8”语句为局部变量分配空间,用[ehp-xxxx]寻址调用这些变量,而参数调用相对于ebp偏移量 是正的,即[ebp+xxxx],因此在逆向时比较容易区分。编译器在优化模式时,通过esp寄存器直接对局部变量和参数进行寻址。当函数退出时,用“add esp,8”指令平衡栈, 以释放局部变量占用的内存。有些编译器(例如Delphi)通过给esp加一个负值来进行内存的分配。另外,编译器可能会用“push reg’”指令取代“sub esp,4”指令,以节省几 字 ...