Что нового

Добавление ресурса в EXE файл средствами AutoIt

Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Ошибочка вышла, функция RemoveResource() не только удаляет ресурс, но ещё и прибовляет вес файлу


Добавлено:
Сообщение автоматически объединено:

В HEX редакторе выяснил что при каждом вызове RemoveResource() в конечный файл добавляются нулевые байта, колличество которых равно колличеству байт исходного exe, попробую исправить..
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Вроде сделал, протестировал - работает, размер файла не растёт, но удаление ресурса происходит явным указанием типа, имени и языка ресурса, для полного удаления всего каталога например иконок, придётся делать другую функцию, либо доводить эту.

Код:
#Include <WinAPIEx.au3>
#Include <APIConstants.au3>

;AddResource(@ScriptDir & '\test.exe', @ScriptDir & '\1.exe', 10, 'EXE1') ;~ Добавляем ресурс в файл 
RemoveResource(@ScriptDir & '\test.exe', 4, 166, 2057) ;~ MENU
RemoveResource(@ScriptDir & '\test.exe', 5, 100, 2057) ;~ DIALOG
RemoveResource(@ScriptDir & '\test.exe', 16, 1, 1033) ;~ VERSION

Func AddResource($sFile, $sResFile, $sResType, $sResName, $sResLang = 0, $uFlag = 0)
	
	Local $OutFile = ($sFile & '.EXTMP'), $uSize, $uFile, $hStruct, $hUpdate, $hFile, $iSize, $tByte, $pByte, $aFile, $nFile, $sRead

    Relocation($sFile, $OutFile) 
	
	$uFile = _WinAPI_CreateFile($sFile, 2, 2)
	If (Not $uFile) Then Return SetError(-1, 0, 0)
	_WinAPI_SetFilePointerEx($uFile, FileGetSize($OutFile), 0)
	$uSize = FileGetSize($sFile)
	If ($uFlag <> 1) Then
        $hStruct = DllStructCreate("char[" & $uSize & "]")
    Else
        $hStruct = DllStructCreate("byte[" & $uSize & "]")
    EndIf
	If _WinAPI_ReadFile($uFile, DllStructGetPtr($hStruct), $uSize, $uSize) Then
	    _WinAPI_CloseHandle($uFile)
        $hUpdate = _WinAPI_BeginUpdateResource($OutFile, False)
	    If $hUpdate Then
            $hFile = _WinAPI_CreateFileEx($sResFile, $OPEN_EXISTING, $GENERIC_READ)
            $iSize = _WinAPI_GetFileSize($hFile)
            $tByte = DllStructCreate('byte[' & $iSize & ']')
            $pByte = DllStructGetPtr($tByte)
            If _WinAPI_ReadFile($hFile, $pByte, $iSize, $iSize) Then
                If _WinAPI_UpdateResource($hUpdate, $sResType, $sResName, $sResLang, $pByte, DllStructGetSize($tByte)) Then
                    _WinAPI_EndUpdateResource($hUpdate, False)
		        EndIf	
			EndIf	
	    EndIf	
	EndIf
	$aFile = _WinAPI_CreateFile($OutFile, 2, 4)
	If (Not $aFile) Then Return SetError(-3, 0, 0)
	_WinAPI_SetFilePointerEx($aFile, 0, 2)
	_WinAPI_WriteFile($aFile, DllStructGetPtr($hStruct), DllStructGetSize($hStruct), $uSize)
	_WinAPI_CloseHandle($aFile)
	FileDelete($sFile)
	$nFile = FileOpen($OutFile)
	$sRead = FileRead($nFile)
	FileClose($nFile)
	FileWrite($sFile, $sRead)
	FileDelete($OutFile)
EndFunc

