一步一步简单的保护我们的源码

    年底了,又赶上离职潮了。离职的coder总想着带走一些代码,自己的无可厚非,别人的就不大好了。如何保护公司的重要代码成了头痛的问题。本文通过添加一些简单的手段保护重要的代码。当然,这些手段有些陈旧,对付老鸟基本无效,但一般的coder拿到这样的代码,只能按delete了。。。吗啡,在药师手上变成了麻醉药,但在瘾君子看来又是一顿饕餮,这些手段如果被离职的coder自己使用,不仅制造bug还代码保护,那交接的coder又要抓狂了~

这里做一些约定VS编译器去除了/Gz 选项(函数调用后检查堆栈),并启用非增量连接方式。

//V1 假设CriticalCodeV1是核心代码 需要隐藏其实现
__declspec(naked) void CriticalCodeV1()
{
	MessageBox(NULL,"Cap","Msg",MB_OK);
	ExitProcess(0);
}

void CriticalCodeEnd()
{
}

int main()
{
	CriticalCodeV1();
}
CriticalCodeV1是我的核心代码,假设这个代码被人觊觎(事实不会)。在文章的结尾,这段代码会被我隐藏的面目全非。

现在逐步开始隐藏代码:

DWORD MsgBoxAddr;
DWORD ExitProcAddr;
__declspec(naked) void CriticalCodeV2()
{
	//因为函数声明为裸函数 不会自动生成函数框架
	//因此需要自己保存函数框架和开辟堆空间
	__asm
	{
		push ebp;
		mov ebp,esp;
		sub esp,0x10;

		mov al,'C';
		mov [ebp-0x04],al;
		mov al,'a';
		mov [ebp-0x03],al;
		mov al,'p';
		mov [ebp-0x02],al;
		xor eax,eax;
		mov [ebp-0x01],al;

		mov al, 'M';
		mov [ebp-0x08],al;
		mov al,'s';
		mov [ebp-0x07],al;
		mov al, 'g';
		mov [ebp-0x06],al;
		xor eax,eax;
		mov [ebp-0x05],al;
		
		push 0x00;
		lea eax,[ebp-0x04]
		push eax; //push "cap"
		lea eax,[ebp-0x08]
		push eax; //push "Msg"
		push 0x00;
		//不同机器 MessageBoxA ExitProcess入口地址不同 需要重定位 
		//此处为了方便 直接硬编码
		mov eax,0x749AFD1E;
		call eax;

		push 0x00;
		mov eax,0x768F79D8;
		call eax;
	}
}

void CriticalCodeEnd()
{
}

int main()
{
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	MsgBoxAddr = (DWORD)GetProcAddress(hU32Mod,"MessageBoxA");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	ExitProcAddr = (DWORD)GetProcAddress(hKrlMod,"ExitProcess");
	//反汇编 记录函数地址的内容
	CriticalCodeV2();
}
这段代码仅仅是一个过渡,用来生成后续的ShellCode。注释中已经写到同样的API在不同的机器上入口地址不同,因此需要重定位,如何重定位?反汇编后记录Call指令之后EIP跳转到一个jmp指令,jmp指令的目标地址就是你机器上API函数的入口,用你的地址替换我的地址。当然,最好的办法是通过PE文件导入表获取,不过这样就不是简单的保护方式了;另外,毕竟是自己的代码,在代码中获得本机API入口还是比较方便的,因此用LoadLibrary(/GetProcAddress)直接加载。啊真是简单粗暴而又有效的方法~

//V3 将V2中的OpCode写入数组,初步隐藏关键代码。创建读写可执行的页,然后跳转到该页执行
int main()
{
	DWORD writtenNum=0;
	DWORD CriticalCodeLen = 0x50;
	//shellcode 写到这 谁能一眼看出是什么鸟语
	char CriticalCodeSCSrc[] = {"\x55\x8B\xEC\x83\xEC\x10\xB0\x43" \
								"\x88\x45\xFC\xB0\x61\x88\x45\xFD" \
								"\xB0\x70\x88\x45\xFE\x33\xC0\x88" \
								"\x45\xFF\xB0\x4D\x88\x45\xF8\xB0" \
								"\x73\x88\x45\xF9\xB0\x67\x88\x45" \
								"\xFA\x33\xC0\x88\x45\xFB\x6A\x00" \
								"\x8D\x45\xFC\x50\x8D\x45\xF8\x50" \
								"\x6A\x00\xB8\x1E\xFD\x9A\x74\xFF" \
								"\xD0\x6A\x00\xB8\xD8\x79\x8F\x76" \
								"\xFF\xD0\xCC\xCC\xCC\xCC\xCC\xCC"};	
	
	char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrc,CriticalCodeLen,&writtenNum);
	assert(state);
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	__asm
	{
		//这句的效果等于 call SMCPtr
		push SMCPtr;
		jmp [esp];
	}
}
程序写到这,CriticalCodeV2已经被数组CriticalCodeSCSrcEnc中的内容取代,一眼看去不知CriticalCodeSCSrcEnc所云何物。不过只要跟着jmp [esp]一起跳转到SMCPtr的地址,就能看到程序正在做啥,更进一步,还可以把代码全记录下来,copy到静态汇编工具慢慢看。

