求助:跨进程获取delphi控件TDBGridEh的内容

[复制链接]
3027|3
 楼主| xxzouzhichao 发表于 2016-9-2 22:38 | 显示全部楼层 |阅读模式
如题:
有一个第三方软件用了TDBGridEh控件,想获取表格控件上的内容,网上看到有用dll hook的办法获取TstringGrid的内容
因此也想用dll hook的办法获取TDBGridEh内容,求高人指点一下
我自己另外写了一个测试软件,可以获取到这个测试软件的对象实例,
但是目标软件无法获取,findcontrol总是失败


以下是我自己写的测试软件的TDBGgridEh的spy++信息:
捕获0.JPG
以下是目标软件的TDBGgridEh的spy++信息:
捕获1.JPG
以下是hook的dll的源码
  1. unit UHook;

  2. interface

  3. uses Windows, Messages, SysUtils, Controls, Grids, DBGrids, DBGridEh, DBGridEhImpExp, Classes;

  4. procedure InstallHook(MainWnd, DestWnd: HWND); stdcall;
  5. procedure UninstallHook; stdcall;
  6. function GetHookedCell: PChar; stdcall;

  7. implementation

  8. uses UShare;

  9. var
  10.   ControlAtom: TAtom;
  11.   ControlAtomString: string;
  12.   RM_GetObjectInstance: DWORD;  // registered window message


  13. function MyFindControl_test(Handle: HWnd): TWinControl;
  14. type  
  15.   PObjectInstance = ^TObjectInstance;
  16.   TObjectInstance = packed record  
  17.     Code: Byte;            { 短跳转 $E8 }  
  18.     Offset: Integer;       { CalcJmpOffset(Instance, @Block^.Code); }
  19.     Next: PObjectInstance; { MainWndProc 地址 }
  20.     Self: Pointer;         { 控件对象地址 }
  21.   end;  
  22. var  
  23.   wc: PObjectInstance;  
  24. begin  
  25.   Result := nil;  
  26.   wc     := Pointer(GetWindowLong(Handle, GWL_WNDPROC));  
  27.   if wc <> nil then  
  28.   begin  
  29.     Result := wc.Self;  
  30.   end;  
  31. end;


  32. function MyFindControl(Handle: HWnd): TWinControl;
  33. var
  34.   OwningProcess: DWORD;
  35. begin
  36.   Result := nil;
  37.   if (Handle <> 0) and (GetWindowThreadProcessID(Handle, OwningProcess) <> 0) and
  38.      (OwningProcess = GetCurrentProcessId) then
  39.   begin
  40.     if GlobalFindAtom(PChar(ControlAtomString)) = ControlAtom then
  41.       Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)))
  42.     else
  43.           Result := Pointer(SendMessage(Handle, RM_GetObjectInstance, 0, 0));
  44.         MessageBeep(MB_OK);
  45.   end;
  46. end;

  47. function MsgWndProc(hwnd: HWND; Msg: UINT; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
  48. var
  49.   DG: TDBGridEh;
  50.   aName: array [0..255] of Char;
  51. begin
  52.   case Msg of
  53.     CM_QUERYROW:                      //获取行数
  54.       begin
  55.         Result := -1;
  56.         if P^.DestWnd <> 0 then
  57.         begin
  58.           GetClassName(P^.DestWnd, aName, 256);
  59.           //if string(aName) = 'TDBGridEh' then MessageBeep(MB_OK);
  60.           DG := Pointer(MyFindControl(P^.DestWnd));
  61.           if DG <> nil then Result := DG.Height;
  62.         end;
  63.         Exit;
  64.       end;
  65.     CM_QUERYCOL:                              //获取列数
  66.       begin
  67.         Result := -1;
  68.         if P^.DestWnd <> 0 then
  69.         begin
  70.           GetClassName(P^.DestWnd, aName, 256);
  71.           //if string(aName) = 'TDBGridEh' then MessageBeep(MB_OK);
  72.           DG := Pointer(MyFindControl(P^.DestWnd));
  73.           if DG <> nil then Result := DG.Width;
  74.         end;
  75.         Exit;
  76.       end;
  77.     CM_HOOKCELL:                                //获取内容
  78.       begin
  79.         DG := Pointer(MyFindControl(P^.DestWnd));
  80.         //if DG <> nil then MessageBeep(MB_OK);
  81.         SaveDBGridEhToExportFile(TDBGridEhExportAsText, DG, 'c:/GridData.txt', true);
  82.         Exit;
  83.       end;
  84.   end;
  85.   Result := DefWindowProc(hwnd, Msg, WParam, LParam);
  86. end;

  87. function GetMsgProc(Code: UINT; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
  88. begin
  89.   if Code = HC_ACTION then
  90.   begin
  91.   end;
  92.   Result := CallNextHookEx(P^.hkMsg, Code, WParam, LParam);
  93. end;

  94. procedure InstallHook(MainWnd, DestWnd: HWND); stdcall;
  95. begin
  96.   if P^.hkMsg = 0 then
  97.     P^.hkMsg := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, HInstance, 0);
  98.   P^.HostWnd := MainWnd;
  99.   P^.HostPID := GetCurrentProcessId;
  100.   P^.DestWnd := DestWnd;
  101. end;

  102. procedure UninstallHook; stdcall;
  103. begin
  104.   if P^.hkMsg <> 0 then
  105.   begin
  106.     UnhookWindowsHookEx(P^.hkMsg);
  107.     P^.hkMsg := 0;
  108.   end;
  109. end;

  110. function GetHookedCell: PChar; stdcall;
  111. begin
  112.   Result := P^.Text;
  113. end;

  114. var
  115.   DoClear: Boolean;
  116.   DestPID: DWORD;
  117.   DestProcess: Boolean = False;
  118.   UtilWindowClass: TWndClass = (
  119.     style: 0;
  120.     lpfnWndProc: @MsgWndProc;
  121.     cbClsExtra: 0;
  122.     cbWndExtra: 0;
  123.     hInstance: 0;
  124.     hIcon: 0;
  125.     hCursor: 0;
  126.     hbrBackground: 0;
  127.     lpszMenuName: nil;
  128.     lpszClassName: 'THookSGMsgWindow');

  129. initialization
  130.   hMapFile := OpenFileMapping(FILE_MAP_WRITE, False, cMapFileName);
  131.   DoClear := hMapFile = 0;
  132.   if hMapFile = 0 then
  133.     hMapFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE,
  134.       0, SizeOf(TShareData), cMapFileName);
  135.   P := MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 0);
  136.   if DoClear then FillChar(P^, SizeOf(TShareData), 0);
  137.   //ControlAtomString := Format('ControlOfs%.8X%.8X', [GetModuleHandle(nil), GetCurrentThreadID]);
  138.   //ControlAtomString := Format('ControlOfs%.8X%.8X', [$50300000, $00000F50]);
  139.   //ControlAtomString := Format('ControlOfs%.8X%.8X', [$00400000, GetCurrentThreadID]);
  140.   ControlAtomString := Format('ControlOfs%.8X%.8X', [GetWindowLong(P^.DestWnd, GWL_HINSTANCE), GetWindowThreadProcessId(P^.DestWnd)]);
  141.   ControlAtom := GlobalAddAtom(PChar(ControlAtomString));
  142.   RM_GetObjectInstance := RegisterWindowMessage(PChar(ControlAtomString));
  143.   if P^.DestWnd <> 0 then
  144.   begin
  145.     GetWindowThreadProcessId(P^.DestWnd, DestPID);
  146.     if DestPID = GetCurrentProcessId then
  147.     begin
  148.           MessageBeep(MB_OK);
  149.       DestProcess := True;
  150.       //UtilWindowClass.hInstance := HInstance;
  151.           UtilWindowClass.hInstance := GetWindowLong(P^.DestWnd, GWL_HINSTANCE);
  152.       Windows.RegisterClass(UtilWindowClass);
  153.       P^.MsgWnd := CreateWindowEx(
  154.         WS_EX_TOOLWINDOW,              // extended window style
  155.         UtilWindowClass.lpszClassName, // pointer to registered class name
  156.         UtilWindowClass.lpszClassName, // pointer to window name
  157.         WS_POPUP,                      // window style
  158.         0,                             // horizontal position of window
  159.         0,                             // vertical position of window
  160.         0,                             // window width
  161.         0,                             // window height
  162.         0,                             // handle to parent or owner window
  163.         0,                             // handle to menu, or child-window identifier
  164.         GetWindowLong(P^.DestWnd, GWL_HINSTANCE),                     // handle to application instance
  165.         nil);                          // pointer to window-creation data
  166.       PostMessage(P^.HostWnd, CM_MSGWNDCREATED, P^.MsgWnd, 1);
  167.     end;
  168.   end;
  169. finalization
  170.   if DestProcess then
  171.   begin
  172.     DestroyWindow(P^.MsgWnd);
  173.     PostMessage(P^.HostWnd, CM_MSGWNDCREATED, P^.MsgWnd, 0);
  174.   end;
  175.   GlobalDeleteAtom(ControlAtom);
  176.   ControlAtomString := '';
  177.   UnmapViewOfFile(P);
  178.   CloseHandle(hMapFile);
  179. end.