Func RemoveResource($sFile, $sResType, $sResName = '', $sResLang = 0)
	
	Local $OutFile = ($sFile & '.EXTMP')

    Relocation($sFile, $OutFile) 
	
	Local $hSourceFile = _WinAPI_CreateFile($sFile, 2, 2)
	If $hSourceFile Then
	    _WinAPI_SetFilePointerEx($hSourceFile, FileGetSize($OutFile), 0)
	    Local $hByte = DllStructCreate("byte[" & FileGetSize($sFile) & "]")
		Local $pByte = DllStructGetPtr($hByte)
		Local $iSize = DllStructGetSize($hByte)
	    If Not _WinAPI_ReadFile($hSourceFile, $pByte, $iSize, $iSize) Then 
			Return SetError(-1, 0, 0)
		EndIf	
	    _WinAPI_CloseHandle($hSourceFile)
		
		Local $hUpdate = _WinAPI_BeginUpdateResource($OutFile, False)
	    If $hUpdate Then
			If _WinAPI_UpdateResource($hUpdate, $sResType, $sResName, $sResLang, 0, 0) Then
				_WinAPI_EndUpdateResource($hUpdate, False)
			EndIf
	    EndIf	

	    Local $hDestFile = _WinAPI_CreateFile($OutFile, 2, 4)
	    If $hDestFile Then 
	        _WinAPI_SetFilePointerEx($hDestFile, 0, 2)
	        If Not _WinAPI_WriteFile($hDestFile, $pByte, $iSize, $iSize) Then
			    Return SetError(-2, 0, 0)
			EndIf	
	        _WinAPI_CloseHandle($hDestFile)
		EndIf
    EndIf
	
    FileDelete($sFile)
	$nFile = FileOpen($OutFile)
	$sRead = FileRead($nFile)
	FileClose($nFile)
	FileWrite($sFile, $sRead)
	FileDelete($OutFile)
EndFunc	

Func ExtractResource($hInstance, $sExtractPath, $sResType, $sResName, $iResLanguage = 0x0400)
	Local $hResource, $aResSize, $aResLoad, $pMemRes
	
	$hResource = _WinAPI_FindResourceEx($hInstance, $sResType, $sResName, $iResLanguage)
	$iSize = _WinAPI_SizeOfResource($hInstance, $hResource)
	$aResLoad = _WinAPI_LoadResource($hInstance, $hResource)
	$pMemRes = _WinAPI_LockResource($aResLoad)
	If @error Then
        Return SetError(@error, @extended, 0)
    EndIf
	
	$tByte = DllStructCreate('byte[' & $iSize & ']', $pMemRes)
	
	$hFile = _WinAPI_CreateFileEx($sExtractPath, $CREATE_ALWAYS, $GENERIC_WRITE)
	_WinAPI_WriteFile($hFile, DllStructGetPtr($tByte), DllStructGetSize($tByte), $tByte)
	If $hFile Then
        _WinAPI_CloseHandle($hFile)
    EndIf
EndFunc


