Example #1
0
        //static constructor: inject code required to perform the call once
        static UnmanagedCall()
        {
            uint loopaddress;
            uint code_alignment;

            uint pAddress;
            uint pStacksize;
            uint ppStack;
            uint pThisPar;
            uint pRetVal;
            uint pStackPointerBackup;

            AsmBuilder asm = new AsmBuilder();

            //should use our own heap, not the default heap; since the code buffer needs execution rights
            m_Parameters = Allocator.AllocateBuffer(7 * 4);
            m_Code       = Allocator.AllocateBuffer(61);

            data_alignment = ((uint)m_Parameters.Address) % 4;
            code_alignment = ((uint)m_Code.Address) % 4;

            pAddress            = (uint)m_Parameters.Address + data_alignment + 4 * 0;
            pStacksize          = (uint)m_Parameters.Address + data_alignment + 4 * 1;
            ppStack             = (uint)m_Parameters.Address + data_alignment + 4 * 2;
            pThisPar            = (uint)m_Parameters.Address + data_alignment + 4 * 3;
            pRetVal             = (uint)m_Parameters.Address + data_alignment + 4 * 4;
            pStackPointerBackup = (uint)m_Parameters.Address + data_alignment + 4 * 5;

            //backup context
            asm.Instructions.Add(new PushAll());
            asm.Instructions.Add(new BackupEsp(pStackPointerBackup));
            //build stack
            asm.Instructions.Add(new MovEcxMemory(pStacksize));
            asm.Instructions.Add(new MovEdxMemory(ppStack));
            //store current position for the stack push loop
            loopaddress = code_alignment + (uint)asm.Size;    //relative
            //build stack builder loop
            asm.Instructions.Add(new MovEaxEdx());
            asm.Instructions.Add(new DereferEax());
            asm.Instructions.Add(new PushEax());
            asm.Instructions.Add(new AddEdx(4));
            asm.Instructions.Add(new DecEcx());
            asm.Instructions.Add(new JnzRelativeShort((int)loopaddress));
            //build call
            asm.Instructions.Add(new MovEcxMemory(pThisPar));
            asm.Instructions.Add(new CallFunctionPointer(pAddress));
            //store return value
            asm.Instructions.Add(new MovMemoryEax(pRetVal));
            //restore context
            asm.Instructions.Add(new RestoreEsp(pStackPointerBackup));
            asm.Instructions.Add(new PopAll());
            //return
            asm.Instructions.Add(new Rtn());

            //write code
            asm.Write(m_Code, (int)code_alignment);

            //build function pointer
            m_Call = (SimpleCallDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)((uint)m_Code.Address + code_alignment), typeof(SimpleCallDelegate));
        }
Example #2
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);
        }