Section Settings
After version 0.2.0, micro uses the section/segment of ELF/PE/Mach-O files to obtain information, no longer using multiple builds.
Section mode supports configuration of limit, UPX compression (need to modify binary under ELF), digital signature, and allows modification of binary after building
File Structure
| ELF/PE/Mach-O Executable | INI settings | PHP or PHAR payload | Other data |
limit Configuration
If the following sfxsize section is not set:
micro_get_sfxsize_limitreturns 0, all data aftersizeis payloadmicro_get_sfxsizereturns, when- ELF: The end of the last Section, if there is no Section table, return the end of the last
Program Header Segment - Mach-O: The end of
__LINKEDIT - Fat Mach-O: End of the last
fat_archmacho (offset + size) - Windows: The end of the last Section
- ELF: The end of the last Section, if there is no Section table, return the end of the last
sfxsize section
The format of the sfxsize section is:
typedef struct _micro_sfxsize_section_t {
uint64_t size; /* sfx size, big endian */
uint64_t limit; /* limit size, big endian */
} __attribute__((pacaked)) micro_sfxsize_section_t;
size represents the size of the executable file binary, in bytes, big endian
limit represents the size of sfx binary + payload, in bytes, big endian
When limit is 0, it means that there is no size limit, and all data after size is payload
ELF
For systems that use ELF as the executable file format, such as Linux, FreeBSD:
micro obtains the above structure through the Section with .sh_name as .sfxsize
Mach-O
For macOS’s Mach-O:
micro obtains the above structure through the __micro_sfxsize Section of the __DATA Segment
Fat (Universal) Mach-O
The following behavior may change before micro’s main version 1.
For Fat Mach-O:
micro will read the section at fat_arch.offset + 0x1000 where cputype == CPU_TYPE_X86
For now, micro do not support x86(32-bit) (maybe able to build, but without any official support). macOS support for x86 have been dropped long long ago (Catalina), and support of x86_64 appears earlier (Snow Leopard), so we reuse CPU_TYPE_X86 type.
0x1000 is size of a minimal x86 executable, this allows a stub for telling use the arch is unsupported.
PE
For PE(EXE) format used by Windows:
micro obtains the above structure through the Section with ID as PHP_MICRO_SIGNATURE_ID
UPX
Under Windows, UPX compression is supported, and the compressed binary can be executed directly.
For ELF, because UPX discards the section table, it is impossible to obtain the real end position after UPX, so the binary needs to be modified:
Drop the data after the last Program Header Segment after UPX compression, so that UPX cannot decompress it, making your program look like a virus.
For reference: Get last Program Header Segment end position first
readelf -l micro.sfx.upxed
The output looks like:
...
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000001000 0x0000000001cb6f88 RW 0x1000
LOAD 0x0000000000000000 0x0000000001cb7000 0x0000000001cb7000
0x000000000065aadb 0x000000000065aadb R E 0x1000
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
...
Truncate the file to the largest Offset+FileSiz(0x0000000000000000 + 0x000000000065aadb = 6662875)
dd if=micro.sfx.upxed of=micro.sfx.upxed.stripped bs=6662875 count=1
chmod 0755 micro.sfx.upxed.stripped
Digital Signature
TODO: Make a tool to facilitate signing
Windows
The digital signature under Windows is to modify part of the PE/COFF header content (without changing the size), and then add some data at the end of the file, so the steps to refer to are:
- Modify sfx as desired, such as changing the logo to a favorite one, you can use Resource Hacker
- Add an
RC_DATAwith IDPHP_MICRO_SIGNATURE_IDor12346in sfx, size is 16 bytes, record the size of sfx at this time - Change the data of the section to real data (
.size= sfx size,.limit= sfx size + payload size, excluding the padding after), refer to the sfxsize section - Align the file to 4096 (512 seems enough, but I use 4096)
- Set the end of the last section to the end of the file
- Sign it
Mach-O
The digital signature under macOS is to add a segment/section, so the operation is:
- Concatenate sfx and payload
- Align to 4096
- Set the end of
__LINKEDITto the end of the file - Sign it