2015-03-11 6 views
5

मैं एक तरह से एक निश्चित पते के इस सवाल में पूछा की तरह पर EDX रजिस्ट्री को पढ़ने के लिए देख रहा हूँ: Read eax registerस्वचालित रूप से सी # कोड से एक डिबग प्रक्रिया और रजिस्टर पढ़ें मूल्यों

हालांकि मेरी समाधान सी # में होने की जरूरत है और मैं इसे करने की कोशिश की, क्या मैं इस समय मिल गया है:

public static IntPtr GetEdx(IntPtr address, Process process) 
    { 
     const uint DBG_EXCEPTION_NOT_HANDLED = 0x80010001; 
     const uint EXCEPTION_SINGLE_STEP = 0x80000004; 
     const int DBG_CONTINUE = 0x00010002; // Seems to work better than DBG_EXCEPTION_NOT_HANDLED 

     //DebugSetProcessKillOnExit(0); 
     DEBUG_EVENT evt = new DEBUG_EVENT(); 
     // Attach to the process we provided the thread as an argument 
     if (!DebugActiveProcess(process.Id)) 
      throw new Win32Exception(); 

     CONTEXT context = new CONTEXT(); 

     foreach (ProcessThread thread in process.Threads) 
     { 
      uint iThreadId = (uint)thread.Id; 
      IntPtr hThread = 
       OpenThread(
        ThreadAccessFlags.SUSPEND_RESUME | ThreadAccessFlags.SET_CONTEXT | 
        ThreadAccessFlags.GET_CONTEXT, false, iThreadId); 

      // Suspent the thread 
      if (SuspendThread(hThread) == -1) throw new ApplicationException("Cannot suspend thread."); 

      context = new CONTEXT 
      { 
       ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_DEBUG_REGISTERS | 
           (uint)CONTEXT_FLAGS.CONTEXT_INTEGER 
      }; 

      // Get the context 
      if (!GetThreadContext(hThread, ref context)) 
       throw new Win32Exception(); 

      // Change the context 

      context.Dr0 = (uint)address; 
      context.Dr7 = 0x00000001; 

      // Set the changed context back 
      if (!SetThreadContext(hThread, ref context)) 
       throw new Win32Exception(); 

      // Check if setting the context give any errors 
      var error = Marshal.GetLastWin32Error(); 
      if (error != 0) 
      { 
       throw new ApplicationException("Error is setting context."); 
      } 

      // Resume the thread 
      if (ResumeThread(hThread) == -1) throw new ApplicationException("Cannot resume thread."); 
     } 

     while (true) 
     { 
      if (!WaitForDebugEvent(out evt, -1)) 
       throw new Win32Exception(); 

      // Multiple if's for easier debugging at this moment 
      if (evt.dwDebugEventCode == (uint)DebugEventType.EXCEPTION_DEBUG_EVENT) 
      { 
       if (evt.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) 
       { 
        if (evt.Exception.ExceptionRecord.ExceptionAddress == address) 
        { 
         context = new CONTEXT 
         { 
          ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_DEBUG_REGISTERS | 
              (uint)CONTEXT_FLAGS.CONTEXT_INTEGER 
         }; 
         GetThreadContext((IntPtr)evt.dwThreadId, ref context); 
         return (IntPtr)context.Ebx; // ebx get 
        } 
       } 
      } 

      ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, DBG_CONTINUE);//DBG_EXCEPTION_NOT_HANDLED); 
     } 
    } 
Kernel32 तरीकों की एक पूरी बहुत कुछ के साथ

:

