放心分发EXE有效保护自己的DotNet源码

前言:
文章的技巧在DotNet1.0发布那年就已经使用,今天心血来潮,只想更新下2年未更新的BLOG,了以充数罢了.


正文:
Dotnet编译的DLL,EXE等文件,通过混淆可以一定程度保护自己的代码安全,我在此介绍自己一直使用的方式--垫片启动.
运行EXE时,先运行C++代码,再装载DotNet应用程序运行环境,然后运行DotNet程序.
本篇不涉及安全保护,代码混淆,加密等操作,只是一个运行机制模式的介绍,如何保护自己的代码安全,由你自己决定.


C++启动DotNet环境.
VC++本地代码,支持DotNet语言的几个本地函数.


ICorRuntimeHost : 运行主机CLR接口
CorBindToRuntimeEx : 运行环境绑定
_AppDomainPtr : 托管AppDomain指针
_AssemblyPtr  : 托管Assembly指针
请注意,mscoree.h头文件的引用



有效使用这些对象提供的方法,可以反射加载应用程序.

#include "stdafx.h"
#include <excpt.h>
#include <windows.h>
#include <mscoree.h>  
#include <assert.h>
#include <stdio.h>
#include <tchar.h> 
#include <atlsafe.h>
#include <iostream>
#include <string.h>

#define RC_LENGTH                   8

void ExecuteAssembly();
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{

	ExecuteAssembly();
	PostQuitMessage(0);
	return 0;
}


void ExecuteAssembly()
{
	//垫片方式启动托管入口
	LPWSTR pszVer = L"v2.0.50727";		// .NET Fx 3.5 needs CLR 2.0
    	LPWSTR pszFlavor = L"svr";		//svr:多核优化处理GC, wks:总是执行单核GC处理;
	ICorRuntimeHost *pClrHost = NULL; 
    	HRESULT hr = ::CorBindToRuntimeEx( 
					pszVer,       
					pszFlavor,    
					STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC, 
					CLSID_CorRuntimeHost, 
					IID_ICorRuntimeHost, 
					(void **)&pClrHost); 
	pClrHost->Start(); // 启动CLR 

	_AppDomainPtr pDefaultDomain = NULL;
    	IUnknownPtr   pAppDomainPunk = NULL; 

    	hr = pClrHost->GetDefaultDomain(&pAppDomainPunk);
	hr = pAppDomainPunk->QueryInterface(__uuidof(_AppDomain),(void**) &pDefaultDomain);

	//资源读取,并装载主程序依赖的引用库(第三方不能商业发布的组件,你可以考虑放在其中)
	CReaderRc *rcDll = new CReaderRc(IDR_SPCLRASM1, _T("spclrasm"), pDefaultDomain);
	/*
	可以将你的代码作为C++的资源,一起编译成EXE
	*/


	//托管的主程序集
	_AssemblyPtr ExeAssembly;
	hr = pDefaultDomain->Load_3(*(rcDll->getByteArray()).GetSafeArrayPtr(), &ExeAssembly);
	delete rcDll;
	/*
	rcDll->getByteArray() 是应用程序程序集文件的字节数组,由CReaderRc负责读取.
	你完全可以在这个里面,采用自己的加/解密算法,操作文件.
	*/


	//找到入口方法,并调用执行
	_MethodInfo* EntryPointInfo;
	hr = ExeAssembly->get_EntryPoint(&EntryPointInfo);

	_variant_t  thisPointer, ReturnValue;
	CComSafeArray<BSTR> Parameters;	//main方法的参数


	hr = EntryPointInfo->Invoke_3(thisPointer, *Parameters.GetSafeArrayPtr() , &ReturnValue);
}

写一段C#代码,编译成EXE.将此EXE放到上面的C++的资源中并编译C++或启动调试.

[STAThread]
		static void Main()
		{
			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);
			Application.Run(new Form1());
		}

主题说明:
整个运行流程,就是将托管反射的应用改成由C++代码通过本地函数调用来实现.
其中放进资源文件的EXE或DLL,你可以使用混淆代码并加密它,然后C++读取资源时解密,并装载到程序域中.找到托管代码的入口函数就完成了.
对于C++的资源,有些工具很容易提取,如果不加密,那提取以后还是很容易看到原码的.



注意点说明:
本文并非最安全的保护,由它一个薄弱可攻击的安全漏洞,这是由于JIT决定的.可以采用C++编写JIT拦截代码,看到你运行的托管函数等信息.
所以只能从一定程度上起到保护作用.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值