首页
社区
课程
招聘
[原创]汇编指令级混淆器的实现
发表于: 2018-1-28 23:58 9413

[原创]汇编指令级混淆器的实现

2018-1-28 23:58
9413

之前在脱壳的时候遇到不少的花指令,指令膨胀,虚拟机之类的壳, 然后想要尝试一下也弄一个这样的壳, 于是便有了写一个指令混淆器的想法, 起初是想写一个直接对opcode进行混淆膨胀的混淆器的, 难度不是一般地小, 这其中包括了膨胀之后call指令和jmp等以偏移作为操作数的指令的操作数的偏移量会被破坏. 虽然能写,但非常麻烦, 需要重组整个代码段, 后来就没有直接写, 写了一个汇编指令级别的混淆器尝试尝试. 这种汇编指令级别的混淆器之所以写得比较容易, 是因为汇编指令可以使用标识符来表示偏移量,而这些标识符在汇编器开始编译汇编代码时会自行计算, 因此, 在汇编指令之间插入指令完全是可行的, 如果想要将指令拆分, 只需将指令的opcode求出,然后拆分重组直接将opcode作为数据定义在源文件中交给编译器是完全没有问题的.

下面便是汇编指令混淆器的实现思路

db伪指令不仅仅可以在数据段中定义数据, 也可以在.code 段中定义数据, 而这些数据如果被eip指向就会被当成代码执行, 如果eip永不指向它, 它虽在代码段中,但也不会被执行. 那么我们完全可以这样做:

这段小程序执行起来之后, 在执行了前两句之后,会接着jmp_START标签之后, 而那段我们在代码中定义的数据将永远不会被使用到. 但有时候这种小伎俩很容易被识破 , 我们再观察另外的情况:

上面这段代码比较正常, 调用printf函数打印hello字符串嘛. 但再看以下这段:

这段代码仍然还是打印字符串hello, 但它的执行流程就没有上面的清晰了, 例如, 它运行之后, 先call到了标签_PUSHSTR处, 因为这是一条call条指令,执行之后是会将返回地址入栈的, 而入栈的地址好巧不巧正是字符串hello在代码段中的地址. 而调用printf函数时, 栈中已经保存了一个字符串的地址. 因此,最后输出的正式字符串hello. 而由于字符串被保存在了代码段中, 当这个程序被OD反编译时,将会被当成opcode解析出来.,在分析时自然就不是很好看了.

一些指令执行之后是不会产生任何作用, 例如 :

这段指令看似会有分支执行 ,但实际不会, 因为or eax,080000000h执行之后, SF符号标志位必定被置1. js指令也必定会被执行. 后续的代码也一样.

整个混淆器的工作流程是这样的:

因此, 它看起来大概是这样的:

至于混淆器对象 , 它是这样做的:

没错,这是个纯虚函数, 因为我把指令分成了不同种类,有数据传输的,有算术运算的,有位运算的, 不同的指令有不同的混淆, 而我不想将所有的代码都放在此函数中实现, 因此, 我派生了几个混淆不同种类指令的混淆器类来,它们分别有:

例如, 对数据传输指令的操作是这样的:

这其中, 涉及到了一个叫做Instruction的类, 这个类没什么逻辑, 它主要提供了操作一条婚变指令的功能.

这个类一般接收一条字符串,例如:mov eax , 1 , 然后通过这个指令的几个成员函数, 就可以得到一条汇编指令的操作数,或者替换指令的操作数了.

还有一个InstructionGroup类, 它负责保存一组指令, 实际上就是一个vector<Instruction>

这毕竟只是花了一个下午写出来的, 因此, 只能当汇编中的高级知识来学学啦, 真心没有啥用.

代码:https://github.com/enoorez/win32-sources-mixer

 
 
 
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 2166
活跃值: (3226)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
2
混淆是加壳保护中重要的一步
2018-2-4 19:10
0
雪    币: 6818
活跃值: (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
2018-2-4 23:20
0
游客
登录 | 注册 方可回帖
返回
//