[DllImport("kernel32.dll")] 
    static extern int ResumeThread(IntPtr hThread); 
    [DllImport("kernel32.dll")] 
    static extern uint SuspendThread(IntPtr hThread); 
    [DllImport("kernel32.dll")] 
    public static extern IntPtr OpenThread(ThreadAccessFlags dwDesiredAccess, bool bInheritHandle, uint dwThreadId); 
    [DllImport("Kernel32.dll", SetLastError = true)] 
    static extern bool DebugActiveProcess(int dwProcessId); 
    [DllImport("Kernel32.dll", SetLastError = true)] 
    static extern bool WaitForDebugEvent([Out] out DEBUG_EVENT lpDebugEvent, int dwMilliseconds); 
    [DllImport("Kernel32.dll", SetLastError = true)] 
    static extern bool ContinueDebugEvent(int dwProcessId, int dwThreadId, uint dwContinueStatus); 
    [DllImport("Kernel32.dll", SetLastError = true)] 
    public static extern bool IsDebuggerPresent(); 
    [DllImport("kernel32.dll")] 
    private static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT lpContext); 
    [DllImport("kernel32.dll")] 
    public static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT lpContext); 

    [StructLayout(LayoutKind.Sequential)] 
    public unsafe struct DEBUG_EVENT 
    { 
     public readonly uint dwDebugEventCode; 
     public readonly int dwProcessId; 
     public readonly int dwThreadId; 


     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 86, ArraySubType = UnmanagedType.U1)] 
     private readonly byte[] debugInfo; 


     public EXCEPTION_DEBUG_INFO Exception 
     { 
      get 
      { 
       if (debugInfo == null) 
        return new EXCEPTION_DEBUG_INFO(); 


       fixed (byte* ptr = debugInfo) 
       { 
        return *(EXCEPTION_DEBUG_INFO*)ptr; 
       } 
      } 
     } 


     public LOAD_DLL_DEBUG_INFO LoadDll 
     { 
      get 
      { 
       if (debugInfo == null) 
        return new LOAD_DLL_DEBUG_INFO(); 


       fixed (byte* ptr = debugInfo) 
       { 
        return *(LOAD_DLL_DEBUG_INFO*)ptr; 
       } 
      } 
     } 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct LOAD_DLL_DEBUG_INFO 
    { 
     public readonly IntPtr hFile; 
     public readonly IntPtr lpBaseOfDll; 
     public readonly uint dwDebugInfoFileOffset; 
     public readonly uint nDebugInfoSize; 
     public readonly IntPtr lpImageName; 
     public readonly ushort fUnicode; 
    } 


    [StructLayout(LayoutKind.Sequential)] 
    public struct EXCEPTION_DEBUG_INFO 
    { 
     public EXCEPTION_RECORD ExceptionRecord; 
     public readonly uint dwFirstChance; 
    } 


    [StructLayout(LayoutKind.Sequential)] 
    public struct EXCEPTION_RECORD 
    { 
     public readonly uint ExceptionCode; 
     public readonly uint ExceptionFlags; 
     public readonly IntPtr ExceptionRecord; 
     public readonly IntPtr ExceptionAddress; 
     public readonly uint NumberParameters; 


     //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15, ArraySubType = UnmanagedType.U4)] 
     //public readonly uint[] ExceptionInformation; 


     public unsafe fixed uint ExceptionInformation[15]; 
    } 


    public enum DebugEventType : int 
    { 
     CREATE_PROCESS_DEBUG_EVENT = 3, //Reports a create-process debugging event. The value of u.CreateProcessInfo specifies a CREATE_PROCESS_DEBUG_INFO structure. 
     CREATE_THREAD_DEBUG_EVENT = 2, //Reports a create-thread debugging event. The value of u.CreateThread specifies a CREATE_THREAD_DEBUG_INFO structure. 
     EXCEPTION_DEBUG_EVENT = 1, //Reports an exception debugging event. The value of u.Exception specifies an EXCEPTION_DEBUG_INFO structure. 
     EXIT_PROCESS_DEBUG_EVENT = 5, //Reports an exit-process debugging event. The value of u.ExitProcess specifies an EXIT_PROCESS_DEBUG_INFO structure. 
     EXIT_THREAD_DEBUG_EVENT = 4, //Reports an exit-thread debugging event. The value of u.ExitThread specifies an EXIT_THREAD_DEBUG_INFO structure. 
     LOAD_DLL_DEBUG_EVENT = 6, //Reports a load-dynamic-link-library (DLL) debugging event. The value of u.LoadDll specifies a LOAD_DLL_DEBUG_INFO structure. 
     OUTPUT_DEBUG_STRING_EVENT = 8, //Reports an output-debugging-string debugging event. The value of u.DebugString specifies an OUTPUT_DEBUG_STRING_INFO structure. 
     RIP_EVENT = 9, //Reports a RIP-debugging event (system debugging error). The value of u.RipInfo specifies a RIP_INFO structure. 
     UNLOAD_DLL_DEBUG_EVENT = 7, //Reports an unload-DLL debugging event. The value of u.UnloadDll specifies an UNLOAD_DLL_DEBUG_INFO structure. 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct CONTEXT 
    { 
     public uint ContextFlags; 
     public uint Dr0; 
     public uint Dr1; 
     public uint Dr2; 
     public uint Dr3; 
     public uint Dr6; 
     public uint Dr7; 
     public FLOATING_SAVE_AREA FloatSave; 
     public uint SegGs; 
     public uint SegFs; 
     public uint SegEs; 
     public uint SegDs; 
     public uint Edi; 
     public uint Esi; 
     public uint Ebx; 
     public uint Edx; 
     public uint Ecx; 
     public uint Eax; 
     public uint Ebp; 
     public uint Eip; 
     public uint SegCs; 
     public uint EFlags; 
     public uint Esp; 
     public uint SegSs; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] 
     public byte[] ExtendedRegisters; 
    } 

    public enum CONTEXT_FLAGS : uint 
    { 
     CONTEXT_i386 = 0x10000, 
     CONTEXT_i486 = 0x10000, 
     CONTEXT_CONTROL = CONTEXT_i386 | 0x01, 
     CONTEXT_INTEGER = CONTEXT_i386 | 0x02, 
     CONTEXT_SEGMENTS = CONTEXT_i386 | 0x04, 
     CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08, 
     CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10, 
     CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20, 
     CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS, 
     CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS 
    } 

    [Flags] 
    public enum ThreadAccessFlags : int 
    { 
     TERMINATE = 0x0001, 
     SUSPEND_RESUME = 0x0002, 
     GET_CONTEXT = 0x0008, 
     SET_CONTEXT = 0x0010, 
     SET_INFORMATION = 0x0020, 
     QUERY_INFORMATION = 0x0040, 
     SET_THREAD_TOKEN = 0x0080, 
     IMPERSONATE = 0x0100, 
     DIRECT_IMPERSONATION = 0x0200 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct FLOATING_SAVE_AREA 
    { 
     public uint ControlWord; 
     public uint StatusWord; 
     public uint TagWord; 
     public uint ErrorOffset; 
     public uint ErrorSelector; 
     public uint DataOffset; 
     public uint DataSelector; 

     // missing some stuff 
     public uint Cr0NpxState; 
    } 

    [DllImport("kernel32.dll")] 
    private static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength); 

    [DllImport("kernel32.dll")] 
    public static extern bool ReadProcessMemory(IntPtr hProcess, int lpBaseAddress, byte[] buffer, int size, 
     int lpNumberOfBytesRead); 

