summaryrefslogtreecommitdiffstats
path: root/lace_x86.asm
diff options
context:
space:
mode:
Diffstat (limited to 'lace_x86.asm')
-rw-r--r--lace_x86.asm149
1 files changed, 149 insertions, 0 deletions
diff --git a/lace_x86.asm b/lace_x86.asm
new file mode 100644
index 0000000..f1076ea
--- /dev/null
+++ b/lace_x86.asm
@@ -0,0 +1,149 @@
+BITS 32
+
+ 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 ; | |
+ db 0x00 ; shoff: 0 (File offset)** align: 0 (No alignment constraints)
+ db 0x00 ; | |
+ db 0x00 ; | |
+ db 0x00 ; | |
+ db 0x00 ; flags: 0
+ db 0x00 ; |
+ db 0x00 ; |
+ db 0x00 ; |
+ 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:
+ mov ebp, esp
+ sub esp, 16 ; alloc struct sockaddr_in
+
+ xor edx, edx ; open(argv[1], 0, 0)
+ xor ecx, ecx
+ mov ebx, [ebp+8]
+ xor eax, eax
+ mov al, 5
+ int 0x80
+
+ cmp eax, 0 ; if fail, exit(1)
+ mov bl, 1
+ jle exit
+
+ mov dl, 16 ; read(fd, sockaddr_in, sizeof(sockaddr_in))
+ mov ecx, esp
+ mov ebx, eax
+ mov al, 3
+ int 0x80
+
+ cmp eax, 16 ; if fail, exit(2)
+ mov bl, 2
+ jne exit
+
+ push 0 ; socket(AF_INET, SOCK_STREAM, 0)
+ push 1
+ push 2
+ mov ecx, esp
+ mov bl, 1
+ mov al, 0x66
+ int 0x80
+
+ push 16 ; connect(sock, sockaddr_in, sizeof(sockaddr_in))
+ lea ecx, [esp+16]
+ push ecx
+ push eax
+ mov ecx, esp
+ mov bl, 3
+ mov al, 0x66
+ int 0x80
+
+ cmp eax, 0 ; if fail, exit(3)
+ mov bl, 3
+ jne exit
+
+ pop edi ; recover socket fd
+ sub esp, 0xff ; alloc data buffer
+
+ xor esi, esi ; pipe(sock, stdin)
+ call pipe
+
+ xchg edi, esi ; pipe(stdin, sock)
+ call pipe
+
+ xor ebx, ebx ; exit(0)
+ jmp exit
+
+pipe:
+ mov dl, 0xff ; read(src, buff, sizeof(buff))
+ lea ecx, [esp+4]
+ mov ebx, esi
+ mov al, 3
+ int 0x80
+
+ cmp eax, 0 ; if finished, return
+ jg pipe_cont
+ ret
+
+pipe_cont:
+ mov edx, eax ; write(dst, buff, nb)
+ mov ebx, edi
+ mov al, 4
+ int 0x80
+ jmp pipe ; loop
+
+exit:
+ mov al, 1
+ int 0x80