summaryrefslogtreecommitdiffstats
path: root/lace_x86.asm
blob: f1076eaa09a5ee86812c472ddadc8e67cc1f019e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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