首页
社区
课程
招聘
[原创]一种新的多态引擎设计思路,理论,以及实现.
发表于: 2009-4-13 15:00 24336

[原创]一种新的多态引擎设计思路,理论,以及实现.

2009-4-13 15:00
24336
原本想写一个"伪"编译器用来实现一个多态引擎.
后来觉得,其实根本没有那个必要, 只要用下面的办法, 就能够构造一个简单高效而又难缠的多态引擎

原本想把完整实现写出来的,
但是自己突然又懒了,不想写了,最后的实现代码应该也非常简单.所以就不写了.
另外, 对于这种多态引擎的检测思路, 我还真没想到比较好的.

p.s. 我仅仅兴趣. 对杀毒软件之类也没什么了解. 如果有代码错误或者完全的认知错误,欢迎指正批评.
如果你有更好的实现方式, 或者检测方法 欢迎交流. (其实我更想知道一些针对此的检测方法)

但愿不要零回复...

理论:
通常情况下,高级编译器所生成的函数代码都是"很规矩"的(理论支持.IDA传说中的F5).
所以,如果我们将病毒所要用到的"有特征的加解密函数"拆解成,n个"执行简单,正常功能的函数",那么这n个单独的函数将是"无特征"的.
然后我们将这n个函数进行随机排序, 则将能生成 n! * 3 * 3个变种.(第一个3是函数的调用方式,stdcall fastcall cdecl, 第二个3是函数尺寸对齐)


特点:
足够的高效(从设计到完成所花时间).
不惧怕基于"无效代码"的检测方式.
与传统的多态引擎相比,不依靠代码指令生成变种,而是以n个"无特征函数"的随机排序方式实现.虽然所产生的变种远远没有传统多态引擎多,但已经足够用来对抗杀毒引擎的查杀.事实上将比传统的多态引擎更加难缠.


不足:


检测:
在知道引擎入口的情况下,跟进call调用然后进行代码匹配.(事实上引擎入口的隐藏非常简单.)


具体实现:
1,先写一个加(解)密函数.

int Encode( PBYTE pInBuffer, int nSize)
{

  for ( int i = 0; i < nSize; i++)
  {

    pInBuffer >>= 1;
  }

  return 1;

}

[课程]Linux pwn 探索篇!

收藏
免费 7
支持
分享
最新回复 (64)
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
2
2.然后将其拆分成n个函数, 我这里n=10.


int Encode( PBYTE pInBuffer, int nSize)
{

IsTrue( pInBuffer, nSize);

for ( int i = GetZero(); CheckIsOut( i, nSize); i++)
{

if ( !FixTheCode( &pInBuffer))
{
return false;

}
}

return 1;

}

//__forceinline
bool CheckIsOut( int i, int nCount)
{

return i < nCount ? true : false;

}

BYTE RightMove( BYTE b)
{

if ( IsZero( b))
{
return false;
}


return b >> 1;
}

bool IsZero( BYTE b)
{
return b != 0 ? true : false;
}

bool IsLessZero( int i)
{
return i < 0 ? true : false;
}

bool IsTruePoint( PVOID p)
{

return IsLessZero( (int)p) ? false : true;

}


bool IsTrueSize( int nSize)
{

return IsLessZero( nSize) ? false : true;
}


bool IsTrue( PBYTE p, int n)
{


return IsTruePoint(p) && IsTrueSize( n) ? true : false;

}

bool FixTheCode( PBYTE p)
{

if ( IsTruePoint( p))
{
*p = RightMove( *p);
return true;
}
else
{

return false;
}
}

int GetZero()
{

return NULL;
}


