BITS 32 %define PORT 0x3905 ; TCP port 1337 %define ADDRESS 0x0100007f ; 127.0.0.1 org 0x00010000 ; Memory load location ; ELF HEADER CONTENT PROGRAM HEADER TBL ENTRY CONTENT ; ------------------------------------------------------------------------------------------------------------------ db 0x7f, "ELF" ; magic number: 7f454c46 db 0x01 ; class: 1 (32-bit) type: 1 (Loadable segment) db 0x00 ; data: 0 (invalid)* | db 0x00 ; version: 0 (invalid)* | db 0x00 ; abi: 0 (System V) | db 0x00 ; abi version: 0 offset: 0 (File offset) db 0x00 ; padding | db 0x00 ; | | db 0x00 ; | | dd $$ ; | vaddr: $$ (File memory location) db 0x02 ; type: 2 (Executable) paddr: 0x00030002 * db 0x00 ; | | db 0x03 ; machine: 3 (Intel i386 x86) | db 0x00 ; | | dd _start ; version: _start (invalid)* filesz: _start (too large)*** dd _start ; entry: _start (Program entry point) memsz: _start *** db 0x04 ; phoff: 4 (File offset) flags: 4 (READ) *** db 0x00 ; | | db 0x00 ; | | db 0x00 ; | | sockaddr: db 0x02 ; shoff: ??? (File offset)** align: ??? db 0x00 ; | | dw PORT ; | | dd ADDRESS ; flags: ??? db 0x34 ; ehsize: 52 db 0x00 ; | db 0x20 ; phentsize: 32 db 0x00 ; | db 0x01 ; phnum: 1 (.text) db 0x00 ; | ;db 0x00 ; shentsize: 0** [ Cut these out to overlap with program code ] ;db 0x00 ; | ;db 0x00 ; shnum: 0** ;db 0x00 ; | ;db 0x00 ; shstrndx: 0** ;db 0x00 ; | ; For space savings, the above constructs the ELF metadata for this program ; without invoking an external linker. The ELF header and the program ; header entry completely overlap each other. Some concessions were made to ; allow this to be possible. See the asterisks above and explainations ; below for details. ; ; * Invalid values are present to leverage overloading fields that go ; unchecked by the loader at runtime. Such values are likely being set ; to what is required by the other data structure. ; ; ** Section headers are not utilized by this program, so no relevant ; header fields are utilized. As with (*) fields, these too go ; unchecked by the loader. ; ; *** phoff must be == 4 in this arrangement, therefore program header flags ; just match it. This is fine, as apparently execute is implied in this ; case. However, since the writable bit is not set, we can not set ; memsz larger than filesz (the loader is not able to 'write' the extra ; initializing zero bytes). Therefore, both fields are set to the value ; of the program entry point, so that the entry point field from ELF ; (which coinsides) can be set properly. The fact that filesz will be ; larger than that of the actual output file is of no consequence. _start: push 0 ; socket(AF_INET, SOCK_STREAM, 0) push 1 push 2 mov ecx, esp mov bl, 0x01 mov al, 0x66 int 0x80 push 16 ; connect(fd, sockaddr, sizeof(sockaddr)) lea ecx, sockaddr push ecx push eax mov ecx, esp mov bl, 0x03 mov al, 0x66 int 0x80 pop edi ; pipe(fd, stdin) mov ecx, esp call pipe inc esi ; pipe(stdout, fd) xchg edi, esi call pipe xor eax, eax ; exit() inc eax int 0x80 pipe_loop: mov edx, eax ; write(edi, ecx, eax) mov ebx, edi mov al, 0x04 int 0x80 pipe: mov dl, 0xff ; read(esi, ecx, 0xff) mov ebx, esi mov al, 0x03 int 0x80 cmp eax, 0 ; eof/error, return jg pipe_loop ret