Jump to content

Threaded Ping


Fr0zT
 Share

Recommended Posts

Hi All, I'm trying to create a function to do threaded pinging. I have some code I've been playing with just to see if I could get anything to work but I'm stuck and wondering if there's a guru out there who can look at this and point me in the right direction. Sorry for the sloppy code, it's very beta right now and I'm n00b to this style. I think one of my main questions here is, if I wish to call a method of a class, like Ping.Send from system.dll, how do I construct this? For now I have just been trying to GetProcAddress of Ping.Send but I have a feeling this is not how it works. I suspect I need to instantiate the Ping class first and then somehow call the method of .Send???

#Include <WindowsConstants.au3>
;Props to w0uter for this...

$v_ASM = DllStructCreate( _
    'byte;int;' _   ;01~02 00401000 >    68 00000000                 PUSH 64                                                  ; TTL = 64
&   'byte;int;' _   ;03~04 00401005   .  68 00000001                 PUSH Protect.00402007                                   ; DF Flag = true
&   'byte;int;' _   ;05~06 00444448 >    B8 EA04D577                 MOV EAX,SYSTEM.PingOptions
&   'byte;byte;' _  ;07~08 0044444D      FFD0                        CALL NEAR EAX ;&   'byte;int;' _   ;09~10 00401019      A2 44332211                 MOV BYTE PTR DS:[11223344],AL
&   'byte' _        ;09~09 0040101E      C3                          RETN
)

DllStructSetData($v_ASM, 01, 0x68)
DllStructSetData($v_ASM, 02, 64)

DllStructSetData($v_ASM, 03, 0x68)
DllStructSetData($v_ASM, 04, 1)

DllStructSetData($v_ASM, 05, 0xB8)
$hDll = DllCall('kernel32.dll', 'int', 'LoadLibrary', 'str', 'system.dll')
$hProc_PingOptions = DllCall('kernel32.dll', 'int', 'GetProcAddress', 'int', $hDll[0], 'str', "PingOptions")
DllStructSetData($v_ASM, 06, $hProc_PingOptions[0])

DllStructSetData($v_ASM, 07, 0xFF)
DllStructSetData($v_ASM, 08, 0xD0)

DllStructSetData($v_ASM, 09, 0xC3)

$res = DllCall('kernel32.dll', 'int', 'CreateThread', 'int', 0, 'int', 0, 'int', DllStructGetPtr($v_ASM), 'int', 0, 'int', 0, 'int', 0)

ConsoleWrite(1 & " " & $res[0] & @CRLF)

