首页
论坛
专栏
课程

[原创]自写保护壳交流——指令的膨胀和花指令的插入

2019-3-23 13:20 5972

[原创]自写保护壳交流——指令的膨胀和花指令的插入

2019-3-23 13:20
5972
从准备写壳到到现在已经有半年多的时间了,期间代码框架重构了很多次。
先说一下总体架构共有三部分
 1.PE部分 ,2.混淆虚拟化部分,3.保护部分 
目前 PE部分只写了简单的操作,没有对代码段的压缩和对导入表的处理.
虚拟化部分 框架大概写蹦了5,6次(目前可以做到简单指令的模拟和对重定位的支持)最近一次是在2个月以前,将架构改成vmp 3.x的链式寻址的时候,又写蹦了框架,现在还没有整合
本帖就说一下近期在写的混淆部分

目前在写代码混淆膨胀部分,目前的设定框架是由3块组成:

1.代码块的拆分
2.全局地址管理器
3.混淆过程

一、代码块的拆分



二、混淆地址管理器( 也叫全局地址管理器,因为vm框架也是用这个地址管理器  ) 在代码混淆过程中,你并不知道接下来的代码区块将会被膨胀到多大,所以必须要一个地址管理器来确定下一区块的大小。 首先要将地址分块,按照去除重定位(401000 处加载基址)的方式分配地址:

 代码块1 :  address 0x40B016 

代码块2 :  address  xxx

代码块3:address  xxx

使用地址管理器将代码块的地方分配并连接起来达到如下效果:



混淆分块后效果图:




三、混淆过程步骤:

使用 代码块的拆分  + 地址管理器  -> 将代码块划分成一个个小的地址快来进行管理
首先划分区块,并将区块打上属性标签

1.区块划分

[DBGLOG]:代码块0,区块属性 JCC

mov eax, 0x1

cmp eax, 0x2

jz 0x40100e


[DBGLOG]:代码块1,区块属性 NULL

add eax, 0x1

inc eax

[DBGLOG]:代码块2,区块属性 JCC

mov eax, eax

add eax, 0x1

cmp eax, 0x1

jnz 0x40101d

[DBGLOG]:代码块3,区块属性 NULL

mov eax, eax

add eax, 0x1

[DBGLOG]:代码块4,区块属性 JCC

add eax, 0x1

dec eax

cmp eax, 0x2

jz 0x40102b

[DBGLOG]:代码块5,区块属性 NULL

mov eax, eax

add eax, 0x1

[DBGLOG]:代码块6,区块属性 JCC

mov eax, eax

mov eax, eax

dec eax

cmp eax, 0x3

jnz 0x40103a

[DBGLOG]:代码块7,区块属性 NULL

mov eax, eax

add eax, 0x1

[DBGLOG]:代码块8,区块属性 End

sub eax, 0x1

mov eax, eax


2.将代码区块使用地址管理器分配地址:

[DBGLOG] 地址:00401000,代码块:0

[DBGLOG] 地址:0040100a,代码块:1

[DBGLOG] 地址:0040100e,代码块:2

[DBGLOG] 地址:00401018,代码块:3

[DBGLOG] 地址:0040101d,代码块:4

[DBGLOG] 地址:00401026,代码块:5

[DBGLOG] 地址:0040102b,代码块:6

[DBGLOG] 地址:00401035,代码块:7

[DBGLOG] 地址:0040103a,代码块:8


3.添加简易重定位支持:
这里对于混淆引擎来说使用到的全局变量应该交由PE部分去处理,但我这边偷懒直接使用vmp的重定位方式(/尴尬)

4.指令处理:
对于混淆虚拟化来说代码的本质是等价替换,这里以举一个最简单的例子 push 0x123456 :
我的方式 主要是对0x123456 进行处理,首先拿到0x123456 这个立即数 对0x123456进行加法,
异或 等操作 imm = ( 0x123456+0x111111 ) ^ 0x22222 = 0x216745在混淆代码中表现出来:
 push eax
 mov eax,imm
 xor eax,0x22222
 sub eax,0x111111
 push eax
 mov eax,dword ptr[esp+0x4]

这样就完成了 对 push 0x123456 指令的混淆。