Func Relocation($sFile, $sOutFile)
	Local $hFile = _WinAPI_CreateFile($sFile, 2, 2)
	If (@error) Or (Not $hFile) Then 
		Return SetError(-1, 0, 0)
	EndIf	
    Local $hFileOut = _WinAPI_CreateFileEx($sOutFile, 2, 2)
	If (Not $hFileOut) Then 
		Return SetError(-2, 0, 0)
	EndIf	
    $IMAGE_DOS_HEADER = READ_IMAGE_DOS_HEADER($hFile, 0) ;~ Извлекаем структуры IMAGE_DOS_HEADER из исходного файла
    WRITE_IMAGE_DOS_HEADER($hFileOut, 0, $IMAGE_DOS_HEADER) ;~ Записываем структуру IMAGE_DOS_HEADER в новый файл
    $iAddress = DllStructGetData($IMAGE_DOS_HEADER, 'lfanew') ;~ Достаём адрес таблицы
    $Signature = READ_SIGNATURE($hFile, $iAddress) ;~ Извлекаем сигнатуру файла
    If DllStructGetData($Signature, 'Signature') <> 0x00004550 And DllStructGetData($Signature, 'Signature') <> 0x50450000 Then ;~ проверяем, если сигнатура не равна PE то возвращаем ошибку
		Return SetError(-3, 0, 0)
	EndIf	
    WRITE_SIGNATURE($hFileOut, $iAddress, $Signature) ;~ Пишем в новый файл сигнатуру по адрессу таблицы
    $iAddress += DllStructGetSize($Signature) ;~ Прибавляем к адресу таблицы размер сигнатуры
    $IMAGE_FILE_HEADER = READ_IMAGE_FILE_HEADER($hFile, $iAddress) ;~ Заполняем структуру IMAGE_FILE_HEADER, считываем по адресу (Таблица + сигнатура)
    WRITE_IMAGE_FILE_HEADER($hFileOut, $iAddress, $IMAGE_FILE_HEADER) ;~ Записываем в новый файл структуру IMAGE_FILE_HEADER
    $iAddress += DllStructGetSize($IMAGE_FILE_HEADER) ;~ Прибавляем ((таблица + сигнатура) + размер IMAGE_FILE_HEADER)
    $IMAGE_OPTIONAL_HEADER = READ_IMAGE_OPTIONAL_HEADER($hFile, $iAddress) ;~ Заполняем структуру IMAGE_OPTIONAL_HEADER
    If DllStructGetData($IMAGE_OPTIONAL_HEADER, 'Magic') <> 0x10b And DllStructGetData($IMAGE_OPTIONAL_HEADER, 'Magic') <> 0x20b Then ;~ Проверяем магическое число, если 0x10b и 0x20b то файл является исполняемым 
		Return SetError(-4, 0, 0)
	EndIf	
    WRITE_IMAGE_OPTIONAL_HEADER($hFileOut, $iAddress, $IMAGE_OPTIONAL_HEADER) ;~ Записываем в новый файл структуру IMAGE_OPTIONAL_HEADER
    $NumberOfSections = DllStructGetData($IMAGE_FILE_HEADER, 'NumberOfSections') ;~ Возвращяем число секций
    $iAddress += DllStructGetSize($IMAGE_OPTIONAL_HEADER) ;~ Прибавляем размер структуры
    $SizeOfHeaders = DllStructGetData($IMAGE_OPTIONAL_HEADER, 'SizeOfHeaders') ;~ Размер заголовка
    ;SizeOf IMAGE_SECTION_HEADER ==> 40
    $RemainderSize = $SizeOfHeaders - ($iAddress + $NumberOfSections * 40) ;~ Размер заголовка - (адресс + колличество секций и * на размер IMAGE_SECTION_HEADER = ( 40 ))
    $DataPos = ($iAddress + $NumberOfSections * 40)
    $DataStruct = READ_DATA($hFile, $DataPos, $RemainderSize) ;~ Считываем данные 
    WRITE_DATA($hFileOut, $DataPos, $DataStruct) ;~ Записываем в новый файл 
    For $i = 1 To $NumberOfSections 
		;~ Пишется столько раз, сколько существует секций 
        $IMAGE_SECTION_HEADER = READ_IMAGE_SECTION_HEADER($hFile, $iAddress) ;~ Считываем IMAGE_SECTION_HEADER из файла
        WRITE_IMAGE_SECTION_HEADER($hFileOut, $iAddress, $IMAGE_SECTION_HEADER) ;~ Записываем в новый файл IMAGE_SECTION_HEADER 
        $PointerToRawData = DllStructGetData($IMAGE_SECTION_HEADER, 'PointerToRawData') ;~ Указатель на первую страницу в файл COFF.
        $SizeOfRawData = DllStructGetData($IMAGE_SECTION_HEADER, 'SizeOfRawData') ;~ Размер инициализированных данных на диске в байтах.
        $VirtualAddress = DllStructGetData($IMAGE_SECTION_HEADER, 'VirtualAddress') ;~ Адрес первого байта раздела при загрузке в память
        $ByteStruct = READ_SECTION($hFile, $PointerToRawData, $SizeOfRawData) ;~ Считываем секцию
        WRITE_SECTION($hFileOut, $PointerToRawData, $byteStruct) ;~ Записываем в новый файл секцию 
        $iAddress += DllStructGetSize($IMAGE_SECTION_HEADER)
    Next
    _WinAPI_CloseHandle($hFile)
    _WinAPI_CloseHandle($hFileOut)
EndFunc	

