Информация из другого приложения
От: Oxygenium  
Дата: 03.05.05 22:51
Оценка:
Пытаюсь выдернуть данные из ListView другого приложения (назовем его "жертва").
Окно ищу с помощью FindWindow(), нахожу там SysListView32, но при попытке получить данные из этого ListView приложение-жертва просто валится.
Вот часть кода:
HWND wnd = FindWindow(0, "Processes");
wnd = ::GetWindow(wnd, GW_CHILD);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
CListViewCtrl list(wnd);
int count = list.GetItemCount(); // Здесь в count возвращается правильное число, т.е. колличество элементов в ListView приложения-жертвы
std::string data;
data.resize(256);
list.GetItemText(5,0, &name[0], 255); // На этой строчке приложение-жерта вылетает с ошибкой.

GetClassName() у полученного HWND проверял, это действительно SysListView32.

Может кто знает в чем проблема, или как по другому получить данные?



04.05.05 08:22: Перенесено модератором из 'ATL/WTL' — Odi$$ey
Re: Информация из другого приложения
От: SWW Россия  
Дата: 04.05.05 04:19
Оценка: +2
Здравствуйте, Oxygenium, Вы писали:

O>Пытаюсь выдернуть данные из ListView другого приложения (назовем его "жертва").

O>Окно ищу с помощью FindWindow(), нахожу там SysListView32, но при попытке получить данные из этого ListView приложение-жертва просто валится.
O>Вот часть кода:
O>
O>list.GetItemText(5,0, &name[0], 255); // На этой строчке приложение-жерта вылетает с ошибкой.
O>

O>GetClassName() у полученного HWND проверял, это действительно SysListView32.

Подозреваю, что данные записываются в адресное пространство "жертвы", потому она и валится. Кстати, а что такое name?
Re: Информация из другого приложения
От: Radmir Россия  
Дата: 04.05.05 05:03
Оценка:
Попробуй так:

#include <commctrl.h>
.
.
.
HWND wnd = FindWindow(0, "Processes");
wnd = ::GetWindow(wnd, GW_CHILD);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);

int count = ListView_GetItemCount(wnd);
std::string data; // А это зачем ????
data.resize(256);
char ItemText [1024];
ListView_GetItemText(wnd,5,0,&ItemText,1024);
... << RSDN@Home 1.1.3 stable >>
Лучше спросить дорогу чем заблудиться
Re[2]: Информация из другого приложения
От: Аноним  
Дата: 04.05.05 07:02
Оценка:
Здравствуйте, Radmir, Вы писали:

R>Попробуй так:


R>
R>#include <commctrl.h>
R>.
R>.
R>.
R>HWND wnd = FindWindow(0, "Processes");
R>wnd = ::GetWindow(wnd, GW_CHILD);
R>wnd = ::GetWindow(wnd, GW_HWNDNEXT);
R>wnd = ::GetWindow(wnd, GW_HWNDNEXT);
R>wnd = ::GetWindow(wnd, GW_HWNDNEXT);
R>wnd = ::GetWindow(wnd, GW_HWNDNEXT);
R>wnd = ::GetWindow(wnd, GW_HWNDNEXT);
R>wnd = ::GetWindow(wnd, GW_HWNDNEXT);

R>int count = ListView_GetItemCount(wnd);
R>std::string data; // А это зачем ????
R>data.resize(256);
R>char ItemText [1024];
R>ListView_GetItemText(wnd,5,0,&ItemText,1024); //это тоже не будет работать

R>ListView_GetItemText(wnd,5,0,ItemText,1024);[/b] //правильнее
R>


Ну а вообще мне кажется, я не уверен, скорее всего это тоже не будет работать. Окно создано в адресном пространстве другого приложения, а вы ему указатель даете из другого адресного пространства. Тут нужно что-то покруче.
Re[3]: Информация из другого приложения
От: Radmir Россия  
Дата: 04.05.05 09:34
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Ну а вообще мне кажется, я не уверен, скорее всего это тоже не будет работать. Окно создано в адресном пространстве другого приложения, а вы ему указатель даете из другого адресного пространства. Тут нужно что-то покруче.

