eXeLab
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 сентября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Русский / Russian English / Английский

Сейчас на форуме: zombi-vadim, dconer1 (+1 невидимый пользователь)
 · Начало · Статистика · Регистрация · Поиск · ПРАВИЛА ФОРУМА · Язык · RSS · SVN ·

 eXeL@B —› Протекторы —› После добавления секции PE файл не запускается
Посл.ответ Сообщение

Ранг: 7.5 (гость)
Статус: Участник

Создано: 31 августа 2016 19:16 New!
Цитата · Личное сообщение · #1

После добавления новой секции в PE-файл он перестает запускаться (невозможно запустить это приложение на вашем пк). Если удалить добавленную секцию при помощи LordPE, то при запуске просто ничего не происходит. Байты заголовка добавленной секции почему-то не обнуляются. Показываю кодесы:

Для открытия и проецирования PE-файла
Code:
  1. int open_input_file(char *filename, file_data *p_file)
  2. {
  3.          HANDLE file;
  4.          HANDLE file_mapping;
  5.          void   *file_base;
  6.          unsigned long size, upper_size;
  7.  
  8.          file = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL,
  9.                                      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  10.          if (file == INVALID_HANDLE_VALUE)
  11.                  return FALSE;
  12.  
  13.          size = GetFileSize(file, &upper_size);
  14.          file_mapping = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, size, NULL);
  15.          if (!file_mapping)
  16.                  return FALSE;
  17.  
  18.          file_base = MapViewOfFile(file_mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size);
  19.          if (file_base == NULL)
  20.                  return FALSE;
  21.  
  22.          p_file->name = filename;
  23.          p_file->size = size;
  24.          p_file->file = file;
  25.          p_file->file_mapping = file_mapping;
  26.          p_file->file_base = (unsigned char *)file_base;
  27.  
  28.          return TRUE;
  29. }


Для сохранения изменений и закрытия:
Code:
  1. void close_file_data(file_data *p_file)
  2. {
  3.          FlushViewOfFile(p_file->file_base, 0);
  4.          UnmapViewOfFile(p_file->file_mapping);
  5.          CloseHandle(p_file->file_mapping);
  6.          SetFilePointer(p_file->file, p_file->size, NULL, FILE_BEGIN);
  7.          SetEndOfFile(p_file->file);
  8.          CloseHandle(p_file->file);
  9. }


Код добавления секции:
Code:
  1. int add_section(file_data *p_file, char *new_section_name, DWORD new_section_size)
  2. {
  3.          PIMAGE_DOS_HEADER dos_header;
  4.          PIMAGE_NT_HEADERS nt_header;
  5.          PIMAGE_SECTION_HEADER last_section, new_section;
  6.  
  7.          dos_header = (PIMAGE_DOS_HEADER)p_file->file_base;
  8.          nt_header  = MakePtr(PIMAGE_NT_HEADERS, p_file->file_base, dos_header->e_lfanew);
  9.  
  10.          last_section = IMAGE_FIRST_SECTION(nt_header) + nt_header->FileHeader.NumberOfSections - 1;
  11.          new_section  = IMAGE_FIRST_SECTION(nt_header) + nt_header->FileHeader.NumberOfSections;
  12.          ZeroMemory(new_section, sizeof(IMAGE_SECTION_HEADER));
  13.          new_section->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
  14.          CopyMemory(new_section->Name, new_section_name, 8);
  15.          new_section->Misc.VirtualSize = new_section_size;
  16.          new_section->PointerToRawData = ALIGN_UP(last_section->PointerToRawData + last_section->SizeOfRawData,
  17.                                                                nt_header->OptionalHeader.FileAlignment);
  18.          new_section->SizeOfRawData = ALIGN_UP(new_section_size, nt_header->OptionalHeader.SectionAlignment);
  19.          new_section->VirtualAddress = ALIGN_UP(last_section->VirtualAddress + last_section->Misc.VirtualSize,
  20.                                                          nt_header->OptionalHeader.SectionAlignment);
  21.          nt_header->OptionalHeader.SizeOfImage = new_section->VirtualAddress + new_section->Misc.VirtualSize;
  22.          nt_header->FileHeader.NumberOfSections++;
  23.  
  24.          return TRUE;
  25. }