Func READ_SECTION($hFile, $MovePos, $iSize)
    Local $nBytes, $byteStruct = DllStructCreate("byte[" & $iSize & "]")
	_WinAPI_SetFilePointerEx($hFile, $MovePos)
	_WinAPI_ReadFile($hFile, DllStructGetPtr($byteStruct), $iSize, $nBytes)
    Return $byteStruct
EndFunc

Func WRITE_SECTION($hFile, $MovePos, $byteStruct)
    Local $nBytes
	_WinAPI_SetFilePointerEx($hFile, $MovePos)
	_WinAPI_WriteFile($hFile, DllStructGetPtr($byteStruct), DllStructGetSize($byteStruct), $nBytes)
EndFunc

Func READ_DATA($hFile, $MovePos, $iSize)
    Local $nBytes, $byteStruct = DllStructCreate("byte[" & $iSize & "]")
	_WinAPI_SetFilePointerEx($hFile, $MovePos)
	_WinAPI_ReadFile($hFile, DllStructGetPtr($byteStruct), $iSize, $nBytes)
    Return $byteStruct
EndFunc

Func WRITE_DATA($hFile, $MovePos, $byteStruct)
	Local $nBytes
	_WinAPI_SetFilePointerEx($hFile, $MovePos)
    _WinAPI_WriteFile($hFile, DllStructGetPtr($byteStruct), DllStructGetSize($byteStruct), $nBytes)
EndFunc

Func READ_IMAGE_DOS_HEADER($hFile, $MovePos)
	Local $tagIMAGE_DOS_HEADER =  '' & _
	'ushort magic;' & _        ;// Сигнатура заголовка
	'ushort cblp;' & _         ;// количество байт на последней странице файла
	'ushort cp;' & _           ;// количество страниц в файле
	'ushort crlc;' & _         ;// Relocations
	'ushort cparhdr;' & _      ;// Размер заголовка в параграфах
	'ushort minalloc;' & _     ;// Минимальные дополнительные параграфы
    'ushort maxalloc;' & _     ;// Максимальные дополнительные параграфы
	'ushort ss;' & _           ;// начальное относительное значение регистра SS
	'ushort sp;' & _           ;// начальное значение регистра SP
	'ushort csum;' & _         ;// контрольная сумма
	'ushort ip;' & _           ;// начальное значение регистра IP
	'ushort cs;' & _           ;// начальное относительное значение регистра CS
	'ushort lfarlc;' & _       ;// адрес в файле на таблицу переадресации
	'ushort ovno;' & _         ;// количество оверлеев
	'ushort res[4];' & _       ;// Зарезервировано
    'ushort oemid;' & _        ;// OEM идентифкатор
	'ushort oeminfo;' & _      ;// OEM информация
	'ushort res2[10];' & _     ;// Зарезервировано
	'dword lfanew'             ;// адрес в файле нового .exe заголовка (PE)            
	
    Local $nBytes, $tIMAGE_DOS_HEADER = DllStructCreate($tagIMAGE_DOS_HEADER)
    _WinAPI_SetFilePointerEx($hFile, $MovePos)
    _WinAPI_ReadFile($hFile, DllStructGetPtr($tIMAGE_DOS_HEADER), DllStructGetSize($tIMAGE_DOS_HEADER),$nBytes)
    Return $tIMAGE_DOS_HEADER
EndFunc

Func WRITE_IMAGE_DOS_HEADER($hFile, $MovePos, $IMAGE_DOS_HEADER)
    Local $nBytes
	_WinAPI_SetFilePointerEx($hFile,$MovePos)
    Return _WinAPI_WriteFile($hFile, DllStructGetPtr($IMAGE_DOS_HEADER), DllStructGetSize($IMAGE_DOS_HEADER), $nBytes)
EndFunc

Func READ_SIGNATURE($hFile, $MovePos)
    Local $nBytes, $hSignature = DllStructCreate('dword Signature')
    _WinAPI_SetFilePointerEx($hFile, $MovePos)
    _WinAPI_ReadFile($hFile, DllStructGetPtr($hSignature), DllStructGetSize($hSignature), $nBytes)
    Return $hSignature
EndFunc