//V4 对数组进行加密,直到关键代码段执行前才解密,进一步隐藏源码
void DeCode(char* SMCPtr,DWORD SMCLen)
{
	for(DWORD i=0;i<SMCLen;i++)
	{
		SMCPtr[i] ^= 0xcc;
	}
}

int main()
{
	DWORD writtenNum=0;
	DWORD CriticalCodeLen = 0x50;
	//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
	//运行前先与0xcc异或解密
	char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
								"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
								"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
								"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
								"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
								"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
								"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
								"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
								"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
								"\x33\x1C\x00\x00\x00\x00\x00\x00"};	
	
	
	char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
	assert(state);
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	DeCode(SMCPtr,CriticalCodeLen);

	__asm
	{
		push SMCPtr;
		jmp [esp];
	}

}
既然,上面可以把隐藏的代码记录下来慢慢分析,那我只能把CriticalCodeSCSrcEnc中的内容加密,在运行DeCode后才解密全部内容,让观察者不能尽兴~加密方式是CriticalCodeSCSrcEnc与0xCC异或。不过问题又来了,这解密函数是明文,观察者自己解密,又能慢慢看了,还真是藏头露尾的办法。下面对解密部分略作修改,办法如V2/V3

//V4中 解密部分源码是为加密的 这等于CriticalCodeSCSrcEnc没有保护
//因此 需要把解密部分的代码也隐藏起来 这段就不用抑或了 要不然又要有人去解密这段代码了
//在V5中将使用V4 DeCode部分实现的OpCode 

__declspec(naked) void DeCodeSMC(char* SMCPtr,DWORD SMCLen)
{
	__asm
	{
		//[ebp+0]:ebp [ebp+0x04]:retAddtr [ebp+0x08]:SMCPtr [ebp+0x0C]:SMCLen
		push ebp;
		mov ebp,esp;
		sub esp,0x10;
		//[ebp-4]:DWORD i;
		mov [ebp-4],0x00;
		mov [ebp-3],0x00;
		mov [ebp-2],0x00;
		mov [ebp-1],0x00;

		jmp Lab2;
Lab1:
		mov eax,[ebp-4];
		inc eax;
		mov [ebp-4],eax
	
Lab2:
		mov ecx,[ebp-4];
		cmp ecx,[ebp+0Ch];
		jae Lab3;

		mov edx,[ebp+8];
		add edx,[ebp-4];
		mov al,[edx];
		xor al,0xCC;
		mov ecx,[ebp+8];
		add ecx,[ebp-4];
		mov [ecx],al;
		jmp Lab1;
Lab3:
		mov esp,ebp;
		pop ebp;
		ret 8
		
	}
	
}

int main()
{
	DWORD writtenNum=0;
	DWORD CriticalCodeLen = 0x50;
	//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
	//运行前先与0xcc异或解密
	char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
								"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
								"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
								"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
								"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
								"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
								"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
								"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
								"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
								"\x33\x1C\x00\x00\x00\x00\x00\x00"};	
	
	
	char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
	assert(state);
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	DeCodeSMC(SMCPtr,CriticalCodeLen);

	__asm
	{
		push SMCPtr;
		jmp [esp];
	}

}
V5又是一个半成品,不说了,直接跳到V5-1

