Example #1
0
 private void button4_Click(object sender, EventArgs e)
 {
     try
     {
         string[] buffs = textBox2.Text.Split(new char[] { ' ' });
         byte[]   bytes = new byte[buffs.Length];
         uint     j     = 0;
         byte     curbyte;
         for (uint i = 0; i < buffs.Length; i++)
         {
             while (!byte.TryParse(buffs[j], System.Globalization.NumberStyles.HexNumber, null, out curbyte))
             {
                 j++;
             }
             bytes[i] = curbyte;
             j++;
         }
         asmInstruction curins = disassembler.disassemble(bytes);
         MessageBox.Show(curins.ToString());
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.ToString());
     }
 }
Example #2
0
        public static void Callibrate(ProcessHandler clientprocess)
        {
            uint           entrypoint;
            Stack <string> errstack = new Stack <string>();
            asmInstruction curinsn  = null;
            asmChunk       curchunk = null;

            entrypoint = clientprocess.MainModule.EntryPointAddress;

            if ((entrypoint == 0) || (entrypoint == 0xFFFFFFFF))
            {
                throw new Exception("Failed to obtain entrypoint address!");
            }

            clientprocess.Position = (long)entrypoint;

            if (System.IO.File.Exists("Callibrations.xml"))
            {
                CallibrationFile.Load("Callibrations.xml");
            }
            else//fall back to the embedded callibrations
            {
                CallibrationFile.Load(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("UOAIBasic.Callibrations.xml"));
            }

            if (!ActionList.actionlists["ActionList1"].ExecuteActionList(clientprocess, Callibrations, ref curchunk, ref curinsn, errstack))
            {
                throw BuildCallibrationException(errstack);
            }
        }
Example #3
0
 public bool Check(asmInstruction tocompare, BinaryTree <uint, long> knowns)
 {
     foreach (Filter f in filters)
     {
         if (!f.Check(tocompare, knowns))
         {
             return(false);
         }
     }
     return(true);
 }
Example #4
0
        private bool CheckOpData(asmInstruction tocheck, int opnumber, uint opdata, bool negate)
        {
            if ((opnumber < 0) || (opnumber >= tocheck.Operands.Count))
            {
                return(false);
            }
            switch (tocheck.Operands[opnumber].Type)
            {
            case x86_op_type.op_immediate:
            case x86_op_type.op_absolute:
                if (!negate)
                {
                    return(GetOpDataAsUInt(tocheck.Operands[opnumber]) == opdata);
                }
                else
                {
                    return(!(GetOpDataAsUInt(tocheck.Operands[opnumber]) == opdata));
                }

            case x86_op_type.op_expression:
                if (!negate)
                {
                    return(tocheck.Operands[opnumber].Data.expression.disp == opdata);
                }
                else
                {
                    return(!(tocheck.Operands[opnumber].Data.expression.disp == opdata));
                }

            case x86_op_type.op_offset:
                if (!negate)
                {
                    return(tocheck.Operands[opnumber].Data.offset == opdata);
                }
                else
                {
                    return(!(tocheck.Operands[opnumber].Data.offset == opdata));
                }

            case x86_op_type.op_relative_far:
                if (!negate)
                {
                    return(((uint)(((int)tocheck.Address + tocheck.Instruction.size + tocheck.Operands[opnumber].Data.relative_far))) == opdata);
                }
                else
                {
                    return(!(((uint)(((int)tocheck.Address + tocheck.Instruction.size + tocheck.Operands[opnumber].Data.relative_far))) == opdata));
                }

            case x86_op_type.op_relative_near:
                if (!negate)
                {
                    return(((uint)(((int)tocheck.Address + tocheck.Instruction.size + tocheck.Operands[opnumber].Data.relative_near)) == opdata));
                }
                else
                {
                    return(!(((uint)(((int)tocheck.Address + tocheck.Instruction.size + tocheck.Operands[opnumber].Data.relative_near)) == opdata)));
                }

            default:
                return(false);
            }
        }
