PageRenderTime 2580ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 1ms

/Source/Inject/Injector.cs

http://thbot.googlecode.com/
C# | 514 lines | 392 code | 83 blank | 39 comment | 17 complexity | f3c251de17beb8698ad94880d9ae507c MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Threading;
  5. using System.IO;
  6. using System.Runtime.InteropServices;
  7. using EasyHook;
  8. using System.Windows.Forms;
  9. using System.Drawing.Win32;
  10. using System.Diagnostics;
  11. namespace HoldemHook
  12. {
  13. public class Injector : EasyHook.IEntryPoint
  14. {
  15. //?getDC@QWidget@@UBEPAUHDC__@@XZ
  16. public InjectClient Interface = null;
  17. public LocalHook CreateFileHook = null;
  18. public LocalHook ExtTextOutHook = null;
  19. public LocalHook QPainter_drawTextHook = null;
  20. public LocalHook QWidget_getDC = null;
  21. public LocalHook QWidgetPrivate_repaint_sysHook=null;
  22. public static StreamWriter Log = null;
  23. public GUINodeMap GuiNodes = new GUINodeMap();
  24. Stack<EventArgs> Queue = new Stack<EventArgs>();
  25. public Injector(
  26. RemoteHooking.IContext InContext,
  27. String InChannelName)
  28. {
  29. if(null==Log)
  30. Log = new StreamWriter("Injector.log");
  31. Log.AutoFlush = true;
  32. Log.WriteLine("Log Started {0}",DateTime.Now);
  33. Interface = RemoteHooking.IpcConnectClient<InjectClient>(InChannelName);
  34. Interface.Ping(RemoteHooking.GetCurrentProcessId());
  35. }
  36. public void Run(
  37. RemoteHooking.IContext InContext,
  38. String InArg1)
  39. {
  40. try
  41. {
  42. Log.WriteLine("Injector.Run {0}", InArg1);
  43. ExtTextOutHook = LocalHook.Create(
  44. LocalHook.GetProcAddress("gdi32.dll", "ExtTextOutW"),
  45. new DExtTextOutW(ExtTextOutW_Hooked),
  46. this);
  47. ExtTextOutHook.ThreadACL.SetExclusiveACL(new Int32[1]);
  48. Log.WriteLine("ExtTextOutW hooked");
  49. #if false
  50. QWidgetPrivate_repaint_sysHook = LocalHook.Create(
  51. LocalHook.GetProcAddress("QtGui4.dll", "?drawWidget@QWidgetPrivate@@QAEXPAVQPaintDevice@@ABVQRegion@@ABVQPoint@@HPAVQPainter@@PAVQWidgetBackingStore@@@Z"),
  52. new D_QWidgetPrivate_repaint_sys(QWidgetPrivate_repaint_sys_Hooked),
  53. this);
  54. QWidgetPrivate_repaint_sysHook.ThreadACL.SetExclusiveACL(new Int32[1]);
  55. Log.WriteLine("QWidgetPrivate::repaint_sys Hooked");
  56. #endif
  57. QPainter_drawTextHook = LocalHook.Create(
  58. LocalHook.GetProcAddress("QtGui4.dll", "?drawTextItem@QPainter@@QAEXABVQPointF@@ABVQTextItem@@@Z"),
  59. new D_QPainter_drawTextItem(
  60. QPainter_drawTextItem_Hooked), this);
  61. QPainter_drawTextHook.ThreadACL.SetExclusiveACL(new Int32[1]);
  62. Log.WriteLine("QPainter::drawText() hooked");
  63. #if false
  64. /*
  65. IntPtr lib=NativeAPI.LoadLibrary("InjectNative.dll");
  66. IntPtr fun = NativeAPI.GetProcAddress(lib, "QPainter_drawTextItem");
  67. if (fun != IntPtr.Zero)
  68. {
  69. QPainter_drawTextHook = LocalHook.CreateUnmanaged(LocalHook.GetProcAddress("QtGui4.dll", "?drawTextItem@QPainter@@QAEXABVQPointF@@ABVQTextItem@@@Z"),
  70. fun, IntPtr.Zero);
  71. QPainter_drawTextHook.ThreadACL.SetExclusiveACL(new Int32[1]);
  72. }*/
  73. QWidget_getDC = LocalHook.Create(
  74. LocalHook.GetProcAddress("QtGui4.dll", "?getDC@QWidget@@UBEPAUHDC__@@XZ"),
  75. new D_QWidget_getDC(
  76. QWidget_getDC_Hooked), this);
  77. QWidget_getDC.ThreadACL.SetExclusiveACL(new Int32[1]);
  78. Log.WriteLine("QWidget::getDC() hooked");
  79. #endif
  80. }
  81. catch (Exception e)
  82. {
  83. /*
  84. Now we should notice our host process about this error...
  85. */
  86. Interface.ReportError(RemoteHooking.GetCurrentProcessId(), e);
  87. Log.WriteLine("Exception in Injector.Run {0}", e);
  88. return;
  89. }
  90. // wait for host process termination...
  91. try
  92. {
  93. Log.Write("Getting process...");
  94. Process myProcess = Process.GetCurrentProcess();
  95. IntPtr hMainWnd = myProcess.MainWindowHandle;
  96. Log.WriteLine("PID={0}, hMainWnd={1}", myProcess.Id, hMainWnd);
  97. // send enum windows
  98. EnumWindows enuWnd = new EnumWindows();
  99. enuWnd.GetWindows(hMainWnd);
  100. WinWnd mainWnd = new WinWnd(hMainWnd);
  101. Log.WriteLine("MAIN WINDOW ({1} childs): {0}", mainWnd,enuWnd.Items.Count);
  102. Interface.FireWindowEvent(new WindowEventArgs(WindowEventType.Add, myProcess.Id, mainWnd, null));
  103. foreach (WinWnd wnd in enuWnd.Items)
  104. {
  105. Log.WriteLine("WINDOW: {0}",wnd);
  106. Interface.FireWindowEvent(new WindowEventArgs(WindowEventType.Add, myProcess.Id, wnd, enuWnd.Items));
  107. }
  108. while (Interface.Ping(RemoteHooking.GetCurrentProcessId()))
  109. {
  110. Log.WriteLine("Waiting queue...");
  111. Log.Flush();
  112. Thread.Sleep(500);
  113. // transmit newly monitored file accesses...
  114. lock (Queue)
  115. {
  116. while (Queue.Count > 0)
  117. {
  118. EventArgs args = Queue.Pop();
  119. //Log.WriteLine("InjectedCall: {0}", args);
  120. if (args is CallEventArgs)
  121. {
  122. // args.Process = RemoteHooking.GetCurrentProcessId();
  123. Interface.FireCallEvent(args as CallEventArgs);
  124. }
  125. else if (args is GUINodeEventArgs)
  126. {
  127. Interface.FireGUINodeEvent(args as GUINodeEventArgs);
  128. }
  129. }
  130. }
  131. }
  132. Log.WriteLine("Exiting Injector...");
  133. }
  134. catch (Exception e)
  135. {
  136. Log.WriteLine("Exiting Injector on exception: {0}", e);
  137. // NET Remoting will raise an exception if host is unreachable
  138. }
  139. }
  140. #region
  141. /* [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
  142. static extern IntPtr CreateFile(
  143. String InFileName,
  144. UInt32 InDesiredAccess,
  145. UInt32 InShareMode,
  146. IntPtr InSecurityAttributes,
  147. UInt32 InCreationDisposition,
  148. UInt32 InFlagsAndAttributes,
  149. IntPtr InTemplateFile);*/
  150. #endregion
  151. #region CreateFile
  152. [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet=CharSet.Unicode, SetLastError=true)]
  153. delegate IntPtr DCreateFile(
  154. String InFileName,
  155. UInt32 InDesiredAccess,
  156. UInt32 InShareMode,
  157. IntPtr InSecurityAttributes,
  158. UInt32 InCreationDisposition,
  159. UInt32 InFlagsAndAttributes,
  160. IntPtr InTemplateFile);
  161. delegate void DCreateFileAsync(
  162. Int32 InClientPID,
  163. IntPtr InHandle,
  164. String InFileName,
  165. UInt32 InDesiredAccess,
  166. UInt32 InShareMode,
  167. IntPtr InSecurityAttributes,
  168. UInt32 InCreationDisposition,
  169. UInt32 InFlagsAndAttributes,
  170. IntPtr InTemplateFile);
  171. // this is where we are intercepting all file accesses!
  172. static IntPtr CreateFile_Hooked(
  173. String InFileName,
  174. UInt32 InDesiredAccess,
  175. UInt32 InShareMode,
  176. IntPtr InSecurityAttributes,
  177. UInt32 InCreationDisposition,
  178. UInt32 InFlagsAndAttributes,
  179. IntPtr InTemplateFile)
  180. {
  181. try
  182. {
  183. Injector This = (Injector)HookRuntimeInfo.Callback;
  184. lock (This.Queue)
  185. {
  186. if(This.Queue.Count < 1000)
  187. This.Queue.Push(new CallEventArgs("CreateFile",null, InFileName, InDesiredAccess, InShareMode, InSecurityAttributes, InCreationDisposition, InFlagsAndAttributes, InTemplateFile));
  188. }
  189. }
  190. catch
  191. {
  192. }
  193. // call original API...
  194. return Api.CreateFile(
  195. InFileName,
  196. InDesiredAccess,
  197. InShareMode,
  198. InSecurityAttributes,
  199. InCreationDisposition,
  200. InFlagsAndAttributes,
  201. InTemplateFile);
  202. }
  203. #endregion
  204. #region ExtTextOutW
  205. [UnmanagedFunctionPointer(CallingConvention.StdCall,
  206. CharSet = CharSet.Auto,
  207. SetLastError = true)]
  208. delegate bool DExtTextOutW(
  209. IntPtr hdc,
  210. int X,
  211. int y,
  212. uint fuOptions,
  213. [In] ref IntPtr lprc,
  214. string lpString,
  215. uint cbCount,
  216. [In] IntPtr lpDx
  217. );
  218. // this is where we are intercepting all file accesses!
  219. static bool ExtTextOutW_Hooked(
  220. IntPtr hdc,
  221. int X,
  222. int Y,
  223. uint fuOptions,
  224. [In] ref IntPtr lprc,
  225. string lpString,
  226. uint cbCount,
  227. [In] IntPtr lpDx)
  228. {
  229. try
  230. {
  231. Injector This = (Injector)HookRuntimeInfo.Callback;
  232. Log.WriteLine("* ExtTextOutW "+lpString);
  233. IntPtr hwnd = Api.WindowFromDC(hdc);
  234. Log.WriteLine(" WindowFromDC({0})={1}", hdc, hwnd);
  235. lock (This.Queue)
  236. {
  237. if (This.Queue.Count < 1000)
  238. This.Queue.Push(new CallEventArgs("ExtTextOutW", null, hwnd, hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx));
  239. }
  240. }
  241. catch
  242. {
  243. }
  244. // call original API...
  245. return Api.ExtTextOutW(
  246. hdc,
  247. X,
  248. Y,
  249. fuOptions,
  250. ref lprc,
  251. lpString,
  252. cbCount,
  253. lpDx
  254. );
  255. }
  256. #endregion
  257. [StructLayout(LayoutKind.Sequential, Pack=8)]
  258. public struct QTextItem
  259. {
  260. System.Int32 a0;
  261. System.Int32 a1;
  262. System.Int32 a2;
  263. System.Int32 a3;
  264. System.Int32 a4;
  265. System.Int32 a5;
  266. System.Int32 a6;
  267. System.Int32 a7;
  268. public System.Int32 len;
  269. [MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 1)]
  270. public string str;
  271. };
  272. [StructLayout(LayoutKind.Sequential, Pack = 8,Size=32)]
  273. public struct QPointF
  274. {
  275. public System.Double x;
  276. public System.Double y;
  277. };
  278. [StructLayout(LayoutKind.Sequential, Size=4)]
  279. public struct QString
  280. {
  281. public IntPtr data;
  282. };
  283. [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet=CharSet.Unicode)]
  284. public struct WIDGETINFO
  285. {
  286. [MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 1)]
  287. public string title;
  288. [MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 1)]
  289. public string name;
  290. [MarshalAs(UnmanagedType.LPStr, SizeParamIndex = 1)]
  291. public string clazz;
  292. public System.Double x;
  293. public System.Double y;
  294. public System.Double w;
  295. public System.Double h;
  296. }
  297. static string widgetInfoString(IntPtr widget)
  298. {
  299. String result = "";
  300. WIDGETINFO wi = new WIDGETINFO();
  301. while (widget != IntPtr.Zero)
  302. {
  303. result += widget;
  304. widget = QWidget_describe(widget, ref wi);
  305. result += " CLASS(" + wi.clazz + ")NAME(" + wi.name + ")TITLE(" + wi.title + ")";
  306. result += "(" + wi.x + "," + wi.y + ",w=" + wi.w + ",h=" + wi.h + ")";
  307. result += " -> ";
  308. //Log.WriteLine("Widget-Parent "+widget+";"+(widget==IntPtr.Zero));
  309. }
  310. return result;
  311. }
  312. [DllImport ("QtGui4.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.ThisCall,
  313. EntryPoint = "?drawTextItem@QPainter@@QAEXABVQPointF@@ABVQTextItem@@@Z")] // Unicode
  314. public static extern void QPainter_drawTextItem(IntPtr obj, IntPtr pt, IntPtr ti);
  315. [UnmanagedFunctionPointer(CallingConvention.ThisCall,
  316. CharSet = CharSet.Unicode, SetLastError = true)]
  317. delegate void D_QPainter_drawTextItem(IntPtr obj, IntPtr pt, IntPtr ti);
  318. static void QPainter_drawTextItem_Hooked( IntPtr obj, IntPtr pt, IntPtr ti)
  319. {
  320. QTextItem qti = (QTextItem)Marshal.PtrToStructure
  321. (ti, typeof(QTextItem));
  322. QPointF qpt = (QPointF)Marshal.PtrToStructure
  323. (pt, typeof(QPointF));
  324. IntPtr widget = QPainter_getWidget(obj);
  325. Log.Write("* QPainter::drawTextItem("+qti.str+";("+qpt.x+","+qpt.y+");");
  326. Log.WriteLine(" with widget="+widgetInfoString(widget));
  327. try
  328. {
  329. Injector This = (Injector)HookRuntimeInfo.Callback;
  330. lock (This.Queue)
  331. {
  332. WIDGETINFO wi = new WIDGETINFO();
  333. List<GUINode> nodes = new List<GUINode>();
  334. int handle = widget.ToInt32();
  335. while (widget != IntPtr.Zero)
  336. {
  337. widget = QWidget_describe(widget, ref wi);
  338. GUINode guiNode = new GUINode();
  339. guiNode.Handle = handle;
  340. guiNode.Bounds = new System.Drawing.RectangleF((float)wi.x, (float)wi.y, (float)wi.w, (float)wi.h);
  341. guiNode.Class = wi.clazz + ":" + wi.name;
  342. guiNode.Title = wi.title;
  343. guiNode.ParentHandle = widget.ToInt32();
  344. nodes.Add(guiNode);
  345. handle = widget.ToInt32();
  346. }
  347. for (int i = 0; i < nodes.Count - 1; i++)
  348. {
  349. nodes[i].Parent = nodes[i + 1];
  350. }
  351. for (int i = 0; i < nodes.Count; i++)
  352. {
  353. if (!This.GuiNodes.Contains(nodes[i].Handle))
  354. {
  355. This.GuiNodes.Add(nodes[i]);
  356. This.Queue.Push(new GUINodeEventArgs(nodes[i]));
  357. }
  358. }
  359. if (This.Queue.Count < 1000)
  360. This.Queue.Push(new CallEventArgs("QPainter::drawtextItem", null,qti.str, qpt.x, qpt.y, handle));
  361. }
  362. }
  363. catch
  364. {
  365. }
  366. QPainter_drawTextItem( obj, pt, ti);
  367. }
  368. #if false
  369. [DllImport("QtGui4.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.ThisCall,
  370. EntryPoint = "?getDC@QWidget@@UBEPAUHDC__@@XZ")] // Unicode
  371. public static extern IntPtr QWidget_getDC_real(IntPtr obj);
  372. [UnmanagedFunctionPointer(CallingConvention.ThisCall,
  373. CharSet = CharSet.Unicode, SetLastError = true)]
  374. delegate IntPtr D_QWidget_getDC(IntPtr obj);
  375. static IntPtr QWidget_getDC_Hooked(IntPtr obj)
  376. {
  377. IntPtr dc = QWidget_getDC_real(obj);
  378. Log.WriteLine(string.Format("* QWidget::getDC()={0:x}",dc));
  379. try
  380. {
  381. Injector This = (Injector)HookRuntimeInfo.Callback;
  382. lock (This.Queue)
  383. {
  384. if (This.Queue.Count < 1000)
  385. This.Queue.Push(new CallEventArgs("QWidget::getDC", dc));
  386. }
  387. }
  388. catch
  389. {
  390. }
  391. return dc;
  392. }
  393. [DllImport("QtGui4.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.ThisCall,
  394. EntryPoint = "?drawWidget@QWidgetPrivate@@QAEXPAVQPaintDevice@@ABVQRegion@@ABVQPoint@@HPAVQPainter@@PAVQWidgetBackingStore@@@Z")] // Unicode
  395. public static extern void QWidgetPrivate_repaint_sys_real(IntPtr obj, IntPtr qpdev, IntPtr qrgn, IntPtr qpt,int i,IntPtr qpaint,IntPtr qbacksto);
  396. [UnmanagedFunctionPointer(CallingConvention.ThisCall,
  397. CharSet = CharSet.Unicode, SetLastError = true)]
  398. delegate void D_QWidgetPrivate_repaint_sys(IntPtr obj, IntPtr qpdev, IntPtr qrgn, IntPtr qpt,int i,IntPtr qpaint,IntPtr qbacksto);
  399. static void QWidgetPrivate_repaint_sys_Hooked(IntPtr obj, IntPtr qpdev, IntPtr qrgn, IntPtr qpt,int i,IntPtr qpaint,IntPtr qbacksto)
  400. {
  401. Log.WriteLine(string.Format("*==> QWidget::drawWidget {{ "+obj));
  402. IntPtr qwidget = QWidgetPrivate_qfunc(obj);
  403. Log.WriteLine("+qfunc "+ qwidget);
  404. IntPtr q2 = Marshal.ReadIntPtr(obj, 4);
  405. Log.WriteLine("+q2 " + q2);
  406. string wtitle = QWidget_title(qwidget);
  407. Log.WriteLine("+windowtitle "+wtitle);
  408. /*IntPtr data = Marshal.ReadIntPtr(wtitle);
  409. Log.WriteLine("+dataptr "+data);
  410. IntPtr chrs = Marshal.ReadIntPtr(data, 12);
  411. Log.WriteLine("+charptr "+chrs);
  412. string s = Marshal.PtrToStringUni(chrs);
  413. Log.WriteLine("title="+s);*/
  414. QWidgetPrivate_repaint_sys_real(obj, qpdev, qrgn, qpt,i,qpaint,qbacksto);
  415. Log.WriteLine(string.Format("*<== QWidget::drawWidget}}"));
  416. }
  417. [DllImport("QtGui4.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.ThisCall,
  418. EntryPoint = "?q_func@QWidgetPrivate@@AAEPAVQWidget@@XZ")] // Unicode
  419. public static extern IntPtr QWidgetPrivate_qfunc(IntPtr obj);
  420. [DllImport("QtGui4.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.ThisCall,
  421. EntryPoint = "?windowTitle@QWidget@@QBE?AVQString@@XZ")] // Unicode
  422. public static extern QString QWidget_windowTitle(IntPtr obj);
  423. #endif
  424. [DllImport("InjectNative.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall,
  425. EntryPoint = "QWidget_describe")] // Unicode
  426. public static extern IntPtr QWidget_describe(IntPtr obj, ref WIDGETINFO info);
  427. [DllImport("InjectNative.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall,
  428. EntryPoint = "QPainter_getWidget")] // Unicode
  429. public static extern IntPtr QPainter_getWidget(IntPtr obj);
  430. }
  431. }