Func WRITE_SIGNATURE($hFile, $MovePos, $Signature)
    Local $nBytes
	_WinAPI_SetFilePointerEx($hFile, $MovePos)
    Return _WinAPI_WriteFile($hFile, DllStructGetPtr($Signature), DllStructGetSize($Signature), $nBytes)
EndFunc

Func READ_IMAGE_FILE_HEADER($hFile, $MovePos)
	Local $tagIMAGE_FILE_HEADER = '' & _
	'ushort Machine;' & _                 ;// Машина
	'ushort NumberOfSections;' & _        ;// Колличество секторов
	'dword TimeDateStamp;' & _            ;// Временной штамп
	'dword PointerToSymbolTable;' & _     ;// Указатель на таблицу символов
	'dword NumberOfSymbols;' & _          ;// Колличество символов
	'ushort SizeOfOptionalHeader;' & _    ;// Размер дополнительного заголовка
	'ushort Characteristics'              ;// Характеристики
	
    Local $nBytes, $tIMAGE_FILE_HEADER = DllStructCreate($tagIMAGE_FILE_HEADER)
    _WinAPI_SetFilePointerEx($hFile, $MovePos)
    _WinAPI_ReadFile($hFile, DllStructGetPtr($tIMAGE_FILE_HEADER), DllStructGetSize($tIMAGE_FILE_HEADER), $nBytes)
    Return $tIMAGE_FILE_HEADER
EndFunc

Func WRITE_IMAGE_FILE_HEADER($hFile, $MovePos, $IMAGE_FILE_HEADER)
    Local $nBytes
	_WinAPI_SetFilePointerEx($hFile, $MovePos)
    Return _WinAPI_WriteFile($hFile, DllStructGetPtr($IMAGE_FILE_HEADER), DllStructGetSize($IMAGE_FILE_HEADER), $nBytes)
EndFunc

Func READ_IMAGE_OPTIONAL_HEADER($hFile, $MovePos)
	Local $tagIMAGE_OPTIONAL_HEADER = '' & _
	'ushort Magic;' & _                       ;// Тип файла
	'ubyte MajorLinkerVersion;' & _           ;// Основной номер версии компоновщика
	'ubyte MinorLinkerVersion;' & _           ;// Дополнительный номер версии компоновщика
	'dword SizeOfCode;' & _                   ;// Размер кода раздела, в байтах, или сумма всех таких участков, если есть несколько разделов кода.
    'dword SizeOfInitializedData;' & _        ;// Размер инициализированных данных раздела, в байтах, или сумма всех таких участков, если есть несколько разделов инициализируется данными.
	'dword SizeOfUninitializedData;' & _      ;// Размер неинициализированных данных раздела, в байтах, или сумма всех таких участков, если есть несколько неинициализированных данных разделов.
	'dword AddressOfEntryPoint;' & _          ;// Указатель на точку входа
	'dword BaseOfCode;' & _                   ;// Указатель на начало секции кода
	'dword BaseOfData;' & _                   ;// Указатель на начало секции данных
    'dword ImageBase;' & _                    ;// Предпочтительный адрес первого байта изображения при загрузке в память. Это значение является кратной 64 байт. Значение по умолчанию для библиотек DLL 0x10000000. Значение по умолчанию для приложений 0x00400000, за исключением Windows CE, где 0x00010000.
	'dword SectionAlignment;' & _             ;// Выравнивание разделов загруженых в память, в байтах (Должно быть больше или равна FileAlignment) 
	'dword FileAlignment;' & _                ;// Согласование исходных данных разделов в файл изображения в байтах.
	'ushort MajorOperatingSystemVersion;' & _ ;// Основной номер версии необходимых операционной системы.
	'ushort MinorOperatingSystemVersion;' & _ ;// Дополнительный номер версии необходимых операционной системы.
    'ushort MajorImageVersion;' & _           ;// Основной номер версии изображения.
	'ushort MinorImageVersion;' & _           ;// Младший номер версии изображения.
	'ushort MajorSubsystemVersion;' & _       ;// Основной номер версии подсистемы.
	'ushort MinorSubsystemVersion;' & _       ;// Дополнительный номер версии подсистемы.
	'dword Win32VersionValue;' & _            ;// Зарезервирован и и должен быть 0.
    'dword SizeOfImage;' & _                  ;// Размер изображения в байтах, включая все заголовки. Должна быть кратна SectionAlignment.
	'dword SizeOfHeaders;' & _                ;// Общий размер из пунктов, округляется до кратного значения, указанного в FileAlignment
	'dword CheckSum;' & _                     ;// Контрольная сумма файла изображения. 
	'ushort Subsystem;' & _                   ;// Подсистемы, необходимые для запуска этого образа.
	'ushort DllCharacteristics;' & _          ;// DLL характеристики изображения.
	'dword SizeOfStackReserve;' & _           ;// Количество байт, резерв для стека.
    'dword SizeOfStackCommit;' & _            ;// Количество байт для совершения в стеке.
	'dword SizeOfHeapReserve;' & _            ;// Количество байт, резерв для локальной массы
	'dword SizeOfHeapCommit;' & _             ;// Количество байт для совершения в локальной массе
	'dword LoaderFlags;' & _                  ;// Этот элемент является устаревшим.
	'dword NumberOfRvaAndSizes;' & _          ;// Количество каталогов в оставшейся части дополнительного заголовка. Каждая запись описывает расположение и размер.
	'byte byteData[128]'                      ;// 
	
    Local $nBytes, $tIMAGE_OPTIONAL_HEADER = DllStructCreate($tagIMAGE_OPTIONAL_HEADER)
    _WinAPI_SetFilePointerEx($hFile, $MovePos)
    _WinAPI_ReadFile($hFile, DllStructGetPtr($tIMAGE_OPTIONAL_HEADER), DllStructGetSize($tIMAGE_OPTIONAL_HEADER), $nBytes)
    Return $tIMAGE_OPTIONAL_HEADER
