0

I'm experimenting on patching my hello world program in order to make it smol.

I started by reducing the size of the program with the following commands:

as --32 ./hello_32.S -o ./hello_32.o
ld -melf_i386 --omagic --strip-all ./hello_32.o -o hello_32
strip --remove-section=.note.gnu.property ./hello_32

By doing so, the size of my program is 332 bytes, but when I take a look at a HTTP server program with 229 bytes of size, I think I can reduce more, but I've no idea how to reduce the size manually

1

2 Answers 2

0

I decided to learn more about ELF format to gain better understanding

references: Sys-V ABI, Wikipedia ELF

I tried peeking at the httpd binary using readelf (thanks to the binutils package for making it easier to read):

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048060
  Start of program headers:          52 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         1
  Size of section headers:           40 (bytes)
  Number of section headers:         0
  Section header string table index: 0

There are no sections in this file.

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000060 0x08048060 0x08048060 0x00084 0x00084 RWE 0x10

There is no dynamic section in this file.

There are no relocations in this file.
No processor specific unwind information to decode

Dynamic symbol information is not available for displaying symbols.

No version information found in this file.

and the program are only constructed by elf header, program header and the text section

meanwhile, comparing to my hello world program:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x80480bc
  Start of program headers:          52 (bytes into file)
  Start of section headers:          212 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         3
  Size of section headers:           40 (bytes)
  Number of section headers:         3
  Section header string table index: 2

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        080480bc 000094 00002d 00 WAX  0   0  1
  [ 2] .shstrtab         STRTAB          00000000 0000c1 000011 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000094 0x080480bc 0x080480bc 0x0002d 0x0002d RWE 0x4
  NOTE           0x000000 0x08048094 0x00000000 0x00000 0x00000 R   0x4
  GNU_PROPERTY   0x000000 0x08048094 0x00000000 0x00000 0x00000 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     
   02     

There is no dynamic section in this file.

There are no relocations in this file.
No processor specific unwind information to decode

No version information found in this file.

I can reduce the size by eliminate some part of the binary, but before patching the program, I need to understand how the structure looks like:

00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000  .ELF............
00000010: 0200 0300 0100 0000 bc80 0408 3400 0000  ............4...
00000020: d400 0000 0000 0000 3400 2000 0300 2800  ........4. ...(.
00000030: 0300 0200 0100 0000 9400 0000 bc80 0408  ................
00000040: bc80 0408 2d00 0000 2d00 0000 0700 0000  ....-...-.......
00000050: 0400 0000 0400 0000 0000 0000 9480 0408  ................
00000060: 0000 0000 0000 0000 0000 0000 0400 0000  ................
00000070: 0400 0000 53e5 7464 0000 0000 9480 0408  ....S.td........
00000080: 0000 0000 0000 0000 0000 0000 0400 0000  ................
00000090: 0400 0000 b804 0000 00bb 0100 0000 b9db  ................
000000a0: 8004 08ba 0e00 0000 cd80 b801 0000 0031  ...............1
000000b0: dbcd 8068 656c 6c6f 2077 6f72 6c64 210a  ...hello world!.
000000c0: 0000 2e73 6873 7472 7461 6200 2e74 6578  ...shstrtab..tex
000000d0: 7400 0000 0000 0000 0000 0000 0000 0000  t...............
000000e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000f0: 0000 0000 0000 0000 0000 0000 0b00 0000  ................
00000100: 0100 0000 0700 0000 bc80 0408 9400 0000  ................
00000110: 2d00 0000 0000 0000 0000 0000 0100 0000  -...............
00000120: 0000 0000 0100 0000 0300 0000 0000 0000  ................
00000130: 0000 0000 c100 0000 1100 0000 0000 0000  ................
00000140: 0000 0000 0100 0000 0000 0000            ............

ELF Header (52 Bytes):

00000000:+0x0 - 00000030:+0x3

Program Header (3 * 32 = 96 Bytes):

00000030:+0x4 - 00000090:+0x3

Segment (64 Bytes):

00000090:+0x4 - 000000d0:+0x3

Section Header (40 * 3 = 120 bytes):

000000d0:+0x4 - 00000140:+0xB

and here's the smol version:

00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000  .ELF............
00000010: 0200 0300 0100 0000 5480 0408 3400 0000  ........T...4...
00000020: 0000 0000 0000 0000 3400 2000 0100 0000  ........4. .....
00000030: 0000 0000 0100 0000 5400 0000 5480 0408  ........T...T...
00000040: 5480 0408 2d00 0000 2d00 0000 0700 0000  T...-...-.......
00000050: 0000 0000 b804 0000 00bb 0100 0000 b973  ...............s
00000060: 8004 08ba 0e00 0000 cd80 b801 0000 0031  ...............1
00000070: dbcd 8068 656c 6c6f 2077 6f72 6c64 210a  ...hello world!.

and after manually delete some part of data, I need to adjust item that depends on file like: Entry point address, Load Offset, VirtAddr, PhysAddr, FileSiz, MemSiz, Align and pointer that passed to write syscall

Now my hello wurld program only contain: 52 Bytes ELF header + 32 Bytes Program header + 45 Bytes text section, 128 Bytes in total

I use vim and xxd to patch the binary

7
  • Worth noting that typically, the ElfXX_Shdr tables aren't used by the kernel's loader, so you can overlap the ElfXX_Phdr over the last 0xc bytes of your ElfXX_Ehdr. Pretty certain the header sizes need to be exact tho.. there were some vulns in that like forever ago so they were hardcoded. Commented May 20 at 16:48
  • is that really work? I tried to overlap it and got the following error while execute it: cannot execute binary file: Exec format error also, can you tell me more about the vuln you mention?
    – Yuki San
    Commented May 21 at 1:11
  • 7f454c4601010100000000000000000002000300010000004e8004082e0000000000000000000000340020000100010000004e0000004e800408548004082d0000002d0000000700000000000000b804000000bb01000000b973800408ba0e000000cd80b80100000031dbcd8068656c6c6f20776f726c64210a Commented May 22 at 14:52
  • used some random elf library i had lying around. ``` import ptypes, elf source=ptypes.setsource(ptypes.prov.file('elf.t2','rw')) z = elf.File().l ph = z['e_data']['e_phoff'].d # shift the segment contents (addr in asm is wrong) z['e_entries'][2].commit(offset=0x4e) # adj entrypoint z['e_data']['e_entry'].set(0x804804e).c # shift the phdrs to overlab the sections z['e_data']['e_phoff'].set(0x2e).c # adj the phdr offset and vaddr/paddr jic ph[0]['p_offset'].set(0x4e) ph[0]['p_vaddr'].set(0x804804e), #ph[0]['p_paddr'].set(0x804804e) ph.commit(offset=0x2e) ``` Commented May 22 at 14:54
  • sorry, for not posting a full comment w/ newlines... that shit gets indexed by search engines. Commented May 22 at 14:55
0
sstrip is a small utility that removes as much as possible from an
ELF file without affecting the file's memory image.

https://github.com/BR903/ELFkickers

Not the answer you're looking for? Browse other questions tagged or ask your own question.