Esempio n. 1
0
 public override void Compile(Instruction i, AsmBuilder ab, List <string> Offsets, MethodDefinition md)
 {
     if (!char.IsDigit(i.OpCode.Name.Split('.').Last()[0]))
     {
         //pop eax
         //mov dword[esp + 4], eax
         ab.Pop("eax");
         ab.Mov("dword[ebp - " + (4 * (Convert.ToInt32(i.Operand.ToString().Split('_').Last()) + 1)) + "]", "eax");
     }
     else
     {
         //pop eax
         //mov dword[esp + 4], eax
         ab.Pop("eax");
         ab.Mov("dword[ebp - " + (4 * (Convert.ToInt32(i.OpCode.Name.Split('.').Last()) + 1)) + "]", "eax");
     }
 }
Esempio n. 2
0
        public override void Compile(Instruction i, AsmBuilder ab, List <string> Offsets, MethodDefinition md)
        {
            if (Compiler.PlugIndex.ContainsKey(Utils.SafeName(i.Operand.ToString())))
            {
                ab.Comment("Pluged");
                ab.Call(Compiler.PlugIndex[Utils.SafeName(i.Operand.ToString())]);
            }
            else
            {
                ab.Call(Utils.SafeName(i.Operand.ToString()));
            }

            if ((i.Operand as MethodReference).ReturnType.ToString() != typeof(void).ToString())
            {
                ab.Push("eax");
            }
        }
Esempio n. 3
0
    public CodeEmitor(string name, Dictionary <string, FuncMeta> funcs)
    {
        Name                = name;
        m_fileName          = name + "_Script.exe";
        FuncName2MethodInfo = new Dictionary <string, MethodInfo>();

        AsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name), AssemblyBuilderAccess.RunAndSave);
        var moduleBuilder = AsmBuilder.DefineDynamicModule(name + "_MainModule", m_fileName);

        TypeBuilder = moduleBuilder.DefineType(name + "_MainClass");

        GlobalField = TypeBuilder.DefineField("s_global", typeof(Dictionary <string, object>), FieldAttributes.Static | FieldAttributes.Private);
        buildStaticConstructor();
        BuildinCodeEmitor.emitBuildins(this);

        var stmts = from kv in funcs select new StmtNodeVisitor_CodeEmitor(this, kv.Value);

        foreach (var stmt in stmts)
        {
            stmt.emit();
        }

        m_mainClass = TypeBuilder.CreateType();
    }
Esempio n. 4
0
 public override void Compile(Instruction i, AsmBuilder ab, List <string> Offsets, MethodDefinition md)
 {
     ab.Pop("ebx"); //addres
     ab.Mov("al", "byte[ebx]");
     ab.Push("eax");
 }
Esempio n. 5
0
 public override void Compile(Instruction i, AsmBuilder ab, List <string> Offsets, MethodDefinition md)
 {
     ab.Mov("eax", "dword [" + Utils.SafeName(i.Operand.ToString()) + "]");
     ab.Push("eax");
 }
Esempio n. 6
0
 public override void Compile(Instruction i, AsmBuilder ab, List <string> Offsets, MethodDefinition md)
 {
     ab.Pop("eax"); //flag
     ab.Cmp("eax", "1");
     ab.Jmpe(Utils.SafeName(md.FullName) + i.Operand.ToString().Split(':')[0]);
 }
Esempio n. 7
0
 public void save()
 {
     AsmBuilder.SetEntryPoint(m_mainClass.GetMethod("Main"), PEFileKinds.ConsoleApplication);
     AsmBuilder.Save(m_fileName);
 }
Esempio n. 8
0
 public override void Compile(Instruction i, AsmBuilder ab, List <string> Offsets, MethodDefinition md)
 {
 }