11111111111
2009-4-13 15:01
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
3
DD 函数原始序号,函数大小,调用子函数的偏移,被调用子函数的原始序号,0结束
DW 0x01,0x63 //函数原始序号, 函数大小
DW 0x0C,0x07 //在函数头+0x0C处, 调用原始序号为0x7的子函数
DW 0x14,0x09 //........+0x14..,...............0x9的子函数
DW 0x2F,0x02 //
DW 0x45,0x08 //
DW 0x00,0x00 // 结束, 后面跟函数体.
DB 55 8B EC 51 8B 45 0C 50 8B 4D 08 51 E8 DF 00 00 00 83 C4 08 E8 57 01 00 00 89 45 FC EB 09 8B 55
FC 83 C2 01 89 55 FC 8B 45 0C 50 8B 4D FC 51 E8 3C 00 00 00 83 C4 08 0F B6 D0 85 D2 74 1C 8B 45
08 03 45 FC 50 E8 E6 00 00 00 83 C4 04 0F B6 C8 85 C9 75 04 33 C0 EB 07 EB C4 B8 01 00 00 00 8B
E5 5D C3

例:
/*
$ ==> >/$ 55 push ebp ; 1
$+1 >|. 8BEC mov ebp, esp
$+3 >|. 51 push ecx
$+4 >|. 8B45 0C mov eax, dword ptr [ebp+C]
$+7 >|. 50 push eax
$+8 >|. 8B4D 08 mov ecx, dword ptr [ebp+8]
$+B >|. 51 push ecx
$+C >|. E8 DF000000 call 00091110
$+11 >|. 83C4 08 add esp, 8
$+14 >|. E8 57010000 call 00091190
$+19 >|. 8945 FC mov dword ptr [ebp-4], eax
$+1C >|. EB 09 jmp short 00091047
$+1E >|> 8B55 FC /mov edx, dword ptr [ebp-4]
$+21 >|. 83C2 01 |add edx, 1
$+24 >|. 8955 FC |mov dword ptr [ebp-4], edx
$+27 >|> 8B45 0C mov eax, dword ptr [ebp+C]
$+2A >|. 50 |push eax
$+2B >|. 8B4D FC |mov ecx, dword ptr [ebp-4]
$+2E >|. 51 |push ecx
$+2F >|. E8 3C000000 |call 00091090
$+34 >|. 83C4 08 |add esp, 8
$+37 >|. 0FB6D0 |movzx edx, al
$+3A >|. 85D2 |test edx, edx
$+3C >|. 74 1C |je short 0009107A
$+3E >|. 8B45 08 |mov eax, dword ptr [ebp+8]
$+41 >|. 0345 FC |add eax, dword ptr [ebp-4]
$+44 >|. 50 |push eax
$+45 >|. E8 E6000000 |call 00091150
$+4A >|. 83C4 04 |add esp, 4
$+4D >|. 0FB6C8 |movzx ecx, al
$+50 >|. 85C9 |test ecx, ecx
$+52 >|. 75 04 |jnz short 00091078
$+54 >|. 33C0 |xor eax, eax
$+56 >|. EB 07 |jmp short 0009107F
$+58 >|>^ EB C4 \jmp short 0009103E
$+5A >|> B8 01000000 mov eax, 1
$+5F >|> 8BE5 mov esp, ebp
$+61 >|. 5D pop ebp
$+62 >\. C3 retn
*/

//跟第二个函数表

DW 0x02,0x0E
DW 0x00,0x00
DB 55 8B EC 8B 45 08 3B 45 0C 0F 9C C0 5D C3
/*
$ ==> >/$ 55 push ebp ; 2
$+1 >|. 8BEC mov ebp, esp
$+3 >|. 8B45 08 mov eax, dword ptr [ebp+8]
$+6 >|. 3B45 0C cmp eax, dword ptr [ebp+C]
$+9 >|. 0F9CC0 setl al
$+C >|. 5D pop ebp
$+D >\. C3 retn
*/

//跟第三函数表

