培训内容:聊聊壳与花指令
12月5号,二进制培训的md
壳
壳是什么
简单来说,壳就是一个正常的程序外面加了一层程序,只有在执行完了第一层的程序后,真正的程序才会(能)被执行
这层壳程序的作用有两种:压缩 **加密
压缩壳就像鸡蛋,脆弱,只为了能把内容包起来(顺便压缩一下),很容易就去掉了
加密壳就像核桃(厚实,能保护好里面没多大的核桃仁),可能需要费一番手脚才能去掉
常见的壳
压缩壳
这类壳主要是为了减小程序的体积
我们经常接触的UPX就是这类壳
- ASPack
Win32可执行程序压缩工具
脱壳机:Un-ASPACK
-
UPX
应用非常广泛的压缩壳,好评不断
脱壳机:UPX、UPX Unpacker(吾爱云盘)、
-
PeCompact
-
NsPack(国产北斗壳)
-
。。。
加密壳
这类壳主要是为了保护程序的内容不被逆向破解以及病毒程序的免杀等
总的来说就是保护自己,让其他人(程序)很难看出程序会做什么
- ASProtect
- Armadillo加密壳(穿山甲)
- EXECryptor
- Themida
- VMProtect(变态强壳)
- 。。。
知识底子
- 脱壳为了啥?
为了看到汇编源码啊!!!压缩了,加密了之后ida看不到程序里面的代码啊
-
什么是OEP
oep指的是original entry point(原始进入点,就是程序入口啦),脱壳就是为了找到正确的oep
-
IAT是啥
逆向工程核心原理:import Address Table (导入表),库函数知道不?函数名知道不?那玩意儿怎么在计算机中定位的?当 PE 文件载入内存时,windows 加载器会定位所有导入的函数或数据将定位到的内容填写至可执行文件的某个位置供其使用,而这个操作是需要借助导入表来完成的。现在不需要关心导入表干了嘛,你只要知道这玩意儿不能错就行。
常用的去壳方法
新手三连:
- 程序是什么语言编写的?
- 程序到底有没有加壳?
- 程序加了什么壳?
认识常见的使用不同编译器编译出来的二进制程序开始头(程序入口特征,不然你明明都到了真正oep了还在傻傻往前找)
手脱第一步:认壳
咋认:
- 工具(exeinfo,detectItEasy。。。。。
-
看区段(利用带模板的16进制编辑器,比如常见的upx,区段特征upx0,upx1
给找到了个总结帖子:https://xz.aliyun.com/t/235
-
猜(改过区段信息,改过特征之类的
针对不同的壳可能有不同的快速有效的脱壳方法,这东西靠经验吧
接下来看看常用的脱壳方法:
- 单步跟踪(非常有意思)
这是是最常用的方式了,使用与壳代码比较短的压缩壳
思路:小跳跳,大跳停,回调略过,(程序跑飞,下断,重载,跟进
-
ESP定律(常用)
利用的是堆栈守恒
我们知道,esp指向的栈顶,而在进入壳程序之前,寄存器里面的东西其实都是正常的,可程序会保存这些值(保存栈的状态)并在壳程序结束的时候恢复这些寄存器里面值(恢复栈的状态),其实说白了就是有入栈必有出栈,这就是栈平衡啦
也就是说咱们在esp变动之后,在保存的内存位置下一个硬件访问断点,下一次,在壳程序取出这些保存好的寄存器的值时就能嘿嘿嘿了
-
一步到达oep
pushad—–> popad
-
内存镜像法
程序加壳后 运行的时候会进行解压(不是所有壳都有) 把加壳之前的结构映射到内存 最后一个一般就是rsrc资源段
下这个断点就是让文件完全映射到内存 然后壳会重新来code段进行一些操作 譬如打乱IAT 让你不能得到未加壳前文件的结构,这样在code段下断就可以来到OEP附近了。也就是,先在.rsrc下断,然后在.text下断
-
脱壳软件
吾爱的云盘里挺多,夺取翻翻
-
脚本脱壳
这个我没试过
-
模拟跟踪法,查看内存。SFX,imports,relocationstc eip<地址(龟速
-
Sfx法
壳在CTF中应用
其实壳在ctf比赛中很常见,但是咱一般也就碰到个UPX,还能用UPX直接脱的那种。稍微整复杂一点就是UPX等压缩壳的变种,一般小比赛不会用强壳来为难大家,毕竟那东西是商用的,安全专家都能研究好久那种。。
花指令
花指令又是什么东西
花指令是企图隐藏掉不想被逆向工程的代码块(或其它功能)的一种方法,在真实代码中插入一些垃圾代码的同时还保证原有程序的正确执行,而程序无法很好地反编译, 难以理解程序内容,达到混淆视听的效果。
简单的说就是在代码中混入一些垃圾数据阻碍你的静态分析。
(能够很好的防护那些使用ida的只会f5的孩子)
比如正常的程序流中加入 push eax;pop eax;
然后可怜的ida按f5就不能正确反编译了
常见的花指令
关于花指令我了解的也不多。所以这里只讲讲花指令的基本概念。有机会咱多多交流
可执行花指令
代码能够执行,但是完全没有意义(执行前执行后寄存器状态时一样的,eip除外,毕竟程序是在往前走的)
这样想,我们不去动程序需要的寄存器,我们对程序当前不需要的寄存器为所欲为,那么反汇编就会读到一堆不知道干了些什么的对栈操作的汇编代码。然后 它 傻 了。
不可执行花指令
ida里面汇编飘红,就是一些不能被执行的代码
int main() {
int a = 1;
uint32_t flag[] = { 1234,5678 };
__asm { //花指令部分
_emit 075h
_emit 2h
_emit 0E9h
_emit 0EDh
//ede90275h
}
printf("%d,%d", flag[0], flag[1]);
return 0;
}
去除花指令的办法
od能用花指令去除工具,ida可以patch掉无关代码
花指令在CTF中的应用
上面那个就是上次哪个安旬杯碰到的例子。。。我没整出来。。。。。