最近在研究编写.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 。欢迎高手给点建议或者意见
解决方案 »
- 将windows应用程序打包成一个exe文件
- 高手给小弟指点一下,谢谢先
- List<T>的Sort方法疑问
- 再次询问泛型~~~
- 一个恶心的东西,VS的卸载…………
- .NET中如何使用Autodesk公司的DWF Viewer控件打开dwg文件
- visual sdudio.net创建关于Web应用程序项目的时候就报http://1.1 500 internal server error错误
- 水晶报表使用了插入---汇总功能,如果没有数据就会什么也不显示,怎么处理
- 【算法问题】按两两之间误差来筛选一组数据
- C# 高速数据的实时 接收\解析\存储 问题
- 请教个sql问题
- DefWndProc怎么捕捉窗体内控件的鼠标消息?
mscoree.dll会检查PE的入口部分,所以对于.Net PE这样坐会导致程序无法启动