Esempio n. 9
0
        //injection: loads the CLR on the specified thread of the specified process
        //it thereafter basically does the following:
        //      appdomain=CLR->CreateDomain(setupparameters={..., AppBase-path, ...})
        //      asm=appdomain->load(specified assembly)
        //      asm->CreateInstance(specified type)
        //... i could have used the default appdomain, but when i was testing remoting from the injected code
        // i noticed that the defautl appdomain gets a basepath equal to that of the injected process, which
        // causes Remoting to fail as client/server are referring different assembly paths, and the injected remoting
        // code can't find the assembly when trying to read type info to setup remoting proxies.
        // Changing the basepath is impossible, so we just create a new appdomain with the right basepath and
        // run code there.
        public static void Inject(ProcessHandler onprocess, ThreadHandler onthread, Assembly toinject, Type tocreate)
        {
            StreamHandler sh = new StreamHandler(onprocess);

            IntPtr RemotePage = onprocess.Allocate(4096);//allocate one page of readable, writable and executable memory

            //inject data
            sh.Position = (long)RemotePage;

            //write GUIDs

            //- write CLSID_CorRuntimeHost
            IntPtr pCLSIDCorRuntimeHost = (IntPtr)sh.Position;

            sh.Write(CLSID_CorRuntimeHost.ToByteArray(), 0, 16);

            //- write IID_ICorRuntimeHost
            IntPtr pIID_ICorRuntimeHost = (IntPtr)sh.Position;

            sh.Write(IID_ICorRuntimeHost.ToByteArray(), 0, 16);

            //- write IID_IAppSetup (not the actualy name i think)
            IntPtr pIID_IAppSetup = (IntPtr)sh.Position;

            sh.Write(IID_IAppSetup.ToByteArray(), 0, 16);

            //- write IID_IAppDomain (not the actualy name i think)
            IntPtr pIID_IAppDomain = (IntPtr)sh.Position;

            sh.Write(IID_IAppDomain.ToByteArray(), 0, 16);

            //- write VARIANT (result var for AppDomain.CreateInstance)
            UINTARG VariantArg = new UINTARG(0);
            IntPtr  pVariant   = (IntPtr)sh.Position;

            sh.Write <UINTARG>(VariantArg);

            //reserve space for variables (<- this could be done better by using the stack?)

            //- reserve uint stackbackup
            IntPtr pStackBackup = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- reserve RuntimeObject pointer
            IntPtr pRuntimeObject = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- reserve Module Handle pointer
            IntPtr pHandle = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- reserve Setup Object pointer (IUnknown version)
            IntPtr pSetupObject = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- reserve AppSetup Object pointer (after QueryInterface, so IAppSetup version)
            IntPtr pAppSetupObject = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- reserve AppDomain object pointer (IUnknown version)
            IntPtr pDomainObject = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- reserve AppDomain object pointer (IAppDomain version, after QueryInterface)
            IntPtr pAppDomainObject = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- reserve Assembly object pointer
            IntPtr pAsm = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- reserve uint function pointers
            IntPtr pCorBindToRuntimeEx = (IntPtr)sh.Position;

            sh.Write <uint>(0);

            //- write strings (for loadlibrary calls)
            sh.EnsureAlignment(2);
            IntPtr pStrCorBindToRuntimeEx = (IntPtr)sh.Position;

            sh.WriteString("CorBindToRuntimeEx");

            sh.EnsureAlignment(2);
            IntPtr pStrMSCorEE = (IntPtr)sh.Position;

            sh.WriteString("MSCorEE.dll");

            sh.EnsureAlignment(2);
            IntPtr pStrwks = (IntPtr)sh.Position;

            sh.WriteUnicodeString("wks");//workstation mode

            sh.EnsureAlignment(2);
            IntPtr pStrDomainName = (IntPtr)sh.Position;

            sh.WriteUnicodeString("injected_domain_" + onprocess.PID.ToString("X"));

            sh.EnsureAlignment(2);
            IntPtr pStrAppBase = (IntPtr)(sh.Position + 4);//+4 to skip pre-pendend length

            sh.WriteBSTR(System.IO.Path.GetDirectoryName(toinject.Location));

            sh.EnsureAlignment(2);
            IntPtr pAssemblyName = (IntPtr)(sh.Position + 4);//+4 to skip pre-pendend length

            sh.WriteBSTR(toinject.GetName().Name);

            sh.EnsureAlignment(2);
            IntPtr pTypeName = (IntPtr)(sh.Position + 4);//+4 to skip pre-pendend length

            sh.WriteBSTR(tocreate.FullName);

            //get required function addresses
            //- LoadLibraryA, GetProcAddress from KERNEL32.dll
            uint pLoadLibraryA   = onprocess.MainModule.PEHeader.ImportedLibraries["KERNEL32.dll"].ImportedSymbols["LoadLibraryA"].Address;
            uint pGetProcAddress = onprocess.MainModule.PEHeader.ImportedLibraries["KERNEL32.dll"].ImportedSymbols["GetProcAddress"].Address;

            //build code
            AsmBuilder _asm = new AsmBuilder();

            //safety measures : push all registers, save the stack pointer
            _asm.Instructions.Add(new PushAll());
            _asm.Instructions.Add(new BackupEsp((uint)pStackBackup));

            //build loadlibrary, getprocaddress calls to get the pCorBindToRuntimeEx from MSCorEE.dll
            _asm.Instructions.Add(new PushImmediate((uint)pStrMSCorEE));
            _asm.Instructions.Add(new CallRelative((int)pLoadLibraryA));
            _asm.Instructions.Add(new MovMemoryEax((uint)pHandle));
            _asm.Instructions.Add(new PushImmediate((uint)pStrCorBindToRuntimeEx));
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new CallRelative((int)pGetProcAddress));
            _asm.Instructions.Add(new MovMemoryEax((uint)pCorBindToRuntimeEx));

            //build CorBindToRuntimeEx call
            _asm.Instructions.Add(new PushImmediate((uint)pRuntimeObject));
            _asm.Instructions.Add(new PushImmediate((uint)pIID_ICorRuntimeHost));
            _asm.Instructions.Add(new PushImmediate((uint)pCLSIDCorRuntimeHost));
            _asm.Instructions.Add(new PushImmediate(2));
            _asm.Instructions.Add(new PushImmediate((uint)pStrwks));
            _asm.Instructions.Add(new PushImmediate((uint)0));
            _asm.Instructions.Add(new CallFunctionPointer((uint)pCorBindToRuntimeEx));

            //pRuntimeObject->Start()
            _asm.Instructions.Add(new MovEaxMemory((uint)pRuntimeObject));
            _asm.Instructions.Add(new MovEcxMemory((uint)pRuntimeObject));//<- shouldn't be necessary, it's not a C++ object, but a COM object, so this doesn't have to be stored in ecx
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new DereferEax());
            _asm.Instructions.Add(new DereferEaxTable(0x28));//Start() is at 0x28 in the vtbl
            _asm.Instructions.Add(new CallEax());

            //pRuntimeObject->CreateDomainSetup(IUnkown ** pSetup)
            _asm.Instructions.Add(new PushImmediate((uint)pSetupObject));
            _asm.Instructions.Add(new MovEaxMemory((uint)pRuntimeObject));
            _asm.Instructions.Add(new MovEcxMemory((uint)pRuntimeObject));//<- shouldn't be necessary, it's not a C++ object, but a COM object, so this doesn't have to be stored in ecx
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new DereferEax());
            _asm.Instructions.Add(new DereferEaxTable(0x48));//CreateDomainSetup() is at 0x48 in the vtbl
            _asm.Instructions.Add(new CallEax());

            //pSetupObject->QueryInterface(&IID_IAppSetup, IID_IAppSetup ** pAppsetup)
            _asm.Instructions.Add(new PushImmediate((uint)pAppSetupObject));
            _asm.Instructions.Add(new PushImmediate((uint)pIID_IAppSetup));
            _asm.Instructions.Add(new MovEaxMemory((uint)pSetupObject));
            _asm.Instructions.Add(new MovEcxMemory((uint)pSetupObject));//<- shouldn't be necessary, it's not a C++ object, but a COM object, so this doesn't have to be stored in ecx
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new DereferEax());
            _asm.Instructions.Add(new DereferEaxTable(0x0));//QueryInterface() is at 0x0 in the vtbl
            _asm.Instructions.Add(new CallEax());

            //AppSetup->put_ApplicationBase(BSTR pStrAppBase)
            _asm.Instructions.Add(new PushImmediate((uint)pStrAppBase));
            _asm.Instructions.Add(new MovEaxMemory((uint)pAppSetupObject));
            _asm.Instructions.Add(new MovEcxMemory((uint)pAppSetupObject));//<- shouldn't be necessary, it's not a C++ object, but a COM object, so this doesn't have to be stored in ecx
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new DereferEax());
            _asm.Instructions.Add(new DereferEaxTable(0x10));//put_ApplicationBase is at 0x10 in the vtbl
            _asm.Instructions.Add(new CallEax());

            //pRuntimeObject->CreateDomainEx(unicode string pStrDomainName,pAppSetup,0,&pDomain);
            _asm.Instructions.Add(new PushImmediate((uint)pDomainObject));
            _asm.Instructions.Add(new PushImmediate(0));
            _asm.Instructions.Add(new MovEaxMemory((uint)pAppSetupObject));
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new PushImmediate((uint)pStrDomainName));
            _asm.Instructions.Add(new MovEaxMemory((uint)pRuntimeObject));
            _asm.Instructions.Add(new MovEcxMemory((uint)pRuntimeObject));//<- shouldn't be necessary, it's not a C++ object, but a COM object, so this doesn't have to be stored in ecx
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new DereferEax());
            _asm.Instructions.Add(new DereferEaxTable(0x44));//CreateDomainEx is at 0x44 in the vtbl
            _asm.Instructions.Add(new CallEax());

            //pDomainObject->QueryInterface(IID_IDomain, IAppDomain * pAppDomain)
            _asm.Instructions.Add(new PushImmediate((uint)pAppDomainObject));
            _asm.Instructions.Add(new PushImmediate((uint)pIID_IAppDomain));
            _asm.Instructions.Add(new MovEaxMemory((uint)pDomainObject));
            _asm.Instructions.Add(new MovEcxMemory((uint)pDomainObject));//<- shouldn't be necessary, it's not a C++ object, but a COM object, so this doesn't have to be stored in ecx
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new DereferEax());
            _asm.Instructions.Add(new DereferEaxTable(0x0));//QueryInterface is at 0x0 in the vtbl
            _asm.Instructions.Add(new CallEax());

            //pAppDomain->Load_2(pAssemblyName, &pAsm)
            _asm.Instructions.Add(new PushImmediate((uint)pAsm));
            _asm.Instructions.Add(new PushImmediate((uint)pAssemblyName));
            _asm.Instructions.Add(new MovEaxMemory((uint)pAppDomainObject));
            _asm.Instructions.Add(new MovEcxMemory((uint)pAppDomainObject));//<- shouldn't be necessary, it's not a C++ object, but a COM object, so this doesn't have to be stored in ecx
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new DereferEax());
            _asm.Instructions.Add(new DereferEaxTable(0xB0));//Load_2 is at 0xB0 in the vtbl
            _asm.Instructions.Add(new CallEax());

            //pAsm->CreateInstance(pTypeName,&pVariant)
            _asm.Instructions.Add(new PushImmediate((uint)pVariant));
            _asm.Instructions.Add(new PushImmediate((uint)pTypeName));
            _asm.Instructions.Add(new MovEaxMemory((uint)pAsm));
            _asm.Instructions.Add(new MovEcxMemory((uint)pAsm));//<- shouldn't be necessary, it's not a C++ object, but a COM object, so this doesn't have to be stored in ecx
            _asm.Instructions.Add(new PushEax());
            _asm.Instructions.Add(new DereferEax());
            _asm.Instructions.Add(new DereferEaxTable(0xA4));//CreateInstance is at 0xA4 in the vtbl
            _asm.Instructions.Add(new CallEax());

            //freelibrary?

            //safety measures : restore stack pointer, pop all registers
            _asm.Instructions.Add(new RestoreEsp((uint)pStackBackup));
            _asm.Instructions.Add(new PopAll());

            //write code
            //- suspend thread
            onthread.Suspend();
            //- read the context
            ThreadHandler.CONTEXT ctx = onthread.Context;
            //- add a jmp to the original eip
            _asm.Instructions.Add(new JmpRelative((int)ctx.Eip));
            //- code will be written at half the allocated page
            ctx.Eip = ((uint)RemotePage + (4096 / 2));
            //- write code
            _asm.Write(onprocess, (int)ctx.Eip);
            //- set the thread's context (EIP now points to our code)
            onthread.Context = ctx;
            //- resume the thread (our code executes and jumps back to the original eip)
            onthread.Resume();
        }