//v5-1
int main()
{
	DWORD writtenNum=0;
	DWORD CriticalCodeLen = 0x50;
	//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
	//运行前先与0xcc异或解密
	char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
								"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
								"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
								"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
								"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
								"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
								"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
								"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
								"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
								"\x33\x1C\x00\x00\x00\x00\x00\x00"};	
	
	DWORD DeCodeSMCLen = 0x80;
	char DeCodeSMC[] = {"\x55\x8B\xEC\x83\xEC\x10\xC6\x45" \
						"\xFC\x00\xC6\x45\xFD\x00\xC6\x45" \
						"\xFE\x00\xC6\x45\xFF\x00\xEB\x07" \
						"\x8B\x45\xFC\x40\x89\x45\xFC\x8B" \
						"\x4D\xFC\x3B\x4D\x0C\x73\x14\x8B" \
						"\x55\x08\x03\x55\xFC\x8A\x02\x34" \
						"\xCC\x8B\x4D\x08\x03\x4D\xFC\x88" \
						"\x01\xEB\xDD\x8B\xE5\x5D\xC2\x08" \
						"\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC"};

	char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
	assert(state);

	char* SMCDecPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	state = WriteProcessMemory(GetCurrentProcess(),SMCDecPtr,DeCodeSMC,DeCodeSMCLen,&writtenNum);
	assert(state);
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	//程序中已经没有DeCodeSMC这个函数 但是进程地址空间中还有类似功能的二进制码 需要显式模拟一次DeCodeSMC调用
	//DeCodeSMC(SMCPtr,CriticalCodeLen);
	__asm
	{
		//注意DeCodeSMC压栈顺序,右边的先入栈-先push
		push CriticalCodeLen
		push SMCPtr
		//模拟调用DeCodeSMC(SMCPtr,CriticalCodeLen);
		call SMCDecPtr
	}

	//SMC完成 跳去受保护的代码端执行
	__asm
	{
		push SMCPtr;
		jmp [esp];
	}

}
借助V5,将DeCodeSMC成功毁容,现在DeCodeSMC已经寄居在DeCodeSMC数组中,程序运行前跳转到DeCodeSMC数组中,解密CriticalCodeSCSrcEnc数组,解密完成才跳转到CriticalCodeSCSrcEnc执行。

写到这,隐藏的够深了吧?No,如果用调试器调试跟踪运行,一切还是白搭,因此下一步要检测调试器是否存在,如果存在,程序退出,麻烦你还是静态分析,因为静态分析已经够麻烦了。

//开始动态反调试前 看个检测调试器的函数
__declspec(naked) bool IsDebuggerPresent()
{
	//windows设定 fs:[30]这个内存为当前进程的进程控制块
	//进程控制块的第二个字节标志进程是否被调试
	__asm
	{
		mov eax,fs:[0x30];
		movzx eax,[eax+0x02];
		ret;
	}
}
原本以为win7带有IsDebuggerPresent这API,结果么得,只能自己实现了。

好的,加上检测调试器:

//V6-1 解密前 检测是否动态调试

//V6-1 解密前 检测是否动态调试

int main()
{
	DWORD writtenNum=0;
	DWORD CriticalCodeLen = 0x50;
	//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
	//运行前先与0xcc异或解密
	char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
								"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
								"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
								"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
								"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
								"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
								"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
								"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
								"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
								"\x33\x1C\x00\x00\x00\x00\x00\x00"};	
	
	DWORD DeCodeSMCLen = 0xC0;
	char DeCodeSMC[] = {
						"\x64\xA1\x30\x00\x00\x00\x0F\xB6" \
						"\x40\x02\x83\xF8\x00\x74\x09\x6A" \
						"\x00\xB8\xD8\x79\x8F\x76\xFF\xD0" \
						"\x90\x90\x90\x90\x90\x90\x90\x90" \
						"\x55\x8B\xEC\x83\xEC\x10\xC6\x45" \
						"\xFC\x00\xC6\x45\xFD\x00\xC6\x45" \
						"\xFE\x00\xC6\x45\xFF\x00\xEB\x07" \
						"\x8B\x45\xFC\x40\x89\x45\xFC\x8B" \
						"\x4D\xFC\x3B\x4D\x0C\x73\x14\x8B" \
						"\x55\x08\x03\x55\xFC\x8A\x02\x34" \
						"\xCC\x8B\x4D\x08\x03\x4D\xFC\x88" \
						"\x01\xEB\xDD\x8B\xE5\x5D\xC2\x08" \
						"\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC"};

	char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
	assert(state);

	char* SMCDecPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	state = WriteProcessMemory(GetCurrentProcess(),SMCDecPtr,DeCodeSMC,DeCodeSMCLen,&writtenNum);
	assert(state);
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	//程序中已经没有DeCodeSMC这个函数 但是进程地址空间中还有类似功能的二进制码 需要显式模拟一次DeCodeSMC调用
	//DeCodeSMC(SMCPtr,CriticalCodeLen);
	__asm
	{
		//注意DeCodeSMC压栈顺序,右边的先入栈-先push
		push CriticalCodeLen
		push SMCPtr
		//模拟DeCodeSMC(SMCPtr,CriticalCodeLen);
		call SMCDecPtr
	}

	//SMC完成 跳去受保护的代码端执行
	__asm
	{
		push SMCPtr;
		jmp [esp];
	}

}
这段Shellcode在DeCodeSMC入口检测调试器,如果存在程序退出。现在可以试试程序直接运行和调试运行的结果。

