最近在研究编写.Net的壳(以.Net3.5 SP1环境做开发测试),思路如下:1.读取要加壳的.Net PE文件,对IL指令进行加密并移动位置(我放到了一个新PE节)
2.一个非托管的DLL,在这个DLL中HOOK JIT编译部分,当对IL指令做即时编译的时候读取并解密整个过程都是没问题的,现在遇到的问题是如何将非托管的DLL加入到目标的进程空间。最好是直接在PE文件上做改动,这样,只需要复制加壳后的文件,就可以直接在其它机器上运行。
而且JIT HOOK必须在Assembly执行前加载,如果被加密的方法被直接执行而缺少JIT HOOK DLL只会直接报错。1. 首先想到的办法是修改.Net PE的 Import Table,将自己的DLL导入。
试过之后发现这种方式不行,NT的PE Loader在检测到PE文件时.Net PE时,会在加载前先调用mscoree.dll中的_CorValidateImage检验文件,文件检验格式非法就返回0xC000002B。
而 CorValidateImage 把.Net PE文件的格式限制得非常死,很多东西不允许改。看下面。text:79005197 push ebp
.text:79005198 mov ebp, esp
.text:7900519A push ecx
.text:7900519B push ecx
.text:7900519C push esi
.text:7900519D mov esi, ecx
.text:7900519F test byte ptr [esi+8], 40h
.text:790051A3 jnz loc_790223BC
.text:790051A3
.text:790051A9 push edi
.text:790051AA lea eax, [ebp+var_4]
.text:790051AD push eax
.text:790051AE call PEDecoder::CheckCorHeader(void)
.text:790051AE
.text:790051B3 xor edi, edi
.text:790051B5 cmp [eax], edi
.text:790051B7 jnz loc_790223C7
.text:790051B7
.text:790051BD push ebx
.text:790051BE mov ecx, esi
.text:790051C0 call PEDecoder::GetNumberOfRvaAndSizes(void)
.text:790051C0
.text:790051C5 xor ebx, ebx
.text:790051C7 inc ebx
.text:790051C8 test eax, eax
.text:790051CA mov [ebp+var_4], eax
.text:790051CD jbe short loc_790051E1
.text:790051CD
.text:790051CF
.text:790051CF loc_790051CF: ; CODE XREF: PEDecoder::CheckILOnly(void)+48j
.text:790051CF push edi
.text:790051D0 mov ecx, esi
.text:790051D2 call PEDecoder::HasDirectoryEntry(int)
.text:790051D2
.text:790051D7 test eax, eax
.text:790051D9 jnz short loc_79005160
.text:790051D9
.text:790051DB
.text:790051DB loc_790051DB: ; CODE XREF: PEDecoder::CheckILOnly(void)-26j
.text:790051DB ; PEDecoder::CheckILOnly(void)-Ej
.text:790051DB inc edi
.text:790051DC cmp edi, [ebp+var_4]
.text:790051DF jb short loc_790051CF
.text:790051DF
.text:790051E1
.text:790051E1 loc_790051E1: ; CODE XREF: PEDecoder::CheckILOnly(void)+36j
.text:790051E1 push ebx
.text:790051E2 mov ecx, esi
.text:790051E4 call PEDecoder::HasDirectoryEntry(int)
.text:790051E4
.text:790051E9 test eax, eax
.text:790051EB jz loc_790223D5
.text:790051EB
.text:790051F1
.text:790051F1 loc_790051F1: ; CODE XREF: PEDecoder::CheckILOnly(void)+1D249j
.text:790051F1 ; PEDecoder::CheckILOnly(void)+1D259j
.text:790051F1 lea eax, [ebp+var_8]
.text:790051F4 push eax
.text:790051F5 mov ecx, esi
.text:790051F7 call PEDecoder::CheckILOnlyImportDlls(void)
.text:790051F7
.text:790051FC xor edi, edi
.text:790051FE cmp [eax], edi
.text:79005200 jnz short loc_7900518B
.text:79005200
.text:79005202 lea eax, [ebp+var_8]
.text:79005205 push eax
.text:79005206 mov ecx, esi
.text:79005208 call PEDecoder::CheckILOnlyBaseRelocations(void)
.text:79005208
.text:7900520D cmp [eax], edi
.text:7900520F jnz loc_7900518B
.text:7900520F
.text:79005215 lea eax, [ebp+var_8]
.text:79005218 push eax
.text:79005219 mov ecx, esi
.text:7900521B call PEDecoder::CheckILOnlyEntryPoint(void)
.text:7900521B
.text:79005220 cmp [eax], edi
.text:79005222 jnz loc_7900518B
mscoree.dll把修改导入表这条路封死了。(我是不是可以试试其它方式?比如IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT??)2.第2个想到的办法是修改.Net入口 EntryPointToken
首先修改.Net PE的MetaTable,加入一个自己的函数,然后修改导入点, 在程序启动的时候调用LoadLibrary一次。不过这样也存在一个问题,如果是ASP.Net Web Site,编译出来是DLL, EntryPointToken 为0, 我试过改成某函数也根本无效。看来mscoree.dll的_CorDllMain完全忽略EntryPointToken 。欢迎高手给点建议或者意见
2.一个非托管的DLL,在这个DLL中HOOK JIT编译部分,当对IL指令做即时编译的时候读取并解密整个过程都是没问题的,现在遇到的问题是如何将非托管的DLL加入到目标的进程空间。最好是直接在PE文件上做改动,这样,只需要复制加壳后的文件,就可以直接在其它机器上运行。
而且JIT HOOK必须在Assembly执行前加载,如果被加密的方法被直接执行而缺少JIT HOOK DLL只会直接报错。1. 首先想到的办法是修改.Net PE的 Import Table,将自己的DLL导入。
试过之后发现这种方式不行,NT的PE Loader在检测到PE文件时.Net PE时,会在加载前先调用mscoree.dll中的_CorValidateImage检验文件,文件检验格式非法就返回0xC000002B。
而 CorValidateImage 把.Net PE文件的格式限制得非常死,很多东西不允许改。看下面。text:79005197 push ebp
.text:79005198 mov ebp, esp
.text:7900519A push ecx
.text:7900519B push ecx
.text:7900519C push esi
.text:7900519D mov esi, ecx
.text:7900519F test byte ptr [esi+8], 40h
.text:790051A3 jnz loc_790223BC
.text:790051A3
.text:790051A9 push edi
.text:790051AA lea eax, [ebp+var_4]
.text:790051AD push eax
.text:790051AE call PEDecoder::CheckCorHeader(void)
.text:790051AE
.text:790051B3 xor edi, edi
.text:790051B5 cmp [eax], edi
.text:790051B7 jnz loc_790223C7
.text:790051B7
.text:790051BD push ebx
.text:790051BE mov ecx, esi
.text:790051C0 call PEDecoder::GetNumberOfRvaAndSizes(void)
.text:790051C0
.text:790051C5 xor ebx, ebx
.text:790051C7 inc ebx
.text:790051C8 test eax, eax
.text:790051CA mov [ebp+var_4], eax
.text:790051CD jbe short loc_790051E1
.text:790051CD
.text:790051CF
.text:790051CF loc_790051CF: ; CODE XREF: PEDecoder::CheckILOnly(void)+48j
.text:790051CF push edi
.text:790051D0 mov ecx, esi
.text:790051D2 call PEDecoder::HasDirectoryEntry(int)
.text:790051D2
.text:790051D7 test eax, eax
.text:790051D9 jnz short loc_79005160
.text:790051D9
.text:790051DB
.text:790051DB loc_790051DB: ; CODE XREF: PEDecoder::CheckILOnly(void)-26j
.text:790051DB ; PEDecoder::CheckILOnly(void)-Ej
.text:790051DB inc edi
.text:790051DC cmp edi, [ebp+var_4]
.text:790051DF jb short loc_790051CF
.text:790051DF
.text:790051E1
.text:790051E1 loc_790051E1: ; CODE XREF: PEDecoder::CheckILOnly(void)+36j
.text:790051E1 push ebx
.text:790051E2 mov ecx, esi
.text:790051E4 call PEDecoder::HasDirectoryEntry(int)
.text:790051E4
.text:790051E9 test eax, eax
.text:790051EB jz loc_790223D5
.text:790051EB
.text:790051F1
.text:790051F1 loc_790051F1: ; CODE XREF: PEDecoder::CheckILOnly(void)+1D249j
.text:790051F1 ; PEDecoder::CheckILOnly(void)+1D259j
.text:790051F1 lea eax, [ebp+var_8]
.text:790051F4 push eax
.text:790051F5 mov ecx, esi
.text:790051F7 call PEDecoder::CheckILOnlyImportDlls(void)
.text:790051F7
.text:790051FC xor edi, edi
.text:790051FE cmp [eax], edi
.text:79005200 jnz short loc_7900518B
.text:79005200
.text:79005202 lea eax, [ebp+var_8]
.text:79005205 push eax
.text:79005206 mov ecx, esi
.text:79005208 call PEDecoder::CheckILOnlyBaseRelocations(void)
.text:79005208
.text:7900520D cmp [eax], edi
.text:7900520F jnz loc_7900518B
.text:7900520F
.text:79005215 lea eax, [ebp+var_8]
.text:79005218 push eax
.text:79005219 mov ecx, esi
.text:7900521B call PEDecoder::CheckILOnlyEntryPoint(void)
.text:7900521B
.text:79005220 cmp [eax], edi
.text:79005222 jnz loc_7900518B
mscoree.dll把修改导入表这条路封死了。(我是不是可以试试其它方式?比如IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT??)2.第2个想到的办法是修改.Net入口 EntryPointToken
首先修改.Net PE的MetaTable,加入一个自己的函数,然后修改导入点, 在程序启动的时候调用LoadLibrary一次。不过这样也存在一个问题,如果是ASP.Net Web Site,编译出来是DLL, EntryPointToken 为0, 我试过改成某函数也根本无效。看来mscoree.dll的_CorDllMain完全忽略EntryPointToken 。欢迎高手给点建议或者意见
解决方案 »
- VC++如何提高画图效率???
- CListCtr如何通过CListCtr::SetItem改变关联的图像索引
- 关于查看ACTIVEX接口函数
- listbox 设置固定行数和删除所有行!! 在线!!
- 菜鸟提问: 关于显示bmp
- 哪位大侠有iphlpapi.h文件源代码,程序没有这个运行不起来,手头没有sdk,清大侠们帮忙,多谢!!!
- 如何使closesocket断开后不出现time_out连接??(请高手回答,谢谢)
- ADO中怎么得到记录个数
- 请教高手!如何分别设置List的右键单击事件和右键单击item事件
- 谁能解释一下磁盘的sector,track,head,不够再加一100分
- 如何使用程序设置VISTA/WIN7的开机引导项?
- 子进程怎么得到父进程句柄?
某牛的DEMO
现在遇到的问题是如何将非托管的DLL加入到目标的进程空间 其它都已经解决了
老外的实现是一个程序加密后,分成三部分
loader.exe 用于启动的loader
native.dll 用于hook compilemethod等关键函数实现运行是解密,这个dll基本是shellcode形式实现
cryxed.dll 加密后的程序,il代码被加过密下面是我还原老外的loader代码,可以看到,以函数的形式执行native代码和启动assemble的方法
,native.dll还没有弄完,期待你的加密壳,可以与我讨论 mail:[email protected]
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
namespace Project1
{
class Program
{
private delegate int obfuscation8();
public static void Main()
{
long num6;
FileStream stream = new FileInfo("native.dll").OpenRead();
long length = stream.Length;
byte[] array = new byte[((int) length) + 1];
stream.Read(array, 0, (int) length);
stream.Close();
long num7 = length;
for (num6 = 0L; num6 <= num7; num6 += 1L)
{
array[(int) num6] = (byte) (array[(int) num6] ^ 0x37);
}
IntPtr destination = new IntPtr();
destination = Marshal.AllocCoTaskMem((int) length);
Marshal.Copy(array, 0, destination, (int) length);
obfuscation8 delegateForFunctionPointer = (obfuscation8) Marshal.GetDelegateForFunctionPointer(destination, typeof(obfuscation8));
File.WriteAllBytes("decrypted_fun.exe", array);
long num = new long();
//System.Reflection.Emit.Break;
num = delegateForFunctionPointer();
System.Console.WriteLine(" num = " + num);
stream = new FileInfo("cryxed.dll").OpenRead();
length = stream.Length;
byte[] buffer2 = new byte[((int) length) + 1];
stream.Read(buffer2, 0, (int) length);
stream.Close();
long num8 = length;
for (num6 = 0L; num6 <= num8; num6 += 1L)
{
buffer2[(int) num6] = (byte) (buffer2[(int) num6] ^ 0x37);
}
File.WriteAllBytes("decrypted_assembly.exe", buffer2);
Assembly assembly = Assembly.Load(buffer2);
object[] parameters = new object[1];
string[] strArray = new string[] { "" };
parameters[0] = strArray;
assembly.EntryPoint.Invoke(null, parameters);
}
}
}