最近在研究编写.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 。欢迎高手给点建议或者意见