Функция для заполнения добавленной секции кодом из некоторого файла:
Code:
  1. void fill_with_code(file_data *p_file, char *p_code, unsigned long code_size, char *new_section_name)
  2. {
  3.          PIMAGE_DOS_HEADER dos_header;
  4.          PIMAGE_NT_HEADERS nt_header;
  5.          PIMAGE_SECTION_HEADER section;
  6.  
  7.          dos_header = (PIMAGE_DOS_HEADER)p_file->file_base;
  8.          nt_header = MakePtr(PIMAGE_NT_HEADERS, p_file->file_base, dos_header->e_lfanew);
  9.  
  10.          if (add_section(p_file, new_section_name, code_size) != TRUE)
  11.          {
  12.                  MessageBox(NULL, "Cant add new section", "Err", MB_OK);
  13.          }
  14.          section = find_section(new_section_name, nt_header);
  15.          if (section == NULL)
  16.          {
  17.                  MessageBox(NULL, "Cant find added section", "Err", MB_OK);
  18.                  return;
  19.          }
  20.  
  21.          MessageBox(NULL, (const char *)section->Name, "Section added", MB_OK);
  22.  
  23.          //CopyMemory((void *)(p_file->file_base + section->PointerToRawData), p_code, code_size);
  24. }


Главная функция:
Code:
  1. int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, PSTR pszCmdLine, int nCmdShow)
  2. {
  3.          file_data in_file, code_file;
  4.          char in_filename[MAX_PATH] = "loader.exe";
  5.          char code_filename[MAX_PATH] = "code.exe";
  6.          HANDLE console;
  7.  
  8.          console = GetStdHandle(STD_OUTPUT_HANDLE);
  9.  
  10.          if (!open_input_file(in_filename, &in_file))
  11.          {
  12.                  MessageBox(NULL, "Err while opening in file", "Err", MB_OK);
  13.                  return 0;
  14.          }
  15.          if (!open_input_file(code_filename, &code_file))
  16.          {
  17.                  MessageBox(NULL, "Err while opening code file", "Err", MB_OK);
  18.                  return 0;
  19.          }
  20.  
  21.          MessageBox(NULL, "Trying to add code", "Info", MB_OK);
  22.          fill_with_code(&in_file, (char *)code_file.file_base, 0x1000, ".loader");
  23.  
  24.          close_file_data(&in_file);
  25.          close_file_data(&code_file);
  26. }


Ну и макросы:
Code:
  1. #ifdef _WIN64
  2.          #define MakePtr(cast, ptr, addValue) (cast)( (DWORD64)(ptr) + (DWORD64)(addValue))
  3. #else
  4.          #define MakePtr(cast, ptr, addValue) (cast)( (DWORD)(ptr) + (DWORD)(addValue) )
  5. #endif
  6.  
  7. #define ALIGN_DOWN(x, align) (& ~(align - 1))
  8. #define ALIGN_UP(x, align) ((& (align - 1)) ? ALIGN_DOWN(x, align) + align : x) 


Что я сделал не так, из-за чего PE-файл портится?


Ранг: 1989.1 (!!!!)
Статус: Модератор
retired

Создано: 31 августа 2016 20:39 New!
Цитата · Личное сообщение · #2

Есть плаг PEVerifier для HIEW, можешь им прогнать свой файл.

Ранг: 7.5 (гость)
Статус: Участник

Создано: 31 августа 2016 20:56 · Поправил: 31 августа 2016 21:53 ZeroMemory New!
Цитата · Личное сообщение · #3

Я перечитал начало статьи "Об упаковщиках в последний раз" и нашел там, что поле SizeOfRawData должно быть меньше поля VirtualSize заголовка секции. Похоже, у меня в функции add_section ошибка, потому что PETools показывает VirtualSize = 600, а RawSize = 1000.

Может быть, тут ошибка, и надо выравнивать на FileAligment?

Code:
  1. new_section->SizeOfRawData = ALIGN_UP(new_section_size, nt_header->OptionalHeader.SectionAlignment);


Теперь эти поля равны, но файл все равно не загружается. Равенство, вроде, допустимо.

Добавлено спустя 57 минут
Archer пишет:
Есть плаг PEVerifier для HIEW, можешь им прогнать свой файл.


Как им пользоваться? Скопировал в папку hiew/hem, на странице про этот аддон нашел, что загружать его надо кнопкой F11, но ничего не происходит.


Ранг: 149.4 (ветеран)
Статус: Участник

Создано: 1 сентября 2016 00:38 · Поправил: 1 сентября 2016 02:36 -=AkaBOSS=- New!
Цитата · Личное сообщение · #4

