本章对使用 UPX 加壳的 CRACKME.exe 程序进行脱壳。

加壳是指通过一种压缩或者加密的手段将程序的可执行代码隐藏起来,避免被轻易的逆向。加壳会在程序中加入额外的区段(STUB,存根),在程序开始运行后,将加密的文件进行解密并保存到内存中其他区段,或者创建原程序中的区段,然后跳转到解密后的代码执行。

现在有很多种类的加壳方式,大部分通过破坏 IAT(import table)也就是导入函数表,以及文件头(HEADER)来保护文件。它们会加入反调试代码来避免被脱壳出原始文件。

最简单的例子就是 UPX 壳,没有任何的反调试或者其他麻烦的手段,所以作为读者学习脱壳的开始。

UPX (Ultimate Packer for Executables) 是一种流行的可执行文件压缩工具,同时也可以被视为一种简单的加壳工具。它被广泛用于减少可执行文件的大小,同时提供一定程度的代码保护。

UPX 加壳的工作原理

  1. 压缩阶段
  2. 运行时解压

加载加壳文件

打开 IDA,勾选 MANUAL LOAD,取消 CREATE IMPORTS SEGMENT,加载所有的区段。IDA 推荐在加载加壳文件时取消这个选项。

如果按默认方式打开壳文件,就会发现 segment 里面只有2个:

UPX0	00401000	00409000	R	W	X	.	L	para	0001	public	CODE	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
UPX1	00409000	0040A000	R	W	X	.	L	para	0002	public	CODE	32	0000	0000	0001	FFFFFFFF	FFFFFFFF

使用上述方式打开结果:

HEADER	00400000	00401000	?	?	?	.	L	page	0004	public	DATA	32	FFFFFFFF	FFFFFFFF	FFFFFFFF	FFFFFFFF	FFFFFFFF
UPX0	  00401000	00409000	R	W	X	.	L	para	0001	public	CODE	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
UPX1	  00409000	0040A000	R	W	X	.	L	para	0002	public	CODE	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
.rsrc	  0040A000	0040B000	R	W	.	.	L	para	0003	public	DATA	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
OVERLAY	0040B000	0040B200	R	W	.	.	L	byte	0000	private	DATA	32	FFFFFFFF	FFFFFFFF	0001	FFFFFFFF	FFFFFFFF

未加壳的原始文件段如下:

HEADER	00400000	00401000	?	?	?	.	L	page	0007	public	DATA	32	FFFFFFFF	FFFFFFFF	FFFFFFFF	FFFFFFFF	FFFFFFFF
CODE	  00401000	00402000	R	.	X	.	L	para	0001	public	CODE	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
DATA	  00402000	00403000	R	W	.	.	L	para	0002	public	DATA	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
.idata	00403000	00404000	R	W	.	.	L	para	0003	public	DATA	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
.edata	00404000	00405000	R	.	.	.	L	para	0004	public	DATA	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
.reloc	00405000	00406000	R	.	.	.	L	para	0005	public	DATA	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
.rsrc	  00406000	00408000	R	.	.	.	L	para	0006	public	DATA	32	0000	0000	0001	FFFFFFFF	FFFFFFFF
OVERLAY	00408000	00408200	R	W	.	.	L	byte	0000	private	DATA	32	FFFFFFFF	FFFFFFFF	0001	FFFFFFFF	FFFFFFFF

加壳前后文件对比

加壳之后的程序入口,地址是 0x409be0,而原始文件的地址是 0x401000

加壳之后,函数列表里面只有一个 start 函数了,其他的都看不见:

image.png