View Single Post
  #8  
Old 07-04-2018, 11:34
cachito cachito is offline
Friend
 
Join Date: Aug 2015
Location: argentina
Posts: 58
Rept. Given: 0
Rept. Rcvd 12 Times in 8 Posts
Thanks Given: 162
Thanks Rcvd at 81 Times in 44 Posts
cachito Reputation: 13
I made this loader/debugger long ago for a simple target, but never finished it. It worked for native x64 targets. I don't know if setting 0x01 (bp il opcode) will fire up the ExceptionCode.STATUS_BREAKPOINT. I tried to follow here https://github.com/dotnet/coreclr/blob/master/src/vm/excep.cpp but I am a very bad coder...


Code:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Microsoft.Samples.Debugging.Native;

namespace Test2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        #region WinNT Definitions
        private const uint CONTEXT_FULL = 0x10007;
        private const ushort IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ
        private const uint IMAGE_NT_SIGNATURE = 0x00004550; // PE00

        private static short SW_SHOWNORMAL = 1;
        private const uint STARTF_USESTDHANDLES = 0x00000100;
        private const uint STARTF_USESHOWWINDOW = 0x00000001;
        private CreateProcessFlags flags;
        #endregion

        private void button1_Click(object sender, EventArgs e)
        {
            // PART 1 !!!!!
            STARTUPINFO si = new STARTUPINFO();
            si.cb = Marshal.SizeOf(si);

            flags = CreateProcessFlags.DEBUG_ONLY_THIS_PROCESS | CreateProcessFlags.CREATE_SUSPENDED;

            PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
            CreateProcess(@"test.exe", null, IntPtr.Zero, IntPtr.Zero, false, flags, IntPtr.Zero, null, si, pi);

            // Taken from Kao's solution in part 1 :)

            PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
            int d;
            NtQueryInformationProcess(pi.hProcess, 0, ref pbi, Marshal.SizeOf(pbi), out d);

            byte[] dummy2 = new byte[8];
            int dummy;
            // in 64bit OS, main module imagebase is at PEB+0x10
            ReadProcessMemory(pi.hProcess, new IntPtr((Int64)pbi.PebBaseAddress + 0x10), dummy2, (UIntPtr)8, out dummy);
            Int64 realImageBase = BitConverter.ToInt64(dummy2, 0);

            textBox1.Text = realImageBase.ToString("X2");

            // STARTUPINFO
            STARTUPINFO StartupInfo = new STARTUPINFO();
            StartupInfo.dwFlags = (int)(STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
            StartupInfo.wShowWindow = SW_SHOWNORMAL;

            /*var IMAGE_SECTION_HEADER = new byte[0x28]; // pish
            var IMAGE_NT_HEADERS = new byte[0xf8]; // pinh
            var IMAGE_DOS_HEADER = new byte[0x40]; // pidh
            var PROCESS_INFO = new int[0x4]; // pi

            byte* pish;
            fixed (byte* p = &IMAGE_SECTION_HEADER[0]) pish = p;

            byte* pinh;
            fixed (byte* p = &IMAGE_NT_HEADERS[0]) pinh = p;

            byte* pidh;
            fixed (byte* p = &IMAGE_DOS_HEADER[0]) pidh = p;

            // Get the DOS header of the EXE.
            ReadProcessMemory(pi.hProcess, new IntPtr(realImageBase), IMAGE_DOS_HEADER, (UIntPtr)IMAGE_DOS_HEADER.Length, out dummy);

            // Sanity check:  See if we have MZ header.
            if (*(ushort*)(pidh + 0x0) != IMAGE_DOS_SIGNATURE)
                MessageBox.Show("Bad MZ header");

            var e_lfanew = *(int*)(pidh + 0x3c);

            textBox2.Text = e_lfanew.ToString("X2");

            // Get the NT header of the EXE.
            ReadProcessMemory(pi.hProcess, new IntPtr(realImageBase + e_lfanew), IMAGE_NT_HEADERS, (UIntPtr)IMAGE_NT_HEADERS.Length, out dummy);

            // Sanity check: See if we have PE00 header.
            if (*(uint*)(pinh + 0x0) != IMAGE_NT_SIGNATURE)
                MessageBox.Show("Bad PE00 header");

            var AddressOfEntryPoint = *(int*)(pinh + 0x28);

            textBox3.Text = AddressOfEntryPoint.ToString("X2");

            byte[] OEPData = new byte[9];
            ReadProcessMemory(pi.hProcess, new IntPtr(realImageBase + AddressOfEntryPoint), OEPData, (UIntPtr)9, out dummy);

            textBox4.Text = BitConverter.ToString(OEPData).Replace("-", "");*/

            // PART 2 !!!!!

            var buffer = new byte[1] { 0xCC };
            var origIN_OUT = new byte[1] { 0x48 };
            var dummy4 = new UIntPtr();
            byte[] buffer2 = new byte[5];

            WriteProcessMemory(pi.hProcess, new IntPtr(realImageBase + 0x1B1AA4), buffer, (UIntPtr)1, out dummy4);
            WriteProcessMemory(pi.hProcess, new IntPtr(realImageBase + 0x1B1AA9), buffer, (UIntPtr)1, out dummy4);

            ContinueStatus dwContinueStatus = ContinueStatus.DBG_CONTINUE;
            DebugEvent64 event64 = new DebugEvent64();

            ResumeThread(pi.hThread);

            bool continuar = true;
            while (continuar)
            {
                if (!WaitForDebugEvent64(ref event64, -1))
                {
                    MessageBox.Show("Debug loop aborted");
                    return;
                }

                switch (event64.header.dwDebugEventCode)
                {
                    case NativeDebugEventCode.EXIT_PROCESS_DEBUG_EVENT:
                        CloseHandle(pi.hThread);
                        CloseHandle(pi.hProcess);
                        return;

                    case NativeDebugEventCode.EXCEPTION_DEBUG_EVENT:
                        {
                            EXCEPTION_DEBUG_INFO exception = event64.union.Exception;

                            switch (exception.ExceptionRecord.ExceptionCode)
                            {
                                case ExceptionCode.STATUS_BREAKPOINT:
                                    {
                                        SuspendThread(pi.hThread); // Always suspend target before getting context or you will get bad data

                                        CONTEXT64 context = new CONTEXT64(); // Create a new Context64 struct.
                                        context.ContextFlags = ContextFlags.AMD64ContextAll;

                                        if (!GetThreadContext(pi.hThread, ref context)) // Read thread context
                                            MessageBox.Show("There was a problem getting context");

                                        if (context.Rip == (ulong)(realImageBase + 0x1B1AA4 + 1)) // Compare in BP
                                        {
                                            context.Rip -= 1; // Change EIP to -1
                                            if (!SetThreadContext(pi.hThread, ref context)) // Update changed context
                                                MessageBox.Show("There was a problem setting context");

                                            // Do the stuff
                                            MessageBox.Show("Message box open");

                                            WriteProcessMemory(pi.hProcess, new IntPtr(realImageBase + 0x1B1AA4), origIN_OUT, (UIntPtr)1, out dummy4); // Set original bytes to resume process

                                        }
                                        if (context.Rip == (ulong)(realImageBase + 0x1B1AA9 + 1)) // Compare out BP
                                        {
                                            context.Rip -= 1; // Change EIP to -1
                                            if (!SetThreadContext(pi.hThread, ref context)) // Update changed context
                                                MessageBox.Show("There was a problem setting context");

                                            // Do the stuff
                                            MessageBox.Show("Message box closed");

                                            WriteProcessMemory(pi.hProcess, new IntPtr(realImageBase + 0x1B1AA9), origIN_OUT, (UIntPtr)1, out dummy4); // Set original bytes to resume process
                                        }

                                        ResumeThread(pi.hThread); // Resume target

                                        await Task.Delay(200); // Small delay before putting BPs back or they might get hit more than once
                                        break;
                                    }

                                default:
                                    {
                                        dwContinueStatus = ContinueStatus.DBG_EXCEPTION_NOT_HANDLED;
                                        break;
                                    }
                            }
                            break;
                        }

                }
                if (!ContinueDebugEvent(event64.header.dwProcessId, event64.header.dwThreadId, dwContinueStatus))
                    MessageBox.Show("Error continuing debug event");

                // Reset
                dwContinueStatus = ContinueStatus.DBG_CONTINUE;

                // Set BPs again
                WriteProcessMemory(pi.hProcess, new IntPtr(realImageBase + 0x1B1AA4), buffer, (UIntPtr)1, out dummy4);
                WriteProcessMemory(pi.hProcess, new IntPtr(realImageBase + 0x1B1AA9), buffer, (UIntPtr)1, out dummy4);
            }
        }

    }
}
Reply With Quote
The Following 2 Users Say Thank You to cachito For This Useful Post:
chants (08-26-2018), taos (07-04-2018)