लेकिन किसी कारण से यह कभी नहीं करता है evt.Exception.ExceptionRecord.ExceptionAddress == address

मैं स्मृति पढ़ने के लिए काफी नया हूं और ऊपर दिए गए कोड के साथ क्या गलत है यह पता लगाने में कठिन समय है।

संपादित करें: अगर मैं context.Dr7 = 0x00000001; को उस एप्लिकेशन को अनजान करता हूं जिसे मैं क्रैश पढ़ने की कोशिश कर रहा हूं।

+0

यह अधिक जानकारी के बिना बताने के लिए मुश्किल है - कार्यक्रम आप डिबग करने के लिए कोशिश कर रहे हैं की प्रकृति क्या है और आप कैसे 'address' पैरामीटर के लिए सही मान निर्धारित किया है? –

+0

@Damien_The_Unbeliever प्रोग्राम स्वयं सी ++ में एक सिंगलप्लेयर गेम है। और मैं धोखा इंजन के उपयोग के कारण सही मूल्यों को जानता हूं। – Julian

उत्तर

1

सिद्धांत:

आप एक प्रक्रिया के लिए देते हैं उस में एक ब्रेकपाइंट शब्दों में कहें, डिबगर आवेदन में एक घटना रजिस्टर और कहा कि घटना के लिए इंतजार करना चाहते हैं। आपको पैरामीटर के रूप में दिए गए पते पर ब्रेकपॉइंट डालना होगा, और संदर्भ को पढ़कर आप EDX की सामग्री को देखने में सक्षम होना चाहिए। यह उचित लगता है, जैसे एक मानव डेवलपर ऐसा करेगा।

कार्यान्वयन:

अपने कार्यान्वयन को देखते हुए, विधि आप पते पर ब्रेकप्वाइंट डाल करने के लिए इस्तेमाल करने की कोशिश संदिग्ध लगता है। पढ़ना here मैं समझता हूं कि चल रहे थ्रेड पर संदर्भ सेट करने का प्रयास करने से अप्रत्याशित परिणाम मिल सकते हैं। आपको पर्याप्त अनुमतियों की भी कमी हो सकती है। मान लें कि आपके पास अनुमतियां हैं, संदर्भ सेट करने से पहले धागे को रोकने का प्रयास करें।

दूसरी समस्या जो मैं भविष्यवाणी करता हूं वह यह है कि वह धागा जिसे आप रोकना चाहते हैं और डीबग करना एक संदर्भ है जिसे जितना संभव हो सके में बदला जाना चाहिए। मुझे लगता है कि आपको पहले धागे को रोकना चाहिए, इसके संदर्भ को पढ़ना चाहिए, ड्रैगन ध्वज (को मानना ​​है कि आप ब्रेकपॉइंट) सेट करते हैं और फिर संदर्भ को अन्य सभी रजिस्टर जानकारी के साथ सेट करते हैं।

इसके बिना, मुझे लगता है कि आप मूल रूप से प्रोग्राम के निष्पादन को बदलते हैं और मुझे एक मजबूत भावना है कि उनमें से कुछ रजिस्ट्रार केवल पढ़ रहे हैं।

