Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

WIP: get managed thread stacks

By: a guest on Nov 7th, 2012  |  syntax: C#  |  size: 12.41 KB  |  views: 38  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1.         public static class ThreadUtil
  2.         {
  3.                 /// <summary>
  4.                 /// Yields back a series of int32 values pulled from [basePtr - (addressesToReadBefore * 4)] to [basePtr + (addressesToReadAfter * 4)]
  5.                 /// </summary>
  6.                 /// <param name="hProc"></param>
  7.                 /// <param name="basePtr"></param>
  8.                 /// <param name="addressesToReadBefore"></param>
  9.                 /// <param name="addressesToReadAfter"></param>
  10.                 /// <returns></returns>
  11.                 public static IEnumerable<Tuple<long, int>> DumpStack32(IntPtr hProc, UIntPtr basePtr, int addressesToReadBefore, int addressesToReadAfter)
  12.                 {
  13.                         var bp = basePtr.ToUInt32();
  14.                         var bufferSizeForAddresses = Marshal.SizeOf(typeof(int)) * addressesToReadBefore;
  15.                         var startAddress = bp - bufferSizeForAddresses;
  16.                         var bufferSize = bufferSizeForAddresses + (addressesToReadAfter * Marshal.SizeOf(typeof(int)));
  17.                         var buffer = new byte[bufferSize];
  18.                         int bytesRead;
  19.                         ReadProcessMemory(hProc, new IntPtr(startAddress), buffer, bufferSize, out bytesRead);
  20.                         using (var br = new BinaryReader(new MemoryStream(buffer)))
  21.                         {
  22.                                 for (int i = 0; i < (addressesToReadBefore + addressesToReadAfter); i++)
  23.                                 {
  24.                                         var offset = (i * 4);
  25.                                         var addr = br.ReadInt32();
  26.                                         yield return Tuple.Create(startAddress + offset, addr);
  27.                                 }
  28.                         }
  29.                 }
  30.  
  31.                 public static string WalkFrom(IntPtr hProc, string name, UIntPtr address, int goBack, int goFwd)
  32.                 {
  33.                         var sb = new StringBuilder();
  34.                         var addressRaw = address.ToUInt32();
  35.                         sb.AppendFormat("\t{0}:0x{1}", name, addressRaw.ToString("X")).AppendLine();
  36.                         var retAddrs = DumpStack32(hProc, address, goBack, goFwd);
  37.                         foreach (var retAddr in retAddrs)
  38.                         {
  39.                                 var memLoc = retAddr.Item1;
  40.                                 var offset = memLoc - addressRaw;
  41.                                 var addr = retAddr.Item2;
  42.                                 sb.AppendFormat("\t\tAddr 0x{0}[{1}{2}0x{3}]:0x{4}", memLoc.ToString("X"), name, offset < 0 ? "-" : "+", Math.Abs(offset).ToString("X"), addr.ToString("X")).AppendLine();
  43.                         }
  44.                         return sb.ToString();
  45.                 }
  46.  
  47.                 public static string DumpThreadInfo(IntPtr hProc, IntPtr hThread, int framesBefore, int framesAfter)
  48.                 {
  49.                         var sb = new StringBuilder();
  50.                         var ctx = new CONTEXT { ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_ALL };
  51.                         GetThreadContext(hThread, ref ctx);
  52.                         sb.AppendFormat("hProc:0x{0} hThread:0x{1}", hProc.ToInt32().ToString("X"), hThread.ToInt32().ToString("X")).AppendLine();
  53.                         sb.AppendFormat("IP:0x{0}", ctx.Eip).AppendLine();
  54.                         sb.AppendFormat(WalkFrom(hProc, "EBP", new UIntPtr(ctx.Ebp), framesBefore, framesAfter)).AppendLine();
  55.                         sb.AppendFormat(WalkFrom(hProc, "ESP", new UIntPtr(ctx.Esp), framesBefore, framesAfter)).AppendLine();
  56.                         return sb.ToString();
  57.                 }
  58.  
  59.                 #region P/Invoke Gobbledegook!
  60.                 #region enums
  61.                 [Flags]
  62.                 public enum ThreadAccess : int
  63.                 {
  64.                         TERMINATE = (0x0001),
  65.                         SUSPEND_RESUME = (0x0002),
  66.                         GET_CONTEXT = (0x0008),
  67.                         SET_CONTEXT = (0x0010),
  68.                         SET_INFORMATION = (0x0020),
  69.                         QUERY_INFORMATION = (0x0040),
  70.                         SET_THREAD_TOKEN = (0x0080),
  71.                         IMPERSONATE = (0x0100),
  72.                         DIRECT_IMPERSONATION = (0x0200)
  73.                 }
  74.                 public enum CONTEXT_FLAGS : uint
  75.                 {
  76.                         CONTEXT_i386 = 0x10000,
  77.                         CONTEXT_i486 = 0x10000,   //  same as i386
  78.                         CONTEXT_CONTROL = CONTEXT_i386 | 0x01, // SS:SP, CS:IP, FLAGS, BP
  79.                         CONTEXT_INTEGER = CONTEXT_i386 | 0x02, // AX, BX, CX, DX, SI, DI
  80.                         CONTEXT_SEGMENTS = CONTEXT_i386 | 0x04, // DS, ES, FS, GS
  81.                         CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08, // 387 state
  82.                         CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10, // DB 0-3,6,7
  83.                         CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20, // cpu specific extensions
  84.                         CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS,
  85.                         CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS
  86.                 }
  87.  
  88.                 public enum ProcessAccessFlags : int
  89.                 {
  90.                         All = 0x001F0FFF,
  91.                         Terminate = 0x00000001,
  92.                         CreateThread = 0x00000002,
  93.                         VMOperation = 0x00000008,
  94.                         VMRead = 0x00000010,
  95.                         VMWrite = 0x00000020,
  96.                         DupHandle = 0x00000040,
  97.                         SetInformation = 0x00000200,
  98.                         QueryInformation = 0x00000400,
  99.                         Synchronize = 0x00100000
  100.                 }
  101.                 #endregion
  102.  
  103.                 #region structs
  104.                 [StructLayout(LayoutKind.Sequential)]
  105.                 public struct FLOATING_SAVE_AREA
  106.                 {
  107.                         public uint ControlWord;
  108.                         public uint StatusWord;
  109.                         public uint TagWord;
  110.                         public uint ErrorOffset;
  111.                         public uint ErrorSelector;
  112.                         public uint DataOffset;
  113.                         public uint DataSelector;
  114.                         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
  115.                         public byte[] RegisterArea;
  116.                         public uint Cr0NpxState;
  117.                 }
  118.  
  119.                 [StructLayout(LayoutKind.Sequential)]
  120.                 public struct CONTEXT
  121.                 {
  122.                         public uint ContextFlags; //set this to an appropriate value
  123.                         // Retrieved by CONTEXT_DEBUG_REGISTERS
  124.                         public uint Dr0;
  125.                         public uint Dr1;
  126.                         public uint Dr2;
  127.                         public uint Dr3;
  128.                         public uint Dr6;
  129.                         public uint Dr7;
  130.                         // Retrieved by CONTEXT_FLOATING_POINT
  131.                         public FLOATING_SAVE_AREA FloatSave;
  132.                         // Retrieved by CONTEXT_SEGMENTS
  133.                         public uint SegGs;
  134.                         public uint SegFs;
  135.                         public uint SegEs;
  136.                         public uint SegDs;
  137.                         // Retrieved by CONTEXT_INTEGER
  138.                         public uint Edi;
  139.                         public uint Esi;
  140.                         public uint Ebx;
  141.                         public uint Edx;
  142.                         public uint Ecx;
  143.                         public uint Eax;
  144.                         // Retrieved by CONTEXT_CONTROL
  145.                         public uint Ebp;
  146.                         public uint Eip;
  147.                         public uint SegCs;
  148.                         public uint EFlags;
  149.                         public uint Esp;
  150.                         public uint SegSs;
  151.                         // Retrieved by CONTEXT_EXTENDED_REGISTERS
  152.                         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
  153.                         public byte[] ExtendedRegisters;
  154.                 }
  155.  
  156.                 public struct BYTES
  157.                 {
  158.                         public byte BaseMid;
  159.                         public byte Flags1;
  160.                         public byte Flags2;
  161.                         public byte BaseHi;
  162.                 }
  163.  
  164.                 public struct BITS
  165.                 {
  166.                         int Value;
  167.                         /// <summary>
  168.                         /// Max set value is 255 (11111111b)
  169.                         /// </summary>
  170.                         public int BaseMid
  171.                         {
  172.                                 get { return (Value & 0xFF); }
  173.                                 set { Value = (Value & unchecked((int)0xFFFFFF00)) | (value & 0xFF); }
  174.                         }
  175.                         /// <summary>
  176.                         /// Max set value is 31 (11111b)
  177.                         /// </summary>
  178.                         public int Type
  179.                         {
  180.                                 get { return (Value & 0x1F00) >> 8; }
  181.                                 set { Value = (Value & unchecked((int)0xFFFFE0FF)) | ((value & 0x1F) << 8); }
  182.                         }
  183.                         /// <summary>
  184.                         /// Max set value is 3 (11b)
  185.                         /// </summary>
  186.                         public int Dpl
  187.                         {
  188.                                 get { return (Value & 0x6000) >> 13; }
  189.                                 set { Value = (Value & unchecked((int)0xFFFF9FFF)) | ((value & 0x3) << 13); }
  190.                         }
  191.                         /// <summary>
  192.                         /// Max set value is 1 (1b)
  193.                         /// </summary>
  194.                         public int Pres
  195.                         {
  196.                                 get { return (Value & 0x4000) >> 15; }
  197.                                 set { Value = (Value & unchecked((int)0xFFFFBFFF)) | ((value & 0x1) << 15); }
  198.                         }
  199.                         /// <summary>
  200.                         /// Max set value is 15 (1111b)
  201.                         /// </summary>
  202.                         public int LimitHi
  203.                         {
  204.                                 get { return (Value & 0xF0000) >> 16; }
  205.                                 set { Value = (Value & unchecked((int)0xFFF0FFFF)) | ((value & 0xF) << 16); }
  206.                         }
  207.                         /// <summary>
  208.                         /// Max set value is 1 (1b)
  209.                         /// </summary>
  210.                         public int Sys
  211.                         {
  212.                                 get { return (Value & 0x100000) >> 20; }
  213.                                 set { Value = (Value & unchecked((int)0xFFEFFFFF)) | ((value & 0x1) << 20); }
  214.                         }
  215.                         /// <summary>
  216.                         /// Max set value is 1 (1b)
  217.                         /// </summary>
  218.                         public int Reserved_0
  219.                         {
  220.                                 get { return (Value & 0x200000) >> 21; }
  221.                                 set { Value = (Value & unchecked((int)0xFFDFFFFF)) | ((value & 0x1) << 21); }
  222.                         }
  223.                         /// <summary>
  224.                         /// Max set value is 1 (1b)
  225.                         /// </summary>
  226.                         public int Default_Big
  227.                         {
  228.                                 get { return (Value & 0x400000) >> 22; }
  229.                                 set { Value = (Value & unchecked((int)0xFFBFFFFF)) | ((value & 0x1) << 22); }
  230.                         }
  231.                         /// <summary>
  232.                         /// Max set value is 1 (1b)
  233.                         /// </summary>
  234.                         public int Granularity
  235.                         {
  236.                                 get { return (Value & 0x800000) >> 23; }
  237.                                 set { Value = (Value & unchecked((int)0xFF7FFFFF)) | ((value & 0x1) << 23); }
  238.                         }
  239.                         /// <summary>
  240.                         /// Max set value is 255 (11111111b)
  241.                         /// </summary>
  242.                         public int BaseHi
  243.                         {
  244.                                 get { return (Value & unchecked((int)0xFF000000)) >> 24; }
  245.                                 set { Value = (Value & unchecked((int)0xFFFFFF)) | ((value & 0xFF) << 24); }
  246.                         }
  247.                 }
  248.  
  249.                 [StructLayout(LayoutKind.Explicit)]
  250.                 public struct HIGHWORD
  251.                 {
  252.                         [FieldOffset(0)]
  253.                         public BYTES Bytes;
  254.                         [FieldOffset(0)]
  255.                         public BITS Bits;
  256.                 }
  257.  
  258.                 public struct LDT_ENTRY
  259.                 {
  260.                         public ushort LimitLow;
  261.                         public ushort BaseLow;
  262.                         public HIGHWORD HighWord;
  263.                 }
  264.  
  265.                 [StructLayout(LayoutKind.Sequential)]
  266.                 public struct MEMORY_BASIC_INFORMATION
  267.                 {
  268.                         public IntPtr BaseAddress;
  269.                         public IntPtr AllocationBase;
  270.                         public uint AllocationProtect;
  271.                         public IntPtr RegionSize;
  272.                         public uint State;
  273.                         public uint Protect;
  274.                         public uint Type;
  275.                 }
  276.  
  277.                 public enum AllocationProtect : uint
  278.                 {
  279.                         PAGE_EXECUTE = 0x00000010,
  280.                         PAGE_EXECUTE_READ = 0x00000020,
  281.                         PAGE_EXECUTE_READWRITE = 0x00000040,
  282.                         PAGE_EXECUTE_WRITECOPY = 0x00000080,
  283.                         PAGE_NOACCESS = 0x00000001,
  284.                         PAGE_READONLY = 0x00000002,
  285.                         PAGE_READWRITE = 0x00000004,
  286.                         PAGE_WRITECOPY = 0x00000008,
  287.                         PAGE_GUARD = 0x00000100,
  288.                         PAGE_NOCACHE = 0x00000200,
  289.                         PAGE_WRITECOMBINE = 0x00000400
  290.                 }
  291.                 #endregion
  292.  
  293.                 #region general calls
  294.                 [DllImport("kernel32.dll", SetLastError = true)]
  295.                 [return: MarshalAs(UnmanagedType.Bool)]
  296.                 public static extern bool CloseHandle(IntPtr hObject);
  297.                 #endregion
  298.  
  299.                 #region window calls
  300.                 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  301.                 public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
  302.  
  303.                 [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  304.                 public static extern int GetWindowTextLength(IntPtr hWnd);
  305.                 #endregion
  306.  
  307.                 #region thread calls
  308.                 [DllImport("kernel32.dll")]
  309.                 public static extern bool TlsSetValue(uint dwTlsIndex, IntPtr lpTlsValue);
  310.  
  311.                 [DllImport("kernel32.dll")]
  312.                 public static extern IntPtr TlsGetValue(uint dwTlsIndex);
  313.  
  314.                 [DllImport("kernel32.dll")]
  315.                 public static extern uint SuspendThread(IntPtr hThread);
  316.  
  317.                 [DllImport("kernel32.dll")]
  318.                 public static extern uint ResumeThread(IntPtr hThread);
  319.  
  320.                 [DllImport("kernel32.dll", SetLastError = true)]
  321.                 public static extern bool GetThreadSelectorEntry(IntPtr hThread, uint dwSelector, out LDT_ENTRY lpSelectorEntry);
  322.  
  323.                 [DllImport("kernel32.dll")]
  324.                 public static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
  325.  
  326.                 [DllImport("kernel32.dll")]
  327.                 public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
  328.  
  329.                 [DllImport("kernel32.dll")]
  330.                 public static extern void ExitThread(uint dwExitCode);
  331.  
  332.                 [DllImport("user32.dll")]
  333.                 [return: MarshalAs(UnmanagedType.Bool)]
  334.                 public static extern bool IsGUIThread([MarshalAs(UnmanagedType.Bool)] bool bConvert);
  335.  
  336.                 [DllImport("kernel32.dll")]
  337.                 public static extern uint GetCurrentThreadId();
  338.  
  339.                 [DllImport("user32.dll")]
  340.                 public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
  341.  
  342.                 [DllImport("user32.dll")]
  343.                 [return: MarshalAs(UnmanagedType.Bool)]
  344.                 public static extern bool EnumThreadWindows(uint dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
  345.  
  346.                 public delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
  347.                 public static void EnumThreadWindows(uint processId, Func<IntPtr, IntPtr, bool> callback)
  348.                 {
  349.                         EnumThreadWindows(processId, new EnumThreadDelegate(callback), IntPtr.Zero);
  350.                 }
  351.                 #endregion
  352.  
  353.                 #region process and memory calls
  354.                 [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
  355.                 public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
  356.  
  357.                 [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
  358.                 public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint dwFreeType);
  359.  
  360.                 [DllImport("kernel32.dll")]
  361.                 public static extern int VirtualQueryEx(
  362.                           IntPtr hProcess,
  363.                           IntPtr lpAddress,
  364.                            out MEMORY_BASIC_INFORMATION lpBuffer,
  365.                            uint dwLength);
  366.  
  367.                 [DllImport("kernel32.dll", SetLastError = true)]
  368.                 public static extern bool ReadProcessMemory(
  369.                           IntPtr hProcess,
  370.                           IntPtr lpBaseAddress,
  371.                           [Out] byte[] lpBuffer,
  372.                            int dwSize,
  373.                            out int lpNumberOfBytesRead);
  374.  
  375.                 [DllImport("kernel32.dll", SetLastError = true)]
  376.                 public static extern bool WriteProcessMemory(
  377.                           IntPtr hProcess,
  378.                           IntPtr lpBaseAddress,
  379.                            byte[] lpBuffer,
  380.                            uint nSize,
  381.                            out UIntPtr lpNumberOfBytesWritten);
  382.  
  383.                 [DllImport("kernel32.dll")]
  384.                 public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
  385.                 #endregion
  386.  
  387.                 #endregion
  388.         }