PE Sniffer на Delphi
ЧАСТЬ 1: NT Заголовок
Доброго времени суток господа Hacker's.
Написать данную статью меня сподвигло то, что очень многие считают Delphi ущербным и не способным на что-то большее чем базы данных и иже сними. Хочу сказать, что базы дан-ных это побочный эффект, а сам Delphi способен на очень многое.(К сожалению сюда не входят драйвера режима ядра).Но хватит лирики и перейдём собственно к делу. Уважаемых гуру прошу не судить меня строго ибо это мой первый печатный опыт.
Итак вопрос, с чего начать? А начнём мы как обычно с краю
))))
Здесь я не буду объяснять устройство PE формата, а расскажу о том как исследовать его про-граммно и именно на Delphi.Итак после того как мы тем или иным образом получили необ-ходимый путь к исполнимому файлу мы должны как-то спроецировать его в память. Я выбрал простейший путь:
Код:
procedure StartDump(wcFilePath: PwideChar);
var
hFile: Cardinal; // Дескриптор открытого файла
hMapp: Cardinal; // Дескриптор Объекта отображения
pMapView: Pointer; // Указатель на спроецированный участок памяти
pNt: ^IMAGE_NT_HEADERS;
begin
hFile:= CreateFile(wcFilePath, GENERIC_READ, FILE_SHARE_READ, NIL, FILE_ATTRIBUTE_NORMAL, 0); //Открываем файл с определёнными привилегиями
if hFile <> INVALID_HANDLE_VALUE then //Проверяем дескриптор на ошибки
begin
hMapp:= CreateFileMapping(hFile, NIL, PAGE_READONLY, 0, 0, NIL);// Создаём объект отображения
if hMapp <> 0 then
begin
pMapView:= MapViewOfFile(hMapp, FILE_MAP_READ, 0, 0, 0); //и отображаем его в память
if Assigned(pMapView) then //Проверка указателя на значение NIL
begin
pNt:= GetNtHeader(pMapView) ; //Получаем указатель на NT заголовок
Здесь необходимо сделать отступление. Можно представить, что первый байт отображения указывает на так называемый DOS заголовок. Но я пошёл другим путём. В библиотеке DbgHelp.DLL имеется очень полезная функция которая обзывается ImageNtHeader, что сле-дует из названия это то, что она возвращает указатель на структуру IMAGE_NT_HEADERS. Но самое печальное то, что она не включена в стандартную поставку Delphi. Но это не проблема. Мы загрузим библиотеку в память и посредством GetProcAddress получим адрес неодходимой нам функции.
В начале модуля после ключевого слова type объявим новый тип данных. Поскольку прото-тип нужной нам функции выглядит следующим образом:
PIMAGE_NT_HEADERS WINAPI ImageNtHeader(PVOID BaseAddr); что это значит мы сей-час разберём. Из прототипа видно, что функция возвращает указатель на структуру типа IM-AGE_NT_HEADERS, а именно этого нам и надо. Ещё из прототипа видно, что функция принимает один параметр: Указатель на первый байт файла отображённого в память. Поэтому мы объявим процедурный тип следующего вида:
TFnImageNtHdr = function(BaseAddr: Pointer): Pointer;stdcall;
Этот новый тип данных есть не что иное как нужный нам прототип. Следующим шагом для удобства будет создание дополнительной функции которая будет возвращать нам указатель на NT заголовок.
Эта функция имеет следующий вид:
Код:
function TForm1. GetNtHdr(LoadBase: Pointer): Pointer;
var
hLib: Cardinal;//Здесь будет храниться дескриптор загруженной библиотеки в памяти
ImageNtHeader: TfnImageNtHdr;//Здесь будет храниться адрес нужной нам функции
pNt: ^IMAGE_NT_HEADERS;
begin
Result:= NIL;
hLib:= LoadLibrary('DbgHelp.DLL');
if hLib <> 0 then
begin
ImageNtHeader:= TFnImageNtHdr(GetProcAddress(hLib, 'ImageNtHeader'));
if Assigned(ImageNtHeader) then
begin
pNt:= ImageNtHeader(LoadBase);
if (Assigned(pNt) and (pNt^.Signature = IMAGE_NT_SIGNATURE) then
begin
Result:= pNt;
FreeLibrary(hLib);//Никогда не забывайте освобождать загруженную вами биб-лиотеку
Exit;
end
else
begin
Result:= NIL;
FreeLibrary(hLib);
end;
end
else
FreeLibrary(hLib);
end;
end;
После того как мы получим указатель на структуру IMAGE_NT_HEADERS нам нужно про-верить сигнатуру PE заголовка, чтобы убедиться, что это действительно PE файл, а не что-то иное.
Код:
if (Assigned(pNt) and (pNt^.Signature = IMAGE_NT_SIGNATURE) then
begin
MessageBox(0, 'Thi is GOOD PE File !!!', 'GOOD!!!', MB_OK);
UnmapViewOfFile(pMapView);
CloseHandle(hMapp);
CloseHandle(hFile);
end
else
begin
MessageBox(0, 'This is BAD PE File', 'ERROR', MB_ICONERROR + MB_ICONSTOP);
UnmapViewOfFile(pMapView);
CloseHandle(hMapp);
CloseHandle(hFile);
end;
end
else
begin
raise TErrMapping.Create('Error mapped file into memory');
CloseHandle(hMapp);
CloseHandle(hFile);
end;
end
else
begin
raise TErrCreateMapping.Create('Error creating object mapped');
CloseHandle(hFile);
end;
end
else
raise TErrCreateFile.Create('Error Open file to mapped into memory');
end;
Ну вот кажись на сегодня всё. В следующей статье я расскажу как пройтись по таблице секций.
До новых встреч.
Автор: bussianko
E-mail: bussianko01@gmail.com