$ipaddr = "74.125.53.106"
$ip = DllStructCreate("char[" & StringLen($ipaddr) & "]")
DllStructSetData($ip,1,$ipaddr)
$data = _UnicodeStruct("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
$timeout = DllStructCreate("int")
DllStructSetData($timeout,1,2000)
$code = DllStructCreate("int",$res[0])

$v2_ASM = DllStructCreate( _
    'byte;int;' _   ;01~02 00401000 >    68 00000000                 PUSH ...                                                  ; IP
&   'byte;int;' _   ;03~04 00401005   .  68 00000001                 PUSH Protect.00402007                                   ; Timeout
&   'byte;int;' _   ;05~06 00401005   .  68 00000001                 PUSH Protect.00402007                                   ; Data
&   'byte;int;' _   ;07~08 00401005   .  68 00000001                 PUSH Protect.00402007                                   ; Code
&   'byte;int;' _   ;09~10 00444448 >    B8 EA04D577                 MOV EAX,SYSTEM.Ping.Send
&   'byte;byte;' _  ;11~12 0044444D      FFD0                        CALL NEAR EAX ;&   'byte;int;' 
&   'byte' _        ;13~13 0040101E      C3                          RETN
)

DllStructSetData($v2_ASM, 01, 0x68)
DllStructSetData($v2_ASM, 02, DllStructGetPtr($ip,1))

DllStructSetData($v2_ASM, 03, 0x68)
DllStructSetData($v2_ASM, 04, DllStructGetPtr($timeout,1))

DllStructSetData($v2_ASM, 05, 0x68)
DllStructSetData($v2_ASM, 06, DllStructGetPtr($data,1))

DllStructSetData($v2_ASM, 07, 0x68)
DllStructSetData($v2_ASM, 08, DllStructGetPtr($code,1))

DllStructSetData($v2_ASM, 09, 0xB8)
$hProc_PingSend = DllCall('kernel32.dll', 'int', 'GetProcAddress', 'int', $hDll[0], 'str', "Ping.Send")
DllStructSetData($v2_ASM, 10, $hProc_PingSend[0])

DllStructSetData($v2_ASM, 11, 0xFF)
DllStructSetData($v2_ASM, 12, 0xD0)

DllStructSetData($v2_ASM, 13, 0xC3)

$res2 = DllCall('kernel32.dll', 'int', 'CreateThread', 'int', 0, 'int', 0, 'int', DllStructGetPtr($v2_ASM), 'int', 0, 'int', 0, 'int', 0)
DllCall('kernel32.dll', 'int', 'FreeLibrary', 'int', $hDll[0])

ConsoleWrite(1 & " " & $res2[0] & @CRLF)

Exit

; creates a struct for an Unicode-String
Func _UnicodeStruct($text)
    ; Prog@ndy
    Local $s = DllStructCreate("wchar[" & StringLen($text)+1 & "]")
    DllStructSetData($s,1,$text)
    Return $s
EndFunc

At this point I'm just watching my firewall logs to see if anything is going out.

Thanks in advance for any help,

FrozT

References:

MSDN Ping Class

Edited by Fr0zT

[size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size]

Link to comment
Share on other sites

You can easy ping with _Timer_SetTimer!

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

@funkey, What Manadar and myself are doing is very different from just using timer ticks because as soon as you call the AutoIt ping command your programs thread will halt until it finishes, which is really bad if you are potentially testing multiple systems which are down (Plus I find that the AutoIt Ping Timeout doesn't work well either with small values like <100ms.)

@Manadar, I tried your example and I think that as far as the functionality I am looking for, it will work. Thanks! :)

I would still encourage anyone playing with threading in AutoIT, albeit unnaturally to look at this and explain for me how to fire a method of a class.

Thanks All!

Edited by Fr0zT

[size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size]

Link to comment
Share on other sites

  • 2 weeks later...

Well I got it in my head that I could do this and so I took the plunge and eventually came up with some working code. So here is my threaded ping, without using any shell calls. Works perfectly for me so far on XP and win7.

#include <Memory.au3>
#include <Array.au3>
#include <Misc.au3> ;Press ESC to exit

Opt('MustDeclareVars', 1)
Global Const $DONT_FRAGMENT = 2, $IP_SUCCESS = 0, $IP_DEST_NET_UNREACHABLE = 11002, $IP_DEST_HOST_UNREACHABLE = 11003, $IP_DEST_PROT_UNREACHABLE = 11004, $IP_DEST_PORT_UNREACHABLE = 11005, _
    $IP_NO_RESOURCES = 11006, $IP_HW_ERROR = 11008, $IP_PACKET_TOO_BIG = 11009, $IP_REQ_TIMED_OUT = 11010, $IP_BAD_REQ = 11011, $IP_BAD_ROUTE = 11012, _
    $IP_TTL_EXPIRED_TRANSIT = 11013, $IP_TTL_EXPIRED_REASSEM = 11014, $IP_PARAM_PROBLEM = 11015, $IP_SOURCE_QUENCH = 11016, $IP_BAD_DESTINATION =11018, _
    $IP_GENERAL_FAILURE = 11050, $NO_STATUS = 10000     ;We will use 10000 as the no status indicator since 0 meens successful reply
Local $hPointers = DllStructCreate("ptr WSAStartup;ptr WSACleanup;ptr IcmpCloseHandle;ptr IcmpSendEcho;ptr IcmpCreateFile;ptr ExitThread")
Local $hws2_32Dll = LibLoad("ws2_32.dll")
DllStructSetData($hPointers,"WSAStartup",GetProcAddress($hws2_32Dll, "WSAStartup"))
DllStructSetData($hPointers,"WSACleanup",GetProcAddress($hws2_32Dll, "WSACleanup"))
Local $hICMPDll = LibLoad("ICMP.dll");Iphlpapi.dll")
DllStructSetData($hPointers,"IcmpCloseHandle",GetProcAddress($hICMPDll, "IcmpCloseHandle"))
DllStructSetData($hPointers,"IcmpSendEcho",GetProcAddress($hICMPDll, "IcmpSendEcho"))
DllStructSetData($hPointers,"IcmpCreateFile",GetProcAddress($hICMPDll, "IcmpCreateFile"))
Local $hkernel32Dll = LibLoad("kernel32.dll")
DllStructSetData($hPointers,"ExitThread",GetProcAddress($hkernel32Dll, "ExitThread"))
LibFree($hws2_32Dll)
LibFree($hICMPDll)
LibFree($hkernel32Dll)
TCPStartup()

Global $pings[1]    ;This array will hold all echo reply data in a struct.
$pings[0] = 0       ;for array management.
ConsoleWrite("Press esc any time to stop" & @CRLF)
pingThreaded("www.google.ca")
pingThreaded("127.0.0.1")
pingThreaded("www.asus.com.tw")
pingThreaded("4.2.2.1",   200,    "PINGDATA",255,  3,      $DONT_FRAGMENT)
;                      TIMEOUTE      DATA    TTL REPEAT        FLAGS

While _IsPressed("1B") = 0 ;Press esc to exit
    _managePings()
WEnd
_Exit()

;Function pingThreaded
;$ip_addr will accept valid DNS Name or Normal IP address.
;Dont bother using really small timeouts like <40ms, they rarely work
Func pingThreaded($ip_addr,$timeout=5000,$data="A",$ttl=255,$numpings=2,$flags=0)
Local $hexIP = encodeIP($ip_addr)
If $hexIP == 0 Then Return 0
Local $pingID = _addPing()
DllStructSetData($pings[$pingID],"ip",$ip_addr)
DllStructSetData($pings[$pingID],"status",$NO_STATUS)
If IsNumber($ttl) = 0 Or Number($ttl) > 255 Then $ttl = 255
If IsNumber($timeout) = 0 Or Number($timeout) > 5000 Then $timeout = 5000
If IsNumber($numpings) = 0 Or Number($numpings) > 10 Then $numpings = 2
If StringLen($data) > 255 Then $data = StringTrimLeft($data,255)
DllStructSetData($pings[$pingID],"datasize",StringLen($data))   ;We may wish to report the data size later
;Props to trancexx
Local $CodeBuffer = DllStructCreate("byte[508]")
Local $RemoteCode = _MemVirtualAlloc(0, DllStructGetSize($CodeBuffer), $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
   DllStructSetData($CodeBuffer, 1, _
        "0x" & _                                                                            ;Original Assembly started at 401000
        "68" & SwapEndian($RemoteCode + 476) & _                                            ;push 00403024
        "6802020000" & _                                                                    ;push 00000202
        "E8B1000000" & _                                                                    ;Call 004010C0  <WSAStartup>
        "0BC0" & _                                                                          ;or eax, eax
        "740F" & _                                                                          ;je 00401022
        "C705" & SwapEndian(DllStructGetPtr($pings[$pingID],"status")) & "0F270000" & _     ;mov dword ptr [0040301C], 0000270F [Set status to 9999 if we couldn't start WSAStartup]
        "E986000000" & _                                                                    ;jmp 004010A8   <kernel32.ExitThread>
        "E8A5000000" & _                                                                    ;Call 004010CC  <IcmpCreateFile>
        "A3" & SwapEndian($RemoteCode + 472) & _                                            ;mov dword ptr [00403010], eax  <hIcmp = IcmpCreateFile Handle>
        "33DB" & _                                                                          ;xor ebx, ebx
        "EB68" & _                                                                          ;jmp 0040108B   <While>
        "53" & _                                                                            ;push ebx
        "C605" & SwapEndian($RemoteCode + 480) & Hex($ttl,2) & _                            ;mov byte ptr [004031AE], xx    <TTL>
        "C605" & SwapEndian($RemoteCode + 481) & "00" & _                                   ;mov byte ptr [004031AF], 00    <TOS>
        "C605" & SwapEndian($RemoteCode + 482) & Hex($flags,2) & _                          ;mov byte ptr [004031B0], 02    <Flags, 0x02=DF Bit Set>
        "C605" & SwapEndian($RemoteCode + 483) & "00" & _                                   ;mov byte ptr [004031B1], 00
        "C705" & SwapEndian($RemoteCode + 484) & "00000000" & _                             ;mov dword ptr [004031B2], 00000000
        "68" & SwapEndian($timeout) & _                                                     ;push 0000xxxx  <Timeout>
        "681E010000" & _                                                                    ;push 0000011E  <Size of Echo reply Struct + ICMP_OPTIONS Struct>
        "68" & SwapEndian($RemoteCode + 488) & _                                            ;push 004031BA  <icmpReply>
        "68" & SwapEndian($RemoteCode + 480) & _                                            ;push 004031B2  <icmpOptions>
        "6A" & Hex(StringLen($data),2) & _                                                  ;push 000000xx  <Data Size>
        "68" & SwapEndian($RemoteCode + 216) & _                                            ;push 00403000  <Data>
        "68" & SwapEndian(Dec($hexIP)) & _                                                  ;push <Hex(IP ADDRESS)>
        "FF35" & SwapEndian($RemoteCode + 472) & _                                          ;push dword ptr [00403010]  <hIcmp>
        "E850000000" & _                                                                    ;Call 004010D2  <IcmpSendEcho>
        "A1" & SwapEndian($RemoteCode + 496) & _                                            ;mov eax, dword ptr [004031C2]  <Get the ms responce time from icmpReply.RoundTripTime>
        "A3" & SwapEndian(DllStructGetPtr($pings[$pingID],"reply")) & _                     ;mov dword ptr [0040301C], eax  <Store the ms responce time>
        "A1" & SwapEndian($RemoteCode + 492) & _                                            ;mov eax, dword ptr [004031BE]  <Get the status from icmpReply.Status>
        "A3" & SwapEndian(DllStructGetPtr($pings[$pingID],"status")) & _                    ;mov dword ptr [00403020], eax  <Store the status>
        "5B" & _                                                                            ;pop ebx
        "43" & _                                                                            ;inc ebx
        "83FB" & Hex($numpings,2) & _                                                       ;cmp ebx, 000000xx  <Default will send 2 x Pings, often the first ping will fail. Results taken from 2nd>
        "7293" & _                                                                          ;jb 0040102D    <Wend>
        "FF35" & SwapEndian($RemoteCode + 472) & _                                          ;push dword ptr [00403010]  <hIcmp>
        "E81E000000" & _                                                                    ;Call 004010C6  <IcmpCloseHandle>
        "E80D000000" & _                                                                    ;Call 004010BA  <WSACleanup>
        "6A00" & _                                                                          ;push 00000000
        "E800000000" & _                                                                    ;Call 004010B4  <ExitThread>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"ExitThread")) & _                   ;JMP dword ptr  <kernel32.ExitThread>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"WSACleanup")) & _                   ;JMP dword ptr  <ws2_32.WSACleanup>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"WSAStartup")) & _                   ;JMP dword ptr  <ws2_32.WSAStartup>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpCloseHandle")) & _              ;JMP dword ptr  <ICMP.IcmpCloseHandle>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpCreateFile")) & _               ;JMP dword ptr  <ICMP.IcmpCreateFile>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpSendEcho"))& _                  ;JMP dword ptr  <ICMP.IcmpSendEcho>
        SwapEndian(StringToBinary($data)) _                                                 ;This is our ping Data, Max 255 bytes of space here.
    )
    _MemMoveMemory(DllStructGetPtr($CodeBuffer), $RemoteCode, DllStructGetSize($CodeBuffer))
    Local $aCall = DllCall("kernel32.dll", "ptr", "CreateThread", "ptr", 0, "int", 0, "ptr", $RemoteCode, "ptr", 0, "int", 0, "dword*", 0)
    Return $aCall[0]
