示例#1
0
        /// <summary>
        /// 计算大于等于 size 字节的最少指令的长度
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static uint SizeofMinNumByte(void *code, int size)
        {
            if (NativeAPI.IsAndroidARM())
            {
                return((uint)((size + 3) / 4) * 4); // 此为 jit 模式下的长度
            }

            UInt32     Length;
            byte *     pOpcode;
            UInt32     Result = 0;
            ldasm_data data   = new ldasm_data();
            bool       is64   = IntPtr.Size == 8;

            do
            {
                Length  = ldasm(code, data, is64);
                pOpcode = (byte *)code + data.opcd_offset;
                Result += Length;
                if (Result >= size)
                {
                    break;
                }
                if ((Length == 1) && (*pOpcode == 0xCC))
                {
                    break;
                }

                code = (void *)((ulong)code + Length);
            } while (Length > 0);

            return(Result);
        }
示例#2
0
        /// <summary>
        /// 计算大于等于5字节的最少指令的长度
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static uint SizeofMin5Byte(void *code)
        {
            UInt32     Length;
            byte *     pOpcode;
            UInt32     Result = 0;
            ldasm_data data   = new ldasm_data();
            bool       is64   = IntPtr.Size == 8;

            do
            {
                Length = ldasm(code, data, is64);

                pOpcode = (byte *)code + data.opcd_offset;
                Result += Length;
                if (Result >= 5)
                {
                    break;
                }
                if ((Length == 1) && (*pOpcode == 0xCC))
                {
                    break;
                }

                code = (void *)((ulong)code + Length);
            } while (Length > 0);

            return(Result);
        }
示例#3
0
 public static int GetASMLength(byte[] b, int index, bool x64)
 {
     unsafe
     {
         IntPtr addr = Marshal.AllocHGlobal(b.Length);
         Marshal.Copy(b, 0, addr, b.Length);
         ldasm_data data = new ldasm_data();
         uint       i    = ldasm((byte *)addr, ref data, x64);
         Marshal.FreeHGlobal(addr);
         return((int)i);
     }
 }
示例#4
0
        public static bool CheckShortCall(void *code, int size, out int index)
        {
            bool result = false;

            index = -1;
            if (NativeAPI.IsAndroidARM())
            {
                return(result);
            }

            UInt32     oneLength;
            byte *     pOpcode;
            UInt32     calledLength = 0;
            ldasm_data data         = new ldasm_data();
            bool       is64         = IntPtr.Size == 8;

            do
            {
                oneLength     = ldasm(code, data, is64);
                pOpcode       = (byte *)code + data.opcd_offset;
                calledLength += oneLength;
                if (calledLength >= size)
                {
                    break;
                }
                if ((oneLength == 1) && (*pOpcode == 0xCC))
                {
                    break;
                }
                byte instruct = ((byte *)code)[calledLength];
                if (instruct == 0xE8 || instruct == 0xE9)
                {
                    index  = (int)calledLength;
                    result = true;
                    break;
                }
                code = (void *)((ulong)code + oneLength);
            } while (oneLength > 0);

            return(result);
        }