DW 0x03,0x33
DW 0x18,0x04
DW 0x00,0x00
DB 55 8B EC 0F B6 45 08 50 E8 23 00 00 00 83 C4 04 0F B6 C8 85 C9 74 04 32 C0 EB 06 0F B6 45 08 D1
F8 5D C3

/*
$+10 >/$ 55 push ebp ; 3
$+11 >|. 8BEC mov ebp, esp
$+13 >|. 0FB645 08 movzx eax, byte ptr [ebp+8]
$+17 >|. 50 push eax
$+18 >|. E8 23000000 call 000910D0
$+1D >|. 83C4 04 add esp, 4
$+20 >|. 0FB6C8 movzx ecx, al
$+23 >|. 85C9 test ecx, ecx
$+25 >|. 74 04 je short 000910BB
$+27 >|. 32C0 xor al, al
$+29 >|. EB 06 jmp short 000910C1
$+2B >|> 0FB645 08 movzx eax, byte ptr [ebp+8]
$+2F >|. D1F8 sar eax, 1
$+31 >|> 5D pop ebp
$+32 >\. C3 retn
*/
111111111111111
2009-4-13 15:02
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
4


接下来随机排序和修正call调用就好了,

还加上一个函数对齐吧.

原本想把完整实现写出来的,
但是自己突然又懒了,不想写了,最后的实现代码应该也非常简单.所以就不写了.
另外, 对于这种多态引擎的检测思路, 我还真没想到比较好的.

p.s. 我仅仅兴趣. 对杀毒软件之类也没什么了解. 如果有代码错误或者完全的认知错误,欢迎指正批评.
如果你有更好的实现方式, 或者检测方法 欢迎交流. (其实我更想知道一些针对此的检测方法)

但愿不要零回复...
2009-4-13 15:03
0
雪    币: 107
活跃值: (811)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
5
收藏学习了,感谢分享
2009-4-13 15:06
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
6
终于不是零回复了..
2009-4-13 15:12
0
雪    币: 107
活跃值: (811)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
7
看完不是很明白
2009-4-13 15:16
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢楼主的分享
2009-4-13 15:45
0
雪    币: 263
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
太强了, 安全不懂
2009-4-13 16:08
0
雪    币: 224
活跃值: (147)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
10
天             书
2009-4-13 16:17
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
11
虽然看不懂. 不过一定很强.
2009-4-13 16:36
0
雪    币: 101
活跃值: (88)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
12
非常难缠。基本上没人会有耐心去看清楚你做了什么。

