原理QTP,编写属于自己的控件控制插件
上一篇 / 下一篇 2009-05-07 17:50:25 / 个人分类:体会
很久没有来51testing了,忙死,看到陈旧的BLOG,就随便写点文章冲数拉,虽然拙劣,但始终是我的原著嘛,我就自己打上水印了,拒绝盗版哦,如有错误或者建议,还是可以通过mythxhg@163.com与我联系.
在QTP应付一些不识别对象或者QTP无法达到自己的期望的时候,许多人都感到无可奈何,也尽量用一些小技巧小方法左缝右补,但始终是显得力不从心,无法达到满意的自动化效果,我也层总结过自己应付这类型问题的方法,下面我就详细讲解一种正面解决问题的方法,也就是编写自己的控件控制插件。
在此之前,先简单讲解一下有关进程内控制以及跨进程控制的基本知识。
1.进程内控制,这个可以说会写代码的人都会,因为他们编写的代码就是控制其控件按其自己想要的方式运行的过程。
例如
在进程内部知道自己的句柄m_hClient后可以这样用
CListCtrl* cw = (CListCtrl*)( CWnd::FromHandle(m_hClient) );
CString sss = cw->GetItemText(0,0);
2.再说说跨进程控制,跨进程控制中,什么信息对我们有用?需要跨进程控制某个窗体,对我们有用的当然是窗口句柄啦。QTP对一些不识别的对象都识别为WINOBJECT.对吧,但QTP虽然不识别,但还是可以做最基本的CLick,Move,获取位置,句柄等等。为什么呢?因为正是使用了句柄。
说到这里可能有很多人想,喔,原来这么简单,那我用QTP取到句柄之后就随便写控制代码啦。真的这么简单吗?51testing上有个例子是用句柄把窗口隐藏,没错,这个直接用ShowWindow(Handle,SW_HIDE)就可以了。的确,直接使用句柄就可以实现部分控制了,但是直接使用所能控制的程度有限,因为你能直接控制时因为对方认为这些操作都是合法的,有权限的,CListCtrl继承于CWnd,而CWnd的大部分方法对外是开放的,这是废话,要不你也操作了不窗口啦,所以CWnd的一些对外开放的操作同样可以用到CListCtrl上,正因如此我们才可以使用这些操作,但是如果你用上面得方法CListCtrl* cw = (CListCtrl*)( CWnd::FromHandle(m_hClient) );CString sss = cw->GetItemText(0,0),我敢保证你取不到任何值,甚至你的程序会崩溃。为什么呢?因为这些操作是CListCtrl内部使用的,它没有对系统公开,要不然WINDOWS就乱套了,随便写点东西就把你的程序改了。
&说了那么多那么乱,其实就说明一个,窗体对你开放的操作你是可以直接用它的句柄进行操作就可以了,但对哪些受保护的操作我们是没有权限取执行的,因为他们位于不同的进程空间,权限是其一,不同进程控件的内存寻址也是导致你无法直接控制的原因。所以,要取得权限,你的操作必须是在对方进程内部使用。
好,那么怎样取得权限?注入。。对,远程注入,注入的方法很多,但现在我讲解其中一种,注入DLL(DLL注入也有几种方法,1是钩子,2是远程调用,下面讲解的是第2种方法,钩子是消息驱动的,各位也可以试试,相对来说钩子更简单,但受限于消息,我更喜欢远程调用)。
理一下思路,现在我们要把
CListCtrl* cw = (CListCtrl*)( CWnd::FromHandle(m_hClient) );
CString sss = cw->GetItemText(0,0);
这些代码放到DLL内部注入到其他进程中。
代码如下:
CString szApp = "TestApp.exe";
CString szDll = "D:\\AtmRobot\\Src\\Hacker\\Debug\\Hacker.dll";
DWORD m_dwProcessId = 0;
DWORD hLibModule; //已加载的DLL的基地址(HMODULE);
PROCESSENTRY32 pe;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Process32First(hSnapshot, &pe);
do{
if(strcmp(pe.szExeFile,szApp) == 0 )
{
m_dwProcessId =pe.th32ProcessID;
break;
}
}while (Process32Next(hSnapshot, &pe));
CloseHandle(hSnapshot);
LPSTR lpszRemoteFile,lpszLibName;
lpszLibName = (LPSTR)(LPCTSTR)szDll;
HANDLE hProcess;
hProcess = OpenProcess(PROCESS_CREATE_THREAD
| PROCESS_VM_OPERATION
| PROCESS_VM_WRITE,
FALSE,
m_dwProcessId);
lpszRemoteFile = (LPSTR)VirtualAllocEx
(hProcess, NULL, sizeof(CHAR) * strlen(lpszLibName) + 1, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, lpszRemoteFile, (PVOID)lpszLibName, sizeof(CHAR) * strlen(lpszLibName) + 1, NULL);
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(