Если хочешь что-то покруче то ставь хуки на "жертву". И с помошью сообшений или файлов отображаемых на память общайся со своим приложением.
... << RSDN@Home 1.1.3 stable >>
Лучше спросить дорогу чем заблудиться
Re[4]: Информация из другого приложения
От: Oxygenium  
Дата: 04.05.05 14:06
Оценка:
Спасибо за ответы.
Да, действительно замена на ListView_GetItemText(wnd,5,0,ItemText,1024) непомогла, жертва все равно падает.
А вот как сделать "покруче" я незнаю, если можно расскажите поподробнее, линки на статьи тоже непомешают.
Re[5]: Информация из другого приложения
От: Андрей Мельник Украина  
Дата: 04.05.05 17:33
Оценка:
Здравствуйте, Oxygenium, Вы писали:

O>Спасибо за ответы.

O>Да, действительно замена на ListView_GetItemText(wnd,5,0,ItemText,1024) непомогла, жертва все равно падает.
O>А вот как сделать "покруче" я незнаю, если можно расскажите поподробнее, линки на статьи тоже непомешают.

Тут набор стандартый GetWindowThreadProcessId, OpenProcess, VirtualAllocEx, ReadProcessMemory. Пример
http://rsdn.ru/Forum/?mid=11702
Re[5]: Информация из другого приложения
От: elGeminy  
Дата: 04.05.05 17:45
Оценка:
Здравствуйте, Oxygenium, Вы писали:

O>Спасибо за ответы.

O>Да, действительно замена на ListView_GetItemText(wnd,5,0,ItemText,1024) непомогла, жертва все равно падает.
O>А вот как сделать "покруче" я незнаю, если можно расскажите поподробнее, линки на статьи тоже непомешают.

Можно ввести dll в адресное пространство процесса, и оттуда уже издеваться над жертвой
Грубо говоря, библотека входит в состав приложения, только приложение об этом не подозревает. Что потом можно намутить, думаю, вы представляете...
Re[6]: Информация из другого приложения
От: Oxygenium  
Дата: 04.05.05 17:48
Оценка:
Здравствуйте, Андрей Мельник, Вы писали:

АМ>Здравствуйте, Oxygenium, Вы писали:


O>>Спасибо за ответы.

O>>Да, действительно замена на ListView_GetItemText(wnd,5,0,ItemText,1024) непомогла, жертва все равно падает.
O>>А вот как сделать "покруче" я незнаю, если можно расскажите поподробнее, линки на статьи тоже непомешают.

АМ>Тут набор стандартый GetWindowThreadProcessId, OpenProcess, VirtualAllocEx, ReadProcessMemory. Пример

АМ>http://rsdn.ru/Forum/?mid=11702
Спасибо, попробую.
Re[6]: Информация из другого приложения
От: Oxygenium  
Дата: 05.05.05 18:18
Оценка:
Здравствуйте, Андрей Мельник, Вы писали:

АМ>Здравствуйте, Oxygenium, Вы писали:


O>>Спасибо за ответы.

O>>Да, действительно замена на ListView_GetItemText(wnd,5,0,ItemText,1024) непомогла, жертва все равно падает.
O>>А вот как сделать "покруче" я незнаю, если можно расскажите поподробнее, линки на статьи тоже непомешают.

АМ>Тут набор стандартый GetWindowThreadProcessId, OpenProcess, VirtualAllocEx, ReadProcessMemory. Пример

АМ>http://rsdn.ru/Forum/?mid=11702

Сделал как написано. Да действительно приложение жертва уже не вылетает, но и результат — всегда пустая строка:

HWND wnd = FindWindow(0, "Processes");
wnd = ::GetWindow(wnd, GW_CHILD);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);
wnd = ::GetWindow(wnd, GW_HWNDNEXT);