EndFunc


;Function _addPing is just for array management of the $pings[] array.
Func _addPing()
    $pings[0] = UBound($pings)
    ReDim $pings[$pings[0]+1]
    $pings[$pings[0]] = DllStructCreate("char ip[15];ulong reply;ulong status;int datasize")
    Return $pings[0]
EndFunc

;Function _removePing is just for array management of the $pings[] array.
Func _removePing($pingID)
    If $pingID > $pings[0] Then Return ;Ensure our ID is valid
    $pings[$pingID] = 0 ;Free the DLLStruct
    _ArrayDelete($pings,$pingID)
    $pings[0] -= 1
EndFunc

Func _managePings()
    Local $pingID, $status
    $pingID = 1
    While $pingID <= $pings[0]
        $status = DllStructGetData($pings[$pingID],"status")
        If $status <> $NO_STATUS Then
            Switch $status
                Case 0
                    If DllStructGetData($pings[$pingID],"reply") = 0 Then
                        ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " replied in <1ms" & @CRLF)
                    Else
                        ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " replied in " & DllStructGetData($pings[$pingID],"reply") & "ms" & @CRLF)
                    EndIf
                Case 9999
                        ConsoleWrite("Could not initiate WSAStartup. Cannot Ping." & @CRLF)
                Case $IP_REQ_TIMED_OUT
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " timed-out" & @CRLF)
                Case $IP_DEST_NET_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination network was unreachable." & @CRLF)
                Case $IP_DEST_HOST_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination host was unreachable." & @CRLF)
                Case $IP_DEST_PROT_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination protocol was unreachable." & @CRLF)
                Case $IP_DEST_PORT_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination port was unreachable." & @CRLF)
                Case $IP_NO_RESOURCES
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " Insufficient IP resources were available." & @CRLF)
                Case $IP_HW_ERROR
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A hardware error occurred." & @CRLF)
                Case $IP_PACKET_TOO_BIG
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The packet was too big." & @CRLF)
                Case $IP_BAD_REQ
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad request." & @CRLF)
                Case $IP_BAD_ROUTE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad route." & @CRLF)
                Case $IP_TTL_EXPIRED_TRANSIT
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The time to live (TTL) expired in transit." & @CRLF) 
                Case $IP_TTL_EXPIRED_REASSEM
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The time to live expired during fragment reassembly." & @CRLF)
                Case $IP_PARAM_PROBLEM
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A parameter problem." & @CRLF)
                Case $IP_SOURCE_QUENCH
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " Datagrams are arriving too fast to be processed and datagrams may have been discarded." & @CRLF)
                Case $IP_BAD_DESTINATION
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad destination." & @CRLF)
                Case $IP_GENERAL_FAILURE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A general failure. This error can be returned for some malformed ICMP packets or lost network connection." & @CRLF)
            EndSwitch
            _removePing($pingID)
        EndIf
        $pingID += 1
    WEnd
EndFunc

Func encodeIP($ip_addr)
    Local $ip_addr_temp = $ip_addr
    If Not _isIP($ip_addr) Then $ip_addr = TCPNameToIP($ip_addr)
        If Not _isIP($ip_addr) Then
            ConsoleWrite($ip_addr_temp & " is not a valid IP Address. If you supplied a hostname ensure DNS is available." & @CRLF)
            Return 0
        Exit
    EndIf
    Return getHexIP($ip_addr)
EndFunc

Func getHexIP($ip_addr)
    Return Hex(_getIPOctet($ip_addr,4),2) & Hex(_getIPOctet($ip_addr,3),2) & Hex(_getIPOctet($ip_addr,2),2) & Hex(_getIPOctet($ip_addr,1),2)