ZeroMemory
покажи хоть файлы до/после обработки, а там уже код копать бум

и кстати говоря, не мешало бы проверять, а есть ли в хидере еще место для новой структуры IMAGE_SECTION_HEADER, или нужно сдвигать все секции дальше (есть такие файлы, у которых секции уже с 0x200 начинаются, в них таким путём можно влететь в физические данные первой секции)

ZeroMemory пишет:
Может быть, тут ошибка, и надо выравнивать на FileAligment?

по сути это некритично, просто надо убедиться что в файл будет записаны данные соответствующей длины.

ZeroMemory пишет:
поле SizeOfRawData должно быть меньше поля VirtualSize

чёт не нашёл там такого.

VirtualSize отвечает за размер выделяемой памяти, а SizeOfRawData - за длину данных считываемых из файла, но их сравнение следует производить только выровняв их на SectionAlignment и FileAlignment соответственно

например, имеется секция с характеристиками
VirtualSize = 0xABC, SizeOfRawData = 0xCDE, FileAlignment = 0x400, SectionAlignment = 0x1000

ALIGN_UP (VirtualSize, SectionAlignment) даст в результате 0x1000
ALIGN_UP (SizeOfRawData, FileAlignment) тоже даст 0x1000
таким образом получится область памяти 0х1000 байт, в которую будет считано соответственно 0х1000 байт из файла (ну или до конца файла, но файл не может быть короче чем PointerToRawData+SizeOfRawData)

Ранг: 408.1 (мудрец)
Статус: Участник

Создано: 1 сентября 2016 05:42 · Поправил: 1 сентября 2016 05:48 dosprog New!
Цитата · Личное сообщение · #5

ZeroMemory пишет:
поле SizeOfRawData должно быть меньше поля VirtualSize заголовка секции.


Или равно.

ZeroMemory пишет:
Как им пользоваться? Скопировал в папку hiew/hem, на странице про этот аддон нашел, что загружать его надо кнопкой F11, но ничего не происходит.


По F11 должно открыться плагинное меню.


Ранг: 49.6 (посетитель)
Статус: Участник

Создано: 1 сентября 2016 06:14 New!
Цитата · Личное сообщение · #6

ZeroMemory пишет:
Что я сделал не так, из-за чего PE-файл портится?

заголовок секции (IMAGE_SECTION_HEADER) вы добавили, а кто будет добавлять тело секции?

Ранг: 7.5 (гость)
Статус: Участник

Создано: 1 сентября 2016 20:18 New!
Цитата · Личное сообщение · #7

-=AkaBOSS=- пишет:
покажи хоть файлы до/после обработки, а там уже код копать бум


Файл до добавления секции: http://rgho.st/8bKfwvKzt
Файл после добавления: http://rgho.st/6tr8KNNTH

-=AkaBOSS=- пишет:
и кстати говоря, не мешало бы проверять, а есть ли в хидере еще место для новой структуры IMAGE_SECTION_HEADER

Я проверил, место есть. Я секции не мержил, и в редакторе видны нулевые байты выравнивания.

-=AkaBOSS=- пишет:
VirtualSize отвечает за размер выделяемой памяти

В том файле, который запускается, эти значения совсем маленькие и точно соответствуют размеру данных без выравнивания. Почему так? Я читал, что VirtualSize - это размер секции в памяти, то есть он должен быть выровнен.

UniSoft пишет:
заголовок секции (IMAGE_SECTION_HEADER) вы добавили, а кто будет добавлять тело секции?

Это верно, но почему-то я не могу добавить тело секции. Вот код:

Code:
  1.  
  2.  
  3.     void fill_with_code(file_data *p_file, char *p_code, unsigned long code_size, char *new_section_name)
  4.     {
  5.              PIMAGE_DOS_HEADER dos_header;
  6.              PIMAGE_NT_HEADERS nt_header;
  7.              PIMAGE_SECTION_HEADER section;
  8.      
  9.              dos_header = (PIMAGE_DOS_HEADER)p_file->file_base;
  10.              nt_header = MakePtr(PIMAGE_NT_HEADERS, p_file->file_base, dos_header->e_lfanew);
  11.      
  12.              if (add_section(p_file, new_section_name, code_size) != TRUE)
  13.              {
  14.                      MessageBox(NULL, "Cant add new section", "Err", MB_OK);
  15.              }
  16.              section = find_section(new_section_name, nt_header);
  17.              if (section == NULL)
  18.              {
  19.                      MessageBox(NULL, "Cant find added section", "Err", MB_OK);
  20.                      return;
  21.              }
  22.      
  23.              MessageBox(NULL, (const char *)section->Name, "Section added", MB_OK);
  24.      
  25.              CopyMemory((void *)(p_file->file_base + section->PointerToRawData), p_code, code_size);
  26.     }
  27.  
  28.  


