Что нового

Узнать размер исполняющего файла без оверлея

Viktor1703

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

Код:
#Include <WinAPIEx.au3>

#Region Global Variables

	#Region IMAGE_DOS_HEADER

		Global Const $tagPE_IMAGE_DOS_HEADER =	'word e_magic;' & _
												'word e_cblp;' & _
												'word e_cp;' & _
												'word e_crlc;' & _
												'word e_cparhdr;' & _
												'word e_minalloc;' & _
												'word e_maxalloc;' & _
												'word e_ss;' & _
												'word e_sp;' & _
												'word e_csum;' & _
												'word e_ip;' & _
												'word e_cs;' & _
												'word e_lfarlc;' & _
												'word e_ovno;' & _
												'word e_res[4];' & _
												'word e_oemid;' & _
												'word e_oeminfo;' & _
												'word e_res2[10];' & _
												'long e_lfanew;'
	#EndRegion

	#Region IMAGE_FILE_HEADER

		Global Const $tagPE_IMAGE_FILE_HEADER =	'word Machine;' & _
												'word NumberOfSections;' & _
												'dword TimeDateStamp;' & _
												'dword PointerToSymbolTable;' & _
												'dword NumberOfSymbols;' & _
												'word SizeOfOptionalHeader;' & _
												'word Characteristics;'
	#EndRegion

	#Region IMAGE_OPTIONAL_HEADER

		If (Not @AutoItX64) Then

			Global $tagPE_IMAGE_OPTIONAL_HEADER  =	'word Magic;' & _
													'byte MajorLinkerVersion;' & _
													'byte MinorLinkerVersion;' & _
													'dword SizeOfCode;' & _
													'dword SizeOfInitializedData;' & _
													'dword SizeOfUninitializedData;' & _
													'dword AddressOfEntryPoint;' & _
													'dword BaseOfCode;' & _
													'dword BaseOfData;' & _
													'dword ImageBase;' & _
													'dword SectionAlignment;' & _
													'dword FileAlignment;' & _
													'word MajorOperatingSystemVersion;' & _
													'word MinorOperatingSystemVersion;' & _
													'word MajorImageVersion;' & _
													'word MinorImageVersion;' & _
													'word MajorSubsystemVersion;' & _
													'word MinorSubsystemVersion;' & _
													'dword Win32VersionValue;' & _
													'dword SizeOfImage;' & _
													'dword SizeOfHeaders;' & _
													'dword CheckSum;' & _
													'word Subsystem;' & _
													'word DllCharacteristics;' & _
													'dword SizeOfStackReserve;' & _
													'dword SizeOfStackCommit;' & _
													'dword SizeOfHeapReserve;' & _
													'dword SizeOfHeapCommit;' & _
													'dword LoaderFlags;' & _
													'dword NumberOfRvaAndSizes;'

		Else

			Global $tagPE_IMAGE_OPTIONAL_HEADER =	'word Magic;' & _
													'byte MajorLinkerVersion;' & _
													'byte MinorLinkerVersion;' & _
													'dword SizeOfCode;' & _
													'dword SizeOfInitializedData;' & _
													'dword SizeOfUninitializedData;' & _
													'dword AddressOfEntryPoint;' & _
													'dword BaseOfCode;' & _
													'ptr ImageBase;' & _
													'dword SectionAlignment;' & _
													'dword FileAlignment;' & _
													'word MajorOperatingSystemVersion;' & _
													'word MinorOperatingSystemVersion;' & _
													'word MajorImageVersion;' & _
													'word MinorImageVersion;' & _
													'word MajorSubsystemVersion;' & _
													'word MinorSubsystemVersion;' & _
													'dword Win32VersionValue;' & _
													'dword SizeOfImage;' & _
													'dword SizeOfHeaders;' & _
													'dword CheckSum;' & _
													'word Subsystem;' & _
													'word DllCharacteristics;' & _
													'ptr SizeOfStackReserve;' & _
													'ptr SizeOfStackCommit;' & _
													'ptr SizeOfHeapReserve;' & _
													'ptr SizeOfHeapCommit;' & _
													'dword LoaderFlags;' & _
													'dword NumberOfRvaAndSizes;'

		EndIf

	#EndRegion

	#Region IMAGE_NT_HEADER

		Global Const $tagPE_IMAGE_NT_HEADER = 'dword Signature;' & $tagPE_IMAGE_FILE_HEADER & $tagPE_IMAGE_OPTIONAL_HEADER

	#EndRegion

	#Region IMAGE_SECTION_HEADER

		Global Const $tagPE_IMAGE_SECTION_HEADER =	'byte Name[8];' & _
													'dword VirtualSize;' & _
													'dword VirtualAddress;' & _
													'dword SizeOfRawData;' & _
													'dword PointerToRawData;' & _
													'dword PointerToRelocations;' & _
													'dword PointerToLinenumbers;' & _
													'word NumberOfRelocations;' & _
													'word NumberOfLinenumbers;' & _
													'dword Characteristics;'

	#EndRegion