Example #5
0
        public bool ExecuteActionList(Stream onstream, BinaryTree <uint, long> knowns, ref asmChunk curChunk, ref asmInstruction curInstruction, Stack <string> ErrorStack)
        {
            bool backwards = false;

            Tools.StreamHandler sh = new Tools.StreamHandler(onstream);

            knowns.Add(0, onstream.Position);

            uint i = 0;

            //first action must be chunk or func parse
            foreach (Action currentaction in Actions)
            {
                switch (currentaction.m_type)
                {
                case ActionType.DISASM_CHUNK:
                    if (!knowns.ContainsKey((uint)currentaction.knownpar))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Missing Dependency: " + currentaction.knownpar.ToString());
                        return(false);
                    }
                    onstream.Position = knowns[(uint)currentaction.knownpar];
                    curChunk          = disassembler.disassemble_chunk(onstream);
                    break;

                case ActionType.DISASM_FUNCTION:
                    if (!knowns.ContainsKey((uint)currentaction.knownpar))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Missing Dependency: " + currentaction.knownpar.ToString());
                        return(false);
                    }
                    onstream.Position = knowns[(uint)currentaction.knownpar];
                    curChunk          = disassembler.disassemble_function(onstream);
                    break;

                case ActionType.FIND_SEQUENCE:
                    if (curChunk == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No disassembled code chunk available to search!");
                        return(false);
                    }
                    if (!currentaction.seqpar.Find(curChunk, backwards, knowns, out curInstruction))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Failed to find sequence: " + currentaction.seqpar.name);
                        return(false);
                    }
                    break;

                case ActionType.FOLLOW_CALL:
                    if ((curInstruction == null) || (curInstruction.Instruction.type != x86_insn_type.insn_call))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Need a call instruction to follow!");
                        return(false);
                    }
                    onstream.Position = curInstruction.ReadAddressOperand();
                    if (currentaction.boolpar)
                    {
                        curChunk = disassembler.disassemble_chunk(onstream);
                    }
                    else
                    {
                        curChunk = disassembler.disassemble_function(onstream);
                    }
                    break;

                case ActionType.JUMP_KNOWN:
                    if (!knowns.ContainsKey((uint)currentaction.knownpar))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Missing Dependency: " + currentaction.knownpar.ToString());
                        return(false);
                    }
                    knowns.Remove(0);
                    knowns.Add(0, knowns[(uint)currentaction.knownpar]);
                    onstream.Position = knowns[(uint)currentaction.knownpar];
                    break;

                case ActionType.RETURN_ADDRESS:
                    if (curInstruction == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No Current Instruction!");
                        return(false);
                    }
                    knowns.Remove((uint)currentaction.knownpar);
                    knowns.Add((uint)currentaction.knownpar, curInstruction.Address);
                    break;

                case ActionType.RETURN_DATA:
                    if ((curInstruction == null) || ((int)currentaction.uintpar > (curInstruction.Operands.Count - 1)))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No Suitable Current Instruction!");
                        return(false);
                    }
                    knowns.Remove((uint)currentaction.knownpar);
                    if (curInstruction.Operands[(int)currentaction.uintpar].Type == x86_op_type.op_expression)
                    {
                        knowns.Add((uint)currentaction.knownpar, (long)curInstruction.Operands[(int)currentaction.uintpar].Data.expression.disp);
                    }
                    else if (curInstruction.Operands[(int)currentaction.uintpar].Type == x86_op_type.op_offset)
                    {
                        knowns.Add((uint)currentaction.knownpar, (long)curInstruction.Operands[(int)currentaction.uintpar].Data.offset);
                    }
                    else
                    {
                        knowns.Add((uint)currentaction.knownpar, (long)curInstruction.Operands[(int)currentaction.uintpar].Data.dword);
                    }
                    break;

                case ActionType.RETURN_DISP:
                    if ((curInstruction == null) || ((int)currentaction.uintpar > (curInstruction.Operands.Count - 1)))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No Suitable Current Instruction!");
                        return(false);
                    }
                    knowns.Remove((uint)currentaction.knownpar);
                    knowns.Add((uint)currentaction.knownpar, (long)curInstruction.Operands[(int)currentaction.uintpar].Data.expression.disp);
                    break;

                case ActionType.SET_BACKWARDS:
                    if (backwards != currentaction.boolpar)
                    {
                        backwards = currentaction.boolpar;
                    }
                    break;

                case ActionType.TO_END:
                    if (curChunk == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No disassembled code chunk available!");
                        return(false);
                    }
                    curChunk.ToEnd();
                    break;

                case ActionType.TO_START:
                    if (curChunk == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No disassembled code chunk available!");
                        return(false);
                    }
                    curChunk.ToStart();
                    break;

                case ActionType.RETURN_TARGETADDRESS:
                    if ((curInstruction == null) || ((int)currentaction.uintpar > (curInstruction.Operands.Count - 1)))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No Suitable Current Instruction!");
                        return(false);
                    }
                    knowns.Remove((uint)currentaction.knownpar);
                    knowns.Add((uint)currentaction.knownpar, curInstruction.ReadAddressOperand());
                    break;

                case ActionType.FUNC_FIND:
                    if (curChunk == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No disassembled code chunk available!");
                        return(false);
                    }
                    if (!FuncFind(onstream, curChunk, currentaction.uintpar, backwards, out curInstruction))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Failed to find stdcall function with stacksize 0x" + currentaction.uintpar.ToString("X") + "!");
                        return(false);
                    }
                    break;

                case ActionType.SWITCH:
                    if (!knowns.ContainsKey((uint)currentaction.knownpar))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Missing Dependency: " + currentaction.knownpar.ToString());
                        return(false);
                    }
                    sh.Position       = (knowns[(uint)currentaction.knownpar] + 4 * currentaction.uintpar);
                    onstream.Position = (long)sh.Read <uint>();
                    if (currentaction.boolpar)
                    {
                        curChunk = disassembler.disassemble_chunk(onstream);
                    }
                    else
                    {
                        curChunk = disassembler.disassemble_function(onstream);
                    }
                    break;

                case ActionType.CONDITIONAL:
                    if (currentaction.actlist != null)
                    {
                        if (currentaction.actlist.ExecuteActionList(onstream, knowns, ref curChunk, ref curInstruction, new Stack <string>()))
                        {
                            if (currentaction.ontrue != null)
                            {
                                if (!currentaction.ontrue.ExecuteActionList(onstream, knowns, ref curChunk, ref curInstruction, ErrorStack))
                                {
                                    ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] OnTrue handler (" + currentaction.ontrue.name + ") of Condition " + currentaction.actlist.ToString() + " failed!");
                                    return(false);
                                }
                            }
                        }
                        else
                        {
                            if (currentaction.onfalse != null)
                            {
                                if (!currentaction.onfalse.ExecuteActionList(onstream, knowns, ref curChunk, ref curInstruction, ErrorStack))
                                {
                                    ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] OnFalse handler (" + currentaction.onfalse.name + ") of Condition " + currentaction.actlist.ToString() + " failed!");
                                    return(false);
                                }
                            }
                        }
                    }
                    break;

                case ActionType.ASSIGN_VALUE:
                    if (knowns.ContainsKey((uint)currentaction.knownpar))
                    {
                        knowns.Remove((uint)currentaction.knownpar);
                    }
                    knowns.Add((uint)currentaction.knownpar, (long)currentaction.uintpar);
                    break;

                case ActionType.ASSIGN_KNOWN:
                    if (knowns.ContainsKey((uint)currentaction.knownpar))
                    {
                        knowns.Remove((uint)currentaction.knownpar);
                    }
                    if (!knowns.ContainsKey((uint)currentaction.knownpar2))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Missing Dependency: " + currentaction.knownpar2.ToString());
                        return(false);
                    }
                    knowns.Add((uint)currentaction.knownpar, knowns[(uint)currentaction.knownpar2]);
                    break;

                case ActionType.CHECK_INSTRUCTION:
                    if (curInstruction == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No Suitable Current Instruction!");
                        return(false);
                    }
                    if (!currentaction.tocheck.Check(curInstruction, knowns))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Instruction verification failed!");
                        return(false);
                    }
                    break;

                case ActionType.EXECUTE_ACTIONSLIST:
                    if (!currentaction.actlist.ExecuteActionList(onstream, knowns, ref curChunk, ref curInstruction, ErrorStack))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] ActionList " + currentaction.actlist.name + " failed!");
                        return(false);
                    }
                    break;

                case ActionType.TRY_ACTIONLIST:
                    if (!currentaction.actlist.ExecuteActionList(onstream, knowns, ref curChunk, ref curInstruction, ErrorStack))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] (Try) ActionList " + currentaction.actlist.name + " failed!");
                    }
                    break;

                case ActionType.FOLLOW_JMP:
                    if ((curInstruction == null) || (!((curInstruction.Instruction.type == x86_insn_type.insn_jmp) || (curInstruction.Instruction.type == x86_insn_type.insn_jcc))))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No Suitable Current Instruction!");
                        return(false);
                    }
                    onstream.Position = curInstruction.ReadAddressOperand();
                    if (currentaction.boolpar)
                    {
                        curChunk = disassembler.disassemble_chunk(onstream);
                    }
                    else
                    {
                        curChunk = disassembler.disassemble_function(onstream);
                    }
                    break;

                case ActionType.RETURN_SCALE:
                    if ((curInstruction == null) || ((int)currentaction.uintpar > (curInstruction.Operands.Count - 1)))
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No Suitable Current Instruction!");
                        return(false);
                    }
                    knowns.Add((uint)currentaction.knownpar, (long)curInstruction.Operands[(int)currentaction.uintpar].Data.expression.scale);
                    break;

                case ActionType.FIND_LOOP:
                    if (curChunk != null)
                    {
                        if (!curChunk.FindLoop(out curInstruction))
                        {
                            ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] Failed to find a loop in the current code chunk!");
                            return(false);
                        }
                    }
                    break;

                case ActionType.RETURN_CHUNK_ADDRESS:
                    if (curChunk == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No disassembled code chunk available!");
                        return(false);
                    }
                    knowns.Add((uint)currentaction.knownpar, curChunk.Address);
                    break;

                case ActionType.MOVE_NEXT:
                    if (curChunk == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No disassembled code chunk available!");
                        return(false);
                    }
                    curChunk.MoveNext();
                    break;

                case ActionType.MOVE_PREVIOUS:
                    if (curChunk == null)
                    {
                        ErrorStack.Push("[#" + i.ToString() + " : " + currentaction.name + "] No disassembled code chunk available!");
                        return(false);
                    }
                    curChunk.MovePrevious();
                    break;
                }
                i++;
            }
            return(true);
        }
