Example #1
0
        private static void TestSizeComputation(byte[] opcodes)
        {
            var reader       = new MemoryStreamReader(opcodes);
            var disassembler = new X86Disassembler(reader);

            while (reader.Position < reader.Length)
            {
                var instruction = disassembler.ReadNextInstruction();

                var expectedSize = reader.Position - instruction.Offset;
                var computeSize  = instruction.ComputeSize();

                if (expectedSize != computeSize)
                {
                    Assert.Fail("The instruction {0} has size {1}, but {2} was computed.", instruction, expectedSize,
                                computeSize);
                }
            }
        }
Example #2
0
        public HookParameters Detect(HookSession session, IntPtr address)
        {
            var fixups = new List <ushort>();

            // Longest x86 instruction possible is 15 bytes. We need 5 bytes at least for a call.
            // Therefore, in the worst case scenario, we need to read 4 + 15 bytes worth of instructions.

            var reader       = new MemoryStreamReader(session.ReadMemory(address, 4 + 15));
            var disassembler = new X86Disassembler(reader, address.ToInt64());

            while (reader.Position - reader.StartPosition < 5)
            {
                var next = disassembler.ReadNextInstruction();
                if (next.OpCode.Op1 == X86OpCodes.Jmp_Rel1632.Op1 ||
                    next.OpCode.Op1 == X86OpCodes.Call_Rel1632.Op1)
                {
                    int offset = (int)(reader.Position - address.ToInt64() - 4);
                    fixups.Add((ushort)offset);
                }
            }

            return(new HookParameters((int)reader.Position, fixups));
        }
