Fr0zT Posted December 4, 2009 Share Posted December 4, 2009 (edited) 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???expandcollapse popup#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 EndFuncAt this point I'm just watching my firewall logs to see if anything is going out.Thanks in advance for any help,FrozTReferences:MSDN Ping Class Edited December 4, 2009 by Fr0zT Gianni 1 [size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size] Link to comment Share on other sites More sharing options...
jvanegmond Posted December 4, 2009 Share Posted December 4, 2009 Hi, I've built a wrapper around the internal Windows ping command. Containing one thread in one process is always much easier, especially when the language provides no native multi threading support. Find it here: http://www.autoitscript.com/forum/index.php?showtopic=104334&view=findpost&p=740697 Greetings. github.com/jvanegmond Link to comment Share on other sites More sharing options...
funkey Posted December 4, 2009 Share Posted December 4, 2009 You can easy ping with _Timer_SetTimer! Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning. Link to comment Share on other sites More sharing options...
jvanegmond Posted December 4, 2009 Share Posted December 4, 2009 You can easy ping with _Timer_SetTimer!Then the timer will be async, not ping. github.com/jvanegmond Link to comment Share on other sites More sharing options...
Fr0zT Posted December 4, 2009 Author Share Posted December 4, 2009 (edited) @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 December 4, 2009 by Fr0zT [size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size] Link to comment Share on other sites More sharing options...
Authenticity Posted December 4, 2009 Share Posted December 4, 2009 (edited) trancexx did a similar thing available here. The other thread uses InternetCheckConnection on two different addresses to report internet connectivity. You may be able to tweak for you purposes. Edited December 4, 2009 by Authenticity Link to comment Share on other sites More sharing options...
Fr0zT Posted December 13, 2009 Author Share Posted December 13, 2009 (edited) 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. expandcollapse popup#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 December 13, 2009 by Fr0zT [size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size] Link to comment Share on other sites More sharing options...
spudw2k Posted December 14, 2009 Share Posted December 14, 2009 Any reason you use _IsPressed to detect Esc(?) instead of using a hotkey? Spoiler Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retrieve SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc Cool Stuff: AutoItObject UDF ◊ Extract Icon From Proc ◊ GuiCtrlFontRotate ◊ Hex Edit Funcs ◊ Run binary ◊ Service_UDF Link to comment Share on other sites More sharing options...
Fr0zT Posted December 14, 2009 Author Share Posted December 14, 2009 (edited) 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) expandcollapse popup#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 January 19, 2010 by Fr0zT [size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size] Link to comment Share on other sites More sharing options...
spudw2k Posted December 14, 2009 Share Posted December 14, 2009 My brain was just at capacity getting the assembly working.Understood. Well done btw. Spoiler Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retrieve SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc Cool Stuff: AutoItObject UDF ◊ Extract Icon From Proc ◊ GuiCtrlFontRotate ◊ Hex Edit Funcs ◊ Run binary ◊ Service_UDF Link to comment Share on other sites More sharing options...
jvanegmond Posted December 14, 2009 Share Posted December 14, 2009 Just saw your message in the other thread. Fantastic work! Now would be a great time to wrap this all up nicely in a UDF. github.com/jvanegmond Link to comment Share on other sites More sharing options...
Fr0zT Posted January 26, 2010 Author Share Posted January 26, 2010 (edited) 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: expandcollapse popup#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 January 26, 2010 by Fr0zT Gianni 1 [size="1"][font="Lucida Console"]My ScriptsTrue multi-threaded ping[/font][/size] Link to comment Share on other sites More sharing options...
rogdog Posted February 8, 2010 Share Posted February 8, 2010 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 More sharing options...
Gianni Posted July 20, 2012 Share Posted July 20, 2012 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. Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now