EndFunc

Func LibLoad($lpLibFileName)
    Local $hKrnl = DllOpen("kernel32.dll")
    Local $LibHandle = DllCall($hKrnl, "int", "LoadLibraryA", "str", $lpLibFileName)
    DllClose($hKrnl)
    Return $LibHandle[0]
EndFunc

Func LibFree($DllHandle)
    Local $hKrnl = DllOpen("kernel32.dll")
    Local $LibFreed = DllCall($hKrnl, "int", "FreeLibrary", "int", $DllHandle)
    return $LibFreed[0]
EndFunc

Func GetProcAddress( $hModule, $lpProcName)
    Local $hKrnl = DllOpen("kernel32.dll")
    Local $ProcessAddy = DllCall($hKrnl,"int","GetProcAddress","int",$hModule,"str",$lpProcName)
    DllClose($hKrnl)
    Return $ProcessAddy[0]
EndFunc

Func SwapEndian($hex)
    Return Hex(Binary($hex))
EndFunc

Func _getIPOctet($ip_addr,$octet=1)
    Switch $octet
        Case 1
            Return Int(StringMid($ip_addr,1,StringInStr($ip_addr,".")))
        Case 4
            Return Int(StringMid($ip_addr,StringInStr($ip_addr,".",0,3)+1))
        Case Else
            Return Int(StringMid($ip_addr,StringInStr($ip_addr,".",0,$octet - 1)+1,StringInStr($ip_addr,".",0,$octet)+1))
    EndSwitch
EndFunc

Func _isIP($text)
    Return StringRegExp($text, "(((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9]?[0-9]))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9]?[0-9]))")
EndFunc

Func _Exit()
    TCPShutdown()
    Exit
EndFunc
Edited by Fr0zT

[size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size]

Link to comment
Share on other sites

Any reason you use _IsPressed to detect Esc(?) instead of using a hotkey?

Not really... My brain was just at capacity getting the assembly working.

(using hotkey instead)

#include <Memory.au3>
#include <Array.au3>

Opt('MustDeclareVars', 1)
HotKeySet("{ESC}", "_Exit")
Global Const $DONT_FRAGMENT = 2, $IP_SUCCESS = 0, $IP_DEST_NET_UNREACHABLE = 11002, $IP_DEST_HOST_UNREACHABLE = 11003, $IP_DEST_PROT_UNREACHABLE = 11004, $IP_DEST_PORT_UNREACHABLE = 11005, _
    $IP_NO_RESOURCES = 11006, $IP_HW_ERROR = 11008, $IP_PACKET_TOO_BIG = 11009, $IP_REQ_TIMED_OUT = 11010, $IP_BAD_REQ = 11011, $IP_BAD_ROUTE = 11012, _
    $IP_TTL_EXPIRED_TRANSIT = 11013, $IP_TTL_EXPIRED_REASSEM = 11014, $IP_PARAM_PROBLEM = 11015, $IP_SOURCE_QUENCH = 11016, $IP_BAD_DESTINATION =11018, _
    $IP_GENERAL_FAILURE = 11050, $NO_STATUS = 10000     ;We will use 10000 as the no status indicator since 0 meens successful reply
Local $hPointers = DllStructCreate("ptr WSAStartup;ptr WSACleanup;ptr IcmpCloseHandle;ptr IcmpSendEcho;ptr IcmpCreateFile;ptr ExitThread")
Local $hws2_32Dll = LibLoad("ws2_32.dll")
DllStructSetData($hPointers,"WSAStartup",GetProcAddress($hws2_32Dll, "WSAStartup"))
DllStructSetData($hPointers,"WSACleanup",GetProcAddress($hws2_32Dll, "WSACleanup"))
Local $hICMPDll = LibLoad("ICMP.dll");Iphlpapi.dll")
DllStructSetData($hPointers,"IcmpCloseHandle",GetProcAddress($hICMPDll, "IcmpCloseHandle"))
DllStructSetData($hPointers,"IcmpSendEcho",GetProcAddress($hICMPDll, "IcmpSendEcho"))
DllStructSetData($hPointers,"IcmpCreateFile",GetProcAddress($hICMPDll, "IcmpCreateFile"))
Local $hkernel32Dll = LibLoad("kernel32.dll")
DllStructSetData($hPointers,"ExitThread",GetProcAddress($hkernel32Dll, "ExitThread"))
LibFree($hws2_32Dll)
LibFree($hICMPDll)
LibFree($hkernel32Dll)
TCPStartup()

Global $pings[1]    ;This array will hold all echo reply data in a struct.
$pings[0] = 0       ;for array management.
ConsoleWrite("Press esc any time to stop" & @CRLF)
pingThreaded("www.google.ca")
pingThreaded("127.0.0.1")
pingThreaded("www.asus.com.tw")
pingThreaded("4.2.2.1",   200,    "PINGDATA",255,  3,      $DONT_FRAGMENT)
;                      TIMEOUTE      DATA    TTL REPEAT        FLAGS

While 1
    _managePings()
WEnd