Example #3
0
        /*
         *  Byte[] asm = { 0xE8, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x00, 0xA1, 0xC0, 0x00, 0x00, 0x00 };
         *  X86Disassembler d = new X86Disassembler(new MemoryStreamReader(asm));
         *  X86Instruction i = d.ReadNextInstruction();
         *  i = d.ReadNextInstruction();
         *  i = d.ReadNextInstruction();
         */

        private static void LoadWadFiles(IntPtr function1Address, int funcOffset, IntPtr functionAddress, IntPtr ECDSA)
        {
            uint functionLength;
            uint functionLength1;
            uint ECDSALen;

            MemoryEditor.FindPattern(@"\xC2\x04\x00\xCC", "xxxx", ECDSA, out ECDSALen);
            MemoryEditor.FindPattern(@"\xC2\x08\x00\xCC", "xxxx", functionAddress, out functionLength);
            MemoryEditor.FindPattern(@"\xC3\x57\xE8\x00\x00\x00\x00\xCC", "xxx????x", function1Address, out functionLength1);
            functionLength  = (functionLength - (uint)functionAddress) + 4;
            ECDSALen        = (ECDSALen - (uint)ECDSA) + 4;
            functionLength1 = (functionLength1 - (uint)function1Address) + 8;
            //Steal the function:
            Byte[] asmECDSA;
            MemoryEditor.ReadBytes(ECDSA, (int)ECDSALen, out asmECDSA);
            Byte[] asm1;
            MemoryEditor.ReadBytes(function1Address, (int)functionLength1, out asm1);
            Byte[] asm;
            MemoryEditor.ReadBytes(functionAddress, (int)functionLength, out asm);
            //Allocate and copy the function to our new memory
            IntPtr AllocatedMemory = MemoryEditor.AllocateMemory(0x1000);
            //MemoryEditor.WriteBytes(AllocatedMemory, asm);
            //Fix the bytecode for the new offsets:
            X86Disassembler disassembler = new X86Disassembler(new MemoryStreamReader(asmECDSA));

            while (disassembler.BaseStream.Position != disassembler.BaseStream.Length)
            {
                X86Instruction instruction = disassembler.ReadNextInstruction();
                if (instruction.Mnemonic == X86Mnemonic.Je && instruction.Offset == 0x49)
                {
                    Buffer.BlockCopy(new Byte[] { 0x90, 0x90 }, 0, asmECDSA, (int)instruction.Offset, 2);
                    continue;
                }
                if (instruction.Mnemonic != X86Mnemonic.Call || (instruction.Operand1 != null && instruction.Operand1.OperandUsage == X86OperandUsage.DwordPointer))
                {
                    continue;
                }

                if (instruction.Operand1.Value.ToString() == "Eax")
                {
                    continue;
                }
                //Fix the Call:
                int offset;
                MemoryEditor.ReadInt(ECDSA + (int)instruction.Offset + 1, out offset);
                int callAddress = (5 + (int)instruction.Offset + (int)ECDSA) + offset;
                offset = callAddress - ((int)AllocatedMemory + (int)instruction.Offset + 5);
                Buffer.BlockCopy(BitConverter.GetBytes(offset), 0, asmECDSA, (int)instruction.Offset + 1, 4);
            }

            MemoryEditor.WriteBytes(AllocatedMemory, asmECDSA);
            AllocatedMemory += asmECDSA.Length;

            disassembler = new X86Disassembler(new MemoryStreamReader(asm));
            while (disassembler.BaseStream.Position != disassembler.BaseStream.Length)
            {
                X86Instruction instruction = disassembler.ReadNextInstruction();

                /*if (instruction.Mnemonic == X86Mnemonic.Jne)
                 * {
                 *  Buffer.BlockCopy(new Byte[] { 0xEB }, 0, asm, (int)instruction.Offset, 1);
                 *  continue;
                 * }*/

                if (instruction.Mnemonic != X86Mnemonic.Call || (instruction.Operand1 != null && instruction.Operand1.OperandUsage == X86OperandUsage.DwordPointer))
                {
                    continue;
                }

                if (instruction.Offset == 0x128)
                {
                    Buffer.BlockCopy(BitConverter.GetBytes(((int)AllocatedMemory - asmECDSA.Length) - ((int)AllocatedMemory + (int)instruction.Offset + 5))
                                     , 0, asm, (int)instruction.Offset + 1, 4);
                    continue;
                }
                //Fix the Call:
                int offset;
                MemoryEditor.ReadInt(functionAddress + (int)instruction.Offset + 1, out offset);
                int callAddress = (5 + (int)instruction.Offset + (int)functionAddress) + offset;
                offset = callAddress - ((int)AllocatedMemory + (int)instruction.Offset + 5);
                Buffer.BlockCopy(BitConverter.GetBytes(offset), 0, asm, (int)instruction.Offset + 1, 4);
            }

            MemoryEditor.WriteBytes(AllocatedMemory, asm);
            AllocatedMemory += asm.Length;

            disassembler = new X86Disassembler(new MemoryStreamReader(asm1));
            while (disassembler.BaseStream.Position != disassembler.BaseStream.Length)
            {
                X86Instruction instruction = disassembler.ReadNextInstruction();

                if (instruction.Mnemonic != X86Mnemonic.Call || (instruction.Operand1 != null && instruction.Operand1.OperandUsage == X86OperandUsage.DwordPointer))
                {
                    continue;
                }

                if (instruction.Offset == funcOffset)
                {
                    Buffer.BlockCopy(BitConverter.GetBytes(((int)AllocatedMemory - asm.Length) - ((int)AllocatedMemory + (int)instruction.Offset + 5))
                                     , 0, asm1, (int)instruction.Offset + 1, 4);
                    continue;
                }

                //Fix the Call:
                int offset;
                MemoryEditor.ReadInt(function1Address + (int)instruction.Offset + 1, out offset);
                int callAddress = (5 + (int)instruction.Offset + (int)function1Address) + offset;
                offset = callAddress - ((int)AllocatedMemory + (int)instruction.Offset + 5);
                Buffer.BlockCopy(BitConverter.GetBytes(offset), 0, asm1, (int)instruction.Offset + 1, 4);
            }
            MemoryEditor.WriteBytes(AllocatedMemory, asm1);
            IntPtr LoadWadFunction = AllocatedMemory;

            AllocatedMemory += asm1.Length;
            //Allocate Variables
            IntPtr StringAddress = AllocatedMemory + 0x10;

            //0x38 for failedFunctionCallback
            AllocatedMemory = StringAddress + 0x110;
            byte[] customAsm =
            {
                0x60, //pushad
                0x6A, 0x00,
                0x68, 0x00, 0x00, 0x00, 0x00,
                0xE8, 0x00, 0x00, 0x00, 0x00,
                0x5B,      //pop x2,
                0x5B,
                0x61,      //popad
                0xEB, 0xFE //Endless Loop so we know to correct the EIP
            };
            Buffer.BlockCopy(BitConverter.GetBytes((uint)StringAddress), 0, customAsm, 0x4, 4);
            Buffer.BlockCopy(BitConverter.GetBytes((uint)LoadWadFunction - ((uint)AllocatedMemory + 0xD)), 0, customAsm, 0x9, 4);
            MemoryEditor.WriteBytes(AllocatedMemory, customAsm);

            int lockedEip = (int)AllocatedMemory + customAsm.Length - 2;

            MemoryEditor.Suspend();
            MemoryEditor.Context context = MemoryEditor.GetThreadContext();
            uint originalEip             = context.Eip;

            //Load Each WADFile:
            foreach (String wadFile in WadFiles)
            {
                MemoryEditor.Suspend();
                context.Eip = (uint)AllocatedMemory;
                MemoryEditor.SetThreadContext(context);
                MemoryEditor.WriteNullTerminatedString(StringAddress, wadFile);
                MemoryEditor.Resume();
                //NOTE: THE CODE HAS TO RUN ON MAIN THREAD TO PROPERLY LOAD WADS
                //MemoryEditor.WaitForSingleObject(MemoryEditor.CreateRemoteThread(AllocatedMemory, IntPtr.Zero));
                bool loop = true;
                while (loop)
                {
                    context = MemoryEditor.GetThreadContext();
                    loop    = context.Eip != lockedEip;
                    MemoryEditor.Resume();
                }
            }
            context.Eip = originalEip;
            MemoryEditor.SetThreadContext(context);
            MemoryEditor.FreeMemory(AllocatedMemory);
        }
Example #4
0
 public DisassemblerInfo(ProcessMemoryReader reader)
 {
     Reader       = reader;
     Disassembler = new X86Disassembler(reader);
 }