Если раскомментировать CopyMemory, то я пытаюсь записать данные по смещению секции (или PointerToRawData, или VirtualAddress). Ни по одному адресу запись не срабатывает, и после сохранения данных при помощи FlushViewOfFile на диске добавляется только заголовок, а тела секции нет ни в каком месте файла.

Добавлено спустя 2 минуты
Главную функцию я сделал немного проще. Добавляю не содержимое бинарного файла в секцию, а строковый литерал.

Code:
  1. int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, PSTR pszCmdLine, int nCmdShow)
  2. {
  3.          file_data in_file;
  4.          char in_filename[MAX_PATH] = "loader.exe";
  5.          char data[] = "TESTSECTION";
  6.  
  7.          if (!open_input_file(in_filename, &in_file))
  8.          {
  9.                  MessageBox(NULL, "Err while opening in file", "Err", MB_OK);
  10.                  return 0;
  11.          }
  12.  
  13.          MessageBox(NULL, "Trying to add section", "Info", MB_OK);
  14.          fill_with_code(&in_file, data, 11, ".loader");
  15.  
  16.          close_file_data(&in_file);
  17. }


Ранг: 1989.1 (!!!!)
Статус: Модератор
retired

Создано: 1 сентября 2016 20:54 New!
Цитата · Личное сообщение · #8

А кто обещал, что маппинг возможно расширять?

| Сообщение посчитали полезным: ajax


Ранг: 7.5 (гость)
Статус: Участник

Создано: 1 сентября 2016 21:02 New!
Цитата · Личное сообщение · #9

То есть кроме как правкой образа на диске добавить секцию никак нельзя? Или можно отобразить файл с запасом?
Про расширение отображенного образа-то я и не подумал.


Ранг: 149.4 (ветеран)
Статус: Участник

Создано: 2 сентября 2016 00:31 · Поправил: 2 сентября 2016 00:38 -=AkaBOSS=- New!
Цитата · Личное сообщение · #10

-=AkaBOSS=- пишет:
и кстати говоря, не мешало бы проверять, а есть ли в хидере еще место для новой структуры IMAGE_SECTION_HEADER


ZeroMemory пишет:
Я проверил, место есть.


да ну?
во-первых, такие вещи надо проверять кодом, а не глазами.
во-вторых - нифига места нету

в первом лоадере - PointerToRawData = 0х200, и на этом оффсете лежит реальный код.
во втором - вместо кода вписан хидер секции, но данные не сдвинуты, а тупо перезаписаны

| Сообщение посчитали полезным: gajemuxi


Ранг: 7.5 (гость)
Статус: Участник

Создано: 3 сентября 2016 14:59 New!
Цитата · Личное сообщение · #11

-=AkaBOSS=- пишет:
во-первых, такие вещи надо проверять кодом, а не глазами.
во-вторых - нифига места нету


Теперь увидел. Там даже опкод FF15 вызова функции.
Какой алгоритм добавления секции в таком случае? Придется не использовать мэппинг и редактировать файл на диске, скопировать все, что после последнего заголовка секции в буфер, добавить заголовок новой секции, записать буфер в конец и отредактировать смещения?

Ранг: 408.1 (мудрец)
Статус: Участник

Создано: 3 сентября 2016 20:44 · Поправил: 3 сентября 2016 20:48 dosprog New!
Цитата · Личное сообщение · #12

ZeroMemory пишет:
Придется не использовать мэппинг и редактировать файл на диске


С этого и надо было начинать.
А то эти все "удобности" в конце концов оборачиваются обычным головняком.

Мапинг изначально задумывался, как это выглядит, для облегчения показа содержимого всяких мультимедийных громадных файлов.
А то многие путались при реализации листаний с подкачкой.

 eXeL@B —› Протекторы —› После добавления секции PE файл не запускается

Оригинальный DVD-ROM: eXeL@B DVD !

Вы находитесь на форуме сайта EXELAB.RU
Проект ReactOS