Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
104 | hidnplayr | 1 | ; Automated dhcp client |
336 | hidnplayr | 2 | ; v 1.3 |
104 | hidnplayr | 3 | ; |
336 | hidnplayr | 4 | ; with thanks to authors of DHCP client for menuetos: Mike Hibbet |
104 | hidnplayr | 5 | ; |
336 | hidnplayr | 6 | ; by HidnPlayr & Derpenguin |
104 | hidnplayr | 7 | |
8 | use32 |
||
9 | org 0x0 |
||
10 | |||
339 | hidnplayr | 11 | db 'MENUET01' ; 8 byte id |
12 | dd 0x01 ; header version |
||
13 | dd START ; start of code |
||
14 | dd IM_END ; size of image |
||
15 | dd I_END ; memory for app |
||
16 | dd I_END ; esp |
||
17 | dd 0x0 , 0x0 ; I_Param , I_Icon |
||
104 | hidnplayr | 18 | |
339 | hidnplayr | 19 | ; CONFIGURATION |
104 | hidnplayr | 20 | |
21 | |||
339 | hidnplayr | 22 | TIMEOUT equ 60 ; in seconds |
23 | BUFFER equ 1024 ; in bytes |
||
24 | __DEBUG__ equ 1 ; enable/disable |
||
25 | __DEBUG_LEVEL__ equ 1 ; 1 = all, 2 = errors |
||
104 | hidnplayr | 26 | |
339 | hidnplayr | 27 | ; CONFIGURATION FOR LINK-LOCAL |
104 | hidnplayr | 28 | |
339 | hidnplayr | 29 | PROBE_WAIT equ 1 ; second (initial random delay) |
30 | PROBE_MIN equ 1 ; second (minimum delay till repeated probe) |
||
31 | PROBE_MAX equ 2 ; seconds (maximum delay till repeated probe) |
||
32 | PROBE_NUM equ 3 ; (number of probe packets) |
||
336 | hidnplayr | 33 | |
339 | hidnplayr | 34 | ANNOUNCE_NUM equ 2 ; (number of announcement packets) |
35 | ANNOUNCE_INTERVAL equ 2 ; seconds (time between announcement packets) |
||
36 | ANNOUNCE_WAIT equ 2 ; seconds (delay before announcing) |
||
104 | hidnplayr | 37 | |
339 | hidnplayr | 38 | MAX_CONFLICTS equ 10 ; (max conflicts before rate limiting) |
104 | hidnplayr | 39 | |
339 | hidnplayr | 40 | RATE_LIMIT_INTERVAL equ 60 ; seconds (delay between successive attempts) |
104 | hidnplayr | 41 | |
339 | hidnplayr | 42 | DEFEND_INTERVAL equ 10 ; seconds (min. wait between defensive ARPs) |
43 | |||
44 | include 'macros.inc' |
||
45 | include 'eth.inc' |
||
46 | include 'debug-fdo.inc' |
||
47 | include 'dhcp.inc' |
||
48 | include 'events.inc' |
||
49 | include 'common.inc' |
||
50 | |||
51 | |||
52 | START: ; start of execution |
||
53 | |||
54 | set_event_mask event_network |
||
55 | eth.set_network_drv 0x00000383 |
||
56 | |||
57 | DEBUGF 1,"Stack Initialized.\n" |
||
58 | |||
59 | eth.status eax ; Read the Stack status |
||
60 | test eax,eax ; if eax is zero, no driver was found |
||
336 | hidnplayr | 61 | jnz @f |
339 | hidnplayr | 62 | DEBUGF 1,"No Card detected\n" |
336 | hidnplayr | 63 | jmp close |
104 | hidnplayr | 64 | |
336 | hidnplayr | 65 | @@: |
339 | hidnplayr | 66 | DEBUGF 1,"Detected card: %x\n",eax |
336 | hidnplayr | 67 | @@: |
68 | eth.check_cable eax |
||
69 | test al,al |
||
70 | jnz @f |
||
339 | hidnplayr | 71 | DEBUGF 1,"Ethernet Cable not connected\n" |
72 | wait 500 ; loop until cable is connected (check every 5 sec) |
||
336 | hidnplayr | 73 | jmp @r |
104 | hidnplayr | 74 | |
75 | @@: |
||
339 | hidnplayr | 76 | DEBUGF 1,"Ethernet Cable status: %d\n",al |
104 | hidnplayr | 77 | |
336 | hidnplayr | 78 | eth.read_mac MAC |
339 | hidnplayr | 79 | DEBUGF 1,"MAC address: %x-%x-%x-%x-%x-%x\n",[MAC]:2,[MAC+1]:2,[MAC+2]:2,[MAC+3]:2,[MAC+4]:2,[MAC+5]:2 |
104 | hidnplayr | 80 | |
339 | hidnplayr | 81 | eth.check_port 68,eax ; Check if port 68 is available |
336 | hidnplayr | 82 | cmp eax,1 |
83 | je @f |
||
84 | |||
339 | hidnplayr | 85 | DEBUGF 1,"Port 68 is already in use!\n" |
336 | hidnplayr | 86 | jmp close |
87 | |||
88 | @@: |
||
339 | hidnplayr | 89 | eth.open_udp 68,67,-1,[socketNum] ; open socket (local,remote,ip,socket) |
90 | DEBUGF 1,"Socket opened: %d\n",eax |
||
91 | ; Setup the first msg we will send |
||
92 | mov byte [dhcpMsgType], 0x01 ; DHCP discover |
||
93 | mov dword [dhcpLease], esi ; esi is still -1 (-1 = forever) |
||
336 | hidnplayr | 94 | |
339 | hidnplayr | 95 | get_time_counter eax |
336 | hidnplayr | 96 | imul eax,100 |
97 | mov [currTime],eax |
||
98 | |||
339 | hidnplayr | 99 | buildRequest: ; Creates a DHCP request packet. |
336 | hidnplayr | 100 | xor eax,eax ; Clear dhcpMsg to all zeros |
104 | hidnplayr | 101 | mov edi,dhcpMsg |
336 | hidnplayr | 102 | mov ecx,BUFFER |
104 | hidnplayr | 103 | cld |
104 | rep stosb |
||
105 | |||
106 | mov edx, dhcpMsg |
||
107 | |||
108 | mov [edx], byte 0x01 ; Boot request |
||
109 | mov [edx+1], byte 0x01 ; Ethernet |
||
110 | mov [edx+2], byte 0x06 ; Ethernet h/w len |
||
111 | mov [edx+4], dword 0x11223344 ; xid |
||
336 | hidnplayr | 112 | mov eax,[currTime] |
113 | mov [edx+8], eax ; secs, our uptime |
||
104 | hidnplayr | 114 | mov [edx+10], byte 0x80 ; broadcast flag set |
336 | hidnplayr | 115 | mov eax, dword [MAC] ; first 4 bytes of MAC |
116 | mov [edx+28],dword eax |
||
117 | mov ax, word [MAC+4] ; last 2 bytes of MAC |
||
118 | mov [edx+32],word ax |
||
104 | hidnplayr | 119 | mov [edx+236], dword 0x63538263 ; magic number |
336 | hidnplayr | 120 | mov [edx+240], word 0x0135 ; option DHCP msg type |
104 | hidnplayr | 121 | mov al, [dhcpMsgType] |
122 | mov [edx+240+2], al |
||
336 | hidnplayr | 123 | mov [edx+240+3], word 0x0433 ; option Lease time = infinity |
104 | hidnplayr | 124 | mov eax, [dhcpLease] |
125 | mov [edx+240+5], eax |
||
336 | hidnplayr | 126 | mov [edx+240+9], word 0x0432 ; option requested IP address |
127 | mov eax, [dhcpClientIP] |
||
128 | mov [edx+240+11], eax |
||
129 | mov [edx+240+15], word 0x0437 ; option request list |
||
104 | hidnplayr | 130 | mov [edx+240+17], dword 0x0f060301 |
131 | |||
336 | hidnplayr | 132 | cmp [dhcpMsgType], byte 0x01 ; Check which msg we are sending |
339 | hidnplayr | 133 | jne request_options |
104 | hidnplayr | 134 | |
336 | hidnplayr | 135 | mov [edx+240+21], byte 0xff ; "Discover" options |
104 | hidnplayr | 136 | |
336 | hidnplayr | 137 | mov [dhcpMsgLen], dword 262 ; end of options marker |
339 | hidnplayr | 138 | jmp send_request |
104 | hidnplayr | 139 | |
339 | hidnplayr | 140 | request_options: |
336 | hidnplayr | 141 | mov [edx+240+21], word 0x0436 ; server IP |
104 | hidnplayr | 142 | mov eax, [dhcpServerIP] |
143 | mov [edx+240+23], eax |
||
144 | |||
336 | hidnplayr | 145 | mov [edx+240+27], byte 0xff ; end of options marker |
104 | hidnplayr | 146 | |
147 | mov [dhcpMsgLen], dword 268 |
||
148 | |||
339 | hidnplayr | 149 | send_request: |
150 | eth.write_udp [socketNum],[dhcpMsgLen],dhcpMsg ; write to socket ( send broadcast request ) |
||
104 | hidnplayr | 151 | |
336 | hidnplayr | 152 | mov eax, dhcpMsg ; Setup the DHCP buffer to receive response |
153 | mov [dhcpMsgLen], eax ; Used as a pointer to the data |
||
104 | hidnplayr | 154 | |
336 | hidnplayr | 155 | mov eax,23 ; wait here for event (data from remote) |
156 | mov ebx,TIMEOUT*10 |
||
104 | hidnplayr | 157 | int 0x40 |
158 | |||
336 | hidnplayr | 159 | eth.poll [socketNum] |
104 | hidnplayr | 160 | |
336 | hidnplayr | 161 | test eax,eax |
339 | hidnplayr | 162 | jnz read_data |
104 | hidnplayr | 163 | |
339 | hidnplayr | 164 | DEBUGF 2,"Timeout!\n" |
336 | hidnplayr | 165 | eth.close_udp [socketNum] |
166 | jmp apipa ; no server found, lets try zeroconf |
||
104 | hidnplayr | 167 | |
168 | |||
339 | hidnplayr | 169 | read_data: ; we have data - this will be the response |
336 | hidnplayr | 170 | eth.read_packet [socketNum], dhcpMsg, BUFFER |
171 | mov [dhcpMsgLen], eax |
||
172 | eth.close_udp [socketNum] |
||
104 | hidnplayr | 173 | |
174 | ; depending on which msg we sent, handle the response |
||
175 | ; accordingly. |
||
176 | ; If the response is to a dhcp discover, then: |
||
177 | ; 1) If response is DHCP OFFER then |
||
178 | ; 1.1) record server IP, lease time & IP address. |
||
179 | ; 1.2) send a request packet |
||
180 | ; If the response is to a dhcp request, then: |
||
181 | ; 1) If the response is DHCP ACK then |
||
182 | ; 1.1) extract the DNS & subnet fields. Set them in the stack |
||
183 | |||
336 | hidnplayr | 184 | cmp [dhcpMsgType], byte 0x01 ; did we send a discover? |
104 | hidnplayr | 185 | je discover |
336 | hidnplayr | 186 | cmp [dhcpMsgType], byte 0x03 ; did we send a request? |
104 | hidnplayr | 187 | je request |
188 | |||
336 | hidnplayr | 189 | jmp close ; really unknown, what we did |
104 | hidnplayr | 190 | |
191 | discover: |
||
192 | call parseResponse |
||
193 | |||
336 | hidnplayr | 194 | cmp [dhcpMsgType], byte 0x02 ; Was the response an offer? |
195 | jne apipa ; NO - so we do zeroconf |
||
196 | mov [dhcpMsgType], byte 0x03 ; DHCP request |
||
104 | hidnplayr | 197 | jmp buildRequest |
198 | |||
199 | request: |
||
339 | hidnplayr | 200 | call parseResponse |
104 | hidnplayr | 201 | |
336 | hidnplayr | 202 | cmp [dhcpMsgType], byte 0x05 ; Was the response an ACK? It should be |
203 | jne apipa ; NO - so we do zeroconf |
||
104 | hidnplayr | 204 | |
339 | hidnplayr | 205 | jmp close |
104 | hidnplayr | 206 | |
207 | ;*************************************************************************** |
||
208 | ; Function |
||
209 | ; parseResponse |
||
210 | ; |
||
211 | ; Description |
||
212 | ; extracts the fields ( client IP address and options ) from |
||
213 | ; a DHCP response |
||
214 | ; The values go into |
||
215 | ; dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP, |
||
216 | ; dhcpDNSIP, dhcpSubnet |
||
217 | ; The message is stored in dhcpMsg |
||
218 | ; |
||
219 | ;*************************************************************************** |
||
220 | parseResponse: |
||
339 | hidnplayr | 221 | DEBUGF 1,"Data received, parsing response\n" |
104 | hidnplayr | 222 | mov edx, dhcpMsg |
223 | |||
224 | pusha |
||
336 | hidnplayr | 225 | eth.set_IP [edx+16] |
226 | mov eax,[edx] |
||
227 | mov [dhcpClientIP],eax |
||
339 | hidnplayr | 228 | DEBUGF 1,"Client: %u.%u.%u.%u\n",[edx+16]:1,[edx+17]:1,[edx+18]:1,[edx+19]:1 |
104 | hidnplayr | 229 | popa |
230 | |||
339 | hidnplayr | 231 | add edx, 240 ; Point to first option |
232 | xor ecx, ecx |
||
104 | hidnplayr | 233 | |
339 | hidnplayr | 234 | next_option: |
235 | add edx, ecx |
||
104 | hidnplayr | 236 | pr001: |
237 | mov al, [edx] |
||
339 | hidnplayr | 238 | cmp al, 0xff ; End of options? |
104 | hidnplayr | 239 | je pr_exit |
240 | |||
339 | hidnplayr | 241 | cmp al, dhcp_msg_type ; Msg type is a single byte option |
242 | jne @f |
||
104 | hidnplayr | 243 | |
244 | mov al, [edx+2] |
||
245 | mov [dhcpMsgType], al |
||
246 | add edx, 3 |
||
339 | hidnplayr | 247 | jmp pr001 ; Get next option |
104 | hidnplayr | 248 | |
339 | hidnplayr | 249 | @@: |
104 | hidnplayr | 250 | inc edx |
251 | movzx ecx, byte [edx] |
||
339 | hidnplayr | 252 | inc edx ; point to data |
104 | hidnplayr | 253 | |
339 | hidnplayr | 254 | cmp al, dhcp_dhcp_server_id ; server ip |
255 | jne @f |
||
256 | mov eax, [edx] |
||
104 | hidnplayr | 257 | mov [dhcpServerIP], eax |
339 | hidnplayr | 258 | DEBUGF 1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1 |
259 | jmp next_option |
||
104 | hidnplayr | 260 | |
339 | hidnplayr | 261 | @@: |
262 | cmp al, dhcp_address_time |
||
263 | jne @f |
||
104 | hidnplayr | 264 | |
265 | pusha |
||
339 | hidnplayr | 266 | mov eax,[edx] |
267 | bswap eax |
||
268 | mov [dhcpLease],eax |
||
269 | DEBUGF 1,"lease: %d\n",eax |
||
104 | hidnplayr | 270 | popa |
271 | |||
339 | hidnplayr | 272 | jmp next_option |
104 | hidnplayr | 273 | |
339 | hidnplayr | 274 | @@: |
275 | cmp al, dhcp_subnet_mask |
||
276 | jne @f |
||
104 | hidnplayr | 277 | |
278 | pusha |
||
336 | hidnplayr | 279 | eth.set_SUBNET [edx] |
339 | hidnplayr | 280 | DEBUGF 1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1 |
336 | hidnplayr | 281 | popa |
104 | hidnplayr | 282 | |
339 | hidnplayr | 283 | jmp next_option |
104 | hidnplayr | 284 | |
339 | hidnplayr | 285 | @@: |
286 | cmp al, dhcp_router |
||
287 | jne @f |
||
104 | hidnplayr | 288 | |
289 | pusha |
||
336 | hidnplayr | 290 | eth.set_GATEWAY [edx] |
339 | hidnplayr | 291 | DEBUGF 1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1 |
104 | hidnplayr | 292 | popa |
293 | |||
339 | hidnplayr | 294 | jmp next_option |
104 | hidnplayr | 295 | |
296 | |||
339 | hidnplayr | 297 | @@: |
298 | cmp al, dhcp_domain_server |
||
299 | jne next_option |
||
300 | |||
336 | hidnplayr | 301 | pusha |
302 | eth.set_DNS [edx] |
||
339 | hidnplayr | 303 | DEBUGF 1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1 |
104 | hidnplayr | 304 | popa |
305 | |||
339 | hidnplayr | 306 | jmp next_option |
104 | hidnplayr | 307 | |
336 | hidnplayr | 308 | pr_exit: |
104 | hidnplayr | 309 | |
339 | hidnplayr | 310 | ; DEBUGF 1,"Sending ARP announce\n" |
311 | ; eth.ARP_ANNOUNCE [dhcpClientIP] ; send an ARP announce packet |
||
104 | hidnplayr | 312 | |
336 | hidnplayr | 313 | jmp close |
104 | hidnplayr | 314 | |
336 | hidnplayr | 315 | apipa: |
316 | call random |
||
339 | hidnplayr | 317 | mov ecx,0xfea9 ; IP 169.254.0.0 link local net, see RFC3927 |
336 | hidnplayr | 318 | mov cx,ax |
339 | hidnplayr | 319 | eth.set_IP ecx ; mask is 255.255.0.0 |
320 | DEBUGF 1,"Link Local IP assinged: 169.254.%u.%u\n",[generator+2]:1,[generator+3]:1 |
||
336 | hidnplayr | 321 | eth.set_SUBNET 0xffff |
322 | eth.set_GATEWAY 0x0 |
||
323 | eth.set_DNS 0x0 |
||
104 | hidnplayr | 324 | |
339 | hidnplayr | 325 | wait PROBE_WAIT*100 |
104 | hidnplayr | 326 | |
336 | hidnplayr | 327 | xor esi,esi |
328 | probe_loop: |
||
339 | hidnplayr | 329 | call random ; create a pseudo random number in eax (seeded by MAC) |
104 | hidnplayr | 330 | |
339 | hidnplayr | 331 | cmp al,PROBE_MIN*100 ; check if al is bigger then PROBE_MIN |
332 | jge @f ; all ok |
||
333 | add al,(PROBE_MAX-PROBE_MIN)*100 ; al is too small |
||
336 | hidnplayr | 334 | @@: |
104 | hidnplayr | 335 | |
336 | hidnplayr | 336 | cmp al,PROBE_MAX*100 |
337 | jle @f |
||
338 | sub al,(PROBE_MAX-PROBE_MIN)*100 |
||
339 | @@: |
||
104 | hidnplayr | 340 | |
336 | hidnplayr | 341 | movzx ebx,al |
339 | hidnplayr | 342 | DEBUGF 1,"Waiting %u0ms\n",ebx |
343 | wait ebx |
||
104 | hidnplayr | 344 | |
339 | hidnplayr | 345 | DEBUGF 1,"Sending Probe\n" |
346 | ; eth.ARP_PROBE MAC |
||
336 | hidnplayr | 347 | inc esi |
104 | hidnplayr | 348 | |
336 | hidnplayr | 349 | cmp esi,PROBE_NUM |
350 | jl probe_loop |
||
104 | hidnplayr | 351 | |
339 | hidnplayr | 352 | ; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned |
336 | hidnplayr | 353 | ; IP within this time, we should create another adress, that have to be done later |
104 | hidnplayr | 354 | |
339 | hidnplayr | 355 | DEBUGF 1,"Waiting %us\n",ANNOUNCE_WAIT |
356 | wait ANNOUNCE_WAIT*100 |
||
104 | hidnplayr | 357 | xor esi,esi |
336 | hidnplayr | 358 | announce_loop: |
104 | hidnplayr | 359 | |
339 | hidnplayr | 360 | DEBUGF 1,"Sending Announce\n" |
361 | ; eth.ARP_ANNOUNCE MAC |
||
104 | hidnplayr | 362 | |
363 | inc esi |
||
336 | hidnplayr | 364 | cmp esi,ANNOUNCE_NUM |
365 | je @f |
||
104 | hidnplayr | 366 | |
339 | hidnplayr | 367 | DEBUGF 1,"Waiting %us\n",ANNOUNCE_INTERVAL |
368 | wait ANNOUNCE_INTERVAL*100 |
||
336 | hidnplayr | 369 | jmp announce_loop |
370 | @@: |
||
339 | hidnplayr | 371 | ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;) |
104 | hidnplayr | 372 | |
339 | hidnplayr | 373 | close: |
374 | DEBUGF 1,"Exiting\n" |
||
375 | exit ; at last, exit |
||
376 | |||
377 | |||
336 | hidnplayr | 378 | random: |
339 | hidnplayr | 379 | |
336 | hidnplayr | 380 | mov eax,[generator] |
381 | add eax,-43ab45b5h |
||
382 | ror eax,1 |
||
383 | bswap eax |
||
384 | xor eax,dword[MAC] |
||
385 | ror eax,1 |
||
386 | xor eax,dword[MAC+2] |
||
387 | mov [generator],eax |
||
339 | hidnplayr | 388 | |
336 | hidnplayr | 389 | ret |
104 | hidnplayr | 390 | |
336 | hidnplayr | 391 | ; DATA AREA |
104 | hidnplayr | 392 | |
339 | hidnplayr | 393 | include_debug_strings |
104 | hidnplayr | 394 | |
395 | IM_END: |
||
396 | |||
336 | hidnplayr | 397 | dhcpClientIP dd 0 |
398 | dhcpMsgType db 0 |
||
399 | dhcpLease dd 0 |
||
400 | dhcpServerIP dd 0 |
||
104 | hidnplayr | 401 | |
336 | hidnplayr | 402 | dhcpMsgLen dd 0 |
403 | socketNum dd 0 |
||
104 | hidnplayr | 404 | |
336 | hidnplayr | 405 | MAC rb 6 |
406 | currTime dd 0 |
||
407 | renewTime dd 0 |
||
408 | generator dd 0 |
||
409 | |||
410 | dhcpMsg rb BUFFER |
||
104 | hidnplayr | 411 | I_END: |