解密函数反动态调试是过了,观察者还能静态分析,为了对付静态分析,我再手贱加点花指令,干扰他们静态分析,深入的花指令看我另一篇博文

__declspec(naked) void DeCodeSMC(char* SMCPtr,DWORD SMCLen)
{
	__asm
	{
		//[ebp+0]:ebp [ebp+0x04]:retAddtr [ebp+0x08]:SMCPtr [ebp+0x0C]:SMCLen
		mov eax,fs:[0x30];
		movzx eax,[eax+0x02];
		cmp eax,0x00;
		jz StartDecode;
		push 0x00;
		mov eax,0x768F79D8;
		call eax;
StartDecode:
		nop;
		nop;
		nop;
		nop;
		push ebp;
		mov ebp,esp;
		sub esp,0x10;
		//[ebp-4]:DWORD i;
		mov [ebp-4],0x00;
		mov [ebp-3],0x00;
		mov [ebp-2],0x00;
		mov [ebp-1],0x00;

		jmp Lab2;
Lab1:
		//插入花指令
		mov eax,0;
		cmp eax,1;
		jnz ThunkCode1;
		jz ThunkCode1;
		_emit 0xE9
ThunkCode1:
		//花指令结束
		mov eax,[ebp-4];
		inc eax;
		mov [ebp-4],eax
	
Lab2:
		mov ecx,[ebp-4];
		cmp ecx,[ebp+0Ch];
		jae Lab3;
		//插入花指令
		mov eax,1;
		cmp eax,0;
		jnz ThunkCode2;
		jz ThunkCode2;
		_emit 0xE9
ThunkCode2:
		//花指令结束
		mov edx,[ebp+8];
		add edx,[ebp-4];
		mov al,[edx];
		xor al,0xCC;
		mov ecx,[ebp+8];
		add ecx,[ebp-4];
		mov [ecx],al;
		jmp Lab1;
Lab3:
		mov esp,ebp;
		pop ebp;
		ret 8
		
	}
	
}

int main()
{
	DWORD writtenNum=0;
	DWORD CriticalCodeLen = 0x50;
	//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
	//运行前先与0xcc异或解密
	char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
								"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
								"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
								"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
								"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
								"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
								"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
								"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
								"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
								"\x33\x1C\x00\x00\x00\x00\x00\x00"};	
	
	
	char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
	assert(state);
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	DeCodeSMC(SMCPtr,CriticalCodeLen);

	__asm
	{
		push SMCPtr;
		jmp [esp];
	}

}
这个也是过渡版,来看下大结局