现在我怀疑是spy++信息中的实例句柄不一致导致的(图中用红笔标示),但又不知道如何修改程序,以前没用过delphi,完全新手
在网上找到一篇靠边的文档,但是信息也不全:
http://bbs.csdn.net/topics/90085650?list=lz
 楼主| xxzouzhichao 发表于 2016-9-3 10:16 来自手机 | 显示全部楼层
yyy71cj 发表于 2016-9-3 07:58
delphi我是用了多年,但是对于这类问题印象也不深。不过可以指给你一个方法。先自己写一个应用,然后用你的 ...

自己写了一个应用,勾到了
但是目标应用就失败了
 楼主| xxzouzhichao 发表于 2016-9-3 17:06 来自手机 | 显示全部楼层
yyy71cj 发表于 2016-9-3 12:07
那有可能版本不一致吧

版本不一致也会失败么?没想过这点额,但我该怎么才能知道原软件的delphi版本呢?
 楼主| xxzouzhichao 发表于 2016-9-4 10:55 | 显示全部楼层
yyy71cj 发表于 2016-9-4 07:04
如果你自己编写的能勾到,而别人编写的勾不到,这一般就只有版本差异了,一般的编码是不会带有版本号的。 ...

这个主意不错!!!!!!!!!!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

298

帖子

6

粉丝
快速回复 在线客服 返回列表 返回顶部