;Function pingThreaded
;$ip_addr will accept valid DNS Name or Normal IP address.
;Timouts only really work when an IP isn't responding. Thats important to remember because if you think you can timeout an IP which is responding with high-pingtimes, you can't!
Func pingThreaded($ip_addr,$timeout=5000,$data="A",$ttl=255,$numpings=2,$flags=0)
Local $hexIP = encodeIP($ip_addr)
If $hexIP == 0 Then Return 0
Local $pingID = _addPing()
DllStructSetData($pings[$pingID],"ip",$ip_addr)
DllStructSetData($pings[$pingID],"status",$NO_STATUS)
If IsNumber($ttl) = 0 Or Number($ttl) > 255 Then $ttl = 255
If IsNumber($timeout) = 0 Or Number($timeout) > 5000 Then $timeout = 5000
If IsNumber($numpings) = 0 Or Number($numpings) > 10 Then $numpings = 2
If StringLen($data) > 255 Then $data = StringTrimRight($data,StringLen($data) - 255)
If IsNumber($flags) = 0 Or Number($flags) > 2 Then $flags = 2
DllStructSetData($pings[$pingID],"datasize",StringLen($data))   ;We may wish to report the data size later
;Props to trancexx
Local $CodeBuffer = DllStructCreate("byte[1156]") ;Code+PingData=471, Echo reply Struct + ICMP_OPTIONS Struct = 286 + WSAData=398
Local $RemoteCode = _MemVirtualAlloc(0, DllStructGetSize($CodeBuffer), $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
   DllStructSetData($CodeBuffer, 1, _
        "0x" & _                                                                            ;Original Assembly started at 401000
        "68" & SwapEndian($RemoteCode + 758) & _                                            ;push 00403024 <WSAData>
        "6802020000" & _                                                                    ;push 00000202
        "E8B1000000" & _                                                                    ;Call 004010C0  <WSAStartup>
        "0BC0" & _                                                                          ;or eax, eax
        "740F" & _                                                                          ;je 00401022
        "C705" & SwapEndian(DllStructGetPtr($pings[$pingID],"status")) & "0F270000" & _     ;mov dword ptr [0040301C], 0000270F [Set status to 9999 if we couldn't start WSAStartup]
        "E986000000" & _                                                                    ;jmp 004010A8   <kernel32.ExitThread>
        "E8A5000000" & _                                                                    ;Call 004010CC  <IcmpCreateFile>
        "A3" & SwapEndian($RemoteCode + 472) & _                                            ;mov dword ptr [00403010], eax  <hIcmp = IcmpCreateFile Handle>
        "33DB" & _                                                                          ;xor ebx, ebx
        "EB68" & _                                                                          ;jmp 0040108B   <While>
        "53" & _                                                                            ;push ebx
        "C605" & SwapEndian($RemoteCode + 480) & Hex($ttl,2) & _                            ;mov byte ptr [004031AE], xx    <TTL>
        "C605" & SwapEndian($RemoteCode + 481) & "00" & _                                   ;mov byte ptr [004031AF], 00    <TOS>
        "C605" & SwapEndian($RemoteCode + 482) & Hex($flags,2) & _                          ;mov byte ptr [004031B0], xx    <Flags, 0x02=DF Bit Set>
        "C605" & SwapEndian($RemoteCode + 483) & "00" & _                                   ;mov byte ptr [004031B1], 00
        "C705" & SwapEndian($RemoteCode + 484) & "00000000" & _                             ;mov dword ptr [004031B2], 00000000
        "68" & SwapEndian(Dec(Hex($timeout,4))) & _                                         ;push 0000xxxx  <Timeout>
        "681E010000" & _                                                                    ;push 0000011E  <Size of Echo reply Struct + ICMP_OPTIONS Struct>
        "68" & SwapEndian($RemoteCode + 488) & _                                            ;push 004031BA  <icmpReply>
        "68" & SwapEndian($RemoteCode + 480) & _                                            ;push 004031B2  <icmpOptions>
        "6A" & Hex(StringLen($data),2) & _                                                  ;push 000000xx  <Data Size>
        "68" & SwapEndian($RemoteCode + 216) & _                                            ;push 00403000  <Data>
        "68" & SwapEndian(Dec($hexIP)) & _                                                  ;push <Hex(IP ADDRESS)>
        "FF35" & SwapEndian($RemoteCode + 472) & _                                          ;push dword ptr [00403010]  <hIcmp>
        "E850000000" & _                                                                    ;Call 004010D2  <IcmpSendEcho>
        "A1" & SwapEndian($RemoteCode + 496) & _                                            ;mov eax, dword ptr [004031C2]  <Get the ms responce time from icmpReply.RoundTripTime>
        "A3" & SwapEndian(DllStructGetPtr($pings[$pingID],"reply")) & _                     ;mov dword ptr [0040301C], eax  <Store the ms responce time>
        "A1" & SwapEndian($RemoteCode + 492) & _                                            ;mov eax, dword ptr [004031BE]  <Get the status from icmpReply.Status>
        "A3" & SwapEndian(DllStructGetPtr($pings[$pingID],"status")) & _                    ;mov dword ptr [00403020], eax  <Store the status>
        "5B" & _                                                                            ;pop ebx
        "43" & _                                                                            ;inc ebx
        "83FB" & Hex($numpings,2) & _                                                       ;cmp ebx, 000000xx  <Default will send 2 x Pings, often the first ping will fail. Results taken from 2nd>
        "7293" & _                                                                          ;jb 0040102D    <Wend>
        "FF35" & SwapEndian($RemoteCode + 472) & _                                          ;push dword ptr [00403010]  <hIcmp>
        "E81E000000" & _                                                                    ;Call 004010C6  <IcmpCloseHandle>
        "E80D000000" & _                                                                    ;Call 004010BA  <WSACleanup>
        "6A00" & _                                                                          ;push 00000000
        "E800000000" & _                                                                    ;Call 004010B4  <ExitThread>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"ExitThread")) & _                   ;JMP dword ptr  <kernel32.ExitThread>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"WSACleanup")) & _                   ;JMP dword ptr  <ws2_32.WSACleanup>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"WSAStartup")) & _                   ;JMP dword ptr  <ws2_32.WSAStartup>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpCloseHandle")) & _              ;JMP dword ptr  <ICMP.IcmpCloseHandle>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpCreateFile")) & _               ;JMP dword ptr  <ICMP.IcmpCreateFile>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpSendEcho"))& _                  ;JMP dword ptr  <ICMP.IcmpSendEcho>
        SwapEndian(StringToBinary($data)) _                                                 ;This is our ping Data, Max 255 bytes of space here.
    )
    _MemMoveMemory(DllStructGetPtr($CodeBuffer), $RemoteCode, DllStructGetSize($CodeBuffer))
    Local $aCall = DllCall("kernel32.dll", "ptr", "CreateThread", "ptr", 0, "int", 0, "ptr", $RemoteCode, "ptr", 0, "int", 0, "dword*", 0)
    Return $aCall[0]
EndFunc


;Function _addPing is just for array management of the $pings[] array.
Func _addPing()
    $pings[0] = UBound($pings)
    ReDim $pings[$pings[0]+1]
    $pings[$pings[0]] = DllStructCreate("char ip[15];ulong reply;ulong status;int datasize")
    Return $pings[0]
EndFunc

;Function _removePing is just for array management of the $pings[] array.
Func _removePing($pingID)
    If $pingID > $pings[0] Then Return ;Ensure our ID is valid
    $pings[$pingID] = 0 ;Free the DLLStruct
    _ArrayDelete($pings,$pingID)
    $pings[0] -= 1
EndFunc