int main()
{
	DWORD writtenNum=0;
	DWORD CriticalCodeLen = 0x50;
	//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
	//运行前先与0xcc异或解密
	char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
								"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
								"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
								"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
								"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
								"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
								"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
								"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
								"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
								"\x33\x1C\x00\x00\x00\x00\x00\x00"};	
	
	DWORD DeCodeSMCLen = 0x110;
	char DeCodeSMC[] = {
						"\x64\xA1\x30\x00\x00\x00\x0F\xB6" \
						"\x40\x02\x83\xF8\x00\x74\x09\x6A" \
						"\x00\xB8\xD8\x79\x8F\x76\xFF\xD0" \
						"\x90\x90\x90\x90\x55\x8B\xEC\x83" \
						"\xEC\x10\xC6\x45\xFC\x00\xC6\x45" \
						"\xFD\x00\xC6\x45\xFE\x00\xC6\x45" \
						"\xFF\x00\xEB\x14\xB8\x00\x00\x00" \
						"\x00\x83\xF8\x01\x75\x03\x74\x01" \
						"\xE9\x8B\x45\xFC\x40\x89\x45\xFC" \
						"\x8B\x4D\xFC\x3B\x4D\x0C\x73\x21" \
						"\xB8\x01\x00\x00\x00\x83\xF8\x00" \
						"\x75\x03\x74\x01\xE9\x8B\x55\x08" \
						"\x03\x55\xFC\x8A\x02\x34\xCC\x8B" \
						"\x4D\x08\x03\x4D\xFC\x88\x01\xEB" \
						"\xC3\x8B\xE5\x5D\xC2\x08\x00\xCC" \
						"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"};

	char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
	assert(state);

	char* SMCDecPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	state = WriteProcessMemory(GetCurrentProcess(),SMCDecPtr,DeCodeSMC,DeCodeSMCLen,&writtenNum);
	assert(state);
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	//程序中已经没有DeCodeSMC这个函数 但是进程地址空间中还有类似功能的二进制码 需要显式模拟一次DeCodeSMC调用
	//DeCodeSMC(SMCPtr,CriticalCodeLen);
	__asm
	{
		//注意DeCodeSMC压栈顺序,右边的先入栈-先push
		push CriticalCodeLen
		push SMCPtr
		//模拟DeCodeSMC(SMCPtr,CriticalCodeLen);
		call SMCDecPtr
	}

	//SMC完成 跳去受保护的代码端执行
	__asm
	{
		push SMCPtr;
		jmp [esp];
	}

}
经手术函数CriticalCodeV1已成功整容,不用几天我也记不得他原本长什么样~

int main()
{
	DWORD writtenNum=0;
	DWORD CriticalCodeLen = 0x50;
	//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
	//运行前先与0xcc异或解密
	char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
								"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
								"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
								"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
								"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
								"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
								"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
								"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
								"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
								"\x33\x1C\x00\x00\x00\x00\x00\x00"};	
	
	DWORD DeCodeSMCLen = 0x110;
	char DeCodeSMC[] = {
						"\x64\xA1\x30\x00\x00\x00\x0F\xB6" \
						"\x40\x02\x83\xF8\x00\x74\x09\x6A" \
						"\x00\xB8\xD8\x79\x8F\x76\xFF\xD0" \
						"\x90\x90\x90\x90\x55\x8B\xEC\x83" \
						"\xEC\x10\xC6\x45\xFC\x00\xC6\x45" \
						"\xFD\x00\xC6\x45\xFE\x00\xC6\x45" \
						"\xFF\x00\xEB\x14\xB8\x00\x00\x00" \
						"\x00\x83\xF8\x01\x75\x03\x74\x01" \
						"\xE9\x8B\x45\xFC\x40\x89\x45\xFC" \
						"\x8B\x4D\xFC\x3B\x4D\x0C\x73\x21" \
						"\xB8\x01\x00\x00\x00\x83\xF8\x00" \
						"\x75\x03\x74\x01\xE9\x8B\x55\x08" \
						"\x03\x55\xFC\x8A\x02\x34\xCC\x8B" \
						"\x4D\x08\x03\x4D\xFC\x88\x01\xEB" \
						"\xC3\x8B\xE5\x5D\xC2\x08\x00\xCC" \
						"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"};

	char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
	assert(state);

	char* SMCDecPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	assert(SMCPtr);
	state = WriteProcessMemory(GetCurrentProcess(),SMCDecPtr,DeCodeSMC,DeCodeSMCLen,&writtenNum);
	assert(state);
	HMODULE hU32Mod = LoadLibrary("user32.dll");
	HMODULE hKrlMod = LoadLibrary("kernel32.dll");
	//程序中已经没有DeCodeSMC这个函数 但是进程地址空间中还有类似功能的二进制码 需要显式模拟一次DeCodeSMC调用
	//DeCodeSMC(SMCPtr,CriticalCodeLen);
	__asm
	{
		//注意DeCodeSMC压栈顺序,右边的先入栈-先push
		push CriticalCodeLen
		push SMCPtr
		//模拟DeCodeSMC(SMCPtr,CriticalCodeLen);
		call SMCDecPtr
	}

	//SMC完成 跳去受保护的代码端执行
	__asm
	{
		push SMCPtr;
		jmp [esp];
	}

}





   

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值