ये 2 चीजें हैं जिन पर आपको विचार करने की आवश्यकता है। आशा करता हूँ की ये काम करेगा।

डिबगिंग:

वह काम नहीं करता, तो आप करने की जरूरत है एक समारोह क्यों कार्यों असफल (मैं SetThreadContext (शक कर रहा हूँ देखने के लिए GetLastError() का उपयोग करता है जोड़ने) के कारण हो जाएगा पहली बार समस्याएं)।

तुम भी जांच करनी चाहिए कि संदर्भ संरचना को सही ढंग से परिभाषित किया गया है और सभी सदस्य एक ही क्रम लोगों परिभाषितhere है की है। संरचना को सी # कोड द्वारा ठीक से अप्रबंधित कोड में गठबंधन किया जाना है।

इसके अलावा, अगर आप एक 64 बिट ओएस पर चल रहे हैं की जाँच करें। 64 बिट ओएस में थ्रेड का संदर्भ 32 बिट के मुकाबले अलग है। रजिस्टरों को 64 बी के लिए बढ़ाया जाता है और इसी तरह। यदि आप 64 बिट ओएस का उपयोग करते हैं, तो संदर्भ संरचना को को फिर से परिभाषित करने की आवश्यकता है। यदि आप एआरएम मशीन का उपयोग करते हैं तो वही होता है।

+0

आपकी बहुत स्पष्ट प्रतिक्रिया के लिए धन्यवाद। मैं घर जा रहा हूं और मैंने जो कहा है उस पर मैं पढ़ूंगा और अपना कोड बदलने की कोशिश करूंगा। – Julian

+0

मैंने कोड को 'सस्पेंड' और थ्रेड को फिर से शुरू किया है। Dr0 वास्तव में वह पता है जिसे मैं पढ़ने की कोशिश कर रहा हूं लेकिन वर्तमान परिवर्तनों के साथ भी यह कभी भी 'evt.Exception.ExceptionRecord.ExceptionAddress == पता' नहीं दबाएगा। – Julian

+0

यहां तक ​​कि बड़ी समस्या यह है कि आप धागे के संदर्भ की प्रतिलिपि नहीं बनाते हैं, इसे बदलते हैं और फिर परिवर्तित को नए संदर्भ के रूप में सेट करते हैं। आपको यह भी करने की ज़रूरत है। – VAndrei

-1

आपका उत्तर किसी अन्य कोड के साथ प्रत्यारोपित टिप्पणियों में से एक में छिपा हुआ प्रतीत होता है ... सेट करने और थ्रेड संदर्भ प्राप्त करने के लिए फ़ंक्शंस को थ्रेड के लिए एक हैंडल की आवश्यकता होती है (शायद कम से कम उचित अनुमतियों का उपयोग करके ओपन थ्रेड के साथ खोला गया है संदर्भ प्राप्त करें/सेट करें)। इसके बजाए, आप स्पष्ट रूप से जाली प्रक्रिया आईडी पास कर रहे हैं। आपको सफलता के लिए वापसी मूल्य की जांच करने पर विचार करना चाहिए, इससे शायद आपकी समस्या की पहचान करने में मदद मिलेगी।

+0

यदि आप लिंक किए गए प्रश्न को देखते हैं तो आप मूल कोड देख सकते हैं। जहां तक ​​लिंक जुड़े प्रश्न में उदाहरण नहीं है, वहां कोई गुम कोड नहीं है। इसके अलावा, मैं वापसी मान की जाँच करें और उन सभी को एक अगर बयान 'evt.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP' – Julian

+0

आह आप' SetThreadContext' के बारे में बात कर रहे हैं और वास्तव में है कि वापसी करता है 'FALSE' के अलावा 'सही' देना । और यह 'मदद, मेरे लिए एक डिबगर लिखो' की तरह नहीं है! मैंने अपना खुद का शोध किया लेकिन मुझे आगे नहीं मिल रहा है। और Win32 एपीआई या इसके तरीकों के बड़े ज्ञान के बिना मैं बस पूछ रहा हूं कि ऊपर दिए गए कोड के साथ क्या गलत होगा। लेकिन मैं देखूंगा कि 'SetThreadContext' विधि के साथ क्या गलत हो सकता है। – Julian

+0

क्यों भी परेशान है, जब माइक स्टाल उत्तम Microsoft.Samples.Debugging पैकेज [कड़ी] (http://blogs.msdn.com/b/jmstall/archive/2006/07/05/managed-wrappers-for-native-debug -api.aspx) NuGet पर हो सकता है और मूल डीबगिंग एपीआई के लिए एक रैपर भी शामिल है? – Eglin

संबंधित मुद्दे