flat assembler
Message board for the users of flat assembler.
Index
> Compiler Internals > Bug with stub in fasm 1.7.3+ |
Author |
|
^_^ 29 Apr 2013, 13:02
Thats it. Fasm 1.67 assembles this to 1024 bytes, while with fasm 1.7.3/1.7.10 I get 1536.
|
|||||||||||
29 Apr 2013, 13:02 |
|
baldr 29 Apr 2013, 17:35
revolution,
With EXE_file.exe_len_mod_512 == 4 code in stub becomes overlay (maybe you meant 40h instead?), then fasm uses only 0x1C bytes of header, adjusting it for correct header-only MZ stub. ----8<---- ^_^, If that field contains 0, it means that stub is 512 bytes long (1.66 ignores that case and recognize stub as invalid MZ; 1.67.37, earliest build of 1.67 I have, does recognize this and handles it correctly), hence PE will be 1536 bytes total. Another option is to put 0x24 there (header 32 bytes + code 4 bytes), in that case PE will start at 0x48 (header is extended to 64 bytes, code is copied afterwards, PE signature is 8-aligned). fasm 1.66 and 1.67.37+ behave identically. In fact, relevant change is four-line insert in FORMATS.INC after stub_from_file: next to movzx edx, word [esi+2]. What is your exact 1.67 build? Can you upload it somewhere? |
|||
29 Apr 2013, 17:35 |
|
bitRAKE 29 Apr 2013, 18:56
Code: format pe gui on "nul" _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
29 Apr 2013, 18:56 |
|
^_^ 30 Apr 2013, 02:37
baldr
That's weird because Microsoft's Link.exe thinks it's valid, but it extends stub to 120 bytes (looks like it extends every stub to 120 b), but I always linked with /align:4 so I missed that. Quote: What is your exact 1.67 build? It's 1.67.21. And it lacks that 4 lines in format.inc. If you still want it http://rghost.ru/45652866 (only exe+source). I will compile to MS COFF anyway. 120 bytes stub kinda suck but it suck less than inability to specify section align, and I have more fun things to do than assemble PE manually. |
|||
30 Apr 2013, 02:37 |
|
baldr 30 Apr 2013, 21:58
^_^,
I think MS linker doesn't bother to analyze stub as long as it starts with 'MZ' (it accepts even 'MZ'*32). If you eliminate DanS/Rich block, stub will remain 64 bytes long, only IMAGE_DOS_HEADER.e_lfanew gets patched with PE offset. You don't have to assemble PE manually, fasm can be used even to replace stub with anything you want: Code: ;;; Source file names filename equ "4k.exe" stubname equ "stub.bin" include "Macro\Struct.Inc" ;;; Some utility macros struc reequ [value] { common restore . . equ value } ;;; Define BYTE/WORD/etc. macros to use struct definitions from SDK almost as-is irp pair, BYTE db, WORD dw, DWORD dd, ULONGLONG dq { match c_type fasm_directive, pair \{ macro c_type [name*] \\{ _name equ name _value equ ? match .name[.count], name \\\{; handle array syntax _name reequ .name _value reequ .count dup ? \\\} match .name .value, _name _value \\\{ .name fasm_directive .value \\\} restore _name, _value \\} \} } struct IMAGE_FILE_HEADER WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; ends struct 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; ; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; ends struct IMAGE_OPTIONAL_HEADER64 WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; ULONGLONG 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; ULONGLONG SizeOfStackReserve; ULONGLONG SizeOfStackCommit; ULONGLONG SizeOfHeapReserve; ULONGLONG SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; ; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; ends struct IMAGE_DATA_DIRECTORY DWORD VirtualAddress; DWORD Size; ends define IMAGE_SIZEOF_SHORT_NAME 8 struct IMAGE_SECTION_HEADER BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union DWORD PhysicalAddress; DWORD VirtualSize; ends DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; ends macro getdata name*, [spec*] {; getdata MZ.e_magic word, "pe_file.exe":0,2 common; 'spec' may contain comma virtual file spec load name from $$ end virtual } irp pair, byte 1, word 2, dword 4, qword 8 { match !type !size, pair \{ macro get\#!type name*, offset* \\{ getdata name !type, filename:offset, !size \\} macro assert\#!type name*, offset*, value* \\{ get\#!type name, offset assert name=value \\} \} } macro copydata [spec*] { common file filename:spec } struc copydata [spec*] { common .: copydata spec } struc copystruct struct_name*, offset* {; accepts 'struct[count]' as 'struct_name' common _name equ struct_name _count equ 1 match !name[!count], struct_name \{ _name reequ !name _count reequ !count \} match !name !count, _name _count \{ virtual . !name sizeof.#. = $-.; actually it's 'count' times bigger end virtual copydata offset, sizeof.\#!name*!count \} restore _name, _count } macro load [arg*] {; accepts 'array[index].field' as an address _arg equ arg match !name !type =from !array[!index]!field, arg \{ _arg reequ !name !type from !array\#!field+(!index)*sizeof.\#!array \} load _arg restore _arg } macro store arg* {; accepts 'array[index].field' as an address _arg equ arg match !name !type =at !array[!index]!field, arg \{ _arg reequ !name !type at !array\#!field+(!index)*sizeof.\#!array \} store _arg restore _arg } macro align value { rb (value-1)-($+value-1) mod value } ;;; Ready, set, GO! format binary as "Exe" assertword MZ.signature, 0, 'MZ' getdword PE, 0x3C assertdword PE.signature, PE, 'PE' PE.FileHeader = PE+4 PE.OptionalHeader = PE.FileHeader+sizeof.IMAGE_FILE_HEADER file stubname store dword newPE at 0x3C ;;; Copy signature and file header newPE copydata PE, 4 newPE.FileHeader copystruct IMAGE_FILE_HEADER, PE.FileHeader ;;; Copy optional header (w/o data directory) getword PE.Magic, PE.OptionalHeader if PE.Magic=0x010B newPE.OptionalHeader copystruct IMAGE_OPTIONAL_HEADER, PE.OptionalHeader else if PE.Magic=0x020B newPE.OptionalHeader copystruct IMAGE_OPTIONAL_HEADER64, PE.OptionalHeader else err "Only PE32 and PE32+ are supported" end if ;;; Copy data directory PE.OptionalHeader.DataDirectory = PE.OptionalHeader+$-newPE.OptionalHeader load newPE.NumberOfRvaAndSizes dword from newPE.OptionalHeader.NumberOfRvaAndSizes newPE.OptionalHeader.DataDirectory copystruct IMAGE_DATA_DIRECTORY[newPE.NumberOfRvaAndSizes], PE.OptionalHeader.DataDirectory sizeof.newPE.OptionalHeader = $-newPE.OptionalHeader ;;; Copy section headers load newPE.NumberOfSections word from newPE.FileHeader.NumberOfSections PE.SectionHeaders = PE.OptionalHeader+sizeof.newPE.OptionalHeader newPE.SectionHeaders copystruct IMAGE_SECTION_HEADER[newPE.NumberOfSections], PE.SectionHeaders ;;; Copy sections load newPE.FileAlignment dword from newPE.OptionalHeader.FileAlignment repeat newPE.NumberOfSections align newPE.FileAlignment load SizeOfRawData dword from newPE.SectionHeaders[%-1].SizeOfRawData load PointerToRawData dword from newPE.SectionHeaders[%-1].PointerToRawData store dword $ at newPE.SectionHeaders[%-1].PointerToRawData; patch section header copydata PointerToRawData, SizeOfRawData end repeat ;;; Patch OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress, if present ;;; Signature'll become invalid anyway IMAGE_DIRECTORY_ENTRY_SECURITY = 4 if newPE.NumberOfRvaAndSizes>IMAGE_DIRECTORY_ENTRY_SECURITY load PE.Certificate.VirtualAddress dword\ from newPE.OptionalHeader.DataDirectory.VirtualAddress+sizeof.IMAGE_DATA_DIRECTORY*IMAGE_DIRECTORY_ENTRY_SECURITY if PE.Certificate.VirtualAddress store dword PE.Certificate.VirtualAddress+$-(PointerToRawData+SizeOfRawData)\ at newPE.OptionalHeader.DataDirectory.VirtualAddress+sizeof.IMAGE_DATA_DIRECTORY*IMAGE_DIRECTORY_ENTRY_SECURITY end if end if ;;; Copy trailer copydata PointerToRawData+SizeOfRawData |
|||
30 Apr 2013, 21:58 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.