-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgasm.asm
More file actions
470 lines (409 loc) · 8.17 KB
/
gasm.asm
File metadata and controls
470 lines (409 loc) · 8.17 KB
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
; =============================================================================
; GASM (Gopher Assembly) - i386 Edition (v5.2)
;
; Fixes: Fixed ESI Register Corruption (Segfault on loop).
; Fixed possible d_reclen infinite loop.
;
; Build: nasm -f elf32 gasm.asm -o gasm.o
; Link: ld -m elf_i386 gasm.o -o gasm
; =============================================================================
section .data
port_w equ 0xD21E ; Port 7890
; Null-terminated strings
tab db 0x09, 0
crlf db 0x0D, 0x0A, 0
end_of_menu db ".", 0x0D, 0x0A, 0
slash db "/", 0
host_str db "localhost", 0
port_str db "7890", 0
err_msg db "3Error", 0x09, "err", 0x09, "0", 0x0D, 0x0A, 0
MAX_BASE_LEN equ 3000
section .bss
; Global State
sockfd resd 1
clientfd resd 1
base_dir resd 1 ; <--- NEW: Store Base Dir Ptr here
; Buffers
req_buf resb 512
path_buf resb 4096
dent_buf resb 4096
file_buf resb 4096
stat_buf resb 144
args resd 6
section .text
global _start
_start:
; --- 1. Argument Parsing ---
pop eax ; argc
cmp eax, 2
jl exit_app
pop ebx ; argv[0]
pop esi ; argv[1] (Base Path)
; Save Base Path to Global (Critical Fix)
mov [base_dir], esi
; Validate Length
mov edi, esi
call strlen
cmp eax, MAX_BASE_LEN
jg exit_app
; --- 2. Socket ---
mov dword [args], 2
mov dword [args+4], 1
mov dword [args+8], 0
mov eax, 102 ; sys_socketcall
mov ebx, 1 ; SYS_SOCKET
mov ecx, args
int 0x80
test eax, eax
js exit_app
mov [sockfd], eax
; --- 3. Set SO_REUSEADDR ---
mov eax, [sockfd]
mov [args], eax
mov dword [args+4], 1
mov dword [args+8], 2
push dword 1
mov eax, esp
mov [args+12], eax
mov dword [args+16], 4
mov eax, 102
mov ebx, 14
mov ecx, args
int 0x80
add esp, 4
; --- 4. Bind ---
xor eax, eax
push eax
push eax
mov word [esp], 2
mov word [esp+2], port_w
mov eax, [sockfd]
mov [args], eax
mov [args+4], esp
mov dword [args+8], 16
mov eax, 102
mov ebx, 2
mov ecx, args
int 0x80
add esp, 16
test eax, eax
js exit_app
; --- 5. Listen ---
mov eax, [sockfd]
mov [args], eax
mov dword [args+4], 10
mov eax, 102
mov ebx, 4
mov ecx, args
int 0x80
server_loop:
; --- 6. Accept ---
mov eax, [sockfd]
mov [args], eax
mov dword [args+4], 0
mov dword [args+8], 0
mov eax, 102
mov ebx, 5
mov ecx, args
int 0x80
test eax, eax
js server_loop
mov [clientfd], eax
; --- 7. Read ---
mov eax, 3
mov ebx, [clientfd]
mov ecx, req_buf
mov edx, 511
int 0x80
test eax, eax
jle close_client
; --- 8. Sanitize ---
mov ecx, eax
mov edi, req_buf
.scan:
cmp byte [edi], 0x0D
je .term
cmp byte [edi], 0x0A
je .term
inc edi
loop .scan
.term:
mov byte [edi], 0
; --- 9. Traversal Check ---
mov edi, req_buf
call check_traversal
cmp eax, 1
je send_error
; --- 10. Build Path ---
; FIX: Load from global [base_dir] instead of ESI
mov edi, path_buf
push dword [base_dir] ; Source
push edi ; Dest
call strcpy
add esp, 8
mov edi, path_buf
call strlen_fast
mov byte [edi], '/'
inc edi
push req_buf
push edi
call strcpy
add esp, 8
; --- 11. Stat ---
mov eax, 195 ; sys_stat64
mov ebx, path_buf
mov ecx, stat_buf
int 0x80
test eax, eax
js send_error
mov ax, [stat_buf + 16] ; st_mode
and ax, 0xF000
cmp ax, 0x4000
je handle_dir
jmp handle_file
; =============================================================================
; Directory Logic
; =============================================================================
handle_dir:
mov eax, 5
mov ebx, path_buf
mov ecx, 0x10000
mov edx, 0
int 0x80
test eax, eax
js send_error
mov esi, eax ; ESI = Dir FD (Safe now, we don't need base_dir in reg)
.read_loop:
mov eax, 220 ; sys_getdents64
mov ebx, esi
mov ecx, dent_buf
mov edx, 4096
int 0x80
test eax, eax
jle .done
mov ebx, eax ; Count
xor edi, edi ; Offset
.process:
cmp edi, ebx
jge .read_loop
mov edx, dent_buf
add edx, edi ; EDX = Entry Pointer
; Filter '.'
mov al, [edx + 19]
cmp al, '.'
je .next
; Type
mov al, [edx + 18]
cmp al, 4
je .is_dir
lea eax, [edx + 19]
call check_txt
test eax, eax
jnz .is_txt
mov al, '9'
jmp .send
.is_dir:
mov al, '1'
jmp .send
.is_txt:
mov al, '0'
.send:
mov [file_buf], al
call send_byte
lea eax, [edx + 19]
call send_str
mov eax, tab
call send_1byte
mov eax, slash
call send_1byte
cmp byte [req_buf], 0
je .no_prefix
mov eax, req_buf
call send_str
mov eax, slash
call send_1byte
.no_prefix:
lea eax, [edx + 19]
call send_str
mov eax, tab
call send_1byte
mov eax, host_str
call send_str
mov eax, tab
call send_1byte
mov eax, port_str
call send_str
mov eax, crlf
call send_str
.next:
movzx eax, word [edx + 16] ; d_reclen
test eax, eax ; Safety: If reclen is 0, abort loop
jz .read_loop ; (Avoid infinite loop)
add edi, eax
jmp .process
.done:
mov eax, 6
mov ebx, esi
int 0x80
mov eax, end_of_menu
call send_str
jmp close_client
; =============================================================================
; File Logic
; =============================================================================
handle_file:
mov eax, 5
mov ebx, path_buf
mov ecx, 0
xor edx, edx
int 0x80
test eax, eax
js send_error
mov esi, eax
.stream:
mov eax, 3
mov ebx, esi
mov ecx, file_buf
mov edx, 4096
int 0x80
test eax, eax
jle .close
mov edx, eax
mov eax, 4
mov ebx, [clientfd]
mov ecx, file_buf
int 0x80
jmp .stream
.close:
mov eax, 6
mov ebx, esi
int 0x80
jmp close_client
; =============================================================================
; Helpers
; =============================================================================
send_error:
mov eax, err_msg
call send_str
jmp close_client
close_client:
mov eax, 6
mov ebx, [clientfd]
int 0x80
jmp server_loop
exit_app:
mov eax, 1
xor ebx, ebx
int 0x80
strlen:
xor eax, eax
push edi
.L: cmp byte [edi], 0
je .D
inc edi
inc eax
jmp .L
.D: pop edi
ret
strlen_fast:
.L: cmp byte [edi], 0
je .D
inc edi
jmp .L
.D: ret
strcpy:
push ebp
mov ebp, esp
push esi
push edi
mov edi, [ebp+8]
mov esi, [ebp+12]
.loop:
mov al, [esi]
mov [edi], al
test al, al
jz .done
inc esi
inc edi
jmp .loop
.done:
pop edi
pop esi
pop ebp
ret
check_traversal:
push edi
.L: mov al, [edi]
test al, al
jz .ok
cmp al, '.'
je .dot
inc edi
jmp .L
.dot:
mov al, [edi+1]
cmp al, '.'
je .bad
inc edi
jmp .L
.bad:
pop edi
mov eax, 1
ret
.ok:
pop edi
xor eax, eax
ret
check_txt:
push edi
mov edi, eax
call strlen
cmp eax, 4
jl .no
add edi, eax
sub edi, 4
mov eax, [edi]
cmp eax, 0x7478742e
je .y
.no:
xor eax, eax
pop edi
ret
.y:
mov eax, 1
pop edi
ret
send_str:
push ebx
push ecx
push edx
push edi
mov edi, eax
call strlen
mov edx, eax
mov ecx, edi
mov eax, 4
mov ebx, [clientfd]
int 0x80
pop edi
pop edx
pop ecx
pop ebx
ret
send_1byte:
push ebx
push ecx
push edx
mov ecx, eax
mov edx, 1
mov eax, 4
mov ebx, [clientfd]
int 0x80
pop edx
pop ecx
pop ebx
ret
send_byte:
mov eax, file_buf
call send_1byte
ret