#EndRegion


$iSizeOfImage = __pe_GetSizeOfImage(@ScriptDir & '\Test.exe')

Switch @error
	Case 1
		ConsoleWrite('Не удалось получить указатель на модуль' & @LF)
	Case 2
		ConsoleWrite('Не удалось извлечь дескриптор указанного модуля' & @LF)
	Case 3
		ConsoleWrite('Файл не является исполняющим' & @LF)
	Case 4
		ConsoleWrite('Не верная сигнатура' & @LF)
EndSwitch

ConsoleWrite($iSizeOfImage & @CRLF)


Func __pe_GetSizeOfImage($vModuleName = '')

	Local $hmod, $pImageBase, $tIdh, $iAddr, $tInh, $tIfh, $tIoh, $tIsh

	If ($vModuleName <> '') Then
		$hmod = _WinAPI_LoadLibrary($vModuleName)
		If ((Not $hmod) And @error) Then
			Return SetError(1, 0, 0)
		EndIf
		$pImageBase = _WinAPI_GetModuleHandle($vModuleName)
		If ((Not $pImageBase) And @error) Then
			_WinAPI_CloseHandle($hmod)
			Return SetError(2, 0, 0)
		EndIf
		_WinAPI_CloseHandle($hmod)
	Else
		$pImageBase = _WinAPI_GetModuleHandle($vModuleName)
		If ((Not $pImageBase) And @error) Then
			Return SetError(2, 0, 0)
		EndIf
	EndIf
	$tIdh = DllStructCreate($tagPE_IMAGE_DOS_HEADER, $pImageBase)
	If (DllStructGetData($tIdh, 'e_magic') <> 0x5A4D) Then
		Return SetError(3, 0, 0)
	EndIf
	$iAddr = ($pImageBase + DllStructGetData($tIdh, 'e_lfanew'))
	$tInh = DllStructCreate($tagPE_IMAGE_NT_HEADER, $iAddr)
	If (DllStructGetData($tInh, 'Signature') <> 0x4550) Then
		Return SetError(4, 0, 0)
	EndIf
	$iAddr = (DllStructGetPtr($tIdh) + DllStructGetData($tIdh, 'e_lfanew') + DllStructGetSize(DllStructCreate('long')))
	$tIfh = DllStructCreate($tagPE_IMAGE_FILE_HEADER, $iAddr)
	$iAddr = (DllStructGetPtr($tIfh) + DllStructGetSize(DllStructCreate($tagPE_IMAGE_FILE_HEADER)))
	$tIoh = DllStructCreate($tagPE_IMAGE_OPTIONAL_HEADER, $iAddr)
	$iAddr = (DllStructGetPtr($tIoh) + DllStructGetData($tIfh, 'SizeOfOptionalHeader'))
	$tIsh = DllStructCreate($tagPE_IMAGE_SECTION_HEADER, $iAddr)
	$iAddr = (DllStructGetPtr($tIsh) + ((DllStructGetData($tIfh, 'NumberOfSections') - 1) * DllStructGetSize(DllStructCreate($tagPE_IMAGE_SECTION_HEADER))))
	$tIsh = DllStructCreate($tagPE_IMAGE_SECTION_HEADER, $iAddr)
	Return (DllStructGetData($tIsh, 'PointerToRawData') + DllStructGetData($tIsh, 'SizeOfRawData'))
EndFunc

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

2. Если нужно извлечь оверлей из самого себя, вызвать функцию без параметра.

3. Узнать адрес с которого начинается оверлей.

Код:
$iOverlay = __pe_GetSizeOfImage(...)


4. Узнать размер оверлея

Код:
;~ Для стороннего файла
$sFile = @ScriptDir & '\Test.exe'

$iFileSize = FileGetSize($sFile)
$iOverlay = __pe_GetSizeOfImage($sFile)

$iOverlaySize = ($iFileSize - $iOverlay)

;~ Для самого себя
If @Compiled Then
	MsgBox(0, 'Размер данных в оверлее', FileGetSize(@ScriptFullPath) - __pe_GetSizeOfImage())
EndIf


5. Не большой тест, скомпилируйте пример

Код:
#Include <WinAPIEx.au3>