但问题是,杀掉病毒不需要知道细节。
2009-4-13 17:02
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
13
怎么杀?
拆解的每一个子函数,就单独的函数而言,是没有病毒特征的.
而如果 用两个子函数的组合来定义病毒特征的话, 函数又是随机分布的, 如何定位?
如果  满足函数A 调用函数B 且函数A,B包含特征. 这样子, 得先早到引擎入口吧?
2009-4-13 17:12
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
14
不太明白~建议楼主还是不要仅停留在想法上
2009-4-13 18:27
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
15
有想法,面对大家这么多的质疑,还是来个实验小程序比较有说服力
2009-4-13 18:54
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
16
举个例子:微点
2009-4-13 19:02
0
雪    币: 6900
活跃值: (3400)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
asd
17
直接写个源码级混淆的编译器
2009-4-13 19:22
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
18
杀软除特征查杀外,还以行为判断程式动向
2009-4-13 19:24
0
雪    币: 217
活跃值: (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
多态对于反破解更有意义些。杀毒软件一般都不会只用2进制特征的。
2009-4-13 21:04
0
雪    币: 7115
活跃值: (639)
能力值: (RANK:1290 )
在线值:
发帖
回帖
粉丝
20
楼主的意思是把一个解密函数按照调用子函数的顺序建立一个表 对吧。  然后把调用顺序记录下来 再调用。 再把 各个函数排列的顺序都打乱(造成特征码的不一样) 是这个意思吗?
如果我的理解没有错的话
那么 这种方法确实问题多多。

调用表函数本身 就出现了特征。
你说的子函数没有特征, 这个看子函数的大小了 小到如果就一个 xor或者ror 之类的确实没有特征。如果稍微大一些自己独特的代码就会出啦。 其实呢? 病毒的加密算法不需要太强 也就是说 很多加密算法也就一个 y = (x + 2) ^ 0x99 这样类似的算法 或者直接一个xor 不太能产生什么子函数之类的。当病毒大部分代码被加密后(特征改变) 加密头的变形就是产生变体的关键了。这也就是最基本的多态病毒了。
楼主的变形其实是把几个子函数颠倒了有一下顺序(如果存在的话) 其实 杀毒软件发展20多年了。 虽然vxker们天天嘴上骂anti-vx 垃圾。 其实其中的技术含量还是很高的。如果仅是变一下位置,就能逃过。那么杀软就都该倒闭了。建议你读下 《计算机病毒防范艺术》

我有些看不懂你发的那个C代码。。。 能添上注释吗?
2009-4-13 21:46
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
21
是这个意思. 子函数没有特征是前提.
传统多态是建立一个代码指定表, 就每个指令而言都是"无特征" & "无用的".
我这里讲的 子函数 是"无特征"的.
解密原本就是一个很简单的函数. 可以很轻易的拆分成无特征的. 所以你讲的" 函数大了就有特征"了 这种问题也不存在, 我现在要做的就是把 函数拆分成无特征的子函数, 然后子函数顺序随机排列.
你可以理解为 把函数拆分成指令.
嗯, 传统多态是把函数拆分成单独的指令, 然后随机空间排序.
我这里则是拆分成无特征的子函数.
2009-4-13 21:57
0
雪    币: 7115
活跃值: (639)
能力值: (RANK:1290 )
在线值:
发帖
回帖
粉丝
22
你其实没有考虑到一些实际情况
1.子函数怎么可能没有特征?
2.而且如果函数内要实现一些流程判断呢?你怎么分析和建立表。
3.就算你这个引擎就是给你自己用的。如果是给其他人用的就要考虑问题2.自己用解密代码可以自己构造。不出现什么重定位和流程判断问题。那总该有个子函数的数量吧。考虑到实际情况这个N就算上4个吧(对于病毒的加密算法真的有点多)那么变体就有4! 也就24个变体。你也不用考虑什么stdcall等调用方式。就算用高级语言写stdcall就是标准的 c的有就最后多个add esp, XXX 而且这些都是编译的时候发生的了。 和变形引擎没联系了。 如果非要算上这个,那么不如写个源代码的混淆。 连调用表 拆分之类的都不用去考虑。如果我是用汇编来写那么更不用考虑这些问题。
4.传统的多态是其实是花指令+指令替换。
2009-4-13 22:18
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
23
1, 你可以看看我拆解的那10个子函数. 你可以找出什么特征来吗?
在asm中,  单独的一个mov eax,ecx是一条指令 是没有特征的
在高级语言中, 同样的, 一个for循环 实际上 就相当于asm中的"一条指令"
既然同样是一条指令, 而且一个"函数"就一条指令? 你如何给他定特征?
这样讲吧. 你能够轻易的在我的代码(某个函数)中定位特征. 结果是, 一大片一大片的误杀.
这跟杀毒软件不会杀你的单一的指令mov eax,ecx一样.

2.这个问题我想是你没有理解我的意思, 当然.也也许是我没有明白你的意思 :)
2009-4-13 22:28
0
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
24
楼主提出了一个新的Concept,但是楼主居然没有Proof of Concept一下~~

不求DEMO,只要POC~

Concept人人会YY,主要是Proof...
2009-4-14 00:40
0
雪    币: 357
活跃值: (3123)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
25
你的n=10,不能再分了吧?
2009-4-14 05:35
0
游客
登录 | 注册 方可回帖
返回
//