Example #6
0
        private static bool FuncFind(Stream onstream, asmChunk fromfunction, uint required_stacksize, bool backwards, out asmInstruction found)
        {
            asmChunk curfunc;

            found = null;
            while (fromfunction.FindByType(x86_insn_type.insn_call, backwards, out found))
            {
                onstream.Position = found.ReadAddressOperand();
                curfunc           = disassembler.disassemble_chunk(onstream);
                if (StackSize(curfunc) == required_stacksize)
                {
                    return(true);
                }
                fromfunction.MoveNext();
            }
            return(false);
        }
Example #7
0
 public bool Find(asmChunk onchunk, bool backwards, BinaryTree <uint, long> knowns, out asmInstruction found)
 {
     found = null;
     for (int i = 0; i < CodeBlocks.Count; i++)
     {
         if (!CodeBlocks[i].Find(onchunk, backwards, knowns, out found))
         {
             return(false);
         }
         if (i != (CodeBlocks.Count - 1))
         {
             if (backwards)
             {
                 onchunk.MovePrevious();
             }
             else
             {
                 onchunk.MoveNext();
             }
         }
     }
     return(true);
 }
Example #8
0
        public bool Find(asmChunk onchunk, bool backwards, BinaryTree <uint, long> knowns, out asmInstruction found)
        {
            bool           _found = true;
            asmInstruction backup, fullbackup;

            fullbackup = onchunk.Current;
            found      = null;
            while (onchunk.Current != null)
            {
                backup = onchunk.Current;
                _found = true;
                for (int i = 0; i < FilterLists.Count; i++)
                {
                    if (!FilterLists[i].Check(onchunk.Current, knowns))
                    {
                        _found = false;
                        break;
                    }

                    if (i != (FilterLists.Count - 1))
                    {
                        onchunk.MoveNext();

                        if (onchunk.Current == null)
                        {
                            _found = false;
                            break;
                        }
                    }
                }

                onchunk.Current = backup;
                if (_found)
                {
                    found = onchunk.Current;
                    return(true);
                }
                if (backwards)
                {
                    onchunk.MovePrevious();
                }
                else
                {
                    onchunk.MoveNext();
                }
            }
            onchunk.Current = fullbackup;
            return(false);
        }