;Function _managePings()
;This is where the reply's get sorted out, and actions taken
Func _managePings()
    Local $pingID, $status
    $pingID = 1
    While $pingID <= $pings[0]
        $status = DllStructGetData($pings[$pingID],"status")
        If $status <> $NO_STATUS Then
            Switch $status
                Case 0
                    If DllStructGetData($pings[$pingID],"reply") = 0 Then
                        ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " replied in <1ms" & @CRLF)
                    Else
                        ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " replied in " & DllStructGetData($pings[$pingID],"reply") & "ms" & @CRLF)
                    EndIf
                Case 9999
                        ConsoleWrite("Could not initiate WSAStartup. Cannot Ping." & @CRLF)
                Case $IP_REQ_TIMED_OUT
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " timed-out" & @CRLF)
                Case $IP_DEST_NET_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination network was unreachable." & @CRLF)
                Case $IP_DEST_HOST_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination host was unreachable." & @CRLF)
                Case $IP_DEST_PROT_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination protocol was unreachable." & @CRLF)
                Case $IP_DEST_PORT_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination port was unreachable." & @CRLF)
                Case $IP_NO_RESOURCES
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " Insufficient IP resources were available." & @CRLF)
                Case $IP_HW_ERROR
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A hardware error occurred." & @CRLF)
                Case $IP_PACKET_TOO_BIG
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The packet was too big." & @CRLF)
                Case $IP_BAD_REQ
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad request." & @CRLF)
                Case $IP_BAD_ROUTE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad route." & @CRLF)
                Case $IP_TTL_EXPIRED_TRANSIT
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The time to live (TTL) expired in transit." & @CRLF) 
                Case $IP_TTL_EXPIRED_REASSEM
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The time to live expired during fragment reassembly." & @CRLF)
                Case $IP_PARAM_PROBLEM
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A parameter problem." & @CRLF)
                Case $IP_SOURCE_QUENCH
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " Datagrams are arriving too fast to be processed and datagrams may have been discarded." & @CRLF)
                Case $IP_BAD_DESTINATION
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad destination." & @CRLF)
                Case $IP_GENERAL_FAILURE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A general failure. This error can be returned for some malformed ICMP packets or lost network connection." & @CRLF)
            EndSwitch
            _removePing($pingID)
        EndIf
        $pingID += 1
    WEnd
EndFunc

Func encodeIP($ip_addr)
    Local $ip_addr_temp = $ip_addr
    If Not _isIP($ip_addr) Then $ip_addr = TCPNameToIP($ip_addr)
    If Not _isIP($ip_addr) Then
        ConsoleWrite($ip_addr_temp & " is not a valid IP Address. If you supplied a hostname ensure DNS is available." & @CRLF)
        Return 0
    EndIf
    Return getHexIP($ip_addr)
EndFunc

Func getHexIP($ip_addr)
    Return Hex(_getIPOctet($ip_addr,4),2) & Hex(_getIPOctet($ip_addr,3),2) & Hex(_getIPOctet($ip_addr,2),2) & Hex(_getIPOctet($ip_addr,1),2)
EndFunc

Func LibLoad($lpLibFileName)
    Local $hKrnl = DllOpen("kernel32.dll")
    Local $LibHandle = DllCall($hKrnl, "int", "LoadLibraryA", "str", $lpLibFileName)
    DllClose($hKrnl)
    Return $LibHandle[0]
EndFunc

Func LibFree($DllHandle)
    Local $hKrnl = DllOpen("kernel32.dll")
    Local $LibFreed = DllCall($hKrnl, "int", "FreeLibrary", "int", $DllHandle)
    return $LibFreed[0]
EndFunc

Func GetProcAddress( $hModule, $lpProcName)
    Local $hKrnl = DllOpen("kernel32.dll")
    Local $ProcessAddy = DllCall($hKrnl,"int","GetProcAddress","int",$hModule,"str",$lpProcName)
    DllClose($hKrnl)
    Return $ProcessAddy[0]
EndFunc

Func SwapEndian($hex)
    ;trancexx
    Return Hex(Binary($hex))
EndFunc

Func _getIPOctet($ip_addr,$octet=1)
    Switch $octet
        Case 1
            Return Int(StringMid($ip_addr,1,StringInStr($ip_addr,".")))
        Case 4
            Return Int(StringMid($ip_addr,StringInStr($ip_addr,".",0,3)+1))
        Case Else
            Return Int(StringMid($ip_addr,StringInStr($ip_addr,".",0,$octet - 1)+1,StringInStr($ip_addr,".",0,$octet)+1))
    EndSwitch
EndFunc

Func _isIP($text)
    Return StringRegExp($text, "(((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9]?[0-9]))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9]?[0-9]))")
EndFunc

Func _Exit()
    TCPShutdown()
    Exit
EndFunc
Edited by Fr0zT

[size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size]

Link to comment
Share on other sites

  • 1 month later...

I have discovered a glitch in my former code and corrected it here. I no longer allow you to choose the number of pings because this would crash if we had already got the first response, and destroyed the ping struct then received a second response which would try to write to that memory space now containing something new... Anyway, if you want to repeat-ping, just call the function more than once.

Also I have shrunk the code quite a bit by removing WSAStartup() from the assembly. This was redundant because this script already calls TCPStartup() which includes WSAStartup() and our threaded ping runs in the virtual address space of this script so you don't need it.

Here is the new and improved code:

#include <Memory.au3>
#include <Array.au3>

Opt('MustDeclareVars', 1)
HotKeySet("{ESC}", "_Exit")
Global Const $DONT_FRAGMENT = 2, $IP_SUCCESS = 0, $IP_DEST_NET_UNREACHABLE = 11002, $IP_DEST_HOST_UNREACHABLE = 11003, $IP_DEST_PROT_UNREACHABLE = 11004, $IP_DEST_PORT_UNREACHABLE = 11005, _
    $IP_NO_RESOURCES = 11006, $IP_HW_ERROR = 11008, $IP_PACKET_TOO_BIG = 11009, $IP_REQ_TIMED_OUT = 11010, $IP_BAD_REQ = 11011, $IP_BAD_ROUTE = 11012, _
    $IP_TTL_EXPIRED_TRANSIT = 11013, $IP_TTL_EXPIRED_REASSEM = 11014, $IP_PARAM_PROBLEM = 11015, $IP_SOURCE_QUENCH = 11016, $IP_BAD_DESTINATION =11018, _
    $IP_GENERAL_FAILURE = 11050, $NO_STATUS = 10000     ;We will use 10000 as the no status indicator since 0 meens successful reply

Local $hPointers = DllStructCreate("ptr IcmpCloseHandle;ptr IcmpSendEcho;ptr IcmpCreateFile;ptr ExitThread")

Global $hkernel32Dll = DllOpen("kernel32.dll")
Global $hKrn = _WinAPI_GetModuleHandle("kernel32.dll")
DllStructSetData($hPointers,"ExitThread",GetProcAddress($hKrn, "ExitThread"))
Global $hICMPDll = LibLoad("ICMP.dll");Iphlpapi.dll")
DllStructSetData($hPointers,"IcmpCloseHandle",GetProcAddress($hICMPDll, "IcmpCloseHandle"))
DllStructSetData($hPointers,"IcmpSendEcho",GetProcAddress($hICMPDll, "IcmpSendEcho"))
DllStructSetData($hPointers,"IcmpCreateFile",GetProcAddress($hICMPDll, "IcmpCreateFile"))

