Jump to content

Extract MAC from STDOUT using REGEX`


Recommended Posts

First of all, my apologies for my woeful lack of regex skill. Now my question.

I am trying to extract the mac address from and windows commandline of:

arp -a <IPADDRESS>

First I ping the address to populate the arp table, then I run the arp -a command and capture the stdout to a string.

Then I want to hit the string with a regex to extract the mac address.

Below is the code I have so far.

#include <Constants.au3>
#include <Array.au3>

$network = "165.240.164"
$startip = InputBox("FIRST IP","Enter first octet of first IP address")
$endip = Inputbox("LAST IP","Enter last octet of last IP address")
$network = "165.240.164"
Local $text

for $x = $startip to $endip
    Run(@ComSpec & " /c " & 'ping -n 5 ' & $network & '.' & $x, "", @SW_HIDE)
    $foo = Run(@ComSpec & " /c " & 'arp -a ' & $network & '.' & $x, "", @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD)

    
    While 1
        $line = StdoutRead($foo)
        If @error Then ExitLoop
        $text &= $line
    Wend

    $text = StringStripWS($text,8)   ;trying to get rid of special characters

    ;curse you regular expression!!!!
    $res = StringRegExp($text, "^[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}", 1) 

    if IsArray($res) then
        _ArrayDisplay($res)
        msgbox(1,"MAC IS",$res[0])
        $res[0] = ""
        Sleep(1500)
    EndIf
    $text = ""
Next
Link to comment
Share on other sites

  • Moderators

"(?i)((?:[a-f\d]{2}\-){5}[a-f\d]{2})\W"

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

"(?i)((?:[a-f\d]{2}\-){5}[a-f\d]{2})\W"

Just to modify that a bit using the xdigit class.

"((?:[[:xdigit:]]{2}\-){5}[[:xdigit:]]{2})\W"

Should be the same and case sense is not required.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

Thanks SmOke_N,

Another crispy, nutritious answer. That regex is right on the money. :mellow:

After adding it, one line of my code was breaking the program:

$text = StringStripWS($text,8)

Once I got rid of that it works like a charm. Here's the working code:

#include <Constants.au3>            ;for STDOUT_CHILD & STDERR_CHILD

Local $network = "165.240.164"
Local $startip = InputBox("FIRST IP","Enter first octet of first IP address")
Local $endip = Inputbox("LAST IP","Enter last octet of last IP address")
Local $network = "165.240.164"
Local $text

for $x = $startip to $endip
    Run(@ComSpec & " /c " & 'ping -n 5 ' & $network & '.' & $x, "", @SW_HIDE)   ;ping ip to populate arp table
                                                                                ;get arp table entry for IP
    $foo = Run(@ComSpec & " /c " & 'arp -a ' & $network & '.' & $x, "", @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD)
    While 1
        $line = StdoutRead($foo)    ;read stdout into line
        If @error Then ExitLoop     ;if no more stdout get out of loop
        $text &= $line              ;append this line of $text into $line
    Wend
    msgbox(1,"TEXT",$text)

    $res = StringRegExp($text, "(?i)((?:[a-f\d]{2}\-){5}[a-f\d]{2})\W", 1)  ;get MAC out of $text thanks SmOke_N

    if IsArray($res) then               ;if regex works $res is an array
        msgbox(1,"MAC IS",$res[0])
        Sleep(1500)
    EndIf
    
    $text = ""
Next
Link to comment
Share on other sites

  • Moderators

Just to modify that a bit using the xdigit class.

"((?:[[:xdigit:]]{2}\-){5}[[:xdigit:]]{2})\W"

Should be the same and case sense is not required.

There's a difference, I did mine the way I did to save the 7 chars :mellow: .

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

That's called shortcuting and whoever it was that got me rolling with RegEx explained that it isn't good to shortcut.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

  • 9 years later...

I have somehow the same problem

the idea is that i want to create a small gui that return the ip address.

at the other side i have a device that returns 169.254.116.53. if i change the device i will get another IP in range 169.254.X.X

My ip address on the broadcast interface is 169.254.179.155

if i do an arp -a i have:


Interface: 169.254.179.155 --- 0x16
  Internet Address      Physical Address      Type
  169.254.116.53        00-1a-37-8a-cc-83     dynamic <- this is what i want to display: line1: IP , line 2: MAC, line3: dynamic
  169.254.199.99        d0-b5-c2-64-58-76     dynamic
  169.254.199.119       00-1c-d7-7c-51-3c     dynamic

can you please help me creating a if and for like below

if ip address from read line = @IPAddress1 and last  = "0x16" (guessing is the same on all computers)

then $var1 = 169.254.116.53

$var2 = 00-1a-37-8a-cc-83

$var3 = dynamic

msgbox(0, var1 & $var2 & $var3)

 

thank you!

 

Link to comment
Share on other sites

Maybe this

#Include <Array.au3>

$txt = "Interface: 169.254.179.155 --- 0x16" & @crlf & _ 
    "  Internet Address      Physical Address      Type" & @crlf & _ 
    "  169.254.116.53        00-1a-37-8a-cc-83     dynamic" & @crlf & _ 
    "  169.254.199.99        d0-b5-c2-64-58-76     dynamic" & @crlf & _ 
    "  169.254.199.119       00-1c-d7-7c-51-3c     dynamic"
; Msgbox(0,"", $txt)

;If StringRegExp($txt, '^\s*.*?' & @IPAddress1 & '.*?0x16') Then _
If StringRegExp($txt, '^\s*.*?169.254.179.155.*?0x16') Then _
    $res = StringRegExp($txt, '(?m)^\h*([\d.]+)\h+([\w-]+)\h+(\w+)', 1)
_ArrayDisplay($res)

 

Link to comment
Share on other sites

Maybe this could help too:

$IP = @IPAddress1


ConsoleWrite(_SendARP($IP) & @CRLF)



Func _inet_addr($sIP)
    Local $aRet = DllCall("ws2_32.dll", "ULONG", "inet_addr", "str", $sIP)
    Return $aRet[0]
EndFunc   ;==>_inet_addr

Func _SendARP($DestIP)
    Local $DestAddress = _inet_addr($DestIP)
    If $DestAddress = 0xFFFFFFFF Then Return SetError(1, 0, "INVALID_IP_ADDRESS")
    Local $tMacAddr = DllStructCreate("BYTE[8]")
    Local $aRet = DllCall("Iphlpapi.dll", "DWORD", "SendARP", "ULONG", $DestAddress, "ULONG", 0, "struct*", $tMacAddr, "ULONG*", 8)
    Local $sMAC = ""
    Switch $aRet[0]
        Case 0
            For $i = 1 To $aRet[4] - 1
                $sMAC &= Hex(DllStructGetData($tMacAddr, 1, $i), 2) & "-"
            Next
            $sMAC &= Hex(DllStructGetData($tMacAddr, 1, $i), 2)
            Return $sMAC
        Case 31
            Return SetError(2, $aRet[0], "ERROR_GEN_FAILURE")
        Case 87
            Return SetError(3, $aRet[0], "ERROR_INVALID_PARAMETER")
        Case 1784
            Return SetError(4, $aRet[0], "ERROR_INVALID_USER_BUFFER")
        Case 67
            Return SetError(5, $aRet[0], "ERROR_BAD_NET_NAME")
        Case 1168
            Return SetError(6, $aRet[0], "ERROR_NOT_FOUND")
    EndSwitch
EndFunc   ;==>_SendARP

 

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

45 minutes ago, mikell said:

Maybe this

#Include <Array.au3>

$txt = "Interface: 169.254.179.155 --- 0x16" & @crlf & _ 
    "  Internet Address      Physical Address      Type" & @crlf & _ 
    "  169.254.116.53        00-1a-37-8a-cc-83     dynamic" & @crlf & _ 
    "  169.254.199.99        d0-b5-c2-64-58-76     dynamic" & @crlf & _ 
    "  169.254.199.119       00-1c-d7-7c-51-3c     dynamic"
; Msgbox(0,"", $txt)

;If StringRegExp($txt, '^\s*.*?' & @IPAddress1 & '.*?0x16') Then _
If StringRegExp($txt, '^\s*.*?169.254.179.155.*?0x16') Then _
    $res = StringRegExp($txt, '(?m)^\h*([\d.]+)\h+([\w-]+)\h+(\w+)', 1)
_ArrayDisplay($res)

 

Thanks @mikell

this is a starting point

now how can i do a for loop if my arp-a is

Interface: 192.168.10.145 --- 0xc
  Internet Address      Physical Address      Type
  192.168.10.1          2c-4d-54-83-00-b0     dynamic
  192.168.10.10         24-5e-be-1c-13-ea     dynamic
  192.168.10.25         24-5e-be-1c-13-eb     dynamic
  192.168.10.118        00-17-88-28-92-25     dynamic
  192.168.10.123        00-1f-29-2a-e2-35     dynamic
  192.168.10.255        ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static
  239.255.255.250       01-00-5e-7f-ff-fa     static
  255.255.255.255       ff-ff-ff-ff-ff-ff     static

Interface: 169.254.179.155 --- 0x16
  Internet Address      Physical Address      Type
  169.254.116.53        00-1a-37-8a-cc-83     dynamic <- this is the ip, mac and type that i need to show
  169.254.199.99        d0-b5-c2-64-58-76     dynamic
  169.254.199.119       00-1c-d7-7c-51-3c     dynamic
  169.254.255.255       ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static
  239.255.255.250       01-00-5e-7f-ff-fa     static
  255.255.255.255       ff-ff-ff-ff-ff-ff     static

Thanks a lot

 

35 minutes ago, funkey said:

Maybe this could help too:

$IP = @IPAddress1


ConsoleWrite(_SendARP($IP) & @CRLF)



Func _inet_addr($sIP)
    Local $aRet = DllCall("ws2_32.dll", "ULONG", "inet_addr", "str", $sIP)
    Return $aRet[0]
EndFunc   ;==>_inet_addr

Func _SendARP($DestIP)
    Local $DestAddress = _inet_addr($DestIP)
    If $DestAddress = 0xFFFFFFFF Then Return SetError(1, 0, "INVALID_IP_ADDRESS")
    Local $tMacAddr = DllStructCreate("BYTE[8]")
    Local $aRet = DllCall("Iphlpapi.dll", "DWORD", "SendARP", "ULONG", $DestAddress, "ULONG", 0, "struct*", $tMacAddr, "ULONG*", 8)
    Local $sMAC = ""
    Switch $aRet[0]
        Case 0
            For $i = 1 To $aRet[4] - 1
                $sMAC &= Hex(DllStructGetData($tMacAddr, 1, $i), 2) & "-"
            Next
            $sMAC &= Hex(DllStructGetData($tMacAddr, 1, $i), 2)
            Return $sMAC
        Case 31
            Return SetError(2, $aRet[0], "ERROR_GEN_FAILURE")
        Case 87
            Return SetError(3, $aRet[0], "ERROR_INVALID_PARAMETER")
        Case 1784
            Return SetError(4, $aRet[0], "ERROR_INVALID_USER_BUFFER")
        Case 67
            Return SetError(5, $aRet[0], "ERROR_BAD_NET_NAME")
        Case 1168
            Return SetError(6, $aRet[0], "ERROR_NOT_FOUND")
    EndSwitch
EndFunc   ;==>_SendARP

 

This only shows the mac address if my broadcast interface. But thanks for sharing also!

Link to comment
Share on other sites

So maybe this :P

#Include <Array.au3>

$txt = "Interface: 192.168.10.145 --- 0xc" & @crlf & _ 
    "  Internet Address      Physical Address      Type" & @crlf & _ 
    "  192.168.10.1          2c-4d-54-83-00-b0     dynamic" & @crlf & _ 
    "  192.168.10.10         24-5e-be-1c-13-ea     dynamic" & @crlf & _ 
    "  192.168.10.25         24-5e-be-1c-13-eb     dynamic" & @crlf & _ 
    "  192.168.10.118        00-17-88-28-92-25     dynamic" & @crlf & _ 
    "  192.168.10.123        00-1f-29-2a-e2-35     dynamic" & @crlf & _ 
    "  192.168.10.255        ff-ff-ff-ff-ff-ff     static" & @crlf & _ 
    "  224.0.0.22            01-00-5e-00-00-16     static" & @crlf & _ 
    "  224.0.0.251           01-00-5e-00-00-fb     static" & @crlf & _ 
    "  224.0.0.252           01-00-5e-00-00-fc     static" & @crlf & _ 
    "  239.255.255.250       01-00-5e-7f-ff-fa     static" & @crlf & _ 
    "  255.255.255.255       ff-ff-ff-ff-ff-ff     static" & @crlf & _ 
    @crlf & _ 
    "Interface: 169.254.179.155 --- 0x16" & @crlf & _ 
    "  Internet Address      Physical Address      Type" & @crlf & _ 
    "  169.254.116.53        00-1a-37-8a-cc-83     dynamic <- this is the ip, mac and type that i need to show" & @crlf & _ 
    "  169.254.199.99        d0-b5-c2-64-58-76     dynamic" & @crlf & _ 
    "  169.254.199.119       00-1c-d7-7c-51-3c     dynamic" & @crlf & _ 
    "  169.254.255.255       ff-ff-ff-ff-ff-ff     static" & @crlf & _ 
    "  224.0.0.22            01-00-5e-00-00-16     static" & @crlf & _ 
    "  224.0.0.251           01-00-5e-00-00-fb     static" & @crlf & _ 
    "  224.0.0.252           01-00-5e-00-00-fc     static" & @crlf & _ 
    "  239.255.255.250       01-00-5e-7f-ff-fa     static" & @crlf & _ 
    "  255.255.255.255       ff-ff-ff-ff-ff-ff     static"
; Msgbox(0,"", $txt)

; first check @IPAddress1, then skip all text up to @IPAddress1 and get the infos from the rest
;If StringRegExp($txt, '^\s*.*?' & @IPAddress1 & '.*?0x16') Then _
If StringRegExp($txt, '(?m)^\s*.*?169.254.179.155.*?0x16') Then _ 
    $res = StringRegExp($txt, '(?ms)^.*?169.254.179.155(*SKIP)(*F)|^\h*([\d.]+)\h+([\w-]+)\h+(\w+)', 1)
    ; $res = StringRegExp($txt, '(?ms)^.*?' & @IPAddress1 & '(*SKIP)(*F)|^\h*([\d.]+)\h+([\w-]+)\h+(\w+)', 1)
_ArrayDisplay($res)

 

Edited by mikell
comment
Link to comment
Share on other sites

tried this but it woun't how anything

 

#include <GUIConstantsEx.au3>
 #include <WindowsConstants.au3>
#include <Constants.au3>
#include <Array.au3>


Global $text
Global $res

$foo = Run("arp -a", @SystemDir, @SW_HIDE, $STDOUT_CHILD)

Global $line = ""

While 1
    $line = StdoutRead($foo)
    If @error Then ExitLoop
       $text &= $line
Wend




;ConsoleWrite($line)

Local $arp_list = StringSplit(StringTrimRight(StringStripCR($text), StringLen(@CRLF)), @CRLF)
    If @error Then
        MsgBox($MB_SYSTEMMODAL, "", "It appears there was an error trying to find all the files in the current script directory.")
    Else

        EndIf

Local $res=""

    For $x = 1 To $arp_list[0]
 
If StringRegExp($arp_list[$x], '(?m)^\s*.*?169.254.179.155.*?0x16') Then _
    $res = StringRegExp($arp_list[$x], '(?ms)^.*?169.254.179.155(*SKIP)(*F)|^\h*([\d.]+)\h+([\w-]+)\h+(\w+)', 1)
   
        _ArrayDisplay($res)

Next

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...