Difference between revisions of "Linux"
m |
(→Introduction) |
||
Line 1: | Line 1: | ||
== Introduction == | == Introduction == | ||
− | For X86 related information, please check the main pages on this website, as a lot of the same tricks will also work with X86 linux sizecoding. This page goes into the specifics of getting small binaries on linux. | + | For X86 related information, please check the main pages on this website, as a lot of the same tricks will also work with X86 linux sizecoding. This page goes into the specifics of getting actual small binaries on linux using assembler. |
+ | While there have been attempts in getting tiny intros to work using self-compilation tricks (using gcc or python hacks), development of actual tiny ELF executables on linux is still in its early days. | ||
+ | |||
+ | So a huge thanks goes out to byteobserver as well as frag/fsqrt for all their research and hard work in producing | ||
+ | tiny ELF binaries for linux. | ||
=== Linux system === | === Linux system === | ||
Line 20: | Line 24: | ||
=== ELF Header Information === | === ELF Header Information === | ||
− | + | Like a 32-bit windows executable, a 32-bit binary for linux comes with a pretty hefty ELF header. | |
+ | |||
+ | <syntaxhighlight lang=nasm> | ||
+ | org 0x00010000 | ||
+ | ehdr: ; Elf32_Ehdr | ||
+ | db 0x7F, "ELF", 1, 1, 1, 0 ; e_ident | ||
+ | times 8 db 0 | ||
+ | dw 2 ; e_type | ||
+ | dw 3 ; e_machine | ||
+ | dd 1 ; e_version | ||
+ | dd _start ; e_entry | ||
+ | dd phdr - $$ ; e_phoff | ||
+ | dd 0 ; e_shoff | ||
+ | dd 0 ; e_flags | ||
+ | dw ehdrsize ; e_ehsize | ||
+ | dw phdrsize ; e_phentsize | ||
+ | dw 1 ; e_phnum | ||
+ | dw 0 ; e_shentsize | ||
+ | dw 0 ; e_shnum | ||
+ | dw 0 ; e_shstrndx | ||
+ | |||
+ | |||
+ | phdr: ; Elf32_Phdr | ||
+ | dd 1 ; p_type | ||
+ | dd 0 ; p_offset | ||
+ | dd $$ ; p_vaddr | ||
+ | dd $$ ; p_paddr | ||
+ | dd filesize ; p_filesz | ||
+ | dd filesize ; p_memsz | ||
+ | dd 5 ; p_flags | ||
+ | dd 0x1000 ; p_align | ||
+ | |||
+ | |||
+ | _start: | ||
+ | |||
+ | ; your program here | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Luckily some parts of the ELF header can be repurposed and used to store some data and code. | ||
+ | There is quite an extensive journey about some header optimisations available at http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html for those that are interested, but eventually you can get the header down to about the 30 bytes range with a | ||
+ | nifty /dev/fb0 string inserted which we'll be able to use later for setting up the framebuffer. | ||
+ | |||
+ | <syntaxhighlight lang=nasm> | ||
+ | org $00010000 | ||
+ | db $7F,"ELF" ; e_ident | ||
+ | dd 1 ; p_type | ||
+ | dd 0 ; p_offset | ||
+ | dd $$ ; p_vaddr | ||
+ | dw 2 ; e_type, p_paddr | ||
+ | dw 3 ; e_machine | ||
+ | dd entry ; e_version, p_filesz | ||
+ | dd entry ; e_entry, p_memsz | ||
+ | dd 4 ; e_phoff, p_flags | ||
+ | fname: | ||
+ | db "/dev/fb0",0 ; e_shoff, p_align, e_flags, e_ehsize | ||
+ | entry: | ||
+ | ; this next instruction overlaps with a critical part of the elf header | ||
+ | ; it needs to look like XX YY YY YY YY where YYYYYYYY=fname | ||
+ | ; so you can change the register to something else or use push | ||
+ | ; but the four byte pointer to fname cannot be changed. | ||
+ | mov ebx,fname ; e_phentsize, e_phnum | ||
+ | |||
+ | ; e_shentsize, e_shnum, e_shstrndx are below but we can put whatever code/bytes we want there | ||
+ | mov cl,1 ; set read/write mode (1 or inc ecx is sufficient for pcopy method, read/write (3) is needed for mmap) | ||
+ | mov al,5 ; 5 = open syscall | ||
+ | int 0x80 ; open /dev/fb0 = 3 | ||
+ | </syntaxhighlight> | ||
=== System Calls === | === System Calls === | ||
Line 28: | Line 98: | ||
A full list of system calls and their expected register arguments is available at: | A full list of system calls and their expected register arguments is available at: | ||
https://syscalls32.paolostivanin.com/ | https://syscalls32.paolostivanin.com/ | ||
− | |||
− | |||
− | |||
== Accessing video == | == Accessing video == |
Revision as of 06:45, 8 August 2021
Contents
Introduction
For X86 related information, please check the main pages on this website, as a lot of the same tricks will also work with X86 linux sizecoding. This page goes into the specifics of getting actual small binaries on linux using assembler.
While there have been attempts in getting tiny intros to work using self-compilation tricks (using gcc or python hacks), development of actual tiny ELF executables on linux is still in its early days.
So a huge thanks goes out to byteobserver as well as frag/fsqrt for all their research and hard work in producing tiny ELF binaries for linux.
Linux system
This section of the sizecoding.org wiki targets 32-bit X86 based Linux binaries (ELF format).
Setting up
Setting up your development platform for Linux development:
- Suggested Distributions : Any X86-based Linux distribution that allows for execution of 32-bit executables.
- Assembler: NASM (or any other linux compatible 32-bit X86 assembler)
Furthermore, it is important that the user has access to the dev/fbo framebuffer. This can be achieved by launching a virtual (fullscreen) console using CTRL-F3/F4 in most distributions, login and making sure the user has access to the video group. If this is not the case for some reason, you can add your user to the videogroup like so:
sudo usermod -a -G video username
ELF Header Information
Like a 32-bit windows executable, a 32-bit binary for linux comes with a pretty hefty ELF header.
org 0x00010000
ehdr: ; Elf32_Ehdr
db 0x7F, "ELF", 1, 1, 1, 0 ; e_ident
times 8 db 0
dw 2 ; e_type
dw 3 ; e_machine
dd 1 ; e_version
dd _start ; e_entry
dd phdr - $$ ; e_phoff
dd 0 ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
dw 1 ; e_phnum
dw 0 ; e_shentsize
dw 0 ; e_shnum
dw 0 ; e_shstrndx
phdr: ; Elf32_Phdr
dd 1 ; p_type
dd 0 ; p_offset
dd $$ ; p_vaddr
dd $$ ; p_paddr
dd filesize ; p_filesz
dd filesize ; p_memsz
dd 5 ; p_flags
dd 0x1000 ; p_align
_start:
; your program here
Luckily some parts of the ELF header can be repurposed and used to store some data and code. There is quite an extensive journey about some header optimisations available at http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html for those that are interested, but eventually you can get the header down to about the 30 bytes range with a nifty /dev/fb0 string inserted which we'll be able to use later for setting up the framebuffer.
org $00010000
db $7F,"ELF" ; e_ident
dd 1 ; p_type
dd 0 ; p_offset
dd $$ ; p_vaddr
dw 2 ; e_type, p_paddr
dw 3 ; e_machine
dd entry ; e_version, p_filesz
dd entry ; e_entry, p_memsz
dd 4 ; e_phoff, p_flags
fname:
db "/dev/fb0",0 ; e_shoff, p_align, e_flags, e_ehsize
entry:
; this next instruction overlaps with a critical part of the elf header
; it needs to look like XX YY YY YY YY where YYYYYYYY=fname
; so you can change the register to something else or use push
; but the four byte pointer to fname cannot be changed.
mov ebx,fname ; e_phentsize, e_phnum
; e_shentsize, e_shnum, e_shstrndx are below but we can put whatever code/bytes we want there
mov cl,1 ; set read/write mode (1 or inc ecx is sufficient for pcopy method, read/write (3) is needed for mmap)
mov al,5 ; 5 = open syscall
int 0x80 ; open /dev/fb0 = 3
System Calls
Interaction with the Linux OS is mostly done via int 0x80 system calls. This usually includes dealing with opening files/framebuffer/audio and handling timers.
A full list of system calls and their expected register arguments is available at: https://syscalls32.paolostivanin.com/
Accessing video
Accessing video
Getting something on screen
To be added soon.
Sound
It is possible to output digital audio by binding the the aplay command into your intro. APLAY is available on most of the Linux distributions and can be tested by running:
$ aplay -c8 /dev/urandom
Make some noise
To be added soon.