Все о чем пойдет речь работает в основном только на 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-ов и т.п. библиотек.
А вообще эта тема очень большая, неоднозначная и подходит для приличной статьи. Если кто присоединится и выскажет свои идеи или варианты - буду только рад. Вот кстати тоже не плохая
статейка сходная этой задаче.