Снятие дампа процесса

Общие вопросы, не зависящие от языка реализации.

Модераторы: Duncon, Hawk, Romeo, Eugie

Ответить
Hellspawn
Сообщения: 5
Зарегистрирован: 01 авг 2004, 07:22
Откуда: Москва

Спасибо, что наставили на путь истинный :roll: конкретизирую ! Нужен
пример, который делает dump блока памяти, где располагаются сегмент кода программы. Вот ! Всем заранее спасибо :D
Если тебе нравится девушка, поставь у нее на компьютере Windows 98. По крайней мере встречаться будете часто!
Аватара пользователя
Naeel Maqsudov
Сообщения: 2570
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

Прошу сильно не наезжать,
Ну как спрашивается тут не наезжать? :)

Во-первых, не понятно, что Вы подразумеваете под "параметры image base, size off image". Может это ресурсы модуля? Тогда дамп не нужен. Нужны функции WinAPI для работы с ресурсами. (Пример программы Resource Explorer есть в DEMOS).

Во-вторых, что такое dump памяти процесса? Блок памяти где располагаются сегмент кода, сегмент стека, и сегмент данных? А может Вам еще нужны блоки памяти, которые процесс взял себе из кучи по LocalAlloc/GlobalAlloc?

В любом случае, Вам понадобятся для этих задач исключительно функции WinAPI, а также учтите, что операционная система не даст просто так доступиться к памятичужого процесса.

Следовательно, совершенно очевидно, что данная тема относится совсем не к Delphi, а к WinAPI, куда благополучно и преезжает...
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

Все о чем пойдет речь работает в основном только на NT-шных системах. Остальные будем надеяться скоро отпадут.
Поностью выкладывать код я не буду, т.к. во-первых его нет, а во-вторых если вы хотите разбираться в таких вещах как память процесса и т.п. придется понят как это работаета а не копировать куски кода.
Ещё одна оговорка, все примеры на С/С++. Как именно это сделать на Делфи я не знаю, но не сомневаюсь, что это возможно и во многом анологично.
Из условия непонятно - дамп кода какого процесса надо получить? Своего или чужого? Разница хоть и не очень большая но существенная. Буду предпологать что всетаки чужого. И так.

I. Открываем процесс
Хотя это достаточно тривиальная задача, обойтись без неё ни как. Допустим, что ID процесса как-нить уже получили (способов для этого куча - все зависит от конкретной задачи) -

Код: Выделить всё

// Открываем процесс (DWORD dwProcessId - идентификатор процесса)
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
II. Получаем HMODULE процесса
Для дальнейшей работы необходим этот идентификатор. Для Своего процесса его можно легко получить с помощью GetModuleHandle(NULL). Как показывает практика он и для других процессов такой же, даже более того он похоже всегда равен 0x00400000, но для надежности следует его получать правильно. А правильно его можно получить с помощью одного выкрутаса -

Код: Выделить всё

// получаем HMODULE 
HMODULE hMod = NULL;
HANDLE hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)GetModuleHandle, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, (LPDWORD)&hMod);
CloseHandle(hThread);
Здесь в другом процессе создается поток который предстовляет собой апишную функцию GetModuleHandle, к счастью параметры его совпадают с параметрами LPTHREAD_START_ROUTINE а адреса таких функций во всех процессах находятся по одним и тем-же адресам, так что вызов её произойдет без особых проблем.

III. Читаем память
Здесь уже может быть куча вариатнов работы. Самое простое воспользоваться функцией из библиотеки PSAPI - GetModuleInformation. Правда для этого в VC 6.0 нужнор последнее SDK или грузить функцию напрямую из psapi.dll. Как с этим обстоят дела в Делфи - незнаю. Вот пример -

Код: Выделить всё

// Получаем стартовый адрес и размер 
MODULEINFO modinfo;
GetModuleInformation(hProc,         // handle to process
                                 hMod,         // handle to module
                                 &modinfo,  // information buffer
                                 sizeof(MODULEINFO)           // size of buffer
                                 );
// Создаем буфер и читаем туда =)
PBYTE pBuffer = new BYTE[modinfo.SizeOfImage];						
ReadProcessMemory(hProc, modinfo.lpBaseOfDll, pBuffer, modinfo.SizeOfImage, &dwReaded);
В этом случаем мы имеем большой кусок памяти в котором лежит весь образ exe файла в пямяти. Т.е pBuffer начинается сначала с досовской сигнатуры, потом идет PE header и все такое. Из этого поучить информация о секциях их размере и где они лежать - уже достаточно тривиальная задача. Все эти заголовки описаны в winnt.h и сушествует множество документации в т.ч. и на русском, описывающей формат PE файлов.
Кроме того, есть один интересный факт позволяющий избавиться от использования библиотеки PSAPI. Дело в том, что hMod это и есть адрес загрузки модуля, т.е. hMod == modinfo.lpBaseOfDll из приведенного примера. Об этом и в MSDN написали. Единственное из него не понятен размер но это уже ни так важно. По этому получить заголовок можно с помощью следующего кода -

Код: Выделить всё

// Запрашиваем размер memory range 
MEMORY_BASIC_INFORMATION mbi;
VirtualQueryEx(hProc, (LPCVOID)hMod, &mbi, sizeof(MEMORY_BASIC_INFORMATION));

// Выделяем память и читаем
PBYTE pBuffer = new BYTE[mbi.RegionSize];
ReadProcessMemory(hProc, mbi.BaseAddress, pBuffer, mbi.RegionSize, &dwReaded);
в этом случае, на сколько я понимаю, в pBuffer лежит так же DOS заголловок и PE header, но уже без всего остального файла. С одной стороны это гораздо удобнее, т.к. не надо выделять огромный кусок для всего файла, а с другой - в этом случае придется для обращений по адресам ведущим из PE header-а каждый раз вызывать VirtualQueryEx и снова копировать память.

С помощью этой методики можно не только получать сегмент кода но и все другие сегменты, кроме того со всем этим работаешь ручками а значит так - как тебе хочется в обход большинства toolhelper-ов и т.п. библиотек.

А вообще эта тема очень большая, неоднозначная и подходит для приличной статьи. Если кто присоединится и выскажет свои идеи или варианты - буду только рад. Вот кстати тоже не плохая статейка сходная этой задаче.
александр1
Сообщения: 4
Зарегистрирован: 19 окт 2009, 20:49

поднему темку. 1 вопрос появился, у меня по чему-то компилятор не видет функцию CreateRemoteThread, вроде все библиотеки подключил, что это может быть?
Ответить