示例#5
0
        static uint ldasm(void *code, ldasm_data ld, bool is64)
        {
            byte *p = (byte *)code;
            byte  s, op, f;
            byte  rexw, pr_66, pr_67;

            s = rexw = pr_66 = pr_67 = 0;

            /* dummy check */
            if ((int)code == 0)
            {
                return(0);
            }

            /* init output data */
            //memset(ld, 0, sizeof(ldasm_data));

            /* phase 1: parse prefixies */
            while ((cflags(*p) & OP_PREFIX) != 0)
            {
                if (*p == 0x66)
                {
                    pr_66 = 1;
                }
                if (*p == 0x67)
                {
                    pr_67 = 1;
                }
                p++; s++;
                ld.flags |= F_PREFIX;
                if (s == 15)
                {
                    ld.flags |= F_INVALID;
                    return(s);
                }
            }

            /* parse REX prefix */
            if (is64 && *p >> 4 == 4)
            {
                ld.rex    = *p;
                rexw      = (byte)((ld.rex >> 3) & 1);
                ld.flags |= F_REX;
                p++; s++;
            }

            /* can be only one REX prefix */
            if (is64 && *p >> 4 == 4)
            {
                ld.flags |= F_INVALID;
                s++;
                return(s);
            }

            /* phase 2: parse opcode */
            ld.opcd_offset = (byte)(p - (byte *)code);
            ld.opcd_size   = 1;
            op             = *p++; s++;

            /* is 2 byte opcode? */
            if (op == 0x0F)
            {
                op = *p++; s++;
                ld.opcd_size++;
                f = cflags_ex(op);
                if ((f & OP_INVALID) != 0)
                {
                    ld.flags |= F_INVALID;
                    return(s);
                }
                /* for SSE instructions */
                if ((f & OP_EXTENDED) != 0)
                {
                    op = *p++; s++;
                    ld.opcd_size++;
                }
            }
            else
            {
                f = cflags(op);
                /* pr_66 = pr_67 for opcodes A0-A3 */
                if (op >= 0xA0 && op <= 0xA3)
                {
                    pr_66 = pr_67;
                }
            }

            /* phase 3: parse ModR/M, SIB and DISP */
            if ((f & OP_MODRM) != 0)
            {
                byte mod = (byte)(*p >> 6);
                byte ro  = (byte)((*p & 0x38) >> 3);
                byte rm  = (byte)(*p & 7);

                ld.modrm  = *p++; s++;
                ld.flags |= F_MODRM;

                /* in F6,F7 opcodes immediate data present if R/O == 0 */
                if (op == 0xF6 && (ro == 0 || ro == 1))
                {
                    f |= OP_DATA_I8;
                }
                if (op == 0xF7 && (ro == 0 || ro == 1))
                {
                    f |= OP_DATA_I16_I32_I64;
                }

                /* is SIB byte exist? */
                if (mod != 3 && rm == 4 && !(!is64 && pr_67 != 0))
                {
                    ld.sib    = *p++; s++;
                    ld.flags |= F_SIB;

                    /* if base == 5 and mod == 0 */
                    if ((ld.sib & 7) == 5 && mod == 0)
                    {
                        ld.disp_size = 4;
                    }
                }

                switch (mod)
                {
                case 0:
                    if (is64)
                    {
                        if (rm == 5)
                        {
                            ld.disp_size = 4;
                            if (is64)
                            {
                                ld.flags |= F_RELATIVE;
                            }
                        }
                    }
                    else if (pr_67 != 0)
                    {
                        if (rm == 6)
                        {
                            ld.disp_size = 2;
                        }
                    }
                    else
                    {
                        if (rm == 5)
                        {
                            ld.disp_size = 4;
                        }
                    }
                    break;

                case 1:
                    ld.disp_size = 1;
                    break;

                case 2:
                    if (is64)
                    {
                        ld.disp_size = 4;
                    }
                    else if (pr_67 != 0)
                    {
                        ld.disp_size = 2;
                    }
                    else
                    {
                        ld.disp_size = 4;
                    }
                    break;
                }

                if (ld.disp_size > 0)
                {
                    ld.disp_offset = (byte)(p - (byte *)code);
                    p        += ld.disp_size;
                    s        += ld.disp_size;
                    ld.flags |= F_DISP;
                }
            }

            /* phase 4: parse immediate data */
            if (rexw != 0 && (f & OP_DATA_I16_I32_I64) != 0)
            {
                ld.imm_size = 8;
            }
            else if ((f & OP_DATA_I16_I32) != 0 || (f & OP_DATA_I16_I32_I64) != 0)
            {
                ld.imm_size = (byte)(4 - (pr_66 << 1));
            }

            /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */
            ld.imm_size += (byte)(f & 3);

            if ((ld.imm_size) != 0)
            {
                s            += ld.imm_size;
                ld.imm_offset = (byte)(p - (byte *)code);
                ld.flags     |= F_IMM;
                if ((f & OP_RELATIVE) != 0)
                {
                    ld.flags |= F_RELATIVE;
                }
            }

            /* instruction is too long */
            if (s > 15)
            {
                ld.flags |= F_INVALID;
            }

            return(s);
        }