DWORD dwProcessId; 
GetWindowThreadProcessId(wnd, &dwProcessId); 
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwProcessId); 
LPSTR lpsz = (LPSTR) VirtualAllocEx(hProcess, NULL, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 
ListView_GetItemText(wnd,0,0,lpsz,1024);
char ItemText[1024];
BOOL r = ReadProcessMemory(hProcess, lpsz, ItemText, 1024, NULL); // После выполнения в ItemText - пустая строка
VirtualFreeEx(hProcess, lpsz, 0, MEM_RELEASE);

Кто знает в чем теперь проблема?
Re[7]: Информация из другого приложения
От: Oxygenium  
Дата: 06.05.05 17:21
Оценка:
Непонятно где-же теперь ошибка. Кто знает как можно проверить где именно ошибка? Может создать приаттачится к прочессу-жертве (самому ее написать) и отловить сообщение там?
Re[8]: Информация из другого приложения
От: Oxygenium  
Дата: 09.05.05 22:34
Оценка: 3 (1)
Наконец понял в чем моя ошибка, вот рабочий код:
void getItemText(HWND wnd, char *text, int item, int subItem)
{
    DWORD dwProcessId; 
    GetWindowThreadProcessId(wnd, &dwProcessId); 
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS/*PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE*/, FALSE, dwProcessId); 
    LPSTR lpsz = (LPSTR)VirtualAllocEx(hProcess, NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 
    LVITEM lvis = { 0 };
    lvis.iSubItem = subItem;
    lvis.cchTextMax = 1024;
    lvis.pszText = lpsz;
    LVITEM *lvi = (LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 
    WriteProcessMemory(hProcess, lvi, &lvis, sizeof(LVITEM), NULL);
    ::SendMessage(wnd, LVM_GETITEMTEXT, (WPARAM)item, (LPARAM)lvi);
    BOOL r = ReadProcessMemory(hProcess, lpsz, text, 1024, NULL); 
    VirtualFreeEx(hProcess, lpsz, 0, MEM_RELEASE); 
}
Re[2]: Информация из другого приложения
От: Alex Alexandrov США  
Дата: 10.05.05 08:10
Оценка:
Здравствуйте, Radmir, Вы писали:

R>Попробуй так:


...

Цитата из CommCtrl.h:

#define SNDMSG ::SendMessage
...
#define ListView_GetItemCount(hwnd) \
    (int)SNDMSG((hwnd), LVM_GETITEMCOUNT, 0, 0L)


Так что, разумеется, любое общение с ListView в конечном счете сводится к посылке сообщения. И ничего хорошего при посылке указателей в другой процесс ожидать не стоит. Это будет работать только для старых элементов управления, пришедших из 3.11. Про это еще дядя Рихтер писал:

The problem is that most common control window messages, such as LVM_GETITEM and LVM_GETITEMPOSITION, do not work across process boundaries.

Here's why: the LVM_GETITEM message requires that you pass the address of an LV_ITEM data structure for the message's LPARAM parameter. Because this memory address is meaningful only to the process that is sending the message, the process receiving the message cannot safely use it. So to make DIPS work as advertised, you must inject code into Explorer.exe that sends LVM_GETITEM and LVM_GETITEMPOSITION messages successfully to the desktop's ListView control.

You can send window messages across process boundaries to interact with built-in controls (such as button, edit, static, combo box, list box, and so on), but you can't do so with the new common controls. For example, you can send a list box control created by a thread in another process an LB_GETTEXT message where the LPARAM parameter points to a string buffer in the sending process. This works because Microsoft checks specifically to see whether an LB_GETTEXT message is being sent, and if so, the operating system internally creates memory-mapped files and copies the string data across process boundaries.

Why did Microsoft decide to do this for the built-in controls and not for the new common controls? The answer is portability. In 16-bit Windows, in which all applications run in a single address space, one application could send an LB_GETTEXT message to a window created by another application. To port these 16-bit applications to Win32 easily, Microsoft went to the extra effort of making sure that this still works. However, the new common controls do not exist in 16-bit Windows and therefore there was no porting issue involved, so Microsoft chose not to do the additional work for the common controls.

[ Posted via RSDN@Home 1.1.4 beta 5 (395) listening to silent ]
It's kind of fun to do the impossible (Walt Disney)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.