一个web server,使用x64汇编
代码和注释如下,还是比较丑陋的
.intel_syntax noprefix
.globl _start.section .text_start:
socket:mov rax, 0x29mov rdi, 2mov rsi, 1mov rdx, 0syscallmov r14, rax
bind:mov rdi, rax # 将socket 的fd mov到rdimov rax, 0x31lea rsi, [socket_addr]mov rdx, 16syscall
listen:mov rax, 0x32mov rdi, 3mov rsi, 0syscall
conn_loop:
accept:mov rax, 0x2bmov rdi, 3mov rsi, 0mov rdx, 0syscallmov r15, rax
# fork child# 39 - - -mov rax, 0x39syscallcmp rax, 0je child_process# 3 unsigned int fd mov rdi, r15mov rax, 3syscall # close accpet fdjmp acceptchild_process:
mov rdi, r14mov rax, 3syscall # close scock fd
read:mov rdi, r15 # we read from the accepted connection, so we use that file descriptorsub rsp, 0x400 # setting up the stack as the buffer variablemov rsi, rspmov rdx, 0x400 # upto how many bytes can be readxor rax, rax # 0 is the syscall value for read()syscall # read(conn, *buf, 1024)mov r14, rax # 保存长度# 根据第一个单词来判断是否是POST
cmp byte ptr [rsp], 71
jne post
get:
lea rdi, [rsp + 4] # 跳过"Get "
xor rcx, rcx
# find filename
find_filename_get:cmp byte ptr [rdi + rcx], 0x20 # 找到下一个空格je end_filename_getinc rcxjmp find_filename_getend_filename_get:mov byte ptr [rdi + rcx], 0x0 # 将空格转为0# open_file:mov rsi, 0 # O_RDONLYmov rax, 0x2syscallmov r14, rax
# read_file:# unsigned int fd char *buf size_t countmov rdi, r14sub rsp, 0x1000mov rsi, rspmov rdx, 0x1000mov rax, 0syscall # readmov r14, rax # 保存长度# closefd:mov rax, 3syscall# write_static_response:mov rax, 1 # write syscallmov rdi, 4lea rsi, [response]mov rdx, 19syscall
# write_file_content:# 1 unsigned int fd const char *buf size_t countmov rdi, r15mov rsi, rspmov rdx, r14mov rax, 1syscall # write filejmp close_accept
post:# find filename
lea rdi, [rsp + 4] # 跳过"Get "
xor rcx, rcx
# 找到文件名
lea rdi, [rsp + 5] # 跳过"Post "xor rcx, rcx# find filename
find_filename:cmp byte ptr [rdi + rcx], 0x20 # 找到下一个空格je end_filenameinc rcxjmp find_filenameend_filename:mov byte ptr [rdi + rcx], 0x0 # 将空格转为0# 找到头长度lea rdi, [rsp] # rdixor rdx, rdxfind_header_length:lea rsi, [end_string] # 将\r\n\r\n拷贝到rsimov rcx, 4repe cmpsb # 重复比较字节直到RCX=0或字节不等jz end_header_lengthinc rdxlea rdi, [rsp]add rdi, rdxjmp find_header_lengthend_header_length:add rdx, 4 # 正文开始的地方mov r8, rsp # 保存开始的地方add r8, rdxmov r9, r14 # 总长度sub r9, rdx # 保存正文的长度# 打开文件# 2 const char *filename int flags umode_t mode
open_file:lea rdi, [rsp+5] # 文件名mov rsi, 00000001 # O_WRONLY xor rsi, 00000100 # O_CREATmov rdx, 0777mov rax, 0x2syscallmov r10, rax# 写回正文内存
write_file_content:# 1 unsigned int fd const char *buf size_t countmov rdi, r10mov rsi, r8mov rdx, r9mov rax, 1syscall # write 正文# close file_fdmov rdi, r10mov rax, 3syscall write_static_response:mov rax, 1 # write syscallmov rdi, r15lea rsi, [response]mov rdx, 19syscallclose_accept:mov rdi, r15mov rax, 3syscall # close accept fd
# jmp conn_loop
exit:mov rdi, 0mov rax, 0x3csyscall.section .datasocket_addr:.word 2 # AF_INET.word 0x5000 # htons(80).long 0 #.zero 8response: .ascii "HTTP/1.0 200 OK\r\n\r\n" end_string: .ascii "\r\n\r\n"
编译方式
gcc -nostdlib server.s -o server