#Region Global Variables

	#Region IMAGE_DOS_HEADER

		Global Const $tagPE_IMAGE_DOS_HEADER =	'word e_magic;' & _
												'word e_cblp;' & _
												'word e_cp;' & _
												'word e_crlc;' & _
												'word e_cparhdr;' & _
												'word e_minalloc;' & _
												'word e_maxalloc;' & _
												'word e_ss;' & _
												'word e_sp;' & _
												'word e_csum;' & _
												'word e_ip;' & _
												'word e_cs;' & _
												'word e_lfarlc;' & _
												'word e_ovno;' & _
												'word e_res[4];' & _
												'word e_oemid;' & _
												'word e_oeminfo;' & _
												'word e_res2[10];' & _
												'long e_lfanew;'
	#EndRegion

	#Region IMAGE_FILE_HEADER

		Global Const $tagPE_IMAGE_FILE_HEADER =	'word Machine;' & _
												'word NumberOfSections;' & _
												'dword TimeDateStamp;' & _
												'dword PointerToSymbolTable;' & _
												'dword NumberOfSymbols;' & _
												'word SizeOfOptionalHeader;' & _
												'word Characteristics;'
	#EndRegion

	#Region IMAGE_OPTIONAL_HEADER

		If (Not @AutoItX64) Then

			Global $tagPE_IMAGE_OPTIONAL_HEADER  =	'word Magic;' & _
													'byte MajorLinkerVersion;' & _
													'byte MinorLinkerVersion;' & _
													'dword SizeOfCode;' & _
													'dword SizeOfInitializedData;' & _
													'dword SizeOfUninitializedData;' & _
													'dword AddressOfEntryPoint;' & _
													'dword BaseOfCode;' & _
													'dword BaseOfData;' & _
													'dword ImageBase;' & _
													'dword SectionAlignment;' & _
													'dword FileAlignment;' & _
													'word MajorOperatingSystemVersion;' & _
													'word MinorOperatingSystemVersion;' & _
													'word MajorImageVersion;' & _
													'word MinorImageVersion;' & _
													'word MajorSubsystemVersion;' & _
													'word MinorSubsystemVersion;' & _
													'dword Win32VersionValue;' & _
													'dword SizeOfImage;' & _
													'dword SizeOfHeaders;' & _
													'dword CheckSum;' & _
													'word Subsystem;' & _
													'word DllCharacteristics;' & _
													'dword SizeOfStackReserve;' & _
													'dword SizeOfStackCommit;' & _
													'dword SizeOfHeapReserve;' & _
													'dword SizeOfHeapCommit;' & _
													'dword LoaderFlags;' & _
													'dword NumberOfRvaAndSizes;'

		Else

			Global $tagPE_IMAGE_OPTIONAL_HEADER =	'word Magic;' & _
													'byte MajorLinkerVersion;' & _
													'byte MinorLinkerVersion;' & _
													'dword SizeOfCode;' & _
													'dword SizeOfInitializedData;' & _
													'dword SizeOfUninitializedData;' & _
													'dword AddressOfEntryPoint;' & _
													'dword BaseOfCode;' & _
													'ptr ImageBase;' & _
													'dword SectionAlignment;' & _
													'dword FileAlignment;' & _
													'word MajorOperatingSystemVersion;' & _
													'word MinorOperatingSystemVersion;' & _
													'word MajorImageVersion;' & _
													'word MinorImageVersion;' & _
													'word MajorSubsystemVersion;' & _
													'word MinorSubsystemVersion;' & _
													'dword Win32VersionValue;' & _
													'dword SizeOfImage;' & _
													'dword SizeOfHeaders;' & _
													'dword CheckSum;' & _
													'word Subsystem;' & _
													'word DllCharacteristics;' & _
													'ptr SizeOfStackReserve;' & _
													'ptr SizeOfStackCommit;' & _
													'ptr SizeOfHeapReserve;' & _
													'ptr SizeOfHeapCommit;' & _
													'dword LoaderFlags;' & _
													'dword NumberOfRvaAndSizes;'

		EndIf

	#EndRegion

	#Region IMAGE_NT_HEADER

		Global Const $tagPE_IMAGE_NT_HEADER = 'dword Signature;' & $tagPE_IMAGE_FILE_HEADER & $tagPE_IMAGE_OPTIONAL_HEADER

	#EndRegion

	#Region IMAGE_SECTION_HEADER

		Global Const $tagPE_IMAGE_SECTION_HEADER =	'byte Name[8];' & _
													'dword VirtualSize;' & _
													'dword VirtualAddress;' & _
													'dword SizeOfRawData;' & _
													'dword PointerToRawData;' & _
													'dword PointerToRelocations;' & _
													'dword PointerToLinenumbers;' & _
													'word NumberOfRelocations;' & _
													'word NumberOfLinenumbers;' & _
													'dword Characteristics;'

	#EndRegion