Esempio n. 10
0
        private LocalHook(uint address, ushort stack_cleanup_size, bool IsVtblEntry)
        {
            uint           skip_call_address;
            asmInstruction curinsn    = null;
            ProcessHandler curprocess = ProcessHandler.CurrentProcess;
            StreamHandler  sh         = new StreamHandler(curprocess);
            CallRelative   crel;
            JmpRelative    jrel;
            int            readsize = 0;

            m_Address  = address;
            m_VtblHook = IsVtblEntry;

            //read original target address

            curprocess.Position = address;
            if (IsVtblEntry)
            {
                original_address = sh.Read <uint>();
            }
            else
            {
                curinsn = disassembler.disassemble(curprocess);
                if (curinsn.Instruction.type == x86_insn_type.insn_call)
                {
                    original_address = (uint)curinsn.ReadAddressOperand();
                }
                else
                {
                    original_address = 0;//not hooking a call
                    readsize         = curinsn.Instruction.size;
                    while (readsize < 5)
                    {
                        curinsn   = disassembler.disassemble(curprocess);
                        readsize += curinsn.Instruction.size;
                    }
                    copied_instructions = new byte[readsize];
                    curprocess.Position = address;
                    curprocess.Read(copied_instructions, 0, readsize);
                }
            }

            //allocate required space (60 bytes)
            m_HookMemory      = Allocator.AllocateBuffer((uint)(46 + 32 + readsize));
            m_EspBackup       = Allocator.AllocateBuffer(4);
            skip_call_address = (uint)(m_HookMemory.Address.ToInt32() + 35 + readsize);

            //build unmanaged function pointer
            m_Delegate     = new InternalHookDelegate(ActualHook);
            m_LateDelegate = new InternalHookDelegate(ActualLateHook);
            IntPtr unmanaged_hook_pointer  = Marshal.GetFunctionPointerForDelegate(m_Delegate);
            IntPtr unmanaged_hook_pointerb = Marshal.GetFunctionPointerForDelegate(m_LateDelegate);

            //build hook code
            AsmBuilder hookcode = new AsmBuilder();

            hookcode.Instructions.Add(new PushAll());
            hookcode.Instructions.Add(new BackupEsp((uint)m_EspBackup.Address.ToInt32()));
            hookcode.Instructions.Add(new PushImmediate(address));
            hookcode.Instructions.Add(new CallRelative(unmanaged_hook_pointer.ToInt32()));
            hookcode.Instructions.Add(new TestEaxEax());
            hookcode.Instructions.Add(new JzRelativeShort((int)skip_call_address));
            hookcode.Instructions.Add(new RestoreEsp((uint)m_EspBackup.Address.ToInt32()));
            hookcode.Instructions.Add(new PopAll());
            //switch vtbl: return, non-call : jmp address+readsize, call, jmp original
            hookcode.Write(curprocess, m_HookMemory.Address.ToInt32());
            if (original_address == 0)
            {
                curprocess.Position = m_HookMemory.Address.ToInt32() + 30;
                curprocess.Write(copied_instructions, 0, readsize);
                hookcode = new AsmBuilder();
                hookcode.Instructions.Add(new JmpRelative((int)address + readsize));
            }
            else
            {
                hookcode = new AsmBuilder();
                hookcode.Instructions.Add(new JmpRelative((int)original_address));
            }
            //end_code
            hookcode.Instructions.Add(new RestoreEsp((uint)m_EspBackup.Address.ToInt32()));
            hookcode.Instructions.Add(new PopAll());
            if (stack_cleanup_size == 0)
            {
                hookcode.Instructions.Add(new Rtn());
            }
            else
            {
                hookcode.Instructions.Add(new RtnStackSize(stack_cleanup_size));
            }
            hookcode.Write(curprocess, (int)m_HookMemory.Address.ToInt32() + 30 + readsize);

            hookcode = new AsmBuilder();
            hookcode.Instructions.Add(new PushImmediate(0));
            hookcode.Instructions.Add(new PushAll());
            hookcode.Instructions.Add(new BackupEsp((uint)m_EspBackup.Address.ToInt32()));
            hookcode.Instructions.Add(new PushImmediate(address));
            hookcode.Instructions.Add(new CallRelative(unmanaged_hook_pointerb.ToInt32()));
            hookcode.Instructions.Add(new RestoreEsp((uint)m_EspBackup.Address.ToInt32()));
            hookcode.Instructions.Add(new PopAll());
            hookcode.Instructions.Add(new Rtn());
            hookcode.Write(curprocess, (int)m_HookMemory.Address.ToInt32() + 46 + readsize);

            m_LateHookAddress = (uint)(m_HookMemory.Address.ToInt32() + 46 + readsize);

            //install hook
            if (original_address != 0)
            {
                if (IsVtblEntry)
                {
                    //vtbl_hook
                    sh.Position = address;
                    sh.Write <int>(m_HookMemory.Address.ToInt32());
                }
                else
                {
                    crel = new CallRelative((int)m_HookMemory.Address.ToInt32());
                    if (crel.Size != curinsn.Instruction.size)
                    {
                        throw new Exception("Can only hook call instructions with size equal to " + crel.Size.ToString());
                    }
                    crel.Write(curprocess, (int)address);
                    curprocess.Position = address + crel.Size;
                }
            }
            else
            {
                //random hook
                jrel = new JmpRelative((int)m_HookMemory.Address.ToInt32());
                jrel.Write(curprocess, (int)address);
                curprocess.Position = address + jrel.Size;
                for (uint i = 0; i < (readsize - jrel.Size); i++)
                {
                    curprocess.WriteByte(0x90);//NOP
                }
            }

            m_Hooks.Add(address, this);
        }