TCPStartup() ;This is required, not only to do DNS lookup, but also for WSAStartup()

Global $pings[1]  = [0]  ;This array will hold all echo reply data in a struct.
ConsoleWrite("Press esc any time to stop" & @CRLF)
pingThreaded("www.google.ca")
pingThreaded("www.asus.com.tw")
Local $pingdata = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Local $timeout = 150
Local $ttl = 255
pingThreaded("www.autoitscript.com", $timeout, $pingdata, $ttl, $DONT_FRAGMENT)

While 1
    _managePings()
WEnd

;Function pingThreaded
;$ip_addr will accept valid DNS Name or Normal IP address.
;Timouts only really work when an IP isn't responding. Thats important to remember because if you think you can timeout an IP which has latent responces, you can't!
Func pingThreaded($ip_addr, $timeout=5000, $data="x", $ttl=255, $flags=0)
    Local $hexIP = encodeIP($ip_addr)
    If $hexIP == 0 Then Return 0
    Local $pingID = _addPing($ip_addr)
    If IsNumber($ttl) = 0 Or Number($ttl) > 255 Then $ttl = 255
    If IsNumber($timeout) = 0 Or Number($timeout) > 5000 Then $timeout = 5000
    If StringLen($data) > 256 Then $data = StringTrimRight($data,StringLen($data) - 256)
    If IsNumber($flags) = 0 Or Number($flags) > 2 Then $flags = 2
    DllStructSetData($pings[$pingID],"datasize",StringLen($data))   ;We may wish to report the data size later
    ;Props to trancexx
    Local $CodeBuffer = DllStructCreate("byte[696]"); Code=154, Data=256, Echo reply Struct + ICMP_OPTIONS Struct = 286
    Local $RemoteCode = _MemVirtualAlloc(0, DllStructGetSize($CodeBuffer), $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
    DllStructSetData($CodeBuffer, 1, _
        "0x" & _                                                            ;Original Assembly started at 401000
        "E889000000" & _                                                ;Call 0040108E  <IcmpCreateFile>
        "A3" & SwapEndian($RemoteCode + 410) & _                            ;mov dword ptr [00403010], eax  <hIcmp = IcmpCreateFile Handle>
        "C605" & SwapEndian($RemoteCode + 418) & Hex($ttl,2) & _            ;mov byte ptr [00403024], xx    <TTL>
        "C605" & SwapEndian($RemoteCode + 419) & "00" & _                                   ;mov byte ptr [00403025], 00    <TOS>
        "C605" & SwapEndian($RemoteCode + 420) & Hex($flags,2) & _          ;mov byte ptr [00403026], 02    <Flags, 0x02=DF Bit Set>
        "C605" & SwapEndian($RemoteCode + 421) & "00" & _                   ;mov byte ptr [00403027], 00
        "C705" & SwapEndian($RemoteCode + 422) & "00000000" & _         ;mov dword ptr [00403028], 00000000
        "68" & SwapEndian(Dec(Hex($timeout,4))) & _                                 ;push 0000xxxx  <Timeout>
        "681E010000" & _                                                ;push 0000011E  <Size of Echo reply Struct + ICMP_OPTIONS Struct>
        "68" & SwapEndian($RemoteCode + 426) & _                            ;push 0040302C  <icmpReply>
        "68" & SwapEndian($RemoteCode + 418) & _                            ;push 00403024  <icmpOptions>
        "6A" & Hex(StringLen($data),2) & _                                  ;push 000000xx  <Data Size>
        "68" & SwapEndian($RemoteCode + 154) & _                            ;push 00403000  <Data>
        "68" & SwapEndian(Dec($hexIP)) & _                              ;push <Hex(IP ADDRESS)>
        "FF35" & SwapEndian($RemoteCode + 410) & _                      ;push dword ptr [00403010]  <hIcmp>
        "E839000000" & _                                                ;Call 00401094  <IcmpSendEcho>
        "A1" & SwapEndian($RemoteCode + 434) & _                            ;mov eax, dword ptr [00403034]  <Get the ms responce time from icmpReply.RoundTripTime>
        "A3" & SwapEndian(DllStructGetPtr($pings[$pingID],"reply")) & _         ;mov dword ptr [0040301C], eax  <Store the ms responce time>
        "A1" & SwapEndian($RemoteCode + 430) & _                            ;mov eax, dword ptr [00403030]  <Get the status from icmpReply.Status>
        "A3" & SwapEndian(DllStructGetPtr($pings[$pingID],"status")) & _        ;mov dword ptr [00403020], eax  <Store the status>
        "FF35" & SwapEndian($RemoteCode + 410) & _                      ;push dword ptr [00403010]  <hIcmp>
        "E80E000000" & _                                                ;Call 00401088  <IcmpCloseHandle>
        "6A00" & _                                                      ;push 00000000
        "E801000000" & _                                                ;Call 00401082  <ExitThread>
        "CC" & _                                                            ;int 03
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"ExitThread")) & _       ;JMP dword ptr  <kernel32.ExitThread>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpCloseHandle")) & _  ;JMP dword ptr  <ICMP.IcmpCloseHandle>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpCreateFile")) & _   ;JMP dword ptr  <ICMP.IcmpCreateFile>
        "FF25" & SwapEndian(DllStructGetPtr($hPointers,"IcmpSendEcho"))& _  ;JMP dword ptr  <ICMP.IcmpSendEcho>
        SwapEndian(StringToBinary($data)) _                             ;This is our ping Data, Max 256 bytes of space here.
    )
    _MemMoveMemory(DllStructGetPtr($CodeBuffer), $RemoteCode, DllStructGetSize($CodeBuffer))
    Local $aCall = DllCall($hkernel32Dll, "ptr", "CreateThread", "ptr", 0, "int", 0, "ptr", $RemoteCode, "ptr", 0, "int", 0, "dword*", 0)
    Return $aCall[0]
EndFunc


;Function _addPing is just for array management of the $pings[] array.
Func _addPing($ip_addr)
    $pings[0] = UBound($pings)
    ReDim $pings[$pings[0]+1]
    $pings[$pings[0]] = DllStructCreate("char ip[" & StringLen($ip_addr) & "];ulong reply;ulong status;int datasize");You could add a timeout struct here
    DllStructSetData($pings[$pings[0]],"ip",$ip_addr)
    DllStructSetData($pings[$pings[0]],"status",$NO_STATUS)
    Return $pings[0]