示例#6
0
        /// <summary>
        /// Performs a SingleStep operation, that is to stay it resumes the process and pauses at the very next instruction.
        /// Jumps are followed, conditional jumps are evaluated, Calls are either stepped into or over depending on StepIntoCalls value.
        /// </summary>
        /// <returns></returns>
        public NIDebugger64 SingleStep()
        {
            getContext(getCurrentThreadId());
            ulong address = Context.Rip;

            if (address == 0x7ffa79b6660e)
            {
                int i = 0;
            }
            byte[] data;
            ReadData(address, 16, out data);

            if (breakpoints.ContainsKey(address) == true)
            {
                Array.Copy(breakpoints[address].originalBytes, data, 2);
                ClearBreakpoint(address);
            }

            ldasm_data ldata = lde.ldasm(data, 0, false);

            uint  size        = ldata.size;
            ulong nextAddress = Context.Rip + size;

            if (ldata.opcd_size == 1 && (data[ldata.opcd_offset] == 0xEB))
            {
                // we have a 1 byte JMP here
                sbyte offset = (sbyte)data[ldata.imm_offset];
                nextAddress = (ulong)((long)Context.Rip + offset) + ldata.size;
            }

            if ((data[ldata.opcd_offset] == 0xE2))
            {
                // LOOP

                if (Context.Rcx == 1)
                {
                    // this instruction will make ECX 0, so we fall thru the jump now
                    nextAddress = (ulong)((long)Context.Rip + ldata.size);
                }
                else if (Context.Rcx > 1)
                {
                    // this instruction will decrement ECX but it wont be 0 yet, so jump!
                    sbyte disp = (sbyte)data[1];
                    nextAddress = (uint)((long)Context.Rip + disp) + ldata.size;
                }
            }

            if ((data[ldata.opcd_offset] == 0xE0))
            {
                //LOOPNZ LOOPNE
                if (Context.Rcx == 1 && Context.GetFlag(NIContextFlag.ZERO) == false)
                {
                    nextAddress = (ulong)((long)Context.Rip + ldata.size);
                }
                else if (Context.Rcx > 1 || Context.GetFlag(NIContextFlag.ZERO) != false)
                {
                    sbyte disp = (sbyte)data[1];
                    nextAddress = (ulong)((long)Context.Rip + disp) + ldata.size;
                }
            }

            if ((data[ldata.opcd_offset] == 0xE1))
            {
                //LOOPZ LOOPE
                if (Context.Rcx == 1 && Context.GetFlag(NIContextFlag.ZERO) == true)
                {
                    nextAddress = (ulong)((long)Context.Rip + ldata.size);
                }
                else if (Context.Rcx > 1 || Context.GetFlag(NIContextFlag.ZERO) != true)
                {
                    sbyte disp = (sbyte)data[1];
                    nextAddress = (ulong)((long)Context.Rip + disp) + ldata.size;
                }
            }

            if (ldata.opcd_size == 1 && ((data[ldata.opcd_offset] == 0xE9) || (data[ldata.opcd_offset] == 0xE8)))
            {
                // we have a long JMP or CALL here
                int offset = BitConverter.ToInt32(data, ldata.imm_offset);
                if ((data[ldata.opcd_offset] == 0xE9) || (StepIntoCalls && (data[ldata.opcd_offset] == 0xE8)))
                {
                    nextAddress = (ulong)((long)Context.Rip + offset) + ldata.size;
                }
            }

            if (ldata.opcd_size == 1 && ((data[ldata.opcd_offset] >= 0x70 && (data[ldata.opcd_offset] <= 0x7F)) || (data[ldata.opcd_offset] == 0xE3)))
            {
                // we have a 1byte jcc here
                bool willJump = evalJcc(data[ldata.opcd_offset]);

                if (willJump)
                {
                    sbyte offset = (sbyte)data[ldata.imm_offset];
                    nextAddress = (ulong)((long)Context.Rip + offset) + ldata.size;
                }
            }

            if (ldata.opcd_size == 2 && ((data[ldata.opcd_offset] == 0x0F) || (data[ldata.opcd_offset + 1] == 0x80)))
            {
                // we have a 2 byte jcc here

                bool willJump = evalJcc(data[ldata.opcd_offset + 1]);

                if (willJump)
                {
                    int offset = BitConverter.ToInt32(data, ldata.imm_offset);
                    nextAddress = (ulong)(((long)Context.Rip + offset) + ldata.size);
                }
            }

            if (data[ldata.opcd_offset] == 0xC3 || data[ldata.opcd_offset] == 0xC2)
            {
                ReadStackValue(0, out nextAddress);
            }

            if (data[ldata.opcd_offset] == 0xFF && ldata.opcd_size == 1 && ldata.modrm != 0x00)
            {
                // let's parse ModRM!
                var  reg2       = (ldata.modrm & 0x38) >> 3;
                var  mod        = (ldata.modrm & 0xC0) >> 6;
                var  reg1       = (ldata.modrm & 0x7);
                bool addressSet = false;
                if (reg2 == 2)
                {
                    if (StepIntoCalls == false)
                    {
                        nextAddress = (uint)Context.Rip + ldata.size;
                        addressSet  = true;
                    }

                    Console.Write("RegOp tells me this is a CALL\r\n");
                }
                else if (reg2 == 4)
                {
                    Console.Write("RegOp tells me this is a JMP\r\n");
                }
                else
                {
                    nextAddress = (uint)Context.Rip + ldata.size;
                    addressSet  = true;
                }

                if (addressSet == false)
                {
                    if (reg1 == 4)
                    {
                        //txtFacts.Text += "Reg1 is a 4 which means there is a SIB byte\r\n";
                        var ss    = (ldata.sib & 0xC0) >> 6;
                        var index = (ldata.sib & 0x38) >> 3;
                        var Base  = (ldata.sib & 0x07);


                        int scale = (int)Math.Pow(2, ss);
                        nextAddress = (uint)GetRegisterByNumber(index) * (uint)scale;
                        if (Base == 5)
                        {
                            if (mod == 0)
                            {
                                nextAddress = (uint)((int)nextAddress + BitConverter.ToInt32(data, ldata.disp_offset));
                            }
                            else if (mod == 1)
                            {
                                nextAddress += GetRegisterByNumber(Base);
                                nextAddress  = (uint)((int)(nextAddress) + (sbyte)data[ldata.disp_offset]);
                            }
                            else if (mod == 2)
                            {
                                nextAddress += GetRegisterByNumber(Base);
                                nextAddress  = (uint)((int)nextAddress + BitConverter.ToInt32(data, ldata.disp_offset));
                            }
                        }
                    }
                    else
                    {
                        if (mod == 0)
                        {
                            if (reg1 != 5)
                            {
                                nextAddress = GetRegisterByNumber(reg1);
                            }
                            else
                            {
                                nextAddress = (uint)BitConverter.ToInt32(data, ldata.disp_offset);
                            }
                        }
                        else if (mod == 1)
                        {
                            nextAddress = GetRegisterByNumber(reg1);
                            nextAddress = (uint)((int)(nextAddress) + (sbyte)data[ldata.disp_offset]);
                        }
                        else if (mod == 2)
                        {
                            nextAddress = GetRegisterByNumber(reg1);
                            nextAddress = (uint)((int)nextAddress + BitConverter.ToInt32(data, ldata.disp_offset));
                        }
                    }
                    if (mod != 3)
                    {
                        //ReadDWORD(nextAddress, out nextAddress);
                    }

                    Console.WriteLine("Next Address: " + nextAddress.ToString("X8"));
                }
            }

            updateContext(getCurrentThreadId());
            SetBreakpoint(nextAddress);

            Continue();

            ClearBreakpoint(nextAddress);

            return(this);
        }