Так как у нас все данные из старого файла будут находиться в одной секции, необходимо их склеить, потом закриптовать/упаковать и выяснить размер. Я не стал писать функцию криптования или упаковки, так как это достаточно просто, да и лень что то стало, ограничился только склеиванием и измерением размера. В любом случае, тут не нужно файловое выравнивание и секция получается меньше, чем в оригинальном файле.
Немножко кода:
4,5,6 пункты у меня объедены в один, так как кода достаточно мало там и 4ый пункт не содержит склейки и криптования упаковки, так как это будет делаться дальше.
add eax, 1Eh ; зарезервируем немножно места под тех инфу add eax, UNPACKSIZE ; добавим размер анпакера invoke GetAlignUp, eax, fAlig ; вычислим получившйся размер с файловым выравниванием mov imgSize, eax ; сохраним размер образа в imgSize, add fileSize, eax ; прибавим к вычисленному размеру файлу размер образа mov eax, fAlig ; скопируем в eax величину выравнивания add fileSize, eax ; прибавим величину выравнивания для резервирования места под IAT
7. Создаем и маппируем новый фаил с необходимым размером.
invoke CreateFile, offset outfilename,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_WRITE, NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, 0 ; создаем фаил mov hOpenfile, eax ; записываем его хендл invoke CreateFileMapping, eax, NULL,PAGE_READWRITE, 0, fileSize , NULL ; мапируем с необходимым размером fileSize mov hOFMap, eax ; записываем хэндл invoke MapViewOfFile, eax, FILE_MAP_WRITE, 0, 0, 0 ; делаем проекцию mov houtfile, eax ; сохраняем указатель на начало нового файла invoke crPEHeader, hinfile, houtfile ; крадем PE заголовок
8. Крадем заголовок из оригинального файла.
crPEHeader proc psrcPEHeader:DWORD, pdstPEHeader:DWORD ;############################### ; in - psrcPEHeader = src header ; in - pdstPEHeader = dst header ; out - eax = start PE header ; out - ecx = size PE header ;############################### LOCAL hinfSize:DWORD ; локальная переменная mov eax, psrcPEHeader ; источник заголовка mov ebx, pdstPEHeader ; место куда будем писать заголовок xor ecx, ecx ; обнуляем ecx mov cx, WORD PTR [eax+IMAGE_DOS_HEADER.e_lfanew] ; записываем в cx размер DOS заголовка add eax, ecx ; прибавляем к eax размер DOS заголовка add ebx, ecx ; прибавляем к ebx размер DOS заголовка add ecx, IMAGE_FILE_HEADER+4h ; прибавляем IMAGE_FILE_HEADER add cx, WORD PTR [eax+IMAGE_FILE_HEADER.SizeOfOptionalHeader+4h] ; прибавляем к ecx размер SizeOfOptionalHeader mov hinfSize, ecx ; копируем в локальную переменную полный размер заголовка mov esi, psrcPEHeader ; в esi - источник mov edi, pdstPEHeader ; в edi - получатель rep movsb ; копируем 1 к 1 заголовок xor ecx, ecx ; обнуляем ecx mov ecx, hinfSize ; копируем в ecx размер из локальной переменной mov eax, ebx ; копируем в eax указатель на начало заголовка в файле получателе ret ; готово crPEHeader endp
9. Создаем секции, учитывая размер из упаковываемого файла.
mov ebx, secCount ; в ebx записываем количество секций mov WORD PTR [eax+IMAGE_FILE_HEADER.NumberOfSections+4h], bx ; записываем количество секий в новый PE заголовок add eax, FULL_IMAGE_FILE_HEADER ; прибавим полный размер IMAGE_FILE_HEADER mov optHeader, eax ; сохраним указатель на опциональный заголовок mov ebx, secCount ; в ebx записываем количество секций (наверно оно тут не нада) dec ebx ; уменьшим на 1 ebx imul ebx, ebx, SECSTRUCSIZE ; вычисляем размер структуры SECSTRUCSIZE add ebx, secMem ; прибавим к этому указатель на secMem invoke GetAlignUp, DWORD PTR [ebx], DWORD PTR [eax+IMAGE_OPTIONAL_HEADER.SectionAlignment] ; вычислим размер с выравниванием секций add eax, DWORD PTR [ebx+4h] ; прибавим к результату выравнивания размер секции mov ebx, houtfile ; скопируем в ebx указатель на начало файла add ebx, pehSize ; прибавим к нему заголовок и окажемся в начале таблицы секций mov DWORD PTR [sSection.vSize], eax ; в структуру занесем размер секции mov eax, optHeader ; занесем в eax указатель на начало опционального заголовка mov eax, DWORD PTR [eax+IMAGE_OPTIONAL_HEADER.SectionAlignment] ; перекинем в eax показатель выравниания секции mov DWORD PTR [sSection.vAddr],eax ; в ячейку виртуального адреса структуры занесем оказатель выравниания секции mov eax, codeStart ; в eax занесем указатель на начало кода mov DWORD PTR [sSection.rAddr],eax ; в RWA адрес занесем указатель на начало кода invoke crSecTableItem, ebx, offset namesec, DWORD PTR [sSection.vSize], DWORD PTR [sSection.vAddr], 0h, DWORD PTR [sSection.rAddr], IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_WRITE ; создаем запись в таблице секций mov eax, DWORD PTR [sSection.vSize] ; в eax копируем виртуальный размер add eax, DWORD PTR [sSection.vAddr] ; складываем с виртуальным адресом mov DWORD PTR [sSection.vAddr], eax ; теперь это виртуальный адрес следующей секции mov eax, optHeader ; занесем в eax указатель на начало опционального заголовка invoke GetAlignUp, imgSize, DWORD PTR [eax+IMAGE_OPTIONAL_HEADER.SectionAlignment] ; вычислим размер с выраванием mov DWORD PTR [sSection.vSize], eax ; теперь это виртуальный размер mov eax, optHeader ; занесем в eax указатель на начало опционального заголовка invoke GetAlignUp, imgSize, fAlig ; получим размер образа наших данных с файловым выравниванием mov DWORD PTR [sSection.rSize], eax ; теперь это RWA размер add ebx, 28h ; сместим указатель на следующую строку в таблице секций invoke crSecTableItem, ebx, offset namesec, DWORD PTR [sSection.vSize], DWORD PTR [sSection.vAddr], DWORD PTR [sSection.rSize], DWORD PTR [sSection.rAddr], IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_WRITE ; создаем запись в таблице секций mov eax, optHeader ; занесем в eax указатель на начало опционального заголовка mov ecx,DWORD PTR [sSection.vAddr] ; в ecx занесем виртуальный адрес предыдущей секции mov DWORD PTR [eax+IMAGE_OPTIONAL_HEADER.BaseOfCode], ecx ; правим базу кода в PE заголовке mov eax, DWORD PTR [sSection.vAddr] ; в eax копируем виртуальный адрес add eax, DWORD PTR [sSection.vSize] ; складываем с виртуальным размером mov DWORD PTR [sSection.vAddr], eax ; теперь это адрес следующей секции mov eax, DWORD PTR [sSection.rSize] ; в eax RWA размер add eax, DWORD PTR [sSection.rAddr] ; складываем с RWA адресом mov DWORD PTR [sSection.rAddr], eax ; теперь это начало следующей секции в файле mov edx, fAlig ; записываем в edx файловое выравнивание mov DWORD PTR [sSection.rSize], edx ; записываем в размер в файле add ebx, 28h ; сместим указатель на следующую строку в таблице секций invoke crSecTableItem, ebx, offset namesec, DWORD PTR [sSection.vSize], DWORD PTR [sSection.vAddr], DWORD PTR [sSection.rSize], DWORD PTR [sSection.rAddr], IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_WRITE ; создаем запись в таблице секций
Процедурка crSecTableItem
crSecTableItem proc uses eax ebx ecx esi edi pEndSec:DWORD, pNameSec:DWORD, vSize:DWORD, vAddr:DWORD, rSize:DWORD, rAddr:DWORD, charac:DWORD mov ebx, pEndSec ; копируем в ebx начало секции mov ecx, 8 ; в 1 поле у нас 8 байт для текстового указателя mov edi, ebx ; копируем в edi указатель на начало секции mov esi, pNameSec ; в esi указатель на начало названия nextChr: ; метка на следующий цикл .if BYTE PTR [esi] == 0 ; если в esi 0, значит буквы закончились jmp endName ; выходим на метку endName .endif movsb ; копируем байт loop nextChr ; повторяем пока не пройдет 8 итераций или не выйдем по if endName: mov eax, vSize ; копируем виртуальный размер в eax mov DWORD PTR [ebx+8h], eax ; записываем его в ячейку VirtualSize mov eax, vAddr ; копируем виртуальный адрес в eax mov DWORD PTR [ebx+0Ch], eax ; записываем его в ячейку SizeOfRawData mov eax, rSize ; копируем реальный размер в eax mov DWORD PTR [ebx+10h], eax ; записываем его в ячейку PointerToRawData mov eax, rAddr ; копируем реальный адрес в eax mov DWORD PTR [ebx+14h], eax ; записываем реальный адрес mov eax, charac ; копируем в eax атрибуты секции mov DWORD PTR [ebx+24h], eax ; записываем в ячейку Characteristics ret crSecTableItem endp
Ну и на сегодня все, дальнейшее описанике приптора будет в следующих частях. Вот ссылка на первую часть.
Комментариев нет:
Отправить комментарий