EndFunc

Func WRITE_IMAGE_OPTIONAL_HEADER($hFile, $MovePos, $IMAGE_OPTIONAL_HEADER)
    Local $nBytes
	_WinAPI_SetFilePointerEx($hFile, $MovePos)
    Return _WinAPI_WriteFile($hFile, DllStructGetPtr($IMAGE_OPTIONAL_HEADER), DllStructGetSize($IMAGE_OPTIONAL_HEADER), $nBytes)
EndFunc

Func READ_IMAGE_SECTION_HEADER($hFile, $MovePos)
	Local $tagIMAGE_SECTION_HEADER = '' & _
	'byte Name[8];' & _                       ;// Имя секции
	'dword Misc;' & _                         ;// Виртуальный размер
	'dword VirtualAddress;' & _               ;// Виртуальный адресс
	'dword SizeOfRawData;' & _                ;// Размер RAW данных
	'dword PointerToRawData;' & _             ;// Указатель на RAW данные
	'dword PointerToRelocations;' & _         ;// Указатель на релокейшены
	'dword PointerToLinenumbers;' & _         ;// Указатель на номера строк
	'ushort NumberOfRelocations;' & _         ;// Колличество релокейшенов
	'ushort NumberOfLinenumbers;' & _         ;// Колличество номеров строк
	'dword Characteristics'                   ;// Характеристики
	
	Local $nBytes, $tIMAGE_SECTION_HEADER = DllStructCreate($tagIMAGE_SECTION_HEADER)
    _WinAPI_SetFilePointerEx($hFile, $MovePos)
    _WinAPI_ReadFile($hFile, DllStructGetPtr($tIMAGE_SECTION_HEADER), DllStructGetSize($tIMAGE_SECTION_HEADER),$nBytes)
    Return $tIMAGE_SECTION_HEADER
EndFunc

Func WRITE_IMAGE_SECTION_HEADER($hFile, $MovePos, $IMAGE_SECTION_HEADER)
    Local $nBytes
    If $MovePos <> 0 Then _WinAPI_SetFilePointerEx($hFile, $MovePos) 
    Return _WinAPI_WriteFile($hFile, DllStructGetPtr($IMAGE_SECTION_HEADER), DllStructGetSize($IMAGE_SECTION_HEADER), $nBytes)
EndFunc
 
Верх