format PE console
use32
entry start
WINNT EQU 0
PORT EQU 80
ADDR_LEN EQU 16
BUFFER_LEN EQU 512
;include '%fasminc%\win32a.inc'
include 'win32a.inc'
section '.code' code readable executable
start:
invoke GetStdHandle, STD_OUTPUT_HANDLE ;To write out to screen/file
mov [StdOutHandle], eax
invoke WSAStartup, 0101h, wsadata
invoke socket, AF_INET, SOCK_STREAM, NULL
mov [SocketHandle], eax
invoke bind, eax, BindParams, BindParams.len
invoke listen, [SocketHandle], 50
AcceptLoop: ;Terminate loop with Ctrl-C
invoke accept, [SocketHandle], PeerAddr, AddrLen
mov [PeerHandle], eax
invoke recv, eax, buffer, BUFFER_LEN, 0 ;Should check EAX for errors
;Use WriteFile instead of WriteConsole to allow redirection to a file.
;In Win9x NumberOfCharsWritten(here BytesCopied) can't be NULL.
invoke WriteFile, [StdOutHandle], buffer, eax, BytesCopied, NULL
;Now parse received string
mov esi, buffer
cmp dword [esi], 'GET '
jne .EndPeer
mov edi, esi
.SeekSlash:
lodsb
cmp al, '/'
jne .SeekSlash
.GetFileName:
cmp al, '%'
jne .Continue
;Convert a double digit hex number to its value
lodsw
IRP REGISTERS, <eax, edx>, <dl, dh> {
xchg REGISTERS
cmp dl, '9'
jbe @f ;Is DL a letter A-F ?
and dl, Not 32 ;Convert to uppercase if necessary
sub dl, 7
@@:
shl al, 4
lea eax, [eax + edx - '0'] ;Don't care about bits 8-31 in EAX and EDX
}
.Continue:
stosb
lodsb
cmp al, ' ' ;Space and ? terminate file name
je .EndOfString
cmp al, '?'
jne .GetFileName
.EndOfString:
mov byte [edi], 0
cmp edi, buffer + 1 ;Did we get only / as file name ?
jne .SendFile
mov esi, DefaultPage
mov ecx, DefaultPage.len
rep movsb
.SendFile:
invoke CreateFile, buffer + 1, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL
cmp eax, 0ffffffffh
jne .Found
invoke send, [PeerHandle], h404, h404.len, NULL
invoke WriteFile, [StdOutHandle], h404, h404.len, BytesCopied, NULL
jmp .EndPeer
.Found:
mov [FileHandle], eax
IF WINNT ;Win NT has an optimized TransmitFile API which Win 9x doesn't have
invoke TransmitFileNT, [PeerHandle], eax, 0, 0, NULL, TransmitLayout, NULL
ELSE
invoke send, [PeerHandle], h200, h200.len, NULL
.loop:
invoke ReadFile, [FileHandle], buffer, BUFFER_LEN, BytesCopied, NULL
invoke send, [PeerHandle], buffer, [BytesCopied], NULL
cmp dword [BytesCopied], BUFFER_LEN
je .loop ;Exit when ReadFile got less bytes than we asked
END IF
invoke CloseHandle, [FileHandle]
.EndPeer:
invoke CloseHandle, [PeerHandle]
jmp AcceptLoop
;exit:
; invoke WSACleanup
; invoke ExitProcess, 0
section '.data' data readable writeable
struc db [data] ;Redefine DB to automatically generate length label
{
common
. db data
.len = $ - .
}
DefaultPage db 'index.html', 0
h404 db 'HTTP/1.1 404 Not Found', 13, 10, 13, 10, \
'<HTML><BODY>404 Not Found</BODY></HTML>', 13, 10
h200 db 'HTTP/1.1 200 OK', 13, 10, 13, 10
IF WINNT
TransmitLayout dd h200, h200.len, NULL, NULL
END IF
BindParams db 2, 0, PORT ShR 8, PORT And 255, 0,0,0,0, 0,0,0,0, 0,0,0,0
wsadata WSADATA
AddrLen dd ADDR_LEN
StdOutHandle rd 1
BytesCopied rd 1
PeerAddr rb ADDR_LEN
SocketHandle rd 1
PeerHandle rd 1
FileHandle rd 1
buffer rb BUFFER_LEN
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL', wsock32,'WSOCK32.DLL'
include 'api\kernel32.inc'
include 'api\wsock32.inc'
;Maybe next lines are useless and you can use TransmitFile from wsock32.inc
;instead of TransmitFileNT from mswsock.
IF WINNT
library mswsock,'MSWSOCK.DLL'
import mswsock, TransmitFileNT,'TransmitFile'
END IF