; ; Automated dhcp client ; ; v 1.1 ; ; by the hidden player ; DEBUG equ 1 TIMEOUT equ 60 ; in seconds use32 org 0x0 db 'MENUET01' ; 8 byte id dd 0x01 ; header version dd START ; start of code dd IM_END ; size of image dd I_END ; memory for app dd I_END ; esp dd 0x0 , 0x0 ; I_Param , I_Icon include 'macros.inc' if DEBUG = 1 include 'debug.inc' end if START: ; start of execution mov eax,40 ; Report events mov ebx,10000000b ; Only Stack int 0x40 mov eax,52 ; first, enable the stack mov ebx,2 mov ecx,0x00000383 int 0x40 if DEBUG = 1 newline dps "DHCP: Stack Initialized" newline end if mov eax, 53 ; then, read in the status mov ebx, 255 mov ecx, 6 int 0x40 cmp eax,0 ; if eax is zero, no driver was found jne @f if DEBUG = 1 dps "DHCP: No Card detected" newline end if jmp close @@: if DEBUG = 1 dps "DHCP: Detected card: " dph eax newline end if ; now that the stack is running, lets start the dhcp request ; First, open socket mov eax, 53 mov ebx, 0 mov ecx, 68 ; local port dhcp client mov edx, 67 ; remote port - dhcp server mov esi, -1 ; broadcast int 0x40 mov [socketNum], eax if DEBUG = 1 dps "DHCP: Socket opened: " dpd eax newline end if ; Setup the first msg we will send mov byte [dhcpMsgType], 0x01 ; DHCP discover mov dword [dhcpLease], esi ; esi is still -1 (-1 = forever) ;*************************************************************************** ; Function ; buildRequest ; ; Description ; Creates a DHCP request packet. ; ;*************************************************************************** buildRequest: ; Clear dhcpMsg to all zeros xor eax,eax mov edi,dhcpMsg mov ecx,512 cld rep stosb mov edx, dhcpMsg mov [edx], byte 0x01 ; Boot request mov [edx+1], byte 0x01 ; Ethernet mov [edx+2], byte 0x06 ; Ethernet h/w len mov [edx+4], dword 0x11223344 ; xid mov [edx+10], byte 0x80 ; broadcast flag set mov [edx+236], dword 0x63538263 ; magic number ; option DHCP msg type mov [edx+240], word 0x0135 mov al, [dhcpMsgType] mov [edx+240+2], al ; option Lease time = infinity mov [edx+240+3], word 0x0433 mov eax, [dhcpLease] mov [edx+240+5], eax ; ; option requested IP address mov [edx+240+9], word 0x0432 ; mov eax, [dhcpClientIP] ; mov [edx+240+11], eax ; option request list mov [edx+240+15], word 0x0437 mov [edx+240+17], dword 0x0f060301 ; Check which msg we are sending cmp [dhcpMsgType], byte 0x01 jne br001 ; "Discover" options ; end of options marker mov [edx+240+21], byte 0xff mov [dhcpMsgLen], dword 262 jmp ctr000 br001: ; "Request" options ; server IP mov [edx+240+21], word 0x0436 mov eax, [dhcpServerIP] mov [edx+240+23], eax ; end of options marker mov [edx+240+27], byte 0xff mov [dhcpMsgLen], dword 268 ctr000: ; write to socket ( send broadcast request ) mov eax, 53 mov ebx, 4 mov ecx, [socketNum] mov edx, [dhcpMsgLen] mov esi, dhcpMsg int 0x40 ; Setup the DHCP buffer to receive response mov eax, dhcpMsg mov [dhcpMsgLen], eax ; Used as a pointer to the data ; now, we wait for data from remote wait_for_data: mov eax,23 ; wait here for event NOTE a TIME-OUT should be placed here mov ebx,TIMEOUT*100 int 0x40 ; Any data in the UDP receive buffer? mov eax, 53 mov ebx, 2 mov ecx, [socketNum] int 0x40 cmp eax, 0 jne ctr002 if DEBUG = 1 dps "DHCP: Timeout!" newline end if jmp close ; we have data - this will be the response ctr002: mov eax, 53 mov ebx, 3 mov ecx, [socketNum] int 0x40 ; read byte - block (high byte) ; Store the data in the response buffer mov eax, [dhcpMsgLen] mov [eax], bl inc dword [dhcpMsgLen] mov eax, 53 mov ebx, 2 mov ecx, [socketNum] int 0x40 ; any more data? cmp eax, 0 jne ctr002 ; yes, so get it ; depending on which msg we sent, handle the response ; accordingly. ; If the response is to a dhcp discover, then: ; 1) If response is DHCP OFFER then ; 1.1) record server IP, lease time & IP address. ; 1.2) send a request packet ; 2) else exit ( display error ) ; If the response is to a dhcp request, then: ; 1) If the response is DHCP ACK then ; 1.1) extract the DNS & subnet fields. Set them in the stack ; 2) else exit ( display error ) cmp [dhcpMsgType], byte 0x01 ; did we send a discover? je discover cmp [dhcpMsgType], byte 0x03 ; did we send a request? je request ; should never get here - we only send discover or request jmp close discover: call parseResponse ; Was the response an offer? It should be cmp [dhcpMsgType], byte 0x02 jne close ; NO - so quit ; send request mov [dhcpMsgType], byte 0x03 ; DHCP request jmp buildRequest request: call parseResponse ; Was the response an ACK? It should be cmp [dhcpMsgType], byte 0x05 jne close ; NO - so quit close: ; close socket mov eax, 53 mov ebx, 1 mov ecx, [socketNum] int 0x40 if DEBUG = 1 dps "DHCP: Exiting" newline end if mov eax,-1 ; at last, exit int 0x40 ;*************************************************************************** ; Function ; parseResponse ; ; Description ; extracts the fields ( client IP address and options ) from ; a DHCP response ; The values go into ; dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP, ; dhcpDNSIP, dhcpSubnet ; The message is stored in dhcpMsg ; ;*************************************************************************** parseResponse: if DEBUG = 1 dps "DHCP: Data received, parsing response" newline end if mov edx, dhcpMsg pusha mov eax,52 ; Set Client IP mov ebx,3 mov ecx, [edx+16] int 0x40 if DEBUG = 1 dps "DHCP: Client: " xor esi,esi .loop: pusha movzx eax,byte[edx+esi+16] call debug_outdec popa inc esi cmp esi,4 jne .loop newline end if popa ; Scan options add edx, 240 ; Point to first option pr001: ; Get option id mov al, [edx] cmp al, 0xff ; End of options? je pr_exit cmp al, 53 ; Msg type is a single byte option jne pr002 mov al, [edx+2] mov [dhcpMsgType], al add edx, 3 jmp pr001 ; Get next option pr002: ; All other (accepted) options are 4 bytes in length inc edx movzx ecx, byte [edx] inc edx ; point to data cmp al, 54 ; server id jne pr0021 mov eax, [edx] ; All options are 4 bytes, so get it mov [dhcpServerIP], eax jmp pr003 pr0021: cmp al, 51 ; lease jne pr0022 if DEBUG = 1 pusha dps "DHCP: lease: " cmp dword[edx],-1 jne no_lease_forever dps "forever" jmp lease_newline no_lease_forever: dpd [edx] lease_newline: newline popa end if jmp pr003 pr0022: cmp al, 1 ; subnet mask jne pr0023 pusha mov eax,52 mov ebx,12 mov ecx,[edx] int 0x40 if DEBUG = 1 dps "DHCP: Subnet: " xor esi,esi .loop: pusha movzx eax,byte[edx+esi] call debug_outdec popa inc esi cmp esi,4 jne .loop newline end if popa jmp pr003 pr0023: cmp al, 6 ; dns ip jne pr0024 pusha mov eax,52 mov ebx,14 mov ecx,[edx] int 0x40 if DEBUG = 1 dps "DHCP: DNS IP: " xor esi,esi .loop: pusha movzx eax,byte[edx+esi] call debug_outdec popa inc esi cmp esi,4 jne .loop newline end if popa pr0024: cmp al, 3 ; gateway ip jne pr003 pusha mov eax,52 mov ebx,11 mov ecx,[edx] int 0x40 if DEBUG = 1 dps "DHCP: Gateway:" xor esi,esi .loop: pusha movzx eax,byte[edx+esi] call debug_outdec popa inc esi cmp esi,4 jne .loop newline end if popa pr003: add edx, ecx jmp pr001 pr_exit: if DEBUG = 1 dps "DHCP: Done" newline end if jmp close ; DATA AREA IM_END: dhcpMsgType: db 0 dhcpLease: dd 0 ;dhcpClientIP: dd 0 dhcpServerIP: dd 0 dhcpMsgLen: dd 0 socketNum: dd 0xFFFF dhcpMsg: rb 512 I_END: