软件的加密与解密
软件的加密与解密技术是矛与盾的关系,它们是在互相斗争中发展进步的。
两者在技术上的较量归根到底是一种利益的冲突。软件开发者为了维护自身的商业利益,不断寻找各种有效的技术来保护软件的版权,推迟软件被解密的时间;而解密者则受盗版所带来的高额利润的驱使或纯粹出于个人兴趣,不断开发新的解密工具,针对新出现的保护方式进行跟踪分析,以找到相应的解密方法。
没有无法解密的保护。对软件的保护仅靠技术是不够的,最终要靠人们的知识产权意识和法制观念的进步及生活水平的提高。如果一种保护技术的强度能达到让解密者在软件的生命周期内都无法将其完全破解的程度,这种保护技术就是成功的。软件保护方式的设计应在一开始就作为软件开发的一部分来考虑,列入开发计划和开发成本,并在保护强度、成本、易用性之间进行折中考虑,选择一个平衡点。
作为一个合格的程序员,要上至需求分析、设计抽象、设计模式,下至系统核心,熟悉整个系统的底层结构。
软件逆向工程
逆向工程(Reverse Engineering)是指根据已有的产物和结果,通过分析来推导出具体的实现方法。
对软件来说,==“可执行程序->反编译-> ...
二进制分析
未读逆向工程开源引擎框架
Capstone, Keystone, Unicorn, Qemu 以及 QiLing 等工具
汇编与反汇编
Capstone
新加坡南洋理工大学团队在 Blackhat USA 2014 上发布的一个反汇编引擎
Capstone 反汇编引擎 官网The Ultimate Disassembly Framework – Capstone – The Ultimate Disassembler (capstone-engine.org)
项目主页:https://github.com/aquynh/capstone
多平台 Windows、*nix
多架构,例如 Arm、Mips 和 x86
支持 C/Python 接口
Keystone
新加坡南洋理工大学团队在 Blackhat USA 2016 上发布的一个汇编框架
Keystone 汇编框架 官网Keystone – The Ultimate Assembler (keystone-engine.org)
项目主页:https://github.com/keystone-engine/keyst ...
二进制分析
未读使用make更新函数库文件¶
函数库文件也就是对Object文件(程序编译的中间文件)的打包文件。在Unix下,一般是由命令 ar 来完成打包工作。
函数库文件的成员¶
一个函数库文件由多个文件组成。你可以用如下格式指定函数库文件及其组成:
1archive(member)
这个不是一个命令,而一个目标和依赖的定义。一般来说,这种用法基本上就是为了 ar 命令来服务的。如:
12foolib(hack.o) : hack.o ar cr foolib hack.o
如果要指定多个member,那就以空格分开,如:
1foolib(hack.o kludge.o)
其等价于:
1foolib(hack.o) foolib(kludge.o)
你还可以使用Shell的文件通配符来定义,如:
1foolib(*.o)
函数库成员的隐含规则¶
当make搜索一个目标的隐含规则时,一个特殊的特性是,如果这个目标是 a(m) 形式的,其会把目标变成 (m) 。于是,如果我们的成员是 %.o 的模式定义,并且如果我们使用 make foo.a(bar.o) 的形式调用Makefile时,隐含规 ...
二进制分析
未读隐含规则¶
在我们使用Makefile时,有一些我们会经常使用,而且使用频率非常高的东西,比如,我们编译C/C++的源程序为中间目标文件(Unix下是 .o 文件,Windows下是 .obj 文件)。本章讲述的就是一些在Makefile中的“隐含的”,早先约定了的,不需要我们再写出来的规则。
“隐含规则”也就是一种惯例,make会按照这种“惯例”心照不喧地来运行,那怕我们的Makefile中没有书写这样的规则。例如,把 .c 文件编译成 .o 文件这一规则,你根本就不用写出来,make会自动推导出这种规则,并生成我们需要的 .o 文件。
“隐含规则”会使用一些我们系统变量,我们可以改变这些系统变量的值来定制隐含规则的运行时的参数。如系统变量 CFLAGS 可以控制编译时的编译器参数。
我们还可以通过“模式规则”的方式写下自己的隐含规则。用“后缀规则”来定义隐含规则会有许多的限制。使用“模式规则”会显得更智能和清楚,但“后缀规则”可以用来保证我们Makefile的兼容性。我们了解了“隐含规则”,可以让其为我们更好的服务,也会让我们知道一些“约定俗成”了的东西,而不至于使得我们在运行Ma ...
make 运行¶
一般来说,最简单的就是直接在命令行下输入make命令,make命令会找当前目录的makefile来执行,一切都是自动的。但也有时你也许只想让make重编译某些文件,而不是整个工程,而又有的时候你有几套编译规则,你想在不同的时候使用不同的编译规则,等等。本章节就是讲述如何使用make命令的。
make的退出码¶
make命令执行后有三个退出码:
0
表示成功执行。
1
如果make运行时出现任何错误,其返回1。
2
如果你使用了make的“-q”选项,并且make使得一些目标不需要更新,那么返回2。
Make的相关参数我们会在后续章节中讲述。
指定Makefile¶
前面我们说过,GNU make找寻默认的Makefile的规则是在当前目录下依次找三个文件——“GNUmakefile”、“makefile”和“Makefile”。其按顺序找这三个文件,一旦找到,就开始读取这个文件并执行。
当前,我们也可以给make命令指定一个特殊名字的Makefile。要达到这个功能,我们要使用make的 -f 或是 --file 参数( --makefile 参数也行 ...
二进制分析
未读使用函数¶
在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能。make 所支持的函数也不算很多,不过已经足够我们的操作了。函数调用后,函数的返回值可以当做变量来使用。
函数的调用语法¶
函数调用,很像变量的使用,也是以 $ 来标识的,其语法如下:
1$(<function> <arguments>)
或是:
1${<function> <arguments>}
这里, <function> 就是函数名,make支持的函数不多。 <arguments> 为函数的参数,参数间以逗号 , 分隔,而函数名和参数之间以“空格”分隔。函数调用以 $ 开头,以圆括号或花括号把函数名和参数括起。感觉很像一个变量,是不是?函数中的参数可以使用变量,为了风格的统一,函数和变量的括号最好一样,如使用 $(subst a,b,$(x)) 这样的形式,而不是 $(subst a,b, ${x}) 的形式。因为统一会更清楚,也会减少一些不必要的麻烦。
还是来看一个 ...
二进制分析
未读使用条件判断¶
使用条件判断,可以让make根据运行时的不同情况选择不同的执行分支。条件表达式可以是比较变量的值,或是比较变量和常量的值。
示例¶
下面的例子,判断 $(CC) 变量是否 gcc ,如果是的话,则使用GNU函数编译目标。
123456789libs_for_gcc = -lgnunormal_libs =foo: $(objects)ifeq ($(CC),gcc) $(CC) -o foo $(objects) $(libs_for_gcc)else $(CC) -o foo $(objects) $(normal_libs)endif
可见,在上面示例的这个规则中,目标 foo 可以根据变量 $(CC) 值来选取不同的函数库来编译程序。
我们可以从上面的示例中看到三个关键字: ifeq 、 else 和 endif 。 ifeq 的意思表示条件语句的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括号括起。 else 表示条件表达式为假的情况。 endif 表示一个条件语句的结束,任何一个条件表达式都应该以 endif 结束。
当我 ...
二进制分析
未读使用变量¶
在Makefile中的定义的变量,就像是C/C语言中的宏一样,他代表了一个文本字串,在Makefile中执行的时候其会自动原模原样地展开在所使用的地方。其与C/C所不同的是,你可以在Makefile中改变其值。在Makefile中,变量可以使用在“目标”,“依赖目标”, “命令”或是Makefile的其它部分中。
变量的命名字可以包含字符、数字,下划线(可以是数字开头),但不应该含有 : 、 # 、 = 或是空字符(空格、回车等)。变量是大小写敏感的,“foo”、“Foo”和“FOO”是三个不同的变量名。传统的Makefile的变量名是全大写的命名方式,但我推荐使用大小写搭配的变量名,如:MakeFlags。这样可以避免和系统的变量冲突,而发生意外的事情。
有一些变量是很奇怪字串,如 < 、 @ 等,这些是自动化变量,我会在后面介绍。
变量的基础¶
变量在声明时需要给予初值,而在使用时,需要给在变量名前加上 $ 符号,但最好用小括号 () 或是大括号 {} 把变量给包括起来。如果你要使用真实的 $字符,那么你需要用 $ 来表示。
变量可以使用在许多 ...
二进制分析
未读书写规则¶
规则包含两个部分,一个是依赖关系,一个是生成目标的方法。
在Makefile中,规则的顺序是很重要的,因为,Makefile中只应该有一个最终目标,其它的目标都是被这个目标所连带出来的,所以一定要让make知道你的最终目标是什么。一般来说,定义在Makefile中的目标可能会有很多,但是第一条规则中的目标将被确立为最终的目标。如果第一条规则中的目标有很多个,那么,第一个目标会成为最终的目标。make所完成的也就是这个目标。
好了,还是让我们来看一看如何书写规则。
规则举例¶
12foo.o: foo.c defs.h # foo模块 cc -c -g foo.c
看到这个例子,各位应该不是很陌生了,前面也已说过, foo.o 是我们的目标, foo.c 和 defs.h 是目标所依赖的源文件,而只有一个命令 cc -c -g foo.c (以Tab键开头)。这个规则告诉我们两件事:
文件的依赖关系, foo.o 依赖于 foo.c 和 defs.h 的文件,如果 foo.c 和 defs.h 的文件日期要比 foo.o 文件日期要新,或是 foo.o 不 ...
书写命令¶
每条规则中的命令和操作系统Shell的命令行是一致的。make会一按顺序一条一条的执行命令,每条命令的开头必须以 Tab 键开头,除非,命令是紧跟在依赖规则后面的分号后的。在命令行之间中的空格或是空行会被忽略,但是如果该空格或空行是以Tab键开头的,那么make会认为其是一个空命令。
我们在UNIX下可能会使用不同的Shell,但是make的命令默认是被 /bin/sh ——UNIX的标准Shell 解释执行的。除非你特别指定一个其它的Shell。Makefile中, # 是注释符,很像C/C++中的 // ,其后的本行字符都被注释。
显示命令¶
通常,make会把其要执行的命令行在命令执行前输出到屏幕上。当我们用 @ 字符在命令行前,那么,这个命令将不被make显示出来,最具代表性的例子是,我们用这个功能来向屏幕显示一些信息。如:
1@echo 正在编译XXX模块......
当make执行时,会输出“正在编译XXX模块……”字串,但不会输出命令,如果没有“@”,那么,make将输出:
12echo 正在编译XXX模块......正在编译XXX模块......
如果mak ...