Что у нас осталось, необходимо доделать секции, разместить информацию в PE заголовке, создать таблицу импорта, закопировать все данные и декриптора, ну и написать сам декриптор.
Начнем потихоньку.
Доделываем таблицу секций и размещаем информацию об ней в PE заголовке.
mov importSec, eax ; запоминаем где начинается секция импорта mov ebx, DWORD PTR [sSection.vAddr] ; пишем виртуальный адрес секции add ebx, DWORD PTR [sSection.vSize] ; складываем его с виртуальным размером mov eax, optHeader ; в eax копируем указатель на опциональный заголовок mov DWORD PTR [eax+IMAGE_OPTIONAL_HEADER.SizeOfImage], ebx ; в размер образа записываем собственно размер mov ebx, DWORD PTR [sSection.vAddr] ; копируем в ebx виртуальный адрес mov DWORD PTR [eax+IMAGE_OPTIONAL_HEADER.BaseOfData], ebx ; в базу пишем получившийся виртуальный адрес add eax, IMAGE_OPTIONAL_HEADER.DataDirectory+8h ; прибавляем к указателю eax размер до DataDirectory mov ebx, DWORD PTR [sSection.vAddr] ; в ebx копируем начало импорт секции mov DWORD PTR [eax], ebx ; записываем в Import Directory RWA получившийся виртуальный адрес
Создаем таблицу импорта для работы распаковщика/декриптора.
mov eax, importSec add eax, houtfile invoke createImport, ebx, eax
Процедура createImport
createImport proc uses eax ebx edi esi ecx vSecAddr:DWORD, rSecAddr:DWORD LOCAL pFunc:DWORD mov ebx, rSecAddr ; пишем в ebx реальный адрес где будет находится import секция add ebx, 0Ch ; прибавляем 12 байт, до поля Name RWA mov eax, vSecAddr ; запишем в eax виртуальный адрес секции add eax, 34h ; прибавим к виртуальному адресу 52 байта, это 2 раза структура 5*4Byte(одна пустая) + таблица IAT из 2х 4 байтовых записей + 1х4байта пустая mov DWORD PTR [ebx], eax ; запишем в поле Name RWA где находиться название kernel32.dll mov edi, rSecAddr ; запишем в edi реальное нахождение секции add edi, 34h ; снова прибавим 52 байта mov ecx, sizeof _kernel32 ; вычислим размер строки "kernel32.dll" и запишем ее в ecx mov esi, offset _kernel32 ; в esi положим указатель на строку "kernel32.dll" rep movsb ; копируем строку в фаил mov pFunc, edi ; запомним где находиться указатель уже на функции импорта add ebx, 4h ; прибавим к ebx 4 байта, чтобы перейти на поле указывающее на IAT mov eax, vSecAddr ; в eax занесем виртуальный адрес add eax, SLOADL ; прибавим константу в 40 байт чтобы был указатель на таблицу IAT mov DWORD PTR [ebx], eax ; записываем в поле IAT указатель на IAT mov ebx, rSecAddr ; помещаем в ebx реальный адрес таблицы импорта add ebx, SLOADL ; прибавляем к нему теже 40 байт mov eax, edi ; копируем указатель из edi в eax sub eax, rSecAddr ; отнимаем от eax реальный адрес и получаем необходимое смещение add eax, vSecAddr ; прибавляем его к виртуальному, чтобы получить адрес IAT таблицы виртуальной mov DWORD PTR [ebx], eax ; записываем его в фаил add edi, 2h ; прибавм к edi 2байта Hintа mov ecx, sizeof _loadlibrary ; вычисляем размер строки с loadlibrary mov esi, offset _loadlibrary ; копируем в esi указатель на строку с loadlibrary rep movsb ; копируем строчку в упакованный фаил dec edi ; уменьшаем edi на 1 add ebx, 4h ; прибавляем к ebx 4 байта, чтобы перейти на следующую позицию в IAT mov eax, edi ; в eax копируем указатель на следующий элемент IAT sub eax, rSecAddr ; отнимаем реальный адрес, получаем смещение add eax, vSecAddr ; прибавляем виртуальный адрес mov DWORD PTR [ebx], eax ; копируем виртуальное смещение на следующую функцию add edi, 2h ; прибавляем к edi 2 байта Hintа mov ecx, sizeof _getprocaddress ; вычисляем размер строки с именем getprocaddress mov esi, offset _getprocaddress ; копируем в esi указатель на имя getprocaddress rep movsb ; записываем строчку в фаил ret createImport endp
Копируем всякие данные в упакованный фаил:
mov ebx, hinfile ; в ebx копируем указатель на начало упаковываемого фаила add ebx, pehSize ; прибавляем к ebx размер PE заголовка mov ecx, secCount ; в ecx копируем количество секций mov edi, houtfile ; в edi копируем адрес упакованного файла add edi, pehSize ; прибавляем к edi размер PE заголовке mov edi, DWORD PTR [edi+14h] ; вычисляем адрес первой секции в упакованном файле add edi, houtfile ; прибавляем к нему адрес упакованного файла mov edx, edi ; копируем в edx idi xor eax, eax ; обнуляем eax writecode: mov esi, DWORD PTR [ebx+14h] ; в esi копируем адрес секции жертвы add esi, hinfile ; прибавляем адрес замапированнного файла жертвы push ecx ; сохраним ecx в стеке mov ecx, DWORD PTR [ebx+8h] ; занесем в ecx реальный размер секции rep movsb ; копируем всю секцию pop ecx ; востановим ecx add ebx, 28h ; прибавим 40 байт до следующей секции loop writecode ; повторим пока все секции не кончатся mov eax, edi ; скопируем в eax указатель на конец скопированного кода sub eax, edx ; отнимим от eax edx чтобы получить адрес смещения на код распаковщика/декриптора mov ebx, optHeader ; скопируем в ebx адрес опционального заголовка PE add eax, DWORD PTR [ebx+IMAGE_OPTIONAL_HEADER.BaseOfCode] ; прибавим к eax адрес базы кода mov DWORD PTR [ebx+IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint], eax ; запишем в точку входа адрес с которого начинается распаковщик/декриптор mov esi, offset unpack ; в esi занесем указатель на функцию распаковки/декриптора mov ecx, UNPACKSIZE ; в ecx занесем размер функции распаковки/декриптора rep movsb ; копируем код распаковки/декриптора
Ну вот и все на сегодня, в следующей и последней части, я опишу тех поля которые понадобяться для распаковки и анпакер/декриптор который нужен будет для нармальной работы файла который будет запакован.
Предыдущие части про упаковщик/криптор можно почитать в Главе1 и Главе2.
Комментариев нет:
Отправить комментарий