Exemplo n.º 1
0
        /// <summary>
        /// Injects instructions at the specified location, overwriting following instructions. This will nop-fill.
        /// </summary>
        /// <param name="address">The injection address.</param>
        /// <param name="assembly">The assembly code to disassemble and inject into the code cave.</param>
        /// <returns>The address of the code cave.</returns>
        public UInt64 InjectCode(UInt64 address, String assembly)
        {
            this.PrintDebugTag();

            assembly = this.ResolveKeywords(assembly);

            Int32 assemblySize = this.GetAssemblySize(assembly, address);

            Byte[] originalBytes = this.CollectOriginalBytes(address, assemblySize);

            if (originalBytes == null)
            {
                throw new Exception("Could not gather original bytes");
            }

            // Determine number of no-ops to fill dangling bytes
            String noOps = (originalBytes.Length - assemblySize > 0 ? "db " : String.Empty) + String.Join(" ", Enumerable.Repeat("0x90,", originalBytes.Length - assemblySize)).TrimEnd(',');

            Byte[] injectionBytes = this.GetAssemblyBytes(assembly + "\n" + noOps, address);
            EngineCore.GetInstance().VirtualMemory.WriteBytes(address.ToIntPtr(), injectionBytes);

            CodeCave codeCave = new CodeCave(address, 0, originalBytes);

            this.CodeCaves.Add(codeCave);

            return(address);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates a code cave that jumps from a given entry address and executes the given assembly. This will nop-fill.
        /// If the injected assmebly code fits in one instruction, no cave will be created.
        /// </summary>
        /// <param name="address">The injection address.</param>
        /// <param name="assembly">The assembly code to disassemble and inject into the code cave.</param>
        /// <returns>The address of the code cave. Returns zero if no allocation was necessary.</returns>
        public UInt64 CreateCodeCave(UInt64 address, String assembly)
        {
            this.PrintDebugTag();

            assembly = this.ResolveKeywords(assembly);

            // Determine size of our injected code
            Int32 assemblySize = this.GetAssemblySize(assembly, address);

            // Determine the minimum number of bytes that need to be replaced
            Int32 minimumReplacementSize = Math.Min(assemblySize, MemoryCore.JumpSize);

            // Gather the original bytes
            Byte[] originalBytes = this.CollectOriginalBytes(address, minimumReplacementSize);

            // Handle case where allocation is not needed
            if (assemblySize <= originalBytes.Length)
            {
                // Determine number of no-ops to fill dangling bytes
                String noOps = assemblySize - originalBytes.Length > 0 ? "db " + String.Join(" ", Enumerable.Repeat("0x90,", assemblySize - originalBytes.Length)).TrimEnd(',') : String.Empty;

                Byte[] injectionBytes = this.GetAssemblyBytes(assembly + Environment.NewLine + noOps, address);
                this.Write(address, injectionBytes);

                CodeCave codeCave = new CodeCave(address, 0, originalBytes);
                this.CodeCaves.Add(codeCave);

                return(address);
            }
            else
            {
                // Determine number of no-ops to fill dangling bytes
                String noOps = originalBytes.Length - minimumReplacementSize > 0 ? "db " + String.Join(" ", Enumerable.Repeat("0x90,", originalBytes.Length - minimumReplacementSize)).TrimEnd(',') : String.Empty;

                // Add code cave jump return automatically
                UInt64 returnAddress = this.GetCaveExitAddress(address);

                // Place jump to return address
                assembly = assembly.Trim()
                           + Environment.NewLine
                           + "jmp " + Conversions.ToHex(returnAddress, formatAsAddress: false, includePrefix: true);
                assemblySize = this.GetAssemblySize(assembly, address);

                // Allocate memory
                UInt64 remoteAllocation;
                if (EngineCore.GetInstance().Processes.IsOpenedProcess32Bit())
                {
                    remoteAllocation = this.Allocate(assemblySize);
                }
                else
                {
                    remoteAllocation = this.Allocate(assemblySize, address);
                }

                // Write injected code to new page
                Byte[] injectionBytes = this.GetAssemblyBytes(assembly, remoteAllocation);
                this.Write(remoteAllocation, injectionBytes);

                // Write in the jump to the code cave
                String codeCaveJump = ("jmp " + Conversions.ToHex(remoteAllocation, formatAsAddress: false, includePrefix: true) + Environment.NewLine + noOps).Trim();
                Byte[] jumpBytes    = this.GetAssemblyBytes(codeCaveJump, address);
                this.Write(address, jumpBytes);

                // Save this code cave for later deallocation
                CodeCave codeCave = new CodeCave(address, remoteAllocation, originalBytes);
                this.CodeCaves.Add(codeCave);

                return(remoteAllocation);
            }
        }