Created
October 23, 2024 04:51
-
-
Save morkev/fd515a786cde6168eacf034993441dc3 to your computer and use it in GitHub Desktop.
Multi-processed assembly to dynamically respond to multiple HTTP POST requests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .intel_syntax noprefix | |
| .globl _start | |
| .section .text | |
| _start: | |
| # Create socket | |
| mov rdi, 2 # AF_INET | |
| mov rsi, 1 # SOCK_STREAM | |
| mov rdx, 0 # Protocol | |
| mov rax, 41 # socket syscall | |
| syscall | |
| mov rbx, rax # Save socket fd | |
| # Bind socket to port 80 | |
| mov rdi, rbx | |
| lea rsi, sa_family_t | |
| mov rdx, 16 | |
| mov rax, 49 # bind syscall | |
| syscall | |
| # Listen with backlog of 0 | |
| mov rdi, rbx | |
| mov rsi, 0 # Backlog of 0 as specified | |
| mov rax, 50 # listen syscall | |
| syscall | |
| accept_loop: | |
| # Accept connection | |
| mov rdi, rbx | |
| mov rsi, 0 | |
| mov rdx, 0 | |
| mov rax, 43 # accept syscall | |
| syscall | |
| mov r12, rax # Save client socket fd | |
| # Fork process | |
| mov rax, 57 # fork syscall | |
| syscall | |
| cmp rax, 0 | |
| je handle_post # Child process handles POST | |
| # Parent process closes client socket and continues accepting | |
| mov rdi, r12 | |
| mov rax, 3 # close syscall | |
| syscall | |
| jmp accept_loop | |
| handle_post: | |
| # Child process closes listening socket | |
| mov rdi, rbx | |
| mov rax, 3 # close syscall | |
| syscall | |
| # Read request | |
| mov rdi, r12 | |
| lea rsi, read_buffer | |
| mov rdx, 1024 | |
| mov rax, 0 # read syscall | |
| syscall | |
| # Extract filename from POST request | |
| lea rdi, read_buffer | |
| mov rsi, 1 # Get first space | |
| lea rdx, space | |
| call get_nth_substr | |
| mov r13, rax | |
| lea rdi, read_buffer | |
| mov rsi, 2 # Get second space | |
| call get_nth_substr | |
| mov r14, rax | |
| sub r14, 1 | |
| # Get filename | |
| mov rdi, r13 | |
| mov rsi, r14 | |
| lea rdx, file_name_buffer | |
| call write_to_buf | |
| # Create/open file | |
| lea rdi, file_name_buffer | |
| mov rsi, 0x41 # O_WRONLY | O_CREAT | |
| mov rdx, 0777 # Permissions | |
| mov rax, 2 # open syscall | |
| syscall | |
| mov r13, rax | |
| # Find POST data | |
| lea rdi, read_buffer | |
| mov rsi, 1 | |
| lea rdx, double_cr_lf | |
| call get_nth_substr | |
| mov rsi, rax | |
| add rsi, 1 | |
| # Get data length and write | |
| mov rdi, rsi | |
| call get_len | |
| mov rdx, rax | |
| sub rdx, 1 | |
| mov rdi, r13 | |
| mov rax, 1 # write syscall | |
| syscall | |
| # Close file | |
| mov rdi, r13 | |
| mov rax, 3 | |
| syscall | |
| # Send response | |
| mov rdi, r12 | |
| lea rsi, write_static | |
| mov rdx, 19 | |
| mov rax, 1 # write syscall | |
| syscall | |
| # Close connection | |
| mov rdi, r12 | |
| mov rax, 3 | |
| syscall | |
| # Exit child | |
| mov rdi, 0 | |
| mov rax, 60 # exit syscall | |
| syscall | |
| get_len: | |
| mov rax, 0 | |
| get_len_loop: | |
| mov r10, rdi | |
| add r10, rax | |
| mov r10, [r10] | |
| add rax, 1 | |
| cmp r10, 0x00 | |
| jne get_len_loop | |
| ret | |
| write_to_buf: | |
| write_to_buf_loop: | |
| add rdi, 1 | |
| mov r9, [rdi] | |
| mov [rdx], r9 | |
| add rdx, 1 | |
| cmp rdi, rsi | |
| jne write_to_buf_loop | |
| mov byte ptr [rdx], 0x00 | |
| ret | |
| get_nth_substr: | |
| mov rcx, 0 | |
| mov r10, rdx | |
| check_character_loop: | |
| mov r9b, [rdi] | |
| cmp r9b, 0x00 | |
| je not_enough_occurrences | |
| cmp r9b, byte ptr [r10] | |
| jne character_not_equal | |
| add r10, 1 | |
| cmp byte ptr [r10], 0x00 | |
| jne after_comparison | |
| mov r10, rdx | |
| add rcx, 1 | |
| jmp after_comparison | |
| character_not_equal: | |
| mov r10, rdx | |
| after_comparison: | |
| cmp rcx, rsi | |
| je match | |
| add rdi, 1 | |
| jmp check_character_loop | |
| match: | |
| mov rax, rdi | |
| ret | |
| not_enough_occurrences: | |
| mov rax, -1 | |
| ret | |
| .section .data | |
| # Network setup for port 80 | |
| sa_family_t: .word 2 # AF_INET | |
| bind_port: .word 0x5000 # Port 80 (0x0050) | |
| bind_address: .double 0x00000000 # 0.0.0.0 | |
| pad: .byte 0,0,0,0,0,0,0,0 | |
| # Buffers and constants | |
| read_buffer: .space 1024 | |
| file_name_buffer: .space 1024 | |
| file_read_buffer: .space 1024 | |
| read_packet_length: .quad 0x0000000000000400 | |
| write_static: .string "HTTP/1.0 200 OK\r\n\r\n" | |
| space: .string " " | |
| double_cr_lf: .string "\r\n\r\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment