Exemplo n.º 1
0
        public static void TraceIt(Process process, ulong patchSite, Logger logger, bool debug, Action <Process, ulong, Logger> installTracer)
        {
            if (debug)
            {
                if (!Win32Imports.DebugActiveProcess(process.Id))
                {
                    throw new Win32Exception();
                }

                if (!Win32Imports.DebugSetProcessKillOnExit(false))
                {
                    throw new Win32Exception();
                }
            }
            foreach (ProcessThread thread in process.Threads)
            {
                var threadId = thread.Id;
                var context  = new Win32Imports.ContextX64();
                ContextManager.getRip((uint)threadId, ref context, ContextManager.GetRipAction.ActionSuspend);
            }

            Console.WriteLine("installing tracer");
            installTracer(process, patchSite, logger);

            var mainThread = 0;

            foreach (ProcessThread thread in process.Threads)
            {
                var threadId     = thread.Id;
                var context      = new Win32Imports.ContextX64();
                var breakAddress = ContextManager.getRip((uint)threadId, ref context, ContextManager.GetRipAction.ActionGetContext);
                var diff         = new BigInteger(breakAddress) - new BigInteger(patchSite);
                diff = diff < 0 ? -diff : diff;
                if (diff < 1000)
                {
                    mainThread = threadId;
                    logger.WriteLine($"thread {threadId} setting Rip to patch site: {patchSite:X}");
                    ContextManager.setRip((uint)threadId, false, patchSite);
                    if (debug)
                    {
                        ContextManager.setTrace((uint)threadId, false);
                    }
                }
                ContextManager.getRip((uint)threadId, ref context, ContextManager.GetRipAction.ActionResume);
            }

            /*if (!Win32Imports.DebugBreakProcess(process.Id)) {
             *  throw new Win32Exception();
             * }*/

            if (debug)
            {
                Dictionary <int, OldState> oldThreadState = new Dictionary <int, OldState>();
                try {
                    while (true)
                    {
                        Win32Imports.DebugEvent evt;
                        if (Win32Imports.WaitForDebugEvent(out evt, -1))
                        {
                            Console.WriteLine($"debug event {evt.dwDebugEventCode}");
                            var continueCode = Win32Imports.DbgContinue;
                            if (evt.dwDebugEventCode == Win32Imports.DebugEventType.ExceptionDebugEvent && evt.dwThreadId == mainThread)
                            {
                                var exceptionAddress = (ulong)evt.Exception.ExceptionRecord.ExceptionAddress.ToInt64();
                                var context          = new Win32Imports.ContextX64();
                                var breakAddress     = ContextManager.getRip((uint)evt.dwThreadId, ref context, ContextManager.GetRipAction.ActionGetContext);
                                var code             = evt.Exception.ExceptionRecord.ExceptionCode;
                                Console.WriteLine($"thread {evt.dwThreadId} break at 0x{exceptionAddress:X} code {code}, 0x{breakAddress:X}");
                                ContextManager.setTrace((uint)evt.dwThreadId);

                                var instr      = AssemblyUtil.Disassemble(process, exceptionAddress);
                                var asm        = AssemblyUtil.FormatInstruction(instr);
                                var strContext = oldThreadState.ContainsKey(evt.dwThreadId) ?
                                                 AssemblyUtil.FormatContextDiff(context, oldThreadState[evt.dwThreadId].Context, oldThreadState[evt.dwThreadId].Instruction) :
                                                 AssemblyUtil.FormatContext(context);
                                logger.WriteLine($"thread {evt.dwThreadId} break at 0x{exceptionAddress:X}, 0x{breakAddress:X} code {code}: {asm}, regs-1: {strContext}");

                                oldThreadState[evt.dwThreadId] = new OldState {
                                    Context     = context,
                                    Instruction = instr
                                };

                                if (code == Win32Imports.ExceptionCodeStatus.ExceptionAccessViolation)
                                {
                                    continueCode = Win32Imports.DbgExceptionNotHandled;
                                }
                            }

                            if (!Win32Imports.ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continueCode))
                            {
                                throw new Win32Exception();
                            }
                        }
                    }
                }
                finally {
                    if (!Win32Imports.DebugActiveProcessStop(process.Id))
                    {
                        throw new Win32Exception();
                    }
                }
            }
        }