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:
xor edx, edx ; open(argv[1], 0, 0)
xor ecx, ecx
mov ebx, [esp+8]
xor eax, eax
mov al, 5
int 0x80
cmp eax, 0 ; if fail, exit(1)
mov bl, 1
jl exit
sub esp, 16 ; alloc struct sockaddr_in
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:
xor eax, eax
mov al, 1
int 0x80
|