介紹
最近正試着從其他程序的listview控件中獲取信息,因爲需要傳遞一個指針以便存放取得的字符串,但Windows使用的是虛擬內存,指針是不允許跨進程訪問的。
Windows是這樣通過虛擬內存來管理分配給所有應用程序的內存的:它讓程序認爲自己擁有2GB的內存空間可用,它也通過保護來避免程序互相佔用內存.這樣當一個程序有問題時,不會影響到其他程序。
寫了一些代碼之後,我認識到我的指針是不允許的,所以無法工作。通過幾個小時在MSDN上的發掘,我找到了這幾個函數VirtualAllocEx(), VirtualFreeEx()
, WriteProcessMemory()
and ReadProcessMemory()
. 有了這些函數的武裝,我修改了我的代碼:
#define WIN32_LEAN_AND_MEAN #include <stdio.h> #include <windows.h> #include <commctrl.h> int main(void) { /* 找到在wnidows下運行的listview. */ HWND hwnd=FindWindow(NULL, "Stealing Program's Memory: ListView"); HWND listview=FindWindowEx(hwnd, NULL, "SysListView32", NULL); int count=(int)SendMessage(listview, LVM_GETITEMCOUNT, 0, 0); int i; char item[512], subitem[512]; /* 顯示 listview 中的每一項以及它的子項 並且一個一個的打印出來. */ LVITEM lvi; lvi.cchTextMax=512; for(i=0; i<count; i++) { lvi.iSubItem=0; lvi.pszText=item; SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)&lvi); lvi.iSubItem=1; lvi.pszText=subitem; SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)&lvi); printf("%s - %s/n", item, subitem); } return 0; }
就象我之前所說的,這無法工作,指向lvi,item和subitem的指針在跨進程訪問時都出現了問題,如何解決呢?通過
WriteProcessMemory()和ReadProcessMemory()來使用其他程序的內存,在其他進程內實現LVM_GETITEMTEXT
並返回。從另外的程序內的listview控件讀取items真象一個黑客。
首先,我們得到listview的進程,象下面這樣:
unsigned long pid; HANDLE process; GetWindowThreadProcessId(listview, &pid); process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ| PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
然後我們創建三個指針LVITEM *_lvi, char *_item
, and char *_subitem 用VirtualAllocEx()把它們分配到
另外程序的虛擬內存空間裏。
LVITEM *_lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM),
MEM_COMMIT, PAGE_READWRITE);
char *_item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
char *_subitem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
現在,我們用lvi.pszText指向
_item並且用WriteMemoryProcess()把它的內存拷貝到_lvi
lvi.pszText=_item;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
現在我們有了一個LVITEM指針它在另外一個程序的虛擬內存空間是可以使用的,我們可以發送LVM_GETITEMTEXT消息給
listvie並且拷貝_item的文本到item中,這樣我們就能在自己的程序裏讀取它。
SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(process, _item, item, max, NULL);
在subitem中重複,然後釋放我在其他程序裏分配的內存:
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);
哈!一切OK,
#define WIN32_LEAN_AND_MEAN #include <stdio.h> #include <windows.h> #include <commctrl.h> int main(void) { HWND hwnd=FindWindow(NULL, "Stealing Program's Memory: ListView"); HWND listview=FindWindowEx(hwnd, NULL, "SysListView32", NULL); int count=(int)SendMessage(listview, LVM_GETITEMCOUNT, 0, 0); int i; LVITEM lvi, *_lvi; char item[512], subitem[512]; char *_item, *_subitem; unsigned long pid; HANDLE process; GetWindowThreadProcessId(listview, &pid); process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ| PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid); _lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE); _item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT, PAGE_READWRITE); _subitem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT, PAGE_READWRITE); lvi.cchTextMax=512; for(i=0; i<count; i++) { lvi.iSubItem=0; lvi.pszText=_item; WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL); SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi); lvi.iSubItem=1; lvi.pszText=_subitem; WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL); SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi); ReadProcessMemory(process, _item, item, 512, NULL); ReadProcessMemory(process, _subitem, subitem, 512, NULL); printf("%s - %s/n", item, subitem); } VirtualFreeEx(process, _lvi, 0, MEM_RELEASE); VirtualFreeEx(process, _item, 0, MEM_RELEASE); VirtualFreeEx(process, _subitem, 0, MEM_RELEASE); return 0; }
轉自:http://blog.csdn.net/jia_xiaoxin/article/details/2916899