脱壳时从授权文件中提取解密密钥。
DLL的解密只能在内存中进行,不能生成临时文件,避免Cracker截获解密后的DLL。这就要用到文件流与加密流的技术,脱壳的部分代码如下:
publicstaticAssemblyasmload(stringasmName)
{Assemblyasmsvr=null;
FileStreamfsr=null;
byte[]byVec=newbyte[16],byKey=newbyte[32];
//asmName待加载的程序集名,由参数带入
stringtoLoad=AppDomain.CurrentDomain.BaseDirectory+asmName+"e.dll";
if(!File.Exists(toLoad))returnnull;
fsr=newFileStream(toLoad,FileMode.Open,FileAccess.Read);
byte[]rawAssembly=newbyte[fsr.Length];
//提取机器指纹并生成DES加密密钥与初向量
createDesKeyVec(refbyVec,refbyKey);
SymmetricAlgorithmdes=SymmetricAlgorithm.Create();
CryptoStreamencStream=newCryptoStream(fsr,des.CreateDecryptor(byKey,byVec),CryptoStreamMode.Read);
//读取并解密到到缓冲区
encStream.Read(rawAssembly,0,(int)fsr.Length);
encStream.Close();
fsr.Close();
asmsvr=AppDomain.CurrentDomain.Load(rawAssembly);
}
6.2DLL调用请求的捕获
根据需要来脱壳也就是当程序集被调用时,临时脱壳并加载,程序集一旦加载,以后需要调用其中的功能时就可以直接从内存中运行,这就既避免了内存的浪费又不会影响程序运行速度。关键是程序集的调用不一定从壳中调用,可以从任何一个已经运行的程序集中调用,怎么才能截获程序集的调用请求呢?
首先要了解应用程序域,它由AppDomain对象来表示,为执行托管代码提供隔离、卸载和安全边界。多个应用程序域可以在一个进程中运行;但是,在应用程序域和线程之间没有一对一的关联。多个线程可以属于一个应用程序域,尽管给定的线程并不局限于一个应用程序域,但在任何给定时间,线程都在一个应用程序域中执行。每当程序运行时,便会自动创建应用程序域。AppDomain实例用于加载和执行程序集(Assembly),AppDomain类实现一组事件,这些事件使应用程序可以在加载程序集、卸载应用程序域或引发未处理的异常时进行响应。本方案中就是通过事件AssemblyResolve来捕获程序集调用请求的。
实现方法是:首先,在壳的main()函数中注册事件AssemblyResolve的响应代码,形如:
AppDomain.CurrentDomain.AssemblyResolve+=new
ResolveEventHandler(CurrentDomain_AssemblyResolve);
然后,再编