Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Array.au3>
- #include <WinAPI.au3>
- ;==============================================
- ; MAC Address Finder
- ; Đào Văn Trong - TRONG.PRO
- : Hàm lấy MAC từ IP (LAN) - Phiên bản cải tiến
- ; $sIP : địa chỉ IP
- ; $bForce : True = vẫn cố tìm kể cả không ping được
- ; $aExtraPorts : mảng các port TCP bổ sung để thử
- ; $iTimeout : timeout cho mỗi TCP connection (ms)
- ; $iRetries : số lần thử lại
- ; $bVerbose : hiển thị thông tin debug
- ;==============================================
- Func _GetMACEx($sIP, $bForce = False, $aExtraPorts = Default, $iTimeout = 1000, $iRetries = 2, $bVerbose = False)
- Local $sMAC = “”
- ; Validate IP address
- If Not __IsValidIP($sIP) Then
- If $bVerbose Then ConsoleWrite("ERROR: Invalid IP address format: " & $sIP & @CRLF)
- Return ""
- EndIf
- If $bVerbose Then ConsoleWrite("INFO: Starting MAC discovery for " & $sIP & @CRLF)
- ; 0) Thử ping trước với timeout ngắn
- Local $iPingResult = Ping($sIP, 500)
- If Not $iPingResult Then
- If $bVerbose Then ConsoleWrite("WARNING: Ping failed for " & $sIP & @CRLF)
- If Not $bForce Then
- If $bVerbose Then ConsoleWrite("INFO: Aborting (force=false)" & @CRLF)
- Return ""
- EndIf
- Else
- If $bVerbose Then ConsoleWrite("INFO: Ping successful (" & $iPingResult & "ms)" & @CRLF)
- EndIf
- ; Retry loop
- For $iRetry = 1 To $iRetries
- If $bVerbose And $iRetry > 1 Then ConsoleWrite("INFO: Retry attempt " & $iRetry & "/" & $iRetries & @CRLF)
- ; 1) Thử SendARP trước
- If $bVerbose Then ConsoleWrite("INFO: Trying SendARP method..." & @CRLF)
- $sMAC = __GetMAC_SendARP($sIP, $bVerbose)
- If $sMAC <> "" Then
- If $bVerbose Then ConsoleWrite("SUCCESS: Found MAC via SendARP: " & $sMAC & @CRLF)
- Return $sMAC
- EndIf
- ; 2) Thử ép ARP qua TCP các cổng phổ biến với timeout
- If $bVerbose Then ConsoleWrite("INFO: Trying TCP ARP probing..." & @CRLF)
- Local $aPorts = [135, 139, 445, 3389, 80, 443, 22, 21, 25, 53]
- __ProbePortsForARP($sIP, $aPorts, $iTimeout, $bVerbose)
- ; 2b) Thử các cổng tùy chỉnh
- If IsArray($aExtraPorts) Then
- If $bVerbose Then ConsoleWrite("INFO: Probing extra ports..." & @CRLF)
- __ProbePortsForARP($sIP, $aExtraPorts, $iTimeout, $bVerbose)
- EndIf
- ; Đợi một chút để ARP table cập nhật
- Sleep(200)
- ; 3) Thử lại SendARP sau khi probe
- If $bVerbose Then ConsoleWrite("INFO: Retry SendARP after probing..." & @CRLF)
- $sMAC = __GetMAC_SendARP($sIP, $bVerbose)
- If $sMAC <> "" Then
- If $bVerbose Then ConsoleWrite("SUCCESS: Found MAC via SendARP (after probe): " & $sMAC & @CRLF)
- Return $sMAC
- EndIf
- ; 4) Thử đọc từ ARP table
- If $bVerbose Then ConsoleWrite("INFO: Trying ARP table lookup..." & @CRLF)
- $sMAC = __GetMAC_ARP($sIP, $bVerbose)
- If $sMAC <> "" Then
- If $bVerbose Then ConsoleWrite("SUCCESS: Found MAC via ARP table: " & $sMAC & @CRLF)
- Return $sMAC
- EndIf
- ; 5) Thử refresh ARP table và đọc lại
- If $iRetry < $iRetries Then
- If $bVerbose Then ConsoleWrite("INFO: Refreshing ARP table..." & @CRLF)
- __RefreshARPTable($sIP)
- Sleep(500) ; Đợi lâu hơn trước retry
- EndIf
- Next
- If $bVerbose Then ConsoleWrite("FAILED: Could not find MAC address for " & $sIP & @CRLF)
- Return ""
- EndFunc
- ;–––––––––––––––––––––––
- ; Validate IP address format
- ;–––––––––––––––––––––––
- Func __IsValidIP($sIP)
- Local $aIP = StringSplit($sIP, “.”, 2)
- If UBound($aIP) <> 4 Then Return False
- For $i = 0 To 3
- If Not StringIsDigit($aIP[$i]) Then Return False
- Local $iOctet = Number($aIP[$i])
- If $iOctet < 0 Or $iOctet > 255 Then Return False
- Next
- Return True
- EndFunc
- ;–––––––––––––––––––––––
- ; Probe multiple ports to trigger ARP
- ;–––––––––––––––––––––––
- Func __ProbePortsForARP($sIP, $aPorts, $iTimeout, $bVerbose = False)
- TCPStartup()
- Local $aConnections[UBound($aPorts)]
- Local $hTimer = TimerInit()
- ; Start all connections
- For $i = 0 To UBound($aPorts) - 1
- $aConnections[$i] = TCPConnect($sIP, $aPorts[$i])
- If $bVerbose And $aConnections[$i] <> -1 Then
- ConsoleWrite("INFO: TCP connection attempt to port " & $aPorts[$i] & @CRLF)
- EndIf
- Next
- ; Wait for timeout or connections
- While TimerDiff($hTimer) < $iTimeout
- Local $bAnyConnected = False
- For $i = 0 To UBound($aConnections) - 1
- If $aConnections[$i] <> -1 Then
- $bAnyConnected = True
- ExitLoop
- EndIf
- Next
- If Not $bAnyConnected Then ExitLoop
- Sleep(10)
- WEnd
- ; Close all connections
- For $i = 0 To UBound($aConnections) - 1
- If $aConnections[$i] <> -1 Then
- TCPCloseSocket($aConnections[$i])
- EndIf
- Next
- TCPShutdown()
- EndFunc
- ;–––––––––––––––––––––––
- ; Enhanced SendARP with better error handling
- ;–––––––––––––––––––––––
- Func __GetMAC_SendARP($sIP, $bVerbose = False)
- ; Convert IP to network byte order
- Local $aIP = DllCall(“ws2_32.dll”, “uint”, “inet_addr”, “str”, $sIP)
- If @error Or $aIP[0] = 0xFFFFFFFF Then
- If $bVerbose Then ConsoleWrite(“ERROR: inet_addr failed for “ & $sIP & @CRLF)
- Return “”
- EndIf
- Local $tMac = DllStructCreate("byte[6]")
- Local $tLen = DllStructCreate("ulong")
- DllStructSetData($tLen, 1, 6)
- Local $aResult = DllCall("iphlpapi.dll", "dword", "SendARP", _
- "uint", $aIP[0], _
- "uint", 0, _
- "ptr", DllStructGetPtr($tMac), _
- "ptr", DllStructGetPtr($tLen))
- If @error Then
- If $bVerbose Then ConsoleWrite("ERROR: SendARP DLL call failed" & @CRLF)
- Return ""
- EndIf
- If $aResult[0] <> 0 Then
- If $bVerbose Then ConsoleWrite("WARNING: SendARP returned error code " & $aResult[0] & @CRLF)
- Return ""
- EndIf
- ; Build MAC string
- Local $sMAC = ""
- For $i = 1 To 6
- If $i > 1 Then $sMAC &= ":"
- $sMAC &= StringFormat("%02X", DllStructGetData($tMac, 1, $i))
- Next
- Return $sMAC
- EndFunc
- ;–––––––––––––––––––––––
- ; Enhanced ARP table reading with multiple patterns
- ;–––––––––––––––––––––––
- Func __GetMAC_ARP($sIP, $bVerbose = False)
- Local $sCmd = @ComSpec & ’ /c arp -a | findstr /i “’ & $sIP & ‘”’
- Local $iPID = Run($sCmd, “”, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
- ProcessWaitClose($iPID, 5000) ; 5 second timeout
- Local $sOutput = StdoutRead($iPID)
- Local $sError = StderrRead($iPID)
- If $sError <> "" And $bVerbose Then
- ConsoleWrite("WARNING: ARP command error: " & $sError & @CRLF)
- EndIf
- If $sOutput = "" Then Return ""
- ; Try multiple regex patterns
- Local $aPatterns[4] = [ _
- $sIP & "\s+([0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2})", _
- "([0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2}[-:][0-9A-Fa-f]{2})", _
- $sIP & ".*?([0-9A-Fa-f-:]{17})", _
- "([0-9A-Fa-f-:]{17})" _
- ]
- For $i = 0 To UBound($aPatterns) - 1
- Local $aMatches = StringRegExp($sOutput, $aPatterns[$i], 3)
- If Not @error And UBound($aMatches) > 0 Then
- Local $sMAC = StringReplace($aMatches[0], "-", ":")
- $sMAC = StringUpper($sMAC)
- If StringLen($sMAC) = 17 Then ; Valid MAC format
- If $bVerbose Then ConsoleWrite("INFO: Found MAC in ARP table: " & $sMAC & @CRLF)
- Return $sMAC
- EndIf
- EndIf
- Next
- If $bVerbose Then ConsoleWrite("WARNING: No valid MAC found in ARP output" & @CRLF)
- Return ""
- EndFunc
- ;–––––––––––––––––––––––
- ; Refresh ARP table by clearing and re-probing
- ;–––––––––––––––––––––––
- Func __RefreshARPTable($sIP)
- ; Clear specific ARP entry
- Run(@ComSpec & “ /c arp -d “ & $sIP, “”, @SW_HIDE)
- Sleep(100)
- ; Force new ARP request with ping
- Ping($sIP, 1000)
- EndFunc
- ;–––––––––––––––––––––––
- ; Batch function to get multiple MACs
- ;–––––––––––––––––––––––
- Func _GetMultipleMACs($aIPs, $bForce = False, $aExtraPorts = Default, $bVerbose = False)
- If Not IsArray($aIPs) Then Return SetError(1, 0, “”)
- Local $aResults[UBound($aIPs)][2]
- For $i = 0 To UBound($aIPs) - 1
- $aResults[$i][0] = $aIPs[$i]
- $aResults[$i][1] = _GetMACEx($aIPs[$i], $bForce, $aExtraPorts, 1000, 2, $bVerbose)
- If $bVerbose Then
- ConsoleWrite("RESULT: " & $aIPs[$i] & " -> " & ($aResults[$i][1] <> "" ? $aResults[$i][1] : "Not found") & @CRLF)
- EndIf
- Next
- Return $aResults
- EndFunc
- ;–––––––––––––––––––––––
- ; Demo usage with enhanced features
- ;–––––––––––––––––––––––
- Func _Demo()
- ConsoleWrite(”=== Enhanced MAC Address Finder Demo ===” & @CRLF)
- ; Single IP with verbose output
- ConsoleWrite(@CRLF & "--- Testing single IP ---" & @CRLF)
- Local $sMAC = _GetMACEx("192.168.1.1", True, [8080, 8443], 1500, 3, True)
- ConsoleWrite("Final result: " & ($sMAC <> "" ? $sMAC : "MAC not found") & @CRLF)
- ; Multiple IPs
- ConsoleWrite(@CRLF & "--- Testing multiple IPs ---" & @CRLF)
- Local $aTestIPs[3] = ["192.168.1.1", "192.168.1.10", "8.8.8.8"]
- Local $aResults = _GetMultipleMACs($aTestIPs, False, Default, True)
- ConsoleWrite(@CRLF & "Summary:" & @CRLF)
- For $i = 0 To UBound($aResults) - 1
- ConsoleWrite($aResults[$i][0] & " -> " & ($aResults[$i][1] <> "" ? $aResults[$i][1] : "Not found") & @CRLF)
- Next
- EndFunc
- ; Uncomment to run demo
- ; _Demo()
Advertisement
Add Comment
Please, Sign In to add comment