3

[原创]谈谈vmp的还原(3)

waiWH 2018-4-14 19:32 1860
0x00 前言

vs2010,代码放在了github:vmp
0x01 寄存器

先说context

init初始化context分两种情况


那么第二种,就是随机生成了

关于pushad pushfd的保存 


选取空闲的context


代码如下:

int n = 0, k = 0;
char cpu[16] = {0};

int _getContextIndex( int type)
{
	if( tpye - 1 >= 2)
	{
		switch(type)
		{
			case 0:
			case 4:
				return dis->reg[0];
			case 1:
			case 5:
				return dis->reg[1];
			case 2:
			case 6:
				return dis->reg[2];
			case 3:
			case 7:
				return dis->reg[3];			
			case 9:
			case 0xD:
				return dis->reg[9];		
			default:
				return 0;												
		}
	}
	else
	{
		switch(type)
		{
		case 0:
		case 1:
		case 2:
		case 3:
		case 5:
		case 6:
		case 7:
		case 8:
		case 9:
		case 0xa:
			return dis->reg[_type];
		case 4:
			return -1;
		default:
			return 0;
		}
	}
}

for( int i = 0; i < 16; i++)
{
	if( dis->reg[i] < 0xff)
	{
			cpu[ dis->reg[i]] = 1;
	}
}
i = 0;
while( cpu[i] || rand()%2 != 1)
{
	i++;
	return _getContextIndex(tpye);
}
dis->reg[k] = n;
return _getContextIndex(tpye);

这里说下,看到这部分实现的时候,脑子里的想法是当成树结构,用dfs去识别判断,因为以为是真轮转。记得,还给校长说,加密与解密那个目录处理的方法好像是图算法。

再注意到a2/v13 == 2, 才会去get context 

随意看一个调用,很明显tpye == 2才会去


那么其他的情况在只是return context,那么就好办了,因为可以得到,并不是真轮转


0x10 变形

下面这个东西,也是我最佩服vmp作者的地方,因为就这点东西,就可以做很多事情了。


注意是倒叙进行判断的

首先这个函数,我也不知道怎么命名好,所以就当成fixed吧,可能叫plasmodium比较好 。

当我进行分析的时候,如果不是语言不在同一个频道,可能就膜拜了。

随意的,举个例子。这里可能会需要一些数据结构的知识 。


记当前结构为一个_cur_node

记当前上一个节点为_prev_node

记当前下一个节点为_next_node


假定

_cur_node: LODS BYTE PTR DS:[ESI]  POP DWORD PTR DS:[EDI+EAX*4]
_next_node: LODS BYTE PTR DS:[ESI]  PUSH DWORD PTR DS:[EDI+EAX*4]

这两条在操作什么,很明显,可以看出vmp不是没有一些组合的

那么可能会出现下面的情况

_next_node变成PUSH ESP

new node,生成一个新的节点,记为_tmp_node

_tmp_node: POP EAX PUSH DWORD PTR ES:[EAX]

之后在插入,如下

Before

LODS BYTE PTR DS:[ESI]  POP DWORD PTR DS:[EDI+EAX*4]
LODS BYTE PTR DS:[ESI]  PUSH DWORD PTR DS:[EDI+EAX*4]

After:

LODS BYTE PTR DS:[ESI]  POP DWORD PTR DS:[EDI+EAX*4]
PUSH ESP
POP EAX PUSH DWORD PTR ES:[EAX]

注意到eax一致,然后明白这个函数了吗?

好像就这些了,我大概想阐述的东西,就这些。


0x11 关于我还原的思路

在我逆的过程中,一直在猜想vmp作者的构造思路。

最开始的时候,我的想法是把esi看成vmp_encodes,那么asm有套opcode的构造手册,vmp作者也应该有一套这样的手册,当然也不是说像intel手册那种。但我一直从各个角度去思考,都想不出,vmp作者是怎么构造出这些精彩的东西的。有兴趣的,可以尝试一下,如果是大一大二,我可能就这样继续下去了 。

之后我想既然知道了规则,可能不同版本,会有一些变化,但大致框架如此。

而不同的是,我所想的是,是还原为encodes,而不是asm,这点也重要,因为即使trace,或者使用插件,是的,你人工可能可以识别,那么代码认识么,当然可以写成分析树或写个虚拟引擎自己跑,但我想,这也是vmp作者愿意看到的情况

那么既然想还原成encodes,先解析esi,之后只要规则到位,那么我们可以得到disp,imm,sib,modrm,prefix。还需要确认的,就只剩下opcode了,所幸的是,相同mnemonic对应的opcode并不多,就大概解决类型不对等的情况了  。



推荐:论坛大聚会| 看雪安全开发者峰会将于7月21号火热来袭!

最后于 2018-4-15 18:22 被waiWH编辑 ,原因:
最新回复 (5)
zengsunsan 2018-4-14 21:40
2
支持
Lixinist 2018-4-15 19:20
3
像楼主这样愿意分享干货的人不多了
落笔飞花 2018-4-17 11:59
4
干货  mark
穆恩 2018-4-17 16:27
5
厉害  楼主分析的VMP主程序是哪个版本的
喂 那谁 2018-6-6 02:46
6
求能破加密狗的老师。付费      Q:646716529
返回