Example #9
0
        public bool Check(asmInstruction tocompare, BinaryTree <uint, long> knowns)
        {
            switch (type)
            {
            case FilterType.OpKnownData:
                if (knowns != null)
                {
                    if (((int)uintpar) < tocompare.Operands.Count)
                    {
                        if ((knowns.ContainsKey(enumpar)) && CheckOpData(tocompare, (int)uintpar, (uint)knowns[enumpar], false))
                        {
                            return(true);
                        }
                    }
                }
                break;

            case FilterType.FilterOr:
                foreach (Filter f in filterlistpar.filters)
                {
                    if (f.Check(tocompare, knowns))
                    {
                        return(true);
                    }
                }
                break;

            case FilterType.ExplicitOpCount:
                if (tocompare.Instruction.explicit_count == uintpar)
                {
                    return(true);
                }
                break;

            case FilterType.OpCount:
                if (((int)uintpar) < tocompare.Operands.Count)
                {
                    if (tocompare.Instruction.operand_count == uintpar)
                    {
                        return(true);
                    }
                }
                break;

            case FilterType.OpData:
                if (((int)uintpar) < tocompare.Operands.Count)
                {
                    if (CheckOpData(tocompare, (int)uintpar, uintpar2, false))
                    {
                        return(true);
                    }
                }
                break;

            case FilterType.OpDataType:
                if (((int)uintpar) < tocompare.Operands.Count)
                {
                    if (tocompare.Operands[(int)uintpar].DataType == (x86_op_datatype)enumpar)
                    {
                        return(true);
                    }
                }
                break;

            case FilterType.OpType:
                if (((int)uintpar) < tocompare.Operands.Count)
                {
                    if (tocompare.Operands[(int)uintpar].Type == (x86_op_type)enumpar)
                    {
                        return(true);
                    }
                }
                break;

            case FilterType.Size:
                if (uintpar == tocompare.Instruction.size)
                {
                    return(true);
                }
                break;

            case FilterType.Type:
                if (tocompare.Instruction.type == (x86_insn_type)enumpar)
                {
                    return(true);
                }
                break;

            case FilterType.OpDataNotEqual:
                if (((int)uintpar) < tocompare.Operands.Count)
                {
                    if (CheckOpData(tocompare, (int)uintpar, uintpar2, true))
                    {
                        return(true);
                    }
                }
                break;
            }
            return(false);
        }
Example #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);
        }