tags: windows - malware
Добавление новой секции с кодом в PE файл
Всем привет! Прошло некоторое время с тех пор, как я постил что-то интересное, и я чувствую, что настал момент еще раз внести свой вклад в этот форум.
Я видел некоторых людей здесь, и на некоторых других форумах, которые делают вид, что понимают формат PE файла и понимают, как его модифицировать. Большое количество кода на форуме - бесполезно, содержит баги или делает зараженный PE файл нестабильным или невалидным!
Данный код является введением в тему модификации PE.
Программа, которую я покажу вам, читает файл, проверяет, является ли он валидным по PE формату, и вставляет новую секцию. С целью показать именно заражение файла, я вставляю простую строку в только что созданную секцию, просто чтобы показать на наглядном примере!
Ниже код, который вы можете улучшать и делать все что захотите! НАСЛАЖДАЙТЕСЬ!!!
#include <stdio.h>
#include <windows.h>
DWORD align(DWORD size, DWORD align, DWORD addr){
if (!(size % align))
return addr + size;
return addr + (size / align + 1) * align;
}
bool AddSection(char *filepath, char *sectionName, DWORD sizeOfSection){
HANDLE file = CreateFile(filepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE)
return false;
DWORD fileSize = GetFileSize(file, NULL);
// теперь мы знаем, какого размера память мы должны выделить для буфера
BYTE *pByte = new BYTE[fileSize];
DWORD dw;
// давайте прочитаем весь файл, чтобы в дальнейшем использовать эту информацию о PE
ReadFile(file, pByte, fileSize, &dw, NULL);
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE)
return false; //invalid PE
PIMAGE_FILE_HEADER FH = (PIMAGE_FILE_HEADER)(pByte + dos->e_lfanew + sizeof(DWORD));
PIMAGE_OPTIONAL_HEADER OH = (PIMAGE_OPTIONAL_HEADER)(pByte + dos->e_lfanew + sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER));
PIMAGE_SECTION_HEADER SH = (PIMAGE_SECTION_HEADER)(pByte + dos->e_lfanew + sizeof(IMAGE_NT_HEADERS));
ZeroMemory(&SH[FH->NumberOfSections], sizeof(IMAGE_SECTION_HEADER));
CopyMemory(&SH[FH->NumberOfSections].Name, sectionName, 8);
// Мы используем 8 байт для имени секции, потому что это максимальный разрешенный размер
// вставляем всю необходимую информацию о нашей новой PE секции
SH[FH->NumberOfSections].Misc.VirtualSize = align(sizeOfSection, OH->SectionAlignment, 0);
SH[FH->NumberOfSections].VirtualAddress = align(SH[FH->NumberOfSections - 1].Misc.VirtualSize, OH->SectionAlignment, SH[FH->NumberOfSections - 1].VirtualAddress);
SH[FH->NumberOfSections].SizeOfRawData = align(sizeOfSection, OH->FileAlignment, 0);
SH[FH->NumberOfSections].PointerToRawData = align(SH[FH->NumberOfSections - 1].SizeOfRawData, OH->FileAlignment, SH[FH->NumberOfSections - 1].PointerToRawData);
SH[FH->NumberOfSections].Characteristics = 0xE00000E0;
/*
0xE00000E0 = IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_CNT_CODE |
IMAGE_SCN_CNT_UNINITIALIZED_DATA |
IMAGE_SCN_MEM_EXECUTE |
IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_MEM_READ
*/
SetFilePointer(file, SH[FH->NumberOfSections].PointerToRawData + SH[FH->NumberOfSections].SizeOfRawData, NULL, FILE_BEGIN);
// перемещаем указатель позиции в файле на значение адреса последней секции + размер файла
SetEndOfFile(file);
// теперь изменим размер образа, для соответствия нашим модификациям
// после добавления новой секции размер увеличился
OH->SizeOfImage = SH[FH->NumberOfSections].VirtualAddress + SH[FH->NumberOfSections].Misc.VirtualSize;
// так как мы добавили новую секцию, их количество увеличилось
FH->NumberOfSections += 1;
SetFilePointer(file, 0, NULL, FILE_BEGIN);
// и в завершении, мы применяем все изменения
WriteFile(file, pByte, fileSize, &dw, NULL);
CloseHandle(file);
return true;
}
bool AddCode(char *filepath){
HANDLE file = CreateFile(filepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE)
return false;
DWORD filesize = GetFileSize(file, NULL);
BYTE *pByte = new BYTE[filesize];
DWORD dw;
ReadFile(file, pByte, filesize, &dw, NULL);
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(pByte + dos->e_lfanew);
// новая секция становится последней
// мы должны получить адрес последней секции, чтобы вставить наши секретные данные
PIMAGE_SECTION_HEADER first = IMAGE_FIRST_SECTION(nt);
PIMAGE_SECTION_HEADER last = first + (nt->FileHeader.NumberOfSections - 1);
SetFilePointer(file, last->PointerToRawData, NULL, FILE_BEGIN);
char *str = "ATHENIAN WAS HERE";
WriteFile(file, str, strlen(str), &dw, 0);
CloseHandle(file);
return TRUE;
}
void main()
{
if (AddSection("C:\\Users\\M\\Desktop\\Athena.exe", ".ATH", 400)){
printf("Section added!\n");
// Вставляем данные в последнюю секцию
if (AddCode("C:\\Users\\M\\Desktop\\Athena.exe")){
printf("Code written!\n");
}
else
printf("Error writting code!\n");
}
else
printf("Error adding section!\n");
}