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