EndFunc

;Function _removePing is just for array management of the $pings[] array.
Func _removePing($pingID)
    If $pingID > $pings[0] Then Return ;Ensure our ID is valid
    $pings[$pingID] = 0 ;Free the DLLStruct
    _ArrayDelete($pings,$pingID)
    $pings[0] -= 1
EndFunc

;Function _managePings()
;This is where the reply's get sorted out, and actions taken
Func _managePings()
    Local $pingID, $status
    $pingID = 1
    While $pingID <= $pings[0]
        $status = DllStructGetData($pings[$pingID],"status")
        If $status <> $NO_STATUS Then
            Switch $status
                Case $IP_SUCCESS
                    If DllStructGetData($pings[$pingID],"reply") = 0 Then
                        ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " replied in <1ms" & @CRLF)
                    Else
                        ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " replied in " & DllStructGetData($pings[$pingID],"reply") & "ms" & @CRLF)
                    EndIf
                Case $IP_REQ_TIMED_OUT
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " timed-out" & @CRLF)
                Case $IP_DEST_NET_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination network was unreachable." & @CRLF)
                Case $IP_DEST_HOST_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination host was unreachable." & @CRLF)
                Case $IP_DEST_PROT_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination protocol was unreachable." & @CRLF)
                Case $IP_DEST_PORT_UNREACHABLE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The destination port was unreachable." & @CRLF)
                Case $IP_NO_RESOURCES
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " Insufficient IP resources were available." & @CRLF)
                Case $IP_HW_ERROR
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A hardware error occurred." & @CRLF)
                Case $IP_PACKET_TOO_BIG
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The packet was too big." & @CRLF)
                Case $IP_BAD_REQ
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad request." & @CRLF)
                Case $IP_BAD_ROUTE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad route." & @CRLF)
                Case $IP_TTL_EXPIRED_TRANSIT
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The time to live (TTL) expired in transit." & @CRLF) 
                Case $IP_TTL_EXPIRED_REASSEM
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " The time to live expired during fragment reassembly." & @CRLF)
                Case $IP_PARAM_PROBLEM
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A parameter problem." & @CRLF)
                Case $IP_SOURCE_QUENCH
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " Datagrams are arriving too fast to be processed and datagrams may have been discarded." & @CRLF)
                Case $IP_BAD_DESTINATION
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A bad destination." & @CRLF)
                Case $IP_GENERAL_FAILURE
                    ConsoleWrite("Ping with " & DllStructGetData($pings[$pingID],"datasize") & " byte(s) to " & DllStructGetData($pings[$pingID],"ip") & " A general failure. This error can be returned for some malformed ICMP packets or lost network connection." & @CRLF)
            EndSwitch
            _removePing($pingID)
    EndIf
;   You may wish to include a feature which can timeout manually here. Just remember if you do that, do not destroy the dllstruct for the ping 
;   because likelly the ping thread will still write to it when it's done.  You will have to wait for that to happen before you destroy it.
        $pingID += 1
    WEnd
EndFunc

Func encodeIP($ip_addr)
    Local $ip_addr_temp = $ip_addr
    If Not _isIP($ip_addr) Then $ip_addr = TCPNameToIP($ip_addr)
        If Not _isIP($ip_addr) Then
        ConsoleWrite($ip_addr_temp & " is not a valid IP Address. If you supplied a hostname ensure DNS is available." & @CRLF)
        Return 0
    EndIf
    Return getHexIP($ip_addr)
EndFunc

Func getHexIP($ip_addr)
    Return Hex(_getIPOctet($ip_addr,4),2) & Hex(_getIPOctet($ip_addr,3),2) & Hex(_getIPOctet($ip_addr,2),2) & Hex(_getIPOctet($ip_addr,1),2)
EndFunc

Func LibLoad($lpLibFileName)
    Local $LibHandle = DllCall($hkernel32Dll, "int", "LoadLibraryA", "str", $lpLibFileName)
    Return $LibHandle[0]
EndFunc

Func LibFree($DllHandle)
    Local $LibFreed = DllCall($hkernel32Dll, "int", "FreeLibrary", "int", $DllHandle)
    return $LibFreed[0]
EndFunc

Func GetProcAddress( $hModule, $lpProcName)
    Local $ProcessAddy = DllCall($hkernel32Dll,"int","GetProcAddress","int",$hModule,"str",$lpProcName)
    Return $ProcessAddy[0]
EndFunc

Func SwapEndian($hex)
    ;trancexx
    Return Hex(Binary($hex))
EndFunc

Func _getIPOctet($ip_addr,$octet=1)
    Switch $octet
        Case 1
        Return Int(StringMid($ip_addr,1,StringInStr($ip_addr,".")))
    Case 4
        Return Int(StringMid($ip_addr,StringInStr($ip_addr,".",0,3)+1))
    Case Else
        Return Int(StringMid($ip_addr,StringInStr($ip_addr,".",0,$octet - 1)+1,StringInStr($ip_addr,".",0,$octet)+1))
    EndSwitch
EndFunc

Func _isIP($text)
    Return StringRegExp($text, "(((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9]?[0-9]))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9]?[0-9]))")
EndFunc

Func _Exit()
    TCPShutdown()
    LibFree($hICMPDll)
    DllClose($hkernel32Dll)
    Exit
EndFunc
Edited by Fr0zT

[size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size]

Link to comment
Share on other sites

  • 2 weeks later...

This might be just what I am after for a project at work. Thankyou very much

My Scripts[topic="73325"]_ReverseDNS()[/topic]Favourite scripts by other members[topic="81687"]SNMP udf[/topic][topic="70759"]Using SNMP - MIB protocol[/topic][topic="39050"]_SplitMon:Section off your monitor!, split your monitor into sections for easy management[/topic][topic="73425"]ZIP.au3 UDF in pure AutoIt[/topic][topic="10534"]WMI ScriptOMatic tool for AutoIt[/topic][topic="51103"]Resources UDF embed/use any data/files into/from AutoIt compiled EXE files[/topic]
Link to comment
Share on other sites

  • 2 years later...

Hello,

How many Pings can be stacked with the pingThreaded() function?

I try to stack 512 IP address with 512 consecutive calls to pingThreaded() from 10.61.0.1 to 10.61.1.254

but with more than 500 pings the routine _managePings() seems to not respond anymore.

if i call 500 consecutive adress the results are fast and without problem.

is there a limit of ip address be passed to the pingThreaded() function?

Thanks for replays.

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

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...