Форум по программированию Delphi Sources

 



Вернуться   Форум по программированию Delphi Sources > Разное > Исходники и статьи
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 04.04.2011, 20:01
bussianko bussianko вне форума
Прохожий
 
Регистрация: 30.03.2011
Адрес: Bataysk
Сообщения: 7
Версия Delphi: Code Gear 2009
Репутация: 10
Лампочка Статья - PE Sniffer на Delphi - Часть вторая: Таблица секций

И снова здравствуйте!И как я и обещал сегодня я расскажу о таблице секций.Это не слишком сложно и поэтому мы можем сразу перейти к кодингу на Delphi.
Значит, что нам необходимо знать так это - то, что таблица секций находится сразу за заголовком IMAGE_NT_HEADERS.Таким образом прибавив указатель на IMAGE_NT_HEADERS к размеру NT заголовка мы получим указатель на первую секцию, а именно указатель на структуру IMAGE_SECTION_HEADER.Так ещё, что нам необходимо знать так это-то где нам взять количество секций находящихся в образе файла.Взять количество секций можно и даже нужно в структуре IMAGE_FILE_HEADER которая в ходит в состав IMAGE_NT_HEADERS.Ниже её описание:
Код:
typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;// Сигнатура PE Файла имеющая вид $4550
    IMAGE_FILE_HEADER FileHeader; // Структура файлового заголовка
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;//Дополнительный заголовок
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

И ещё несколько слов о структуре IMAGE_SECTION_HEADER. Значит в этой структуре 10 полей, но нас интересует только 5 полей, а именно: Name - в этом поле содержится имя текущей секции.VirtualAddress - адрес структуры в образе. SizeOfData - размер данных. PointerToRAWData - указатель на данные и последний но не менее важный член - это Characteristic - Аттрибуты доступа текущей секции.Суммируя всё это начинаем шкодить
Сначала создадим процедуру которая будет перечислять секции:

Код:
procedure TForm1.LoadSection(pBaseAddr: Pointer);
var
  Nt: ^IMAGE_NT_HEADERS;
begin
  Nt:= GetNtHdr(pBaseAddr);
  if (Assigned(Nt) and (Nt^.Signature = IMAGE_NT_SIGNATURE)) then
  begin
    Section:= Pointer(Cardinal(Nt) + SizeOf(Nt^));//Получаем указатель на первую секцию.
    CountSection:= Nt^.FileHeader.NumberOfSections;
  end;
end;

Здесь мы как и раньше сначала получаем указатель на NT заголовок, потом мы проверяем его сигнатуру и если всё OK тогда мы получаем указатель на первую секцию путём сложения адреса NT заголовка и его размера. Потом получаем количество секций из файлового заголовка.Предварительно я в приватной секции обЪявил две переменные следующего вида:
Код:
private
  Section: ^IMAGE_SECTION_HEADER;//Указатель на Заголовок Секций
  CountSection: Integer;//Количество секций

И наконец я написал ещё одну процедуру которая выводит информацию о каждой секции:

Код:
procedure TForm1.Print_s;
var
  i: Integer;
  Buffer: array [0..7] of WideChar;
  OutStr: String;
  Item: TListItem;
begin
  for i := 1 to CountSection do
  begin
    Item:= ListView1.Items.Add;
    GetSectionName(Buffer, Section^);
    OutStr:= Format('%s', [Buffer]);
    Item.Caption:= OutStr;
    OutStr:= Format('%x', [Section^.VirtualAddress]);
    Item.SubItems.Add(OutStr);
    OutStr:= Format('%x', [Section^.SizeOfRawData]);
    Item.SubItems.Add(OutStr);
    OutStr:= Format('%p', [Pointer(Section^.PointerToRawData)]);
    Item.SubItems.Add(OutStr);
    OutStr:= Format('%x', [Section^.Characteristics]);
    Item.SubItems.Add(OutStr);
    Section:= Pointer(Cardinal(Section) + SizeOf(IMAGE_SECTION_HEADER));
  end;
end;

Вывод я решил осуществить в компонент ListView.Здесь переменная Buffer будет содержать имя текущей секции, а OutStr будет содержать форматированный текст содержащий различные значения взятые из текущего IMAGE_SECTION_HEADER. Далее в цикле перебираю значения и вывожу в компонент.И последний момент, имя секции содержится в массиве типа BYTE, но тип BYTE не совместим с символьными типами Delphi и трактуется как короткое целое.Для того, чтобы получить имя секции я написал ещё одну процедуру которая декодирует имя секции в необходимый нам вид, а именно WideChar потому как я работаю со строками UNICODE.Ниже приведена эта процедура:

Код:
procedure TForm1.GetSectionName(var Buf: array of WideChar;
  var ISH: IMAGE_SECTION_HEADER);
var
  ind: Integer;
begin
{Так как имя секции храниться в массиве типа BYTE, а он не совместим
с символьными типами в Delphi пришлось написать проседуру декодирующую
байты в символы. И так как мы используем кодировку символов UNICODE
приэтом нам необходимо ещё и расширить символы до UNICODE.}
  for ind := 0 to 7 do
  begin
    Buf[ind]:= WideChar(Chr(ISH.Name[ind]));
  end;
end;

Тут из комментариев должно быть всё понятно. В процедуру передаётся по ссылке массив в который мы будем помещать декодированные символы, и по ссылке передаётся структура текущей секции.Это и правда несложно Ну вот и подошла к концу ещё одна статья. В следующей статье расскажу о таблице импорта и это будет гораздо сложнее, но как говориться да осилит дорогу идущий.И вконце концов мы осилм всё.До новых втреч!!!
Изображения
Тип файла: jpg CheckSection.jpg (59.2 Кбайт, 28 просмотров)
Вложения
Тип файла: rar ViewPESection.rar (14.2 Кбайт, 25 просмотров)
Ответить с цитированием
Ответ



Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 20:09.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources", 2004-2020

ВКонтакте   Facebook   Twitter