#EndRegion

If @Compiled Then
	$iSizeOfImage = __pe_GetSizeOfImage()

	Switch @error
		Case 0
			MsgBox(0, '', 'Адрес оверлея: ' & $iSizeOfImage & @CRLF & 'Размер данных в оверлее: ' & (FileGetSize(@ScriptFullPath) - $iSizeOfImage) & ' байт')
		Case 1
			MsgBox(0, '', 'Не удалось получить указатель на модуль')
		Case 2
			MsgBox(0, '', 'Не удалось извлечь дескриптор указанного модуля')
		Case 3
			MsgBox(0, '', 'Файл не является исполняющим')
		Case 4
			MsgBox(0, '', 'Не верная сигнатура')
	EndSwitch
EndIf


Func __pe_GetSizeOfImage($vModuleName = '')

	Local $hmod, $pImageBase, $tIdh, $iAddr, $tInh, $tIfh, $tIoh, $tIsh

	If ($vModuleName <> '') Then
		$hmod = _WinAPI_LoadLibrary($vModuleName)
		If ((Not $hmod) And @error) Then
			Return SetError(1, 0, 0)
		EndIf
		$pImageBase = _WinAPI_GetModuleHandle($vModuleName)
		If ((Not $pImageBase) And @error) Then
			_WinAPI_CloseHandle($hmod)
			Return SetError(2, 0, 0)
		EndIf
		_WinAPI_CloseHandle($hmod)
	Else
		$pImageBase = _WinAPI_GetModuleHandle($vModuleName)
		If ((Not $pImageBase) And @error) Then
			Return SetError(2, 0, 0)
		EndIf
	EndIf
	$tIdh = DllStructCreate($tagPE_IMAGE_DOS_HEADER, $pImageBase)
	If (DllStructGetData($tIdh, 'e_magic') <> 0x5A4D) Then
		Return SetError(3, 0, 0)
	EndIf
	$iAddr = ($pImageBase + DllStructGetData($tIdh, 'e_lfanew'))
	$tInh = DllStructCreate($tagPE_IMAGE_NT_HEADER, $iAddr)
	If (DllStructGetData($tInh, 'Signature') <> 0x4550) Then
		Return SetError(4, 0, 0)
	EndIf
	$iAddr = (DllStructGetPtr($tIdh) + DllStructGetData($tIdh, 'e_lfanew') + DllStructGetSize(DllStructCreate('long')))
	$tIfh = DllStructCreate($tagPE_IMAGE_FILE_HEADER, $iAddr)
	$iAddr = (DllStructGetPtr($tIfh) + DllStructGetSize(DllStructCreate($tagPE_IMAGE_FILE_HEADER)))
	$tIoh = DllStructCreate($tagPE_IMAGE_OPTIONAL_HEADER, $iAddr)
	$iAddr = (DllStructGetPtr($tIoh) + DllStructGetData($tIfh, 'SizeOfOptionalHeader'))
	$tIsh = DllStructCreate($tagPE_IMAGE_SECTION_HEADER, $iAddr)
	$iAddr = (DllStructGetPtr($tIsh) + ((DllStructGetData($tIfh, 'NumberOfSections') - 1) * DllStructGetSize(DllStructCreate($tagPE_IMAGE_SECTION_HEADER))))
	$tIsh = DllStructCreate($tagPE_IMAGE_SECTION_HEADER, $iAddr)
	Return (DllStructGetData($tIsh, 'PointerToRawData') + DllStructGetData($tIsh, 'SizeOfRawData'))
EndFunc

Запустите полученный исполняющий файл, убедитесь что размер оверлея равен нулю, откройте файл в HEX редакторе, добавьте несколько байт в самый конец файла, сохраните, запустите полученный файл и вы увидите сколько байт вы добавили в конец исполняющего файла. Данный пример особенно пригодится тем кто любит строить свои билдеры которые в ходе выполнения извлекают из себя стаб и добавляют в него некую информацию.

P.S. Если вы используете AutoIt v3.3.10.2 то в оверлее после компиляции ни чего не будет, так как скрипт добавляется в ресурсы исполняющего файла, если же версию AutoIt v3.3.8.1 и ниже, то изначально в оверлее будет некоторое количество байт, так как там уже хранится скрипт.

Вот простой пример

Test.exe - файл в который будут записываться данные
Write.exe - файл который будет записывать данные

Запустите Test.exe и убедитесь что в него ни чего не записано, в 'Размер данных в оверлее' должно стоять 0 (ноль), запустите Write.exe, введите в поле текст и нажмите OK, далее снова запустите Test.exe, теперь вы увидите размер данных в оверлее и сами данные.
 
Верх