简易VM混淆编程--使用C语言源码

(1)本文提出一种不同寻常的混淆,即类似VMP的一种方法,但本文不提供类似VMP的自动工具

(2)本方法主要用于核心算法区域核心加密函数的混淆

(3)但本方法因没有相关辅助开发工具,需要使用汇编的方式

首先,我们写2篇代码,实现一个基于堆栈的虚拟机

 

#pragma once

//首先就是定义各种操作码的值,程序上进行顺序调整就改变了枚举值的值
//此处枚举值不写值,便于调整打乱
enum CV_ENUM
{
	vMark,
	vAdd1,
	vPushStr,
	vGotoIfN,
	vPushInt,
	vPushVst,
	vSub1,
	vEnd,
	vCmpIntSt,
	vGoto,
	vPushChar,
	vLoadChar,
	vSaveChar,
	vCalcMod,
	vCalcXorChar,
};


#define vSt(x) (x) //表示从栈底找变量
#define vMark(x) (x) //表示跳转位置

enum cVmDType
{
	vxtInteger,
	vxtString,
	vxtReal,
	vxtQword,
};

struct cVmData
{
	cVmDType vxxxType;
	int      vxxxSLen;
	union
	{
		__int64  asInteger;
		wchar_t* asString;
		double   asReal;
		DWORD64  asQword;
	};
};

#define ERR_OUT_OF_INDEX 1
#define ERR_POP_EMPTY_STACK 2
#define ERR_PUSH_FULL_STACK 3
#define ERR_SEH_EXEC_INST 4
#define ERR_UNSUPPORT_INST 5

BOOL CvMachine_ExcuteCode(DWORD_PTR* pCodePtr, int cVmMaxMark, int* m_MarkTable, int cVmMaxStack, cVmData* m_stack, int& IN OUT m_StTop, int & OUT nErr, int& OUT nErrPos);
BOOL CvMachine_ScanMark(DWORD_PTR* pCodePtr, int cVmMaxMark, int* m_MarkTable, int& OUT nErr, int& OUT nErrPos);
bool CvM_ExecuteOnInstruct(int Code, DWORD_PTR* pParams, bool& OUT bEnd, bool& OUT bNeedJump, int& OUT nJumpOffset, int& OUT exceptionErr, int* m_MarkTable, int cVmMaxStack, cVmData* m_stack, int& IN OUT m_StTop);
cVmData& CvM_ref_stack(DWORD_PTR nFromBottom, int cVmMaxStack, cVmData* m_stack);
cVmData CvM_pop(int& IN OUT m_StTop, cVmData* m_stack);
void CvM_push_v(cVmData& cv, int& IN OUT m_StTop, int cVmMaxStack, cVmData* m_stack);
void CvM_push_int(__int64 V, int& IN OUT m_StTop, int cVmMaxStack, cVmData* m_stack);
void CvM_push_str(wchar_t* pStr, int Len, int& IN OUT m_StTop, int cVmMaxStack, cVmData* m_stack);


template<int cVmMaxStack = 128, int cVmMaxMark = 32>
class CvMachine//内部放一个栈,不要动态分配
{
public:
	CvMachine()
	{
		m_StTop = -1;
	}
	~CvMachine() {}

	BOOL ExcuteCode(DWORD_PTR* pCodePtr, int& OUT nErrCode, int& OUT nErrPos)
	{
		return CvMachine_ExcuteCode(pCodePtr, cVmMaxMark, m_MarkTable, cVmMaxStack, m_stack, m_StTop, nErrCode, nErrPos);
	}

private:
	cVmData      m_stack[cVmMaxStack];//64个栈变量空间1KB,128=2KB
	int          m_StTop;//放在中间不容易被逆向找到,注意传递引用
	int          m_MarkTable[cVmMaxMark];//支持这么多的标记点
};

下面是个例子,表示我们实现一个基于此虚拟机的异或函数,这样通过IDA反编译就看不出它的代码

BOOL VxxStringXOR(WCHAR* pText, int lenTxt, WCHAR* pKey, int lenKey)
{
	BOOL bRet = 0;
	//我们用CodingVM写一个字符串异或加密方法
	//for(i = 0; i < lenKey; i++)
	//{
	//	pText[i]=pText[i]^pKey[i%lenKey];
	//}
	DWORD_PTR vxxCode[] =
	{
		//先压入参数,记住,栈底0位置为第一个参数
		vPushStr, (DWORD_PTR)pText, lenTxt,  //v0 Input
		vPushStr, (DWORD_PTR)pKey, lenKey,   //v1 Key
		vPushInt,  lenTxt,        //v2 lenTxt
		vPushInt,  lenKey,        //v3 lenKey
		vEnd,
	};

	static DWORD_PTR vxxCode2[] =
	{
		vPushInt,  0,             //v4 I
		//然后开使进行加密
		vMark,     0,//标记跳转点
		vPushVst,  vSt(4),
		vLoadChar, vSt(0),       //T[i]到栈顶
		//calc I%KeyLen
		vPushVst,  vSt(4),
		vPushVst,  vSt(3),
		vCalcMod,
		vLoadChar, vSt(1),       //K[KL%I] 到顶
		vCalcXorChar, //top = xor ret
		vPushVst,  vSt(4),
		vSaveChar, vSt(0),
		vCmpIntSt, vSt(4), vSt(2),
		vGotoIfN, (DWORD_PTR)(-1), 1,
		vAdd1,     vSt(4),
		vGoto,     0,
		vMark,     1,
		//完成了
		//到结束符号停止,若没有结束符号可能崩溃哟
		vEnd,
	};
	CvMachine machine;

	if(machine.ExcuteCode(vxxCode))
	{
		if(machine.ExcuteCode(vxxCode2))
		{
			bRet = TRUE;
		}
	}

	return bRet;
}

至于如何实现执行这个虚拟指令的代码,能看懂此文的都能自己实现出来,这里就不再写出了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值