5.花指令的插入
在全局 有一个控制花指令插入的开关 _flower_code 由它决定是否插入花指令,部分代码如下:
void CodeObfuscationEngine::_insert_flower_code(asmjit::X86Assembler *& _a)
{
    if (_insert_junk_code_number % 100 > _flower_code)
        return;

    int r = rand() % 3;
    switch (r)
    {
    case 0:
    {
        Label label = _a->newLabel();
        _a->jmp(label);
        _a->db(0xE8);
        _a->bind(label);
    }break;
    case 1:
    {
        Label label = _a->newLabel();
        _a->jmp(label);
        _a->db(0xE9);
        _a->bind(label);
    }break;
    case 2:
    {
        Label label = _a->newLabel();
        int addr = rand() % 0x66 + 0x5;
        _a->call(label);
        _a->db(0x74);
        _a->db(addr);
        _a->bind(label);
        _a->add(esp, 4);
    }break;
    default:
        break;
    }



正常代码块:

代码块拆分:

代码混淆部分+花部分 :
里面去除了对某些指令的膨胀(比方xor)相对比较简单,新手项可以看未加壳部分,要求是逆出key

 CrackMe :

原始的未混淆部分:

写在最后:
自己的工程参考了很多很多代码(多到我也记不清了,就不一一署名),先谢谢前辈们无私的奉献。
目前很少看到在群里有人认真的讨论一些问题,基本都是在发图吹水,如果有人问一个技术性的问题,那么突然间整个群好像卡死一般的没人说话,过一段时间有个人试探性的往群里发了一张水图,整个群的气氛就又活跃起来,导致很多人的问题都得不到解答,所以我自己建了个小群,希望对加壳脱壳、vm虚拟机研究、膨胀指令还原的小伙伴能加群一起讨论问题,对我多多指点,谢谢。

群号是Crackme里面的key



[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最后于 2019-3-24 20:34 被Wszzy编辑 ,原因:
上传的附件:
打赏 + 3.00
打赏次数 2 金额 + 3.00
收起 
赞赏  Editor   +2.00 2019/03/26
赞赏  demoscene   +1.00 2019/03/25
最新回复 (20)
天水姜伯约 3 2019-3-23 17:38
2
0
我也在研究这个,但学生狗目前没办法摸到电脑,能不能私发一下我群号?
Wszzy 1 2019-3-23 17:45
3
0
三十二变 [em_2]我也在研究这个,但学生狗目前没办法摸到电脑,能不能私发一下我群号?
已发
Lixinist 1 2019-3-24 08:59
4
0
已加群
LooPg 2019-3-24 09:42
5
0
膜拜大佬,流口水
xiaohang 3 2019-3-25 21:06
6
0
不错,自写指令膨胀还是蛮有意思的。鼓励一下
demoscene 7 2019-3-25 21:41
7
0
现在还研究壳的已经不多了,LZ是准备商业化吗,可能是未来的竞争对手

异或 等操作 imm = ( 0x123456+0x111111 ) ^ 0x22222 = 0x216745在混淆代码中表现出来

这个不能简单的进行算术替换,你没考虑标记位问题,大多数时候是没问题的,但是要是遇到下面这样的代码,你直接在中间插入算术运算就标记位就会出问题。
cmp eax, 0
push 0x123456
jnz xxx

Wszzy 1 2019-3-25 22:36
8
0
xiaohang 不错,自写指令膨胀还是蛮有意思的。鼓励一下
谢谢!
1lu29e 1 2019-3-25 22:50
9
0
demoscene 现在还研究壳的已经不多了,LZ是准备商业化吗,可能是未来的竞争对手 异或 等操作 imm = ( 0x123456+0x111111 ) ^ 0x22222 = 0x2167 ...
mapo大佬,我可以研究你们的Mapoengine么挑战一下
Wszzy 1 2019-3-25 22:54
10
0
demoscene 现在还研究壳的已经不多了,LZ是准备商业化吗,可能是未来的竞争对手 异或 等操作 imm = ( 0x123456+0x111111 ) ^ 0x22222 = 0x2167 ...
谢谢 demoscene 指出这个问题。算数运算指令是会改变eflage标志寄存器,之前想push 中间寄存器的时候将flage寄存器也压栈保存一下,不过这样做特征太明显,很容易被定位针对,还没有想到什么好的方法。
目前在修PE模块的重定位模块,单独处理混淆部分的重定位数据。这样混淆起来就不必考虑必须模拟需要修正重定位部分的代码。
在写壳的过程中我发现如果只是自己的壳保护自己的代码是比较容易的,碰到问题可以很快解决,如果写一个商用的壳真的需要考虑很多东西,因为总有一些在测试中不会出现的问题出现在计划之外,所以商业化应该是很遥远的事情,不过即使商业化也不会做成网络验证的,应该是一套保护系统,壳只是其中一部分。
我是自己在做这个东西,平时上班很忙、加上没什么人交流所以进度很慢,希望可以有些志同道合的小伙伴多多交流

猪会被杀掉 1 2019-3-25 23:03
11
0
喷一句打击的话,毫无技术含量。虽然我认识demoscene。
猪会被杀掉 1 2019-3-25 23:05
12
0
VMP还是做的不错的,对于代码保护以及兼容性,这种保护只能用在工具类产品上,对于互联网来说毫无价值。
Wszzy 1 2019-3-25 23:15
13
0
猪会被杀掉 喷一句打击的话,毫无技术含量。虽然我认识demoscene。
除了你的帖子 https://bbs.pediy.com/thread-250431.htm  大家也可以去看看  https://bbs.pediy.com/thread-223629.htm  这个demo写的也挺好
猪会被杀掉 1 2019-3-25 23:20
14
0
Wszzy 除了你的帖子 https://bbs.pediy.com/thread-250431.htm 大家也可以去看看 https://bbs.pediy.com/thread-223629.htm 这 ...
我没说自己写的好,这种github上很多代码,我想喷的是你居然当个宝贝一样,还只发图不发代码,版主还给了精华。我发了代码不求精华。
猪会被杀掉 1 2019-3-25 23:20
15
0
这种过时的技术有必要当个宝贝?
demoscene 7 2019-3-26 08:35
16
0
ilyzqe mapo大佬[em_41],我可以研究你们的Mapoengine么[em_86]挑战一下
这个写得太挫了,经不起大佬们的研究,还是研究VMP吧
demoscene 7 2019-3-26 08:39
17
0
猪会被杀掉 我没说自己写的好,这种github上很多代码,我想喷的是你居然当个宝贝一样,还只发图不发代码,版主还给了精华。我发了代码不求精华。
稻哥还是这么热血,有文章讲原理也是一种分享
猪会被杀掉 1 2019-3-26 09:31
18
0
demoscene 稻哥还是这么热血,有文章讲原理也是一种分享
麻婆大哥讲的有道理,别喊稻哥,承受不起。
Anskya 20 2019-3-26 17:55
19
0
根据《虚拟机系统与进程的通用平台》的定义
vmp3的跳转属于直接线索寻址,在gcc下goto可以直接goto *ip这样跳转(看过jvm的代码就知道,jvm也是这么干的)

楼主的标志位处理真的是一个很严重的问题,而且这种xor隐藏没啥意义,把参数当作opcode读取出来再解密的安全性更高。
麻婆其实就是一个低配版的vmp2---我仅仅是说1.3版,许多地方做的还不如vmp2好,比如标志位处理部分

其实楼主的vm更像是themida的CISC VM,有空逆向一下themida的vm看看就知道了,他的RISC VM就是楼主准备接下来写的架构。

VM可以走两个极端走,要么把handler复杂化让分析变得异常痛苦(Themida方向)
要么走VMP的路线,handler简单但是编译器写的比较复杂。
都可以起到保护代码的作用,看你选择哪个方向了。
如果楼主想要好好发展mutation部分的话可以选择走TMD的路线。

现在最没意思的就是大家都抄袭VMP的VM架构,一点原创精神都没有。过段时间发布新版本的vxpack来弥补这个问题
Wszzy 1 2019-3-26 20:12
20
0
Anskya 根据《虚拟机系统与进程的通用平台》的定义 vmp3的跳转属于直接线索寻址,在gcc下goto可以直接goto *ip这样跳转(看过jvm的代码就知道,jvm也是这么干的) 楼主的标志位处理真的 ...
谢谢小零的解析,tmd的混淆技术已经相当成熟了,我也明白这个混淆引擎写下去会很像它。
我示意的push imm 混淆其实之所以没有处理标记位是急于想找人交流,直接从vm框架中 vmhandle 加解密里面直接拿出来用的,vm框架中veip指令流是按小零说的将pcode 用加减 not xor  rol ror等随机加密的。
因为写壳是小众中的小众,所以一直没有完整的学习框架,大家都是在摸索中学习,却不把知识传承。这也可能导致大家一直在学这些东西,但没办法能站在巨人的肩膀上继续创新的原因。
map1.3的虚拟机像vmp2.x 的原因我想可能是他写壳的时候3.x 没出来,我现在的虚拟机是3.x 架构,因为打算写壳的时候3.x 授权分析都已经出来了。在保护强度其实大家都是在消磨crack 者们的耐心。所以时至今日对我来说,代码已经不重要了,重要的有一种思路,一种新的思想。
最后于 2019-3-26 20:18 被Wszzy编辑 ,原因:
azhankai 2019-4-10 08:18
21
0
学习了
游客
登录 | 注册 方可回帖
返回