Example #1
0
        /// <summary>
        /// Seek backward n instructions from a target address
        /// </summary>
        /// <param name="address">target address</param>
        /// <param name="nInstructions">number of instructions</param>
        /// <returns> address - n on failure, else the address of an instruction n back from the target address</returns>
        public async Task <ulong> SeekBack(ulong address, int nInstructions)
        {
            ICollection <DisasmInstruction> ret = null;
            ulong defaultAddr = address >= (ulong)nInstructions ? address - (ulong)nInstructions : 0;

            lock (_disassemlyCache)
            {
                // check the cache, look for it to contain nInstructions back from the address
                var kv = _disassemlyCache.FirstOrDefault((p) => p.Value.TryFetch(address, -nInstructions, out ret));
                if (kv.Value != null)
                {
                    return(ret.First().Addr);
                }
            }
            ulong endAddress;
            ulong startAddress;
            var   range = await _process.FindValidMemoryRange(address, (uint)(_process.MaxInstructionSize * (nInstructions + 1)), (int)(_process.MaxInstructionSize * -nInstructions));

            startAddress = range.Item1;
            endAddress   = range.Item2;
            if (endAddress - startAddress == 0 || address < startAddress) // bad address range, no instructions
            {
                return(defaultAddr);
            }
            lock (_disassemlyCache)
            {
                // check the cache with the adjusted range
                var kv = _disassemlyCache.FirstOrDefault((p) => p.Value.TryFetch(startAddress, address < endAddress ? address : endAddress, out ret));
            }
            if (ret == null)
            {
                DisasmInstruction[] instructions = await Disassemble(_process, startAddress, endAddress);

                if (instructions == null)
                {
                    return(defaultAddr);    // unknown error condition
                }

                // when seeking back require that the disassembly contain an instruction at the target address (x86 has varying length instructions)
                instructions = await VerifyDisassembly(instructions, startAddress, endAddress, address);

                ret = UpdateCache(address, -nInstructions, instructions);
                if (ret == null)
                {
                    return(defaultAddr);
                }
            }

            int nLess = ret.Count((i) => i.Addr < address);

            if (nLess < nInstructions)
            {
                // not enough instructions were fetched; back up one byte for each missing instruction
                return(ret.First().Addr < (ulong)(nInstructions - nLess) ? 0 : (ulong)((long)ret.First().Addr - (nInstructions - nLess)));
            }
            else
            {
                return(ret.First().Addr);
            }
        }