├── BACnet-discover-enumerate.nse ├── LICENSE ├── README.md ├── atg-info.nse ├── codesys-v2-discover.nse ├── cspv4-info.nse ├── dnp3-info.nse ├── enip-enumerate.nse ├── fox-info.nse ├── modicon-info.nse ├── omrontcp-info.nse ├── omronudp-info.nse ├── pcworx-info.nse ├── proconos-info.nse └── s7-enumerate.nse /BACnet-discover-enumerate.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | local unicode = require "unicode" 8 | local ipOps = require "ipOps" 9 | 10 | description = [[ 11 | Discovers and enumerates BACNet Devices collects device information based off 12 | standard requests. In some cases, devices may not strictly follow the 13 | specifications, or may comply with older versions of the specifications, and 14 | will result in a BACNET error response. Presence of this error positively 15 | identifies the device as a BACNet device, but no enumeration is possible. 16 | 17 | This Nmap Script will also attempt to enumerate the BBMD (BACnet Broadcast 18 | Management Device). This allows a device on one network to communicate with a 19 | device on another network by using the BBMD to forward and route the messages. 20 | Also the NSE will attempt to pull the FDT (Foreign-Device-Table), as well as the 21 | (TTL) Time To Live, and time-out until the device willbe removed from the foreign 22 | device table. To utilize this feature, run with --script-args full=yes. 23 | 24 | This process was submitted via Jeff Meden via the original 25 | BACnet-discover-enumerate.nse script on github, it was determined to create a 26 | new script with the submitted methods. 27 | 28 | Note: Requests and responses are via UDP 47808, ensure scanner will receive UDP 29 | 47808 source and destination responses. 30 | 31 | http://digitalbond.com 32 | 33 | ]] 34 | 35 | --- 36 | -- @usage 37 | -- nmap --script BACnet-discover-enumerate.nse -sU -p 47808 38 | -- 39 | -- @args full If set yes the script will run the FDT and BBMD Checks 40 | -- 41 | -- @output 42 | --47808/udp open BACNet -- Building Automation and Control Networks 43 | --| BACnet-discover-enumerate.nse: 44 | --| Vendor ID: BACnet Stack at SourceForge (260) 45 | --| Instance Number: 260001 46 | --| Firmware: 0.8.2 47 | --| Application Software: 1.0 48 | --| Object Name: SimpleServer 49 | --| Model Name: GNU 50 | --| Description: server 51 | --| Location: USA 52 | --| BACnet Broadcast Management Device (BBMD): 53 | --| 192.168.0.100:47808 54 | --| Foreign Device Table (FDT): 55 | --|_ 192.168.1.101:47809:ttl=60:timeout=37 56 | 57 | -- 58 | -- @xmloutput 59 | --BACnet Stack at SourceForge (260) 60 | --260001 61 | --0.8.2 62 | --1.0 63 | --SimpleServer 64 | --GNU 65 | --server 66 | --USA 67 | --192.168.0.100:47808 68 | --192.168.1.101:47809:ttl=60:timeout=37 69 | 70 | author = "Stephen Hilt(Digital Bond)" 71 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 72 | categories = {"discovery", "intrusive"} 73 | 74 | -- 75 | -- Function to define the portrule as per nmap standards 76 | -- 77 | -- 78 | -- 79 | 80 | portrule = shortport.port_or_service(47808, "bacnet", "udp") 81 | 82 | --- 83 | -- Function to determine if a string starts with the parameter that is passed in 84 | -- 85 | -- First argument is the string to be evaluated, the second argument is 86 | -- the character(s) to be tested if the string starts with this argument. Uses Lua 87 | -- string.sub and string.len 88 | -- @param String String to be passed in. 89 | -- @param Start The char you want to test to see the string starts with. 90 | function string.starts(String,Start) 91 | return string.sub(String,1,string.len(Start))==Start 92 | end 93 | 94 | --- 95 | -- Table to look up the Vendor Name based on Vendor ID 96 | -- Table data from http://www.bacnet.org/VendorID/BACnet%20Vendor%20IDs.htm 97 | -- Fetched on 3/18/2014 98 | -- 99 | -- @key vennum Vendor number parsed out of the BACNet packet 100 | local vendor_id = { 101 | [0] = "ASHRAE", 102 | [1] = "NIST", 103 | [2] = "The Trane Company", 104 | [3] = "McQuay International", 105 | [4] = "PolarSoft", 106 | [5] = "Johnson Controls Inc.", 107 | [6] = "American Auto-Matrix", 108 | [7] = "Siemens Schweiz AG (Formerly: Landis & Staefa Division Europe)", 109 | [8] = "Delta Controls", 110 | [9] = "Siemens Schweiz AG", 111 | [10] = "Schneider Electric", 112 | [11] = "TAC", 113 | [12] = "Orion Analysis Corporation", 114 | [13] = "Teletrol Systems Inc.", 115 | [14] = "Cimetrics Technology", 116 | [15] = "Cornell University", 117 | [16] = "United Technologies Carrier", 118 | [17] = "Honeywell Inc.", 119 | [18] = "Alerton / Honeywell", 120 | [19] = "TAC AB", 121 | [20] = "Hewlett-Packard Company", 122 | [21] = "Dorsette.s Inc.", 123 | [22] = "Siemens Schweiz AG (Formerly: Cerberus AG)", 124 | [23] = "York Controls Group", 125 | [24] = "Automated Logic Corporation", 126 | [25] = "CSI Control Systems International", 127 | [26] = "Phoenix Controls Corporation", 128 | [27] = "Innovex Technologies Inc.", 129 | [28] = "KMC Controls Inc.", 130 | [29] = "Xn Technologies Inc.", 131 | [30] = "Hyundai Information Technology Co. Ltd.", 132 | [31] = "Tokimec Inc.", 133 | [32] = "Simplex", 134 | [33] = "North Building Technologies Limited", 135 | [34] = "Notifier", 136 | [35] = "Reliable Controls Corporation", 137 | [36] = "Tridium Inc.", 138 | [37] = "Sierra Monitor Corporation/FieldServer Technologies", 139 | [38] = "Silicon Energy", 140 | [39] = "Kieback & Peter GmbH & Co KG", 141 | [40] = "Anacon Systems Inc.", 142 | [41] = "Systems Controls & Instruments LLC", 143 | [42] = "Lithonia Lighting", 144 | [43] = "Micropower Manufacturing", 145 | [44] = "Matrix Controls", 146 | [45] = "METALAIRE", 147 | [46] = "ESS Engineering", 148 | [47] = "Sphere Systems Pty Ltd.", 149 | [48] = "Walker Technologies Corporation", 150 | [49] = "H I Solutions Inc.", 151 | [50] = "MBS GmbH", 152 | [51] = "SAMSON AG", 153 | [52] = "Badger Meter Inc.", 154 | [53] = "DAIKIN Industries Ltd.", 155 | [54] = "NARA Controls Inc.", 156 | [55] = "Mammoth Inc.", 157 | [56] = "Liebert Corporation", 158 | [57] = "SEMCO Incorporated", 159 | [58] = "Air Monitor Corporation", 160 | [59] = "TRIATEK LLC", 161 | [60] = "NexLight", 162 | [61] = "Multistack", 163 | [62] = "TSI Incorporated", 164 | [63] = "Weather-Rite Inc.", 165 | [64] = "Dunham-Bush", 166 | [65] = "Reliance Electric", 167 | [66] = "LCS Inc.", 168 | [67] = "Regulator Australia PTY Ltd.", 169 | [68] = "Touch-Plate Lighting Controls", 170 | [69] = "Amann GmbH", 171 | [70] = "RLE Technologies", 172 | [71] = "Cardkey Systems", 173 | [72] = "SECOM Co. Ltd.", 174 | [73] = "ABB Gebäetechnik AG Bereich NetServ", 175 | [74] = "KNX Association cvba", 176 | [75] = "Institute of Electrical Installation Engineers of Japan (IEIEJ)", 177 | [76] = "Nohmi Bosai Ltd.", 178 | [77] = "Carel S.p.A.", 179 | [78] = "AirSense Technology Inc.", 180 | [79] = "Hochiki Corporation", 181 | [80] = "Fr. Sauter AG", 182 | [81] = "Matsushita Electric Works Ltd.", 183 | [82] = "Mitsubishi Electric Corporation Inazawa Works", 184 | [83] = "Mitsubishi Heavy Industries Ltd.", 185 | [84] = "ITT Bell & Gossett", 186 | [85] = "Yamatake Building Systems Co. Ltd.", 187 | [86] = "The Watt Stopper Inc.", 188 | [87] = "Aichi Tokei Denki Co. Ltd.", 189 | [88] = "Activation Technologies LLC", 190 | [89] = "Saia-Burgess Controls Ltd.", 191 | [90] = "Hitachi Ltd.", 192 | [91] = "Novar Corp./Trend Control Systems Ltd.", 193 | [92] = "Mitsubishi Electric Lighting Corporation", 194 | [93] = "Argus Control Systems Ltd.", 195 | [94] = "Kyuki Corporation", 196 | [95] = "Richards-Zeta Building Intelligence Inc.", 197 | [96] = "Scientech R&D Inc.", 198 | [97] = "VCI Controls Inc.", 199 | [98] = "Toshiba Corporation", 200 | [99] = "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works", 201 | [100] = "Custom Mechanical Equipment LLC", 202 | [101] = "ClimateMaster", 203 | [102] = "ICP Panel-Tec Inc.", 204 | [103] = "D-Tek Controls", 205 | [104] = "NEC Engineering Ltd.", 206 | [105] = "PRIVA BV", 207 | [106] = "Meidensha Corporation", 208 | [107] = "JCI Systems Integration Services", 209 | [108] = "Freedom Corporation", 210 | [109] = "Neuberger Gebäeautomation GmbH", 211 | [110] = "Sitronix", 212 | [111] = "Leviton Manufacturing", 213 | [112] = "Fujitsu Limited", 214 | [113] = "Emerson Network Power", 215 | [114] = "S. A. Armstrong Ltd.", 216 | [115] = "Visonet AG", 217 | [116] = "M&M Systems Inc.", 218 | [117] = "Custom Software Engineering", 219 | [118] = "Nittan Company Limited", 220 | [119] = "Elutions Inc. (Wizcon Systems SAS)", 221 | [120] = "Pacom Systems Pty. Ltd.", 222 | [121] = "Unico Inc.", 223 | [122] = "Ebtron Inc.", 224 | [123] = "Scada Engine", 225 | [124] = "AC Technology Corporation", 226 | [125] = "Eagle Technology", 227 | [126] = "Data Aire Inc.", 228 | [127] = "ABB Inc.", 229 | [128] = "Transbit Sp. z o. o.", 230 | [129] = "Toshiba Carrier Corporation", 231 | [130] = "Shenzhen Junzhi Hi-Tech Co. Ltd.", 232 | [131] = "Tokai Soft", 233 | [132] = "Blue Ridge Technologies", 234 | [133] = "Veris Industries", 235 | [134] = "Centaurus Prime", 236 | [135] = "Sand Network Systems", 237 | [136] = "Regulvar Inc.", 238 | [137] = "AFDtek Division of Fastek International Inc.", 239 | [138] = "PowerCold Comfort Air Solutions Inc.", 240 | [139] = "I Controls", 241 | [140] = "Viconics Electronics Inc.", 242 | [141] = "Yaskawa America Inc.", 243 | [142] = "DEOS control systems GmbH", 244 | [143] = "Digitale Mess- und Steuersysteme AG", 245 | [144] = "Fujitsu General Limited", 246 | [145] = "Project Engineering S.r.l.", 247 | [146] = "Sanyo Electric Co. Ltd.", 248 | [147] = "Integrated Information Systems Inc.", 249 | [148] = "Temco Controls Ltd.", 250 | [149] = "Airtek International Inc.", 251 | [150] = "Advantech Corporation", 252 | [151] = "Titan Products Ltd.", 253 | [152] = "Regel Partners", 254 | [153] = "National Environmental Product", 255 | [154] = "Unitec Corporation", 256 | [155] = "Kanden Engineering Company", 257 | [156] = "Messner Gebäetechnik GmbH", 258 | [157] = "Integrated.CH", 259 | [158] = "Price Industries", 260 | [159] = "SE-Elektronic GmbH", 261 | [160] = "Rockwell Automation", 262 | [161] = "Enflex Corp.", 263 | [162] = "ASI Controls", 264 | [163] = "SysMik GmbH Dresden", 265 | [164] = "HSC Regelungstechnik GmbH", 266 | [165] = "Smart Temp Australia Pty. Ltd.", 267 | [166] = "Cooper Controls", 268 | [167] = "Duksan Mecasys Co. Ltd.", 269 | [168] = "Fuji IT Co. Ltd.", 270 | [169] = "Vacon Plc", 271 | [170] = "Leader Controls", 272 | [171] = "Cylon Controls Ltd.", 273 | [172] = "Compas", 274 | [173] = "Mitsubishi Electric Building Techno-Service Co. Ltd.", 275 | [174] = "Building Control Integrators", 276 | [175] = "ITG Worldwide (M) Sdn Bhd", 277 | [176] = "Lutron Electronics Co. Inc.", 278 | [178] = "LOYTEC Electronics GmbH", 279 | [179] = "ProLon", 280 | [180] = "Mega Controls Limited", 281 | [181] = "Micro Control Systems Inc.", 282 | [182] = "Kiyon Inc.", 283 | [183] = "Dust Networks", 284 | [184] = "Advanced Building Automation Systems", 285 | [185] = "Hermos AG", 286 | [186] = "CEZIM", 287 | [187] = "Softing", 288 | [188] = "Lynxspring", 289 | [189] = "Schneider Toshiba Inverter Europe", 290 | [190] = "Danfoss Drives A/S", 291 | [191] = "Eaton Corporation", 292 | [192] = "Matyca S.A.", 293 | [193] = "Botech AB", 294 | [194] = "Noveo Inc.", 295 | [195] = "AMEV", 296 | [196] = "Yokogawa Electric Corporation", 297 | [197] = "GFR Gesellschaft füelungstechnik", 298 | [198] = "Exact Logic", 299 | [199] = "Mass Electronics Pty Ltd dba Innotech Control Systems Australia", 300 | [200] = "Kandenko Co. Ltd.", 301 | [201] = "DTF Daten-Technik Fries", 302 | [202] = "Klimasoft Ltd.", 303 | [203] = "Toshiba Schneider Inverter Corporation", 304 | [204] = "Control Applications Ltd.", 305 | [205] = "KDT Systems Co. Ltd.", 306 | [206] = "Onicon Incorporated", 307 | [207] = "Automation Displays Inc.", 308 | [208] = "Control Solutions Inc.", 309 | [209] = "Remsdaq Limited", 310 | [210] = "NTT Facilities Inc.", 311 | [211] = "VIPA GmbH", 312 | [212] = "TSC21 Association of Japan", 313 | [213] = "Strato Automation", 314 | [214] = "HRW Limited", 315 | [215] = "Lighting Control & Design Inc.", 316 | [216] = "Mercy Electronic and Electrical Industries", 317 | [217] = "Samsung SDS Co.Ltd", 318 | [218] = "Impact Facility Solutions Inc.", 319 | [219] = "Aircuity", 320 | [220] = "Control Techniques Ltd.", 321 | [221] = "OpenGeneral Pty. Ltd.", 322 | [222] = "WAGO Kontakttechnik GmbH & Co. KG", 323 | [223] = "Cerus Industrial", 324 | [224] = "Chloride Power Protection Company", 325 | [225] = "Computrols Inc.", 326 | [226] = "Phoenix Contact GmbH & Co. KG", 327 | [227] = "Grundfos Management A/S", 328 | [228] = "Ridder Drive Systems", 329 | [229] = "Soft Device SDN BHD", 330 | [230] = "Integrated Control Technology Limited", 331 | [231] = "AIRxpert Systems Inc.", 332 | [232] = "Microtrol Limited", 333 | [233] = "Red Lion Controls", 334 | [234] = "Digital Electronics Corporation", 335 | [235] = "Ennovatis GmbH", 336 | [236] = "Serotonin Software Technologies Inc.", 337 | [237] = "LS Industrial Systems Co. Ltd.", 338 | [238] = "Square D Company", 339 | [239] = "S Squared Innovations Inc.", 340 | [240] = "Aricent Ltd.", 341 | [241] = "EtherMetrics LLC", 342 | [242] = "Industrial Control Communications Inc.", 343 | [243] = "Paragon Controls Inc.", 344 | [244] = "A. O. Smith Corporation", 345 | [245] = "Contemporary Control Systems Inc.", 346 | [246] = "Intesis Software SL", 347 | [247] = "Ingenieurgesellschaft N. Hartleb mbH", 348 | [248] = "Heat-Timer Corporation", 349 | [249] = "Ingrasys Technology Inc.", 350 | [250] = "Costerm Building Automation", 351 | [251] = "WILO SE", 352 | [252] = "Embedia Technologies Corp.", 353 | [253] = "Technilog", 354 | [254] = "HR Controls Ltd. & Co. KG", 355 | [255] = "Lennox International Inc.", 356 | [256] = "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG", 357 | [257] = "Thermomax Ltd.", 358 | [258] = "ELCON Electronic Control Ltd.", 359 | [259] = "Larmia Control AB", 360 | [260] = "BACnet Stack at SourceForge", 361 | [261] = "G4S Security Services A/S", 362 | [262] = "Exor International S.p.A.", 363 | [263] = "Cristal Controles", 364 | [264] = "Regin AB", 365 | [265] = "Dimension Software Inc.", 366 | [266] = "SynapSense Corporation", 367 | [267] = "Beijing Nantree Electronic Co. Ltd.", 368 | [268] = "Camus Hydronics Ltd.", 369 | [269] = "Kawasaki Heavy Industries Ltd.", 370 | [270] = "Critical Environment Technologies", 371 | [271] = "ILSHIN IBS Co. Ltd.", 372 | [272] = "ELESTA Energy Control AG", 373 | [273] = "KROPMAN Installatietechniek", 374 | [274] = "Baldor Electric Company", 375 | [275] = "INGA mbH", 376 | [276] = "GE Consumer & Industrial", 377 | [277] = "Functional Devices Inc.", 378 | [278] = "ESAC", 379 | [279] = "M-System Co. Ltd.", 380 | [280] = "Yokota Co. Ltd.", 381 | [281] = "Hitranse Technology Co.LTD", 382 | [282] = "Federspiel Controls", 383 | [283] = "Kele Inc.", 384 | [284] = "Opera Electronics Inc.", 385 | [285] = "Gentec", 386 | [286] = "Embedded Science Labs LLC", 387 | [287] = "Parker Hannifin Corporation", 388 | [288] = "MaCaPS International Limited", 389 | [289] = "Link4 Corporation", 390 | [290] = "Romutec Steuer-u. Regelsysteme GmbH", 391 | [291] = "Pribusin Inc.", 392 | [292] = "Advantage Controls", 393 | [293] = "Critical Room Control", 394 | [294] = "LEGRAND", 395 | [295] = "Tongdy Control Technology Co. Ltd.", 396 | [296] = "ISSARO Integrierte Systemtechnik", 397 | [297] = "Pro-Dev Industries", 398 | [298] = "DRI-STEEM", 399 | [299] = "Creative Electronic GmbH", 400 | [300] = "Swegon AB", 401 | [301] = "Jan Brachacek", 402 | [302] = "Hitachi Appliances Inc.", 403 | [303] = "Real Time Automation Inc.", 404 | [304] = "ITEC Hankyu-Hanshin Co.", 405 | [305] = "Cyrus E&M Engineering Co. Ltd.", 406 | [306] = "Racine Federated Inc.", 407 | [307] = "Cirrascale Corporation", 408 | [308] = "Elesta GmbH Building Automation", 409 | [309] = "Securiton", 410 | [310] = "OSlsoft Inc.", 411 | [311] = "Hanazeder Electronic GmbH", 412 | [312] = "Honeywell Security DeutschlandNovar GmbH", 413 | [313] = "Siemens Energy & Automation Inc.", 414 | [314] = "ETM Professional Control GmbH", 415 | [315] = "Meitav-tec Ltd.", 416 | [316] = "Janitza Electronics GmbH", 417 | [317] = "MKS Nordhausen", 418 | [318] = "De Gier Drive Systems B.V.", 419 | [319] = "Cypress Envirosystems", 420 | [320] = "SMARTron s.r.o.", 421 | [321] = "Verari Systems Inc.", 422 | [322] = "K-W Electronic Service Inc.", 423 | [323] = "ALFA-SMART Energy Management", 424 | [324] = "Telkonet Inc.", 425 | [325] = "Securiton GmbH", 426 | [326] = "Cemtrex Inc.", 427 | [327] = "Performance Technologies Inc.", 428 | [328] = "Xtralis (Aust) Pty Ltd", 429 | [329] = "TROX GmbH", 430 | [330] = "Beijing Hysine Technology Co.Ltd", 431 | [331] = "RCK Controls Inc.", 432 | [332] = "Distech Controls SAS", 433 | [333] = "Novar/Honeywell", 434 | [334] = "The S4 Group Inc.", 435 | [335] = "Schneider Electric", 436 | [336] = "LHA Systems", 437 | [337] = "GHM engineering Group Inc.", 438 | [338] = "Cllimalux S.A.", 439 | [339] = "VAISALA Oyj", 440 | [340] = "COMPLEX (Beijing) TechnologyCo. Ltd.", 441 | [341] = "SCADAmetrics", 442 | [342] = "POWERPEG NSI Limited", 443 | [343] = "BACnet Interoperability Testing Services Inc.", 444 | [344] = "Teco a.s.", 445 | [345] = "Plexus Technology Inc.", 446 | [346] = "Energy Focus Inc.", 447 | [347] = "Powersmiths International Corp.", 448 | [348] = "Nichibei Co. Ltd.", 449 | [349] = "HKC Technology Ltd.", 450 | [350] = "Ovation Networks Inc.", 451 | [351] = "Setra Systems", 452 | [352] = "AVG Automation", 453 | [353] = "ZXC Ltd.", 454 | [354] = "Byte Sphere", 455 | [355] = "Generiton Co. Ltd.", 456 | [356] = "Holter Regelarmaturen GmbH & Co. KG", 457 | [357] = "Bedford Instruments LLC", 458 | [358] = "Standair Inc.", 459 | [359] = "WEG Automation - R&D", 460 | [360] = "Prolon Control Systems ApS", 461 | [361] = "Inneasoft", 462 | [362] = "ConneXSoft GmbH", 463 | [363] = "CEAG Notlichtsysteme GmbH", 464 | [364] = "Distech Controls Inc.", 465 | [365] = "Industrial Technology Research Institute", 466 | [366] = "ICONICS Inc.", 467 | [367] = "IQ Controls s.c.", 468 | [368] = "OJ Electronics A/S", 469 | [369] = "Rolbit Ltd.", 470 | [370] = "Synapsys Solutions Ltd.", 471 | [371] = "ACME Engineering Prod. Ltd.", 472 | [372] = "Zener Electric Pty Ltd.", 473 | [373] = "Selectronix Inc.", 474 | [374] = "Gorbet & Banerjee LLC.", 475 | [375] = "IME", 476 | [376] = "Stephen H. Dawson Computer Service", 477 | [377] = "Accutrol LLC", 478 | [378] = "Schneider Elektronik GmbH", 479 | [379] = "Alpha-Inno Tec GmbH", 480 | [380] = "ADMMicro Inc.", 481 | [381] = "Greystone Energy Systems Inc.", 482 | [382] = "CAP Technologie", 483 | [383] = "KeRo Systems", 484 | [384] = "Domat Control System s.r.o.", 485 | [385] = "Efektronics Pty. Ltd.", 486 | [386] = "Hekatron Vertriebs GmbH", 487 | [387] = "Securiton AG", 488 | [388] = "Carlo Gavazzi Controls SpA", 489 | [389] = "Chipkin Automation Systems", 490 | [390] = "Savant Systems LLC", 491 | [391] = "Simmtronic Lighting Controls", 492 | [392] = "Abelko Innovation AB", 493 | [393] = "Seresco Technologies Inc.", 494 | [394] = "IT Watchdogs", 495 | [395] = "Automation Assist Japan Corp.", 496 | [396] = "Thermokon Sensortechnik GmbH", 497 | [397] = "EGauge Systems LLC", 498 | [398] = "Quantum Automation (ASIA) PTE Ltd.", 499 | [399] = "Toshiba Lighting & Technology Corp.", 500 | [400] = "SPIN Engenharia de Automaç Ltda.", 501 | [401] = "Logistics Systems & Software Services India PVT. Ltd.", 502 | [402] = "Delta Controls Integration Products", 503 | [403] = "Focus Media", 504 | [404] = "LUMEnergi Inc.", 505 | [405] = "Kara Systems", 506 | [406] = "RF Code Inc.", 507 | [407] = "Fatek Automation Corp.", 508 | [408] = "JANDA Software Company LLC", 509 | [409] = "Open System Solutions Limited", 510 | [410] = "Intelec Systems PTY Ltd.", 511 | [411] = "Ecolodgix LLC", 512 | [412] = "Douglas Lighting Controls", 513 | [413] = "iSAtech GmbH", 514 | [414] = "AREAL", 515 | [415] = "Beckhoff Automation GmbH", 516 | [416] = "IPAS GmbH", 517 | [417] = "KE2 Therm Solutions", 518 | [418] = "Base2Products", 519 | [419] = "DTL Controls LLC", 520 | [420] = "INNCOM International Inc.", 521 | [421] = "BTR Netcom GmbH", 522 | [422] = "Greentrol AutomationInc", 523 | [423] = "BELIMO Automation AG", 524 | [424] = "Samsung Heavy Industries CoLtd", 525 | [425] = "Triacta Power Technologies Inc.", 526 | [426] = "Globestar Systems", 527 | [427] = "MLB Advanced MediaLP", 528 | [428] = "SWG Stuckmann Wirtschaftliche Gebäesysteme GmbH", 529 | [429] = "SensorSwitch", 530 | [430] = "Multitek Power Limited", 531 | [431] = "Aquametro AG", 532 | [432] = "LG Electronics Inc.", 533 | [433] = "Electronic Theatre Controls Inc.", 534 | [434] = "Mitsubishi Electric Corporation Nagoya Works", 535 | [435] = "Delta Electronics Inc.", 536 | [436] = "Elma Kurtalj Ltd.", 537 | [437] = "ADT Fire and Security Sp. A.o.o.", 538 | [438] = "Nedap Security Management", 539 | [439] = "ESC Automation Inc.", 540 | [440] = "DSP4YOU Ltd.", 541 | [441] = "GE Sensing and Inspection Technologies", 542 | [442] = "Embedded Systems SIA", 543 | [443] = "BEFEGA GmbH", 544 | [444] = "Baseline Inc.", 545 | [445] = "M2M Systems Integrators", 546 | [446] = "OEMCtrl", 547 | [447] = "Clarkson Controls Limited", 548 | [448] = "Rogerwell Control System Limited", 549 | [449] = "SCL Elements", 550 | [450] = "Hitachi Ltd.", 551 | [451] = "Newron System SA", 552 | [452] = "BEVECO Gebouwautomatisering BV", 553 | [453] = "Streamside Solutions", 554 | [454] = "Yellowstone Soft", 555 | [455] = "Oztech Intelligent Systems Pty Ltd.", 556 | [456] = "Novelan GmbH", 557 | [457] = "Flexim Americas Corporation", 558 | [458] = "ICP DAS Co. Ltd.", 559 | [459] = "CARMA Industries Inc.", 560 | [460] = "Log-One Ltd.", 561 | [461] = "TECO Electric & Machinery Co. Ltd.", 562 | [462] = "ConnectEx Inc.", 563 | [463] = "Turbo DDC Sü", 564 | [464] = "Quatrosense Environmental Ltd.", 565 | [465] = "Fifth Light Technology Ltd.", 566 | [466] = "Scientific Solutions Ltd.", 567 | [467] = "Controller Area Network Solutions (M) Sdn Bhd", 568 | [468] = "RESOL - Elektronische Regelungen GmbH", 569 | [469] = "RPBUS LLC", 570 | [470] = "BRS Sistemas Eletronicos", 571 | [471] = "WindowMaster A/S", 572 | [472] = "Sunlux Technologies Ltd.", 573 | [473] = "Measurlogic", 574 | [474] = "Frimat GmbH", 575 | [475] = "Spirax Sarco", 576 | [476] = "Luxtron", 577 | [477] = "Raypak Inc", 578 | [478] = "Air Monitor Corporation", 579 | [479] = "Regler Och Webbteknik Sverige (ROWS)", 580 | [480] = "Intelligent Lighting Controls Inc.", 581 | [481] = "Sanyo Electric Industry Co.Ltd", 582 | [482] = "E-Mon Energy Monitoring Products", 583 | [483] = "Digital Control Systems", 584 | [484] = "ATI Airtest Technologies Inc.", 585 | [485] = "SCS SA", 586 | [486] = "HMS Industrial Networks AB", 587 | [487] = "Shenzhen Universal Intellisys Co Ltd", 588 | [488] = "EK Intellisys Sdn Bhd", 589 | [489] = "SysCom", 590 | [490] = "Firecom Inc.", 591 | [491] = "ESA Elektroschaltanlagen Grimma GmbH", 592 | [492] = "Kumahira Co Ltd", 593 | [493] = "Hotraco", 594 | [494] = "SABO Elektronik GmbH", 595 | [495] = "Equip'Trans", 596 | [496] = "TCS Basys Controls", 597 | [497] = "FlowCon International A/S", 598 | [498] = "ThyssenKrupp Elevator Americas", 599 | [499] = "Abatement Technologies", 600 | [500] = "Continental Control Systems LLC", 601 | [501] = "WISAG Automatisierungstechnik GmbH & Co KG", 602 | [502] = "EasyIO", 603 | [503] = "EAP-Electric GmbH", 604 | [504] = "Hardmeier", 605 | [505] = "Mircom Group of Companies", 606 | [506] = "Quest Controls", 607 | [507] = "MestekInc", 608 | [508] = "Pulse Energy", 609 | [509] = "Tachikawa Corporation", 610 | [510] = "University of Nebraska-Lincoln", 611 | [511] = "Redwood Systems", 612 | [512] = "PASStec Industrie-Elektronik GmbH", 613 | [513] = "NgEK Inc.", 614 | [514] = "FAW Electronics Ltd", 615 | [515] = "Jireh Energy Tech Co. Ltd.", 616 | [516] = "Enlighted Inc.", 617 | [517] = "El-Piast Sp. Z o.o", 618 | [518] = "NetxAutomation Software GmbH", 619 | [519] = "Invertek Drives", 620 | [520] = "Deutschmann Automation GmbH & Co. KG", 621 | [521] = "EMU Electronic AG", 622 | [522] = "Phaedrus Limited", 623 | [523] = "Sigmatek GmbH & Co KG", 624 | [524] = "Marlin Controls", 625 | [525] = "CircutorSA", 626 | [526] = "UTC Fire & Security", 627 | [527] = "DENT Instruments Inc.", 628 | [528] = "FHP Manufacturing Company - Bosch Group", 629 | [529] = "GE Intelligent Platforms", 630 | [530] = "Inner Range Pty Ltd", 631 | [531] = "GLAS Energy Technology", 632 | [532] = "MSR-Electronic-GmbH", 633 | [533] = "Energy Control Systems Inc.", 634 | [534] = "EMT Controls", 635 | [535] = "Daintree Networks Inc.", 636 | [536] = "EURO ICC d.o.o", 637 | [537] = "TE Connectivity Energy", 638 | [538] = "GEZE GmbH", 639 | [539] = "NEC Corporation", 640 | [540] = "Ho Cheung International Company Limited", 641 | [541] = "Sharp Manufacturing Systems Corporation", 642 | [542] = "DOT CONTROLS a.s.", 643 | [543] = "BeaconMedæ0220", 644 | [544] = "Midea Commercial Aircon", 645 | [545] = "WattMaster Controls", 646 | [546] = "Kamstrup A/S", 647 | [547] = "CA Computer Automation GmbH", 648 | [548] = "Laars Heating Systems Company", 649 | [549] = "Hitachi Systems Ltd.", 650 | [550] = "Fushan AKE Electronic Engineering Co. Ltd.", 651 | [551] = "Toshiba International Corporation", 652 | [552] = "Starman Systems LLC", 653 | [553] = "Samsung Techwin Co. Ltd.", 654 | [554] = "ISAS-Integrated Switchgear and Systems P/L", 655 | [556] = "Obvius", 656 | [557] = "Marek Guzik", 657 | [558] = "Vortek Instruments LLC", 658 | [559] = "Universal Lighting Technologies", 659 | [560] = "Myers Power Products Inc.", 660 | [561] = "Vector Controls GmbH", 661 | [562] = "Crestron Electronics Inc.", 662 | [563] = "A&E Controls Limited", 663 | [564] = "Projektomontaza A.D.", 664 | [565] = "Freeaire Refrigeration", 665 | [566] = "Aqua Cooler Pty Limited", 666 | [567] = "Basic Controls", 667 | [568] = "GE Measurement and Control Solutions Advanced Sensors", 668 | [569] = "EQUAL Networks", 669 | [570] = "Millennial Net", 670 | [571] = "APLI Ltd", 671 | [572] = "Electro Industries/GaugeTech", 672 | [573] = "SangMyung University", 673 | [574] = "Coppertree Analytics Inc.", 674 | [575] = "CoreNetiX GmbH", 675 | [576] = "Acutherm", 676 | [577] = "Dr. Riedel Automatisierungstechnik GmbH", 677 | [578] = "Shina System Co.Ltd", 678 | [579] = "Iqapertus", 679 | [580] = "PSE Technology", 680 | [581] = "BA Systems", 681 | [582] = "BTICINO", 682 | [583] = "Monico Inc.", 683 | [584] = "iCue", 684 | [585] = "tekmar Control Systems Ltd.", 685 | [586] = "Control Technology Corporation", 686 | [587] = "GFAE GmbH", 687 | [588] = "BeKa Software GmbH", 688 | [589] = "Isoil Industria SpA", 689 | [590] = "Home Systems Consulting SpA", 690 | [591] = "Socomec", 691 | [592] = "Everex Communications Inc.", 692 | [593] = "Ceiec Electric Technology", 693 | [594] = "Atrila GmbH", 694 | [595] = "WingTechs", 695 | [596] = "Shenzhen Mek Intellisys Pte Ltd.", 696 | [597] = "Nestfield Co. Ltd.", 697 | [598] = "Swissphone Telecom AG", 698 | [599] = "PNTECH JSC", 699 | [600] = "Horner APG LLC", 700 | [601] = "PVI Industries LLC", 701 | [602] = "Ela-compil", 702 | [603] = "Pegasus Automation International LLC", 703 | [604] = "Wight Electronic Services Ltd.", 704 | [605] = "Marcom", 705 | [606] = "Exhausto A/S", 706 | [607] = "Dwyer Instruments Inc.", 707 | [608] = "Link GmbH", 708 | [609] = "Oppermann Regelgerate GmbH", 709 | [610] = "NuAire Inc.", 710 | [611] = "Nortec Humidity Inc.", 711 | [612] = "Bigwood Systems Inc.", 712 | [613] = "Enbala Power Networks", 713 | [614] = "Inter Energy Co. Ltd.", 714 | [615] = "ETC", 715 | [616] = "COMELEC S.A.R.L", 716 | [617] = "Pythia Technologies", 717 | [618] = "TrendPoint Systems Inc.", 718 | [619] = "AWEX", 719 | [620] = "Eurevia", 720 | [621] = "Kongsberg E-lon AS", 721 | [622] = "FlaktWoods", 722 | [623] = "E + E Elektronik GES M.B.H.", 723 | [624] = "ARC Informatique", 724 | [625] = "SKIDATA AG", 725 | [626] = "WSW Solutions", 726 | [627] = "Trefon Electronic GmbH", 727 | [628] = "Dongseo System", 728 | [629] = "Kanontec Intelligence Technology Co. Ltd.", 729 | [630] = "EVCO S.p.A.", 730 | [631] = "Accuenergy (CANADA) Inc.", 731 | [632] = "SoftDEL", 732 | [633] = "Orion Energy Systems Inc.", 733 | [634] = "Roboticsware", 734 | [635] = "DOMIQ Sp. z o.o.", 735 | [636] = "Solidyne", 736 | [637] = "Elecsys Corporation", 737 | [638] = "Conditionaire International Pty. Limited", 738 | [639] = "Quebec Inc.", 739 | [640] = "Homerun Holdings", 740 | [641] = "RFM Inc.", 741 | [642] = "Comptek", 742 | [643] = "Westco Systems Inc.", 743 | [644] = "Advancis Software & Services GmbH", 744 | [645] = "Intergrid LLC", 745 | [646] = "Markerr Controls Inc.", 746 | [647] = "Toshiba Elevator and Building Systems Corporation", 747 | [648] = "Spectrum Controls Inc.", 748 | [649] = "Mkservice", 749 | [650] = "Fox Thermal Instruments", 750 | [651] = "SyxthSense Ltd", 751 | [652] = "DUHA System S R.O.", 752 | [653] = "NIBE", 753 | [654] = "Melink Corporation", 754 | [655] = "Fritz-Haber-Institut", 755 | [656] = "MTU Onsite Energy GmbHGas Power Systems", 756 | [657] = "Omega Engineering Inc.", 757 | [658] = "Avelon", 758 | [659] = "Ywire Technologies Inc.", 759 | [660] = "M.R. Engineering Co. Ltd.", 760 | [661] = "Lochinvar LLC", 761 | [662] = "Sontay Limited", 762 | [663] = "GRUPA Slawomir Chelminski", 763 | [664] = "Arch Meter Corporation", 764 | [665] = "Senva Inc.", 765 | [667] = "FM-Tec", 766 | [668] = "Systems Specialists Inc.", 767 | [669] = "SenseAir", 768 | [670] = "AB IndustrieTechnik Srl", 769 | [671] = "Cortland Research LLC", 770 | [672] = "MediaView", 771 | [673] = "VDA Elettronica", 772 | [674] = "CSS Inc.", 773 | [675] = "Tek-Air Systems Inc.", 774 | [676] = "ICDT", 775 | [677] = "The Armstrong Monitoring Corporation", 776 | [678] = "DIXELL S.r.l", 777 | [679] = "Lead System Inc.", 778 | [680] = "ISM EuroCenter S.A.", 779 | [681] = "TDIS", 780 | [682] = "Trade FIDES", 781 | [683] = "KnübH (Emerson Network Power)", 782 | [684] = "Resource Data Management", 783 | [685] = "Abies Technology Inc.", 784 | [686] = "Amalva", 785 | [687] = "MIRAE Electrical Mfg. Co. Ltd.", 786 | [688] = "HunterDouglas Architectural Projects Scandinavia ApS", 787 | [689] = "RUNPAQ Group Co.Ltd", 788 | [690] = "Unicard SA", 789 | [691] = "IE Technologies", 790 | [692] = "Ruskin Manufacturing", 791 | [693] = "Calon Associates Limited", 792 | [694] = "Contec Co. Ltd.", 793 | [695] = "iT GmbH", 794 | [696] = "Autani Corporation", 795 | [697] = "Christian Fortin", 796 | [698] = "HDL", 797 | [699] = "IPID Sp. Z.O.O Limited", 798 | [700] = "Fuji Electric Co.Ltd", 799 | [701] = "View Inc.", 800 | [702] = "Samsung S1 Corporation", 801 | [703] = "New Lift", 802 | [704] = "VRT Systems", 803 | [705] = "Motion Control Engineering Inc.", 804 | [706] = "Weiss Klimatechnik GmbH", 805 | [707] = "Elkon", 806 | [708] = "Eliwell Controls S.r.l.", 807 | [709] = "Japan Computer Technos Corp", 808 | [710] = "Rational Network ehf", 809 | [711] = "Magnum Energy Solutions LLC", 810 | [712] = "MelRok", 811 | [713] = "VAE Group", 812 | [714] = "LGCNS", 813 | [715] = "Berghof Automationstechnik GmbH", 814 | [716] = "Quark Communications Inc.", 815 | [717] = "Sontex", 816 | [718] = "mivune AG", 817 | [719] = "Panduit", 818 | [720] = "Smart Controls LLC", 819 | [721] = "Compu-Aire Inc.", 820 | [722] = "Sierra", 821 | [723] = "ProtoSense Technologies", 822 | [724] = "Eltrac Technologies Pvt Ltd", 823 | [725] = "Bektas Invisible Controls GmbH", 824 | [726] = "Entelec", 825 | [727] = "Innexiv", 826 | [728] = "Covenant" 827 | } 828 | --return vendor information 829 | function vendor_lookup(vennum) 830 | local vendorname = vendor_id[vennum] or "Unknown Vendor Number" 831 | return string.format("%s (%d)", vendorname, vennum) 832 | end 833 | 834 | --- 835 | -- Function to lookup the length of the Field to be used for Vendor ID, Firmware 836 | -- Object Name, Software Version, and Location. It will then return the Value 837 | -- that is stored inside the packet for this information as a String Value. 838 | -- The field is located in the 18th byte of the data field of a valid packet. 839 | -- Depending on this field the information will be stored in field 20 + length 840 | -- or in field 22 + length. 841 | -- 842 | -- @param packet The packet that was received and is ready to be parsed 843 | function field_size(packet) 844 | local info 845 | 846 | -- read the Length field from the packet data byte 18 847 | local offset 848 | -- Verify the field from byte 18 to determine if the vendor number is one byte or two bytes? 849 | local value = string.byte(packet, 18) 850 | if ( value % 0x10 < 5 ) then 851 | value = value % 0x10 - 1 852 | offset = 19 853 | else 854 | value = string.byte(packet, 19) - 1 855 | offset = 20 856 | end 857 | -- unpack a string of length 858 | offset, charset, info = bin.unpack("CA" .. tostring(value), packet, offset) 859 | -- return information that was found in the packet 860 | if charset == 0 then -- UTF-8 861 | return info 862 | elseif charset == 4 then -- UCS-2 big-endian 863 | return unicode.transcode(info, unicode.utf16_dec, unicode.utf8_enc, true, nil) 864 | else -- TODO: other encodings not supported by unicode.lua 865 | return info 866 | end 867 | end 868 | --- 869 | -- Function to set the nmap output for the host, if a valid BACNet packet 870 | -- is received then the output will show that the port is open instead of 871 | -- open|filtered 872 | -- 873 | -- @param host Host that was passed in via nmap 874 | -- @param port port that BACNet is running on (Default UDP/47808) 875 | function set_nmap(host, port) 876 | 877 | --set port Open 878 | port.state = "open" 879 | -- set version name to BACNet 880 | port.version.name = "BACNet -- Building Automation and Control Networks" 881 | nmap.set_port_version(host, port) 882 | nmap.set_port_state(host, port, "open") 883 | 884 | end 885 | 886 | --- 887 | -- Function to send a query to the discovered BACNet devices. This will pull extra 888 | -- information to help identify the device. Information such as firmware, application software 889 | -- object name, description, and location parameters configured inside of the device. 890 | -- 891 | -- @param socket The socket that was created in the action function 892 | -- @param type Type is the type of packet to send, this can be firmware, application, object, description, or location 893 | function standard_query(socket, type) 894 | 895 | 896 | -- set the query for vendor name 897 | local vendor_query = bin.pack("H","810a001101040005010c0c023FFFFF1979") 898 | -- set the firmware version query data for sending 899 | local firmware_query = bin.pack("H","810a001101040005010c0c023FFFFF192c") 900 | -- set the application version query data for sending 901 | local appsoft_query = bin.pack("H","810a001101040005010c0c023FFFFF190c") 902 | -- set the object name query data for sending 903 | local object_query = bin.pack("H","810a001101040005010c0c023FFFFF194d") 904 | -- set the model name query data for sending 905 | local model_query = bin.pack("H","810a001101040005010c0c023FFFFF1946") 906 | -- set the desc name query data for sending 907 | local desc_query = bin.pack("H","810a001101040005010c0c023FFFFF191c") 908 | -- set the location name query data for sending 909 | local location_query = bin.pack("H","810a001101040005010c0c023FFFFF193A") 910 | local query 911 | 912 | -- 913 | -- determine what type of packet to send 914 | if (type == "firmware") then 915 | query = firmware_query 916 | elseif (type == "application") then 917 | query = appsoft_query 918 | elseif (type == "model") then 919 | query = model_query 920 | elseif (type == "object") then 921 | query = object_query 922 | elseif (type == "description") then 923 | query = desc_query 924 | elseif (type == "location") then 925 | query = location_query 926 | elseif (type == "vendor") then 927 | query = vendor_query 928 | end 929 | 930 | --try to pull the information 931 | local status, result = socket:send(query) 932 | if(status == false) then 933 | stdnse.debug1("Socket error sending query: %s", result) 934 | return nil 935 | end 936 | -- receive packet from response 937 | local rcvstatus, response = socket:receive() 938 | if(rcvstatus == false) then 939 | stdnse.debug1("Socket error receiving: %s", response) 940 | return nil 941 | end 942 | -- validate valid BACNet Packet 943 | if( string.starts(response, "\x81")) then 944 | -- Lookup byte 7 (pakcet type) 945 | local pos, value = bin.unpack("C", response, 7) 946 | -- verify that the response packet was not an error packet 947 | if( value ~= 0x50) then 948 | --collect information by looping thru the packet 949 | return field_size(response) 950 | -- if it was an error packet, set the string to error for later purposes 951 | else 952 | stdnse.debug1("Error receiving: BACNet Error") 953 | return nil 954 | end 955 | -- else ERROR 956 | else 957 | stdnse.debug1("Error receiving Vendor ID: Invalid BACNet packet") 958 | return nil 959 | end 960 | 961 | end 962 | --- 963 | -- Function to send a query to the discovered BACNet devices. This function queries extra 964 | -- information to help identify the device. Vendor ID query is sent with this 965 | -- function and the Vendor ID number is parsed out of the packet. 966 | -- 967 | -- @param socket The socket that was created in the action function 968 | function vendornum_query(socket) 969 | 970 | -- set the vendor query data for sending 971 | local vendor_query = bin.pack("H","810a001101040005010c0c023FFFFF1978") 972 | 973 | 974 | --send the vendor information 975 | local status, result = socket:send(vendor_query) 976 | if(status == false) then 977 | stdnse.debug1("Socket error sending vendor query: %s", result) 978 | return nil 979 | end 980 | -- receive vendor information packet 981 | local rcvstatus, response = socket:receive() 982 | if(rcvstatus == false) then 983 | stdnse.debug1("Socket error receiving vendor query: %s", response) 984 | return nil 985 | end 986 | -- validate valid BACNet Packet 987 | if( string.starts(response, "\x81")) then 988 | local pos, value = bin.unpack("C", response, 7) 989 | --if the vendor query resulted in an error 990 | if( value ~= 0x50) then 991 | -- read values for byte 18 in the packet data 992 | -- this value determines if vendor number is 1 or 2 bytes 993 | pos, value = bin.unpack("C", response, 18) 994 | else 995 | stdnse.debug1("Error receiving Vendor ID: BACNet Error") 996 | return nil 997 | end 998 | -- if value is 21 (byte 18) 999 | if( value == 0x21 ) then 1000 | -- convert hex to decimal 1001 | local vendornum = string.byte(response, 19) 1002 | -- look up vendor name from table 1003 | return vendor_lookup(vendornum) 1004 | -- if value is 22 (byte 18) 1005 | elseif( value == 0x22 ) then 1006 | -- convert hex to decimal 1007 | local vendornum 1008 | pos, vendornum = bin.unpack(">S", response, 19) 1009 | -- look up vendor name from table 1010 | return vendor_lookup(vendornum) 1011 | else 1012 | -- set return value to an Error if byte 18 was not 21/22 1013 | stdnse.debug1("Error receiving Vendor ID: Invalid BACNet packet") 1014 | return nil 1015 | end 1016 | end 1017 | 1018 | end 1019 | 1020 | --- 1021 | -- Function to send a request for BVLC info to the discovered BACNet devices. 1022 | -- This includes the BBMD and the FDT queries. These are read only and do not 1023 | -- attempt to join the router as a Foreign Device. 1024 | -- 1025 | -- @param socket The socket that was created in the action function 1026 | -- @param type Type is the type of packet to send, this can be bbmd or fdt 1027 | function bvlc_query(socket, type) 1028 | 1029 | -- set the BVLC query data for sending 1030 | -- BBMD = 0x02 1031 | local bbmd_query = bin.pack("H","81020004") 1032 | -- FDT = 0x06 1033 | local fdt_query = bin.pack("H","81060004") 1034 | -- initialize query var 1035 | local query 1036 | 1037 | -- Based on type parameter passed in from Action 1038 | if (type == "bbmd") then 1039 | query = bbmd_query 1040 | elseif (type == "fdt") then 1041 | query = fdt_query 1042 | end 1043 | 1044 | -- Send the query that was set by the type 1045 | local status, result = socket:send(query) 1046 | if(status == false) then 1047 | stdnse.debug1("BVLC-" .. type .. ": Socket error sending query: %s", result) 1048 | return nil 1049 | end 1050 | -- Recive response from the query 1051 | local rcvstatus, response = socket:receive() 1052 | if(rcvstatus == false) then 1053 | stdnse.debug1("BVLC-" .. type .. ": Socket error receiving: %s", response) 1054 | return nil 1055 | end 1056 | 1057 | -- Validate that packet is BACNet, if it is then we will start parsing more response 1058 | if( string.starts(response, "\x81")) then 1059 | 1060 | -- init up vars 1061 | local info = "" 1062 | local ips = {} 1063 | local length 1064 | local mask 1065 | local resptype 1066 | 1067 | -- unpack response type, this will be used to determine BBMD vs FDT 1068 | local pos, resptype = bin.unpack("C", response, 2) 1069 | 1070 | -- unpack length, this will be the length of the information to be parsed 1071 | pos, length = bin.unpack(">S", response, 3) 1072 | -- add one to length since Lua starts at 1 not 0 1073 | length = length + 1 1074 | stdnse.debug1("BVLC-" .. type .. ": starting on bacnet bytes: " .. length) 1075 | -- if length is 7(packet size 6), then we will test to see if it was NAK response 1076 | if length == 7 then 1077 | -- response type will be BVLC-Result 1078 | if resptype == 0 then 1079 | -- unpack two bytes of interest 1080 | pos, byte1 = bin.unpack("C", response, 4) 1081 | pos, byte2 = bin.unpack("C", response, 6) 1082 | if byte1 == 0x06 and byte2 == 0x40 then 1083 | return "Non-Acknowledgement (NAK)" 1084 | elseif byte1 == 0x06 and byte2 == 0x20 then 1085 | return "Non-Acknowledgement (NAK)" 1086 | end 1087 | end 1088 | -- if the packet length is 5(packet size 4) then check to see if a Empty response 1089 | elseif length == 5 then 1090 | -- validate the response is for the FDT query 1091 | if resptype == 7 then 1092 | return "Empty Table" 1093 | end 1094 | -- if packet is not long enough then we will exit 1095 | elseif length < 15 then 1096 | stdnse.debug1( 1097 | "BVLC-" .. type .. ": stopping, this response had not enough bytes: " .. length .. " < 15") 1098 | return nil 1099 | end 1100 | -- While loop for the length of the packet as determined from above. 1101 | while pos < length do 1102 | local ipaddr = "" 1103 | --Unpack and the IP Address from the response 1104 | pos, info = bin.unpack("S", response, pos) 1110 | -- Make string to be stored in output table to be returned to Nmap 1111 | ipaddr = ipaddr .. ":" .. info 1112 | -- shift by 4 bytes 1113 | pos = pos + 4 1114 | 1115 | -- else if the type is FDT 1116 | elseif resptype == 7 then 1117 | --Unpack port number 1118 | pos, info = bin.unpack(">S", response, pos) 1119 | ipaddr = ipaddr .. ":" .. info 1120 | --Unpack TTL field 1121 | pos, info = bin.unpack(">S", response, pos) 1122 | ipaddr = ipaddr .. ":ttl=" .. info 1123 | --Unpack the timeout field 1124 | pos, info = bin.unpack(">S", response, pos) 1125 | ipaddr = ipaddr .. ":timeout=" .. info 1126 | stdnse.debug1("BVLC-" .. type .. ": found this: " .. ipaddr) 1127 | -- else the type was not something we were asking for 1128 | --we don't know what response type this is! 1129 | else 1130 | stdnse.debug1("BVLC-" .. type .. ": unknown response type encountered!") 1131 | return nil 1132 | end 1133 | -- insert to the ips table for output to Nmap 1134 | table.insert(ips, ipaddr) 1135 | 1136 | -- consider if its time to quit based on the last pos from the last 1137 | -- unpack was the end of the packet 1138 | if pos == length then 1139 | stdnse.debug1("BVLC-" .. type .. ": bailing because we are at the end: " .. pos) 1140 | return ips 1141 | end 1142 | stdnse.debug1("BVLC-" .. type .. ": done with loop") 1143 | end 1144 | -- else ERROR 1145 | else 1146 | stdnse.debug1("Invalid BACNet packet in response to: " .. type) 1147 | return nil 1148 | end 1149 | 1150 | end 1151 | 1152 | --- 1153 | -- Action Function that is used to run the NSE. This function will send the initial query to the 1154 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 1155 | -- is a BACNet device. If it is then more actions are taken to gather extra information. 1156 | -- 1157 | -- @param host Host that was scanned via nmap 1158 | -- @param port port that was scanned via nmap 1159 | action = function(host, port) 1160 | --set the first query data for sending 1161 | local orig_query = bin.pack("H","810a001101040005010c0c023FFFFF194b" ) 1162 | 1163 | local to_return = nil 1164 | -- create new socket 1165 | local sock = nmap.new_socket() 1166 | -- Bind to port for niceness with BACNet this may need to be commented out if 1167 | -- scanning more than one host at a time, may fix some issues seen on Windows 1168 | -- 1169 | local status, err = sock:bind(nil, 47808) 1170 | if(status == false) then 1171 | stdnse.debug1( 1172 | "Couldn't bind to 47808/udp. Continuing anyway, results may vary") 1173 | end 1174 | -- connect to the remote host 1175 | local constatus, conerr = sock:connect(host, port) 1176 | if not constatus then 1177 | stdnse.debug1( 1178 | 'Error establishing a UDP connection for %s - %s', host, conerr 1179 | ) 1180 | return nil 1181 | end 1182 | -- send the original query to see if it is a valid BACNet Device 1183 | local sendstatus, senderr = sock:send(orig_query) 1184 | if not sendstatus then 1185 | stdnse.debug1( 1186 | 'Error sending BACNet request to %s:%d - %s', 1187 | host.ip, port.number, senderr 1188 | ) 1189 | return nil 1190 | end 1191 | 1192 | -- receive response 1193 | local rcvstatus, response = sock:receive() 1194 | if(rcvstatus == false) then 1195 | stdnse.debug1("Receive error: %s", response) 1196 | return nil 1197 | end 1198 | 1199 | -- if the response starts with 0x81 then its BACNet 1200 | if( string.starts(response, "\x81")) then 1201 | local pos, value = bin.unpack("C", response, 7) 1202 | --if the first query resulted in an error 1203 | -- 1204 | if( value == 0x50) then 1205 | -- set the nmap output for the port and version 1206 | set_nmap(host, port) 1207 | -- return that BACNet Error was received 1208 | to_return = "\nBACNet ADPU Type: Error (5) \n\t" .. stdnse.tohex(response) 1209 | --else pull the InstanceNumber and move onto the pulling more information 1210 | -- 1211 | else 1212 | to_return = stdnse.output_table() 1213 | -- set the nmap output for the port and version 1214 | set_nmap(host, port) 1215 | 1216 | -- Vendor Number to Name lookup 1217 | to_return["Vendor ID"] = vendornum_query(sock) 1218 | 1219 | -- vendor name 1220 | to_return["Vendor Name"] = standard_query(sock, "vendor") 1221 | 1222 | -- Instance Number (object number) 1223 | local instance_upper, instance 1224 | pos, instance_upper, instance = bin.unpack("C>S", response, 20) 1225 | to_return["Object-identifier"] = instance_upper * 0x10000 + instance 1226 | 1227 | --Firmware Verson 1228 | to_return["Firmware"] = standard_query(sock, "firmware") 1229 | 1230 | -- Application Software Version 1231 | to_return["Application Software"] = standard_query(sock, "application") 1232 | 1233 | -- Object Name 1234 | to_return["Object Name"] = standard_query(sock, "object") 1235 | 1236 | -- Model Name 1237 | to_return["Model Name"] = standard_query(sock, "model") 1238 | 1239 | -- Description 1240 | to_return["Description"] = standard_query(sock, "description") 1241 | 1242 | -- Location 1243 | to_return["Location"] = standard_query(sock, "location") 1244 | 1245 | -- for each element in the table, if it is nil, then remove the information from the table 1246 | for key,value in pairs(to_return) do 1247 | if(string.len(to_return[key]) == 0) then 1248 | to_return[key] = nil 1249 | end 1250 | end 1251 | -- check for script-args, if its set to yes, then run this additional queries 1252 | local arguments = stdnse.get_script_args('full') 1253 | if ( arguments == "yes" ) then 1254 | -- BACnet Broadcast Management Device Query/Response 1255 | to_return["Broadcast Distribution Table (BDT)"] = bvlc_query(sock, "bbmd") 1256 | 1257 | -- Foreign Device Table Query/Response 1258 | to_return["Foreign Device Table (FDT)"] = bvlc_query(sock, "fdt") 1259 | end 1260 | end 1261 | else 1262 | -- return nothing, no BACNet was detected 1263 | -- close socket 1264 | sock:close() 1265 | return nil 1266 | end 1267 | -- close socket 1268 | sock:close() 1269 | -- return all information that was found 1270 | return to_return 1271 | 1272 | end 1273 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Same as Nmap--See http://nmap.org/book/man-legal.html -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Redpoint 2 | 3 | 4 | ###Digital Bond's ICS Enumeration Tools 5 | 6 | Redpoint is a Digital Bond research project to enumerate ICS applications and devices. 7 | 8 | We use our Redpoint tools in assessments to discover ICS devices and pull information that would be helpful in secondary testing. A portion of those tools will be made available as Nmap NSE scripts to the public in this repository. 9 | 10 | The Redpoint tools use legitimate protocol or application commands to discover and enumerate devices and applications. There is no effort to exploit or crash anything. However many ICS devices and applications are fragile and can crash or respond in an unexpected way to any unexpected traffic so use with care. 11 | 12 | Each script is documented below and available in a .nse file in this repository. 13 | 14 | * [BACnet-discover-enumerate.nse](https://github.com/digitalbond/Redpoint#bacnet-discover-enumeratense) - Identify and enumerate BACnet devices 15 | 16 | * [codesys-v2-discover.nse](http://github.com/digitalbond/Redpoint#codesys-v2-discovernse) - Identify and enumerate CoDeSys V2 controllers 17 | 18 | * [enip-enumerate.nse](https://github.com/digitalbond/Redpoint#enip-enumeratense) - Identify and enumerate EtherNet/IP devices from Rockwell Automation and other vendors 19 | 20 | * [fox-info.nse](https://github.com/digitalbond/Redpoint/blob/master/README.md#fox-infonse) - Identify and enumerate Niagara Fox devices 21 | 22 | * [modicon-info.nse](https://github.com/digitalbond/Redpoint/blob/master/README.md#modicon-infonse) - Identify and enumerate Schneider Electric Modicon PLCs 23 | 24 | * [omron-info.nse](https://github.com/digitalbond/Redpoint/blob/master/README.md#omron-infonse) - Identify and enumerate Omron PLCs 25 | 26 | * [pcworx-info.nse](https://github.com/digitalbond/Redpoint/blob/master/README.md#pcworx-infonse) - Identify and enumerate PC Worx Protocol enabled PLCs 27 | 28 | * [proconos-info.nse](https://github.com/digitalbond/Redpoint/blob/master/README.md#pcworx-infonse) - Identify and enumerate ProConOS enabled PLCs 29 | 30 | * [s7-enumerate.nse](https://github.com/digitalbond/Redpoint#s7-enumeratense) - Identify and enumerate Siemens SIMATIC S7 PLCs 31 | 32 | == 33 | 34 | ###BACnet-discover-enumerate.nse 35 | 36 | ![BACnet-discover-enumerate Sample Output] (http://digibond.wpengine.netdna-cdn.com/wp-content/uploads/2014/03/BACnet-nse.png) 37 | 38 | ####Authors 39 | 40 | Stephen Hilt and Michael Toecker 41 | [Digital Bond, Inc](http://www.digitalbond.com) 42 | 43 | ####Purpose and Description 44 | 45 | The purpose of BACnet-discover-enumerate.nse is to first identify if an IP connected devices is running BACnet. This works by querying the device with a pre-generated BACnet message. Newer versions of the BACnet protocol will respond with an acknowledgement, older versions will return a BACnet error message. Presence of either the acknowledgement or the error is sufficient to prove a BACnet capable device is at the target IP Address. 46 | 47 | Second, if an acknowledgement is received, this script will also attempt to enumerate several BACnet properties on a responsive BACnet device. Again, the device is queried with a pregenerated BACnet message. Successful enumeration uses specially crafted requests, and will not be successful if the BACnet device does not support the property. 48 | 49 | BACnet properties queried by this script are: 50 | 51 | 1. Vendor ID - A number that corresponds to a registered BACnet Vendor. The script returns the associated vendor name as well. 52 | 53 | 2. Vendor Number - A String that represents the Vendor Name that is configured on the device. This can differ from the Vendor ID as the Vendor ID is the Number registered with ASHARE. 54 | 55 | 3. Object Identifier - A number that uniquely identifies the device. If the Object-Identifier is known, it is possible to send commands with BACnet client software, including those that change values, programs, schedules, and other operational information on BACnet devices. This is a required property for all BACnet devices. 56 | 57 | 4. Firmware Revision - The revision number of the firmware on the BACnet device. 58 | 59 | 5. Application Software Revision - The revision number of the software being used for BACnet communication. 60 | 61 | 6. Object Name - A user defined string that assigns a name to the BACnet device, commonly entered by technicians on commissioning. This is a required property for all BACnet devices. 62 | 63 | 7. Model Name - The model of the BACnet device 64 | 65 | 8. Description - A user defined string for describing the device, commonly entered by technicians on commissioning 66 | 67 | 9. Location - A user defined string for recording the physical location of the device, commonly entered by technicians on commissioning 68 | 69 | 11. Broadcast Distribution Table (BDT) - A list of the BACnet Broadcast Management Devices (BBMD) in the BACnet network. This will identify all of the subnets that are part of the BACnet network. 70 | 71 | 12. Foreign Device Table (FDT) - A list of foreign devices registered with the BACnet device. A foreign device is any device that is not on a subnet that is part of the BACnet network, not in the BDT. Foreign devices often are located on external networks and could be an attacker's IP address. 72 | 73 | The BDT and FDT can be large lists and may be not desired in a large Nmap scan. The basic script will not pull down the BDT and FDT. Run the command with the --script-args full=yes to pull the BDT and FDT, see the Usage section. 74 | 75 | ![BACnet-discover-enumerate Sample Output with BDT and FDT] 76 | (http://digibond.wpengine.netdna-cdn.com/wp-content/uploads/2014/08/screenshot_bacnet-1.png) 77 | 78 | This script uses a feature added in 2004 to the BACnet specification in order to retrieve the Object Identifier of a device with a single request, and without joining the BACnet network as a foreign device. (See ANSI/ASHRAE Addendum a to ANSI/ASHRAE Standard 135-2001 for details) 79 | 80 | 81 | ####History and Background 82 | 83 | From Wikipedia article on BACnet http://en.wikipedia.org/wiki/BACnet: 84 | 85 | > BACnet is a communications protocol for building automation and control networks. It is an ASHRAE, ANSI, and ISO standard[1] protocol. The default port for BACnet traffic is UDP/47808. 86 | 87 | > BACnet is used in building automation and control systems for applications such as heating, ventilating, and air-conditioning control, lighting control, access control, and fire detection systems and their associated equipment. The BACnet protocol provides mechanisms for computerized building automation devices to exchange information, regardless of the particular building service they perform. 88 | 89 | 90 | ####Installation 91 | 92 | This script requires nmap to run. If you do not have Nmap download and Install Nmap based off the Nmap instructions. 93 | http://nmap.org/download.html 94 | 95 | #####Windows 96 | 97 | After downloading bacnet-discover.nse you'll need to move it into the NSE Scripts directory, this will have to be done as an administrator. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 98 | 99 | move BACnet-discover-enumerate.nse C:\Program Files (x86)\Nmap\scripts 100 | 101 | #####Linux 102 | 103 | After Downloading BACnet-discover-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as sudo/root. 104 | 105 | sudo mv BACnet-discover-enumerate.nse /usr/share/nmap/scripts 106 | 107 | 108 | ####Usage 109 | 110 | Inside a Terminal Window/Command Prompt use one of the following commands where host is the target you wish you scan for BACNet. Use --script-args full=yes if you want the output to included the BDT and FDT. 111 | 112 | Windows: nmap -sU -p 47808 --script BACnet-discover-enumerate 113 | Windows: nmap -sU -p 47808 --script BACnet-discover-enumerate --script-args full=yes 114 | 115 | Linux: sudo nmap -sU -p 47808 --script BACnet-discover-enumerate 116 | Linux: sudo nmap -sU -p 47808 --script BACnet-discover-enumerate --script-args full=yes 117 | 118 | To speed up results by not performing DNS lookups during the scan use the -n option, also disable pings to determine if the device is up by doing a -Pn option for full results. 119 | 120 | nmap -sU -Pn -p 47808 -n --script BACnet-discover-enumerate 121 | 122 | 123 | ####Notes 124 | 125 | The official version of this script is maintained at: https://github.com/digitalbond/Redpoint/blob/master/BACnet-discover-enumerate.nse 126 | 127 | This script uses the standard BACnet source and destination port of UDP 47808. 128 | 129 | Newer (after February 25, 2004) BACnet devices are required by spec to respond to specific requests that use a 'catchall' object-identifier with their own valid instance number (see ANSI/ASHRAE Addendum a to ANSI/ASHRAE Standard 135-2001). Older versions of BACnet devices may not respond to this catchall, and will respond with a BACnet error packet instead. 130 | 131 | This script does not attempt to join a BACnet network as a foreign device, it simply sends BACnet requests directly to an IP addressable device. 132 | 133 | == 134 | ###codesys-v2-discover.nse 135 | ![codesys-v2-discover Sample Output] (http://digibond.wpengine.netdna-cdn.com/wp-content/uploads/2016/03/codesys-v2-discover-win.png) 136 | 137 | ####Authors 138 | 139 | Stephen Hilt, 140 | Reid Wightman 141 | 142 | ####Purpose and Description 143 | 144 | The codesys-v2-discover.nse script identifies PLCs which run the version 2 ladder logic runtime made by 3S-Software GmbH. These controllers speak a proprieaty binary protocol for installing new ladder logic, as well as debugging the running ladder logic. The protocol can require authentication. In practice, few devices support this behavior. This script does not test for authentication. 145 | 146 | This script sends a simple request for identification to the device. The response message may include the operating system and specific point release of CoDeSys running on the PLC. 147 | 148 | ####History and Background 149 | 150 | Digital Bond released details of the CoDeSys runtime system being insecure-by-design in April 2012. The protocol usually uses TCP/1200 or TCP/2455 as its control port. The control protocol contains functions to upload and download files from the controllers. The protocol also may provide a command shell, which offers additional functionality. Shell features typically include the ability to start and stop the currently-running ladder logic, as well as retrieve debugging information from the controller. 151 | 152 | The initial advisory applied only to version 2 of the runtime. Digital Bond also released a proof-of-concept Nmap script, originally written by HD Moore as part of his internet-scanning project. 153 | 154 | A Nessus script was also produced for this version of the protocol, however the Nessus script contains an error and does not properly check for controllers with big-endian CPUs. 155 | 156 | ####Installation 157 | 158 | This script requires Nmap to run. If you do not have Nmap download and Install Nmap based off the Nmap instructions. 159 | http://nmap.org/download.html 160 | 161 | #####Windows 162 | 163 | After downloading enip-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as an administrator. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 164 | 165 | move codesys-v2-discover.nse C:\Program Files (x86)\Nmap\scripts 166 | 167 | #####Linux 168 | 169 | After Downloading enip-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as sudo/root. 170 | 171 | sudo mv codesys-v2-discover.nse /usr/share/nmap/scripts 172 | 173 | ####Usage 174 | 175 | Inside a Terminal Window/Command Prompt use one of the following commands where is the target you wish you scan for EtherNet/IP. 176 | 177 | Windows: nmap -p 1200,2455 --script codesys-v2-discover 178 | 179 | Linux: sudo nmap -p 1200,2455 --script codesys-v2-discover 180 | 181 | 182 | ####Notes 183 | 184 | The official version of this script is maintained at:https://github.com/digitalbond/Redpoint/codesys-v2-discover.nse 185 | 186 | This script will attempt to send the CoDeSys requests on any open port. While the standard ports of 1200 or 2455 are used by most controllers, some controllers use alternate ports such as 1201, 1217, and yet other ports. 187 | 188 | == 189 | ###enip-enumerate.nse 190 | ![enip-enumerate Sample Output] (http://digibond.wpengine.netdna-cdn.com/wp-content/uploads/2014/04/enip.png) 191 | 192 | ####Author 193 | 194 | Stephen Hilt 195 | [Digital Bond, Inc](http://www.digitalbond.com) 196 | 197 | 198 | ####Purpose and Description 199 | 200 | The purpose of enip-enumerate.nse is to identify and enumerate EtherNet/IP devices. Rockwell Automation / Allen Bradley developed the protocol and is the primary maker of these devices, e.g. ControlLogix and MicroLogix, but it is an open standard and a number of vendors offer an EtherNet/IP interface card or solution. 201 | 202 | An EtherNet/IP device is positively identified by querying TCP/44818 with a list Identities Message (0x63). The response messages will determine if it is a EtherNet/IP device and parse the information to enumerate the device. 203 | 204 | The EtherNet/IP Request List Identities pulls basic information about the device known as the Device's "electronic key". Information includes Vendor, Product Name, Serial Number, Device Type, Product Code and Revision Number. Also the script parses the devices configured IP address from the Socket Address Field within the EtherNet/IP frame of the packet. 205 | 206 | EtherNet/IP properties parsed by this script are: 207 | 208 | 1. Vendor - A two Byte integer that is used to look up Vendor Name 209 | 210 | 2. Product Name - A string that represents a short description of the product/product family, maximum length is 32 chars 211 | 212 | 3. Serial Number - A six Byte Hexadecimal Number that is stored little Endian 213 | 214 | 4. Device Type - Two byte integer that is used to look up Device type. This field is often not used and set to 0. 215 | 216 | 5. Product Code - The vendor assigned Product Code identifies a particular product within a device type. The script does not have access to the vendor product code tables so the number is displayed. 217 | 218 | 6. Revision - Two one-byte integers that lists the major and minor revision number of the device 219 | 220 | 7. Device IP - Four one-byte integers that represent the device's configured IP address. This address often differs from the IP address scanned by the script. 221 | 222 | ####History and Background 223 | 224 | From Wikipedia article on EtherNet/IP http://en.wikipedia.org/wiki/EtherNet/IP 225 | 226 | > EtherNet/IP was developed in the late 1990s by Rockwell Automation as part of Rockwell's industrial Ethernet networking solutions. Rockwell gave EtherNet/IP its moniker and handed it over to ODVA, which now manages the protocol and assures multi-vendor system interoperability by requiring adherence to established standards whenever new products that utilize the protocol are developed today. 227 | 228 | >EtherNet/IP is most commonly used in industrial automation control systems, such as for water processing plants, manufacturing facilities and utilities. Several control system vendors have developed programmable automation controllers and I/O capable of communicating via EtherNet/IP. 229 | 230 | 231 | ####Installation 232 | 233 | This script requires Nmap to run. If you do not have Nmap download and Install Nmap based off the Nmap instructions. 234 | http://nmap.org/download.html 235 | 236 | #####Windows 237 | 238 | After downloading enip-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as an administrator. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 239 | 240 | move enip-enumerate.nse C:\Program Files (x86)\Nmap\scripts 241 | 242 | #####Linux 243 | 244 | After Downloading enip-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as sudo/root. 245 | 246 | sudo mv enip-enumerate.nse /usr/share/nmap/scripts 247 | 248 | 249 | ####Usage 250 | 251 | Inside a Terminal Window/Command Prompt use one of the following commands where is the target you wish you scan for EtherNet/IP. 252 | 253 | Windows: nmap -p 44818 --script enip-enumerate 254 | 255 | Linux: sudo nmap -p 44818 --script enip-enumerate 256 | 257 | 258 | ####Notes 259 | 260 | The official version of this script is maintained at:https://github.com/digitalbond/Redpoint/enip-enumerate.nse 261 | 262 | This script uses the standard Ethernet/IP destination port of TCP 44818. 263 | 264 | == 265 | 266 | ###fox-info.nse 267 | ![fox-info Sample Output] (http://www.digitalbond.com/wp-content/uploads/2014/10/fox-example.png) 268 | 269 | ####Author 270 | 271 | Stephen Hilt 272 | [Digital Bond, Inc](http://www.digitalbond.com) 273 | 274 | ####Purpose and Description 275 | 276 | The purpose of fox-info.nse is to first identify devices running the Niagara Fox protocol. This script is based off the work and examples provided by Billy Rios and Terry McCorkle. 277 | 278 | Upon successful connection to a Niagara Fox device, the script will be parse the response sent from the device and display enumerated information. 279 | 280 | Niagara Fox properties queried by this script are: 281 | 282 | 1. Fox Version - The version of the Fox protocol that is currently running on the device. 283 | 284 | 2. Host Name - The host name of the device. This usually is the workstation name of the remote device. 285 | 286 | 3. Host Address - The IP address configured on the device. This can be the IP address scanned or a private address if the device is behind something performing network address translations(NAT). 287 | 288 | 4. Application Name - The application name that is running on the remote device. This is typically either "Workbench" or "Station". 289 | 290 | 5. Application Version - The version number of the application name previously enumerated. 291 | 292 | 6. VM Name - The name of the Java Virtual Machine that is running the application. 293 | 294 | 7. VM Version - The version number of the VM that is running on the remote device. This will be most likely the Java HotSpot Version Number. 295 | 296 | 8. OS Name - Name of the OS running the Fox protocol on the device, e.g. QNX or Windows XP. 297 | 298 | 9. Time Zone - The local time zone configured on the device. 299 | 300 | 10. Host ID - a unique ID that is used to identify the device. 301 | 302 | 11. VM UUID - The Java VM Universally Unique Identifier. 303 | 304 | 12. Brand ID - Every licensed station and tool has a Brand Identifier. This field holds a text descriptor that the OEM chooses as the identifier for its product line. Each station or tool can have only one BrandID entry. 305 | 306 | ####History and Background 307 | 308 | Fox is a proprietary TCP/IP protocol used for station-to-station and workbench-to-station communication in the Niagara Framework of the Tridium building automation solutions. Tridium is a wholly owned subsidiary of Honeywell. 309 | 310 | ####Installation 311 | 312 | This script requires Nmap to run. If you do not have Nmap download and install Nmap, see: 313 | http://nmap.org/download.html 314 | 315 | #####Windows 316 | 317 | After downloading fox-info.nse, move it into the NSE Scripts directory. This move must be done as an administrator. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 318 | 319 | move fox-info.nse C:\Program Files (x86)\Nmap\scripts 320 | 321 | #####Linux 322 | 323 | After Downloading fox-info.nse, move it into the NSE Scripts directory. This must be done as sudo/root. 324 | 325 | sudo mv fox-info.nse /usr/share/nmap/scripts 326 | 327 | 328 | ####Usage 329 | 330 | Inside a Terminal Window/Command Prompt use one of the following commands where host is the target you wish you scan for devices that support the Niagara Fox protocol. 331 | 332 | Windows: nmap -p 1911 --script fox-info 333 | 334 | Linux: sudo nmap -p 1911 --script fox-info 335 | 336 | 337 | ####Notes 338 | 339 | The official version of this script is maintained at: https://github.com/digitalbond/Redpoint/blob/master/fox-info.nse 340 | 341 | This script uses the standard Niagara Fox source and destination port of TCP 1911. 342 | 343 | == 344 | 345 | ###modicon-info.nse 346 | ![modicon-info sample output] (http://www.digitalbond.com/wp-content/uploads/2014/09/Modicon.png) 347 | 348 | 349 | ####Author 350 | 351 | Stephen Hilt 352 | [Digital Bond, Inc](http://www.digitalbond.com) 353 | 354 | ####Purpose and Description 355 | 356 | The purpose of modicon-info.nse is to first identify and enumerate Modicon PLC's made by Schneider Electric. 357 | 358 | The script first identifies if an IP connected device is sending a Modbus function code 43 request. The response is sufficient to identify Modbus devices even if they do not support function code 43. If the response vendor name contains the string Schneider, the script will enumerate the device using the Schneider Electric proprietary Modbus function code 90. 359 | 360 | Modbus function code 43 and function code 90 properties that are included in the script output are: 361 | 362 | 1) Vendor Name - This script will ignore all devices that do not contain "Schneider". 363 | 364 | 2) Network Module - The Ethernet communications module in the Modicon PLC. 365 | 366 | 3) CPU Module - The CPU module in the Modicon PLC. 367 | 368 | 4) Firmware - The firmware version on the CPU module in the Modicon PLC. 369 | 370 | 5) Memory Card - The model number of the memory card in the CPU module. 371 | 372 | 6) Project Information - Miscellaneous information about the project, such as the project name, the version of Unity Pro that was used to configure it, as well as the workstation name that programmed the PLC. Some Devices will provide the location of the .stu file on the workstation that configured the device. 373 | 374 | 7) Project Revision - The revision of the project running on the PLC, the project revision number increments by 1 each time a the project is built, and transferred to the PLC. 375 | 376 | 8) Project Last Modified Date - A time stamp that is stored for when the last time the PLC was modified by a technician. 377 | 378 | ####History and Background 379 | 380 | From Wikipedia article on Programmable Logic Controllers http://en.wikipedia.org/wiki/Programmable_logic_controller#History: 381 | 382 | > In 1968 GM Hydra-Matic (the automatic transmission division of General Motors) issued a request for proposals for an electronic replacement for hard-wired relay systems based on a white paper written by engineer Edward R. Clark. The winning proposal came from Bedford Associates of Bedford, Massachusetts. The first PLC, designated the 084 because it was Bedford Associates' eighty-fourth project, was the result.[2] Bedford Associates started a new company dedicated to developing, manufacturing, selling, and servicing this new product: Modicon, which stood for MOdular DIgital CONtroller. One of the people who worked on that project was Dick Morley, who is considered to be the "father" of the PLC.[3] The Modicon brand was sold in 1977 to Gould Electronics, and later acquired by German Company AEG and then by French Schneider Electric, the current owner. 383 | 384 | ####Installation 385 | 386 | This script requires Nmap to run. If you do not have Nmap download and install Nmap. 387 | 388 | http://nmap.org/download.html 389 | 390 | #####Windows 391 | 392 | After downloading modicon-info.nse, move it into the NSE Scripts directory. This will require Administrator privileges. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 393 | 394 | move modicon-info.nse C:\Program Files (x86)\Nmap\scripts 395 | 396 | #####Linux 397 | 398 | After downloading modicon-info.nse, move it into the NSE Scripts directory. This will have to be done as sudo/root. 399 | 400 | sudo mv modicon-info.nse /usr/share/nmap/scripts 401 | 402 | 403 | ####Usage 404 | 405 | Inside a Terminal Window/Command Prompt use one of the following commands where is the target you wish you scan for Modicon PLCs. 406 | 407 | Windows: nmap -p 502 --script modicon-info.nse -sV 408 | 409 | Linux: sudo nmap -p 502 --script modicon-info.nse -sV 410 | 411 | 412 | ####Notes 413 | 414 | The official version of this script is maintained at:https://github.com/digitalbond/Redpoint/modicon-info.nse 415 | 416 | This script uses the standard Modbus destination port of TCP 502. 417 | 418 | == 419 | ###omrontcp-info.nse & omronudp-info.nse 420 | ![omrontcp/udp-info Sample Output] (http://www.digitalbond.com/wp-content/uploads/2015/02/Region.png) 421 | 422 | ####Author 423 | 424 | Stephen Hilt 425 | [Digital Bond, Inc](http://www.digitalbond.com) 426 | 427 | 428 | ####Purpose and Description 429 | 430 | The purpose of omrontcp-info and omronudp-info is to identify and enumerate OMRON FINS devices. Omron develed the protocol and is the primary maker of the devices that support this protocol. 431 | 432 | An OMRON FINS device is positively identified by querying TCP/9600 or UDP 9600 with a Read Controller Satus (0x0501). The response messages will determine if it is a OMRON FINS device device and parse the information to enumerate the device. 433 | 434 | The OMRONS FINS Read Controller Status pulls basic information about the devie such as Controller Model, Controller Version, Program area size, IOM size, No. of DM Words, Timer/Counter size, Expansion DMZ size, No. of steps/transitions, Kind of memory card and memory card size. 435 | 436 | OMRON FINS properties parsed by this script are: 437 | 438 | 1. Controller Model - A string no larger than 20 bytes that represents the Controller Model 439 | 440 | 2. Controller Version - A string to represent a version number that is no larger than 20 bytes. 441 | 442 | 3. For System Use - Reserved for system use. Collecting Information just to see if there is anything intresting in this field 443 | 444 | 4. Program area size - The size of PC Setup and program area. 445 | 446 | 5. IOM size - The size of the area in which bit/word commands can be used. 447 | 448 | 6. No. of DM words - Total words in the DM area. 449 | 450 | 7. Timer/counter size - Maximum no. of timers/counters available. 451 | 452 | 8. Expansion DM size - Banks in the expansion DM area 453 | 454 | 9. No. of steps/transitions - Maximum no. of steps/transitions available 455 | 456 | 10. Kind of memory card - 00: No memory card 457 | 01: SPRAM 458 | 02: EPROM 459 | 03: EEPROM 460 | 461 | 11. Memory card size - Size of the memory card in Kb 462 | 463 | 464 | ####History and Background 465 | 466 | 467 | > FINS or Factory Intelligent Network Services is a protocol that utlizes commands to communicate to PLCs. The protocol supports a version over UDP as well as a version over TCP. There are some differences on the two protocols thats why two scripts are written to support scanning both TCP and UDP services. 468 | 469 | >OMRON FINS is used in industrial automation control systems, such as for water processing plants, manufacturing facilities and utilities. 470 | 471 | 472 | ####Installation 473 | 474 | This script requires Nmap to run. If you do not have Nmap download and Install Nmap based off the Nmap instructions. 475 | http://nmap.org/download.html 476 | 477 | #####Windows 478 | 479 | After downloading enip-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as an administrator. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 480 | 481 | move omron*.nse C:\Program Files (x86)\Nmap\scripts 482 | 483 | #####Linux 484 | 485 | After Downloading enip-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as sudo/root. 486 | 487 | sudo mv omron*.nse /usr/share/nmap/scripts 488 | 489 | 490 | ####Usage 491 | 492 | Inside a Terminal Window/Command Prompt use one of the following commands where is the target you wish you scan for OMRON FINS. 493 | 494 | Windows: nmap -p 9600 --script omrontcp-info 495 | Windows: nmap -sU -p 9600 --script omronudp-info 496 | 497 | Linux: nmap -p 9600 --script omrontcp-info 498 | Linux: sudo nmap -sU -p 9600 --script omronudp-info 499 | 500 | 501 | ####Notes 502 | 503 | The official TCP version of this script is maintained at:https://github.com/digitalbond/Redpoint/omrontcp-info.nse 504 | 505 | The official UDP version of this script is maintained at:https://github.com/digitalbond/Redpoint/omronudp-info.nse 506 | 507 | These scripts use the standard FINS and TCP/FINS destination port of UDP 9600 and TCP 9600. 508 | 509 | == 510 | ###pcworx-info.nse 511 | ![pcworx-info Sample Output] (http://www.digitalbond.com/wp-content/uploads/2015/02/pcworx.png) 512 | 513 | ####Author 514 | 515 | Stephen Hilt 516 | [Digital Bond, Inc](http://www.digitalbond.com) 517 | 518 | 519 | ####Purpose and Description 520 | 521 | The purpose of pcworx-info.nse is to identify and enumerate Phoenix Contact ILC PLCs via the PC Worx protocol. A PLC is positively identified by querying TCP/1962 with pre-generated requests. The response messages will determine if it is a PC Worx capable PLC and lead to additional enumeration. 522 | 523 | In total three packets will be sent to the PLC with this script to build up the communications and then to request the information from the PLC. 524 | 525 | PC Worx properties parsed by this script are: 526 | 527 | 1. PLC Type - A string that represents the ILC PLC Type. 528 | 529 | 2. Model Number - A string of ASCII numbers that represents the Model of the PLC Such as a [2737193](https://www.phoenixcontact.com/online/portal/us?urile=pxc-oc-itemdetail:pid=2737193). 530 | 531 | 3. Firmware Version - A string that represents the Firmware version running on the PLC. 532 | 533 | 4. Firmware Date - A string that represents the build date of the Firmware running on the PLC. 534 | 535 | 5. Firmware Time - A string that represents the build time of the Firmware running on the PLC. 536 | 537 | ####History and Background 538 | 539 | From Phoenix Contact product webpage [Link](https://www.phoenixcontact.com/online/portal/us?1dmy&urile=wcm:path:/usen/web/main/products/subcategory_pages/programming_p-19-05/8b777145-e7f2-4eaa-ae5e-4dacdce30223/8b777145-e7f2-4eaa-ae5e-4dacdce30223) 540 | 541 | > PC Worx is the consistent engineering software for all controllers from Phoenix Contact. It combines programming - according to IEC 61131, fieldbus configuration and system diagnostics – in a single software solution. This provides optimum interaction between hardware and software. PC Worx can be used to implement complex automation concepts. Depending on the number of I/Os to be supported, you have two versions to choose from: PC WORX BASIC and PC WORX PRO. 542 | 543 | ####Installation 544 | 545 | This script requires Nmap to run. If you do not have Nmap download and Install Nmap based off the Nmap instructions. 546 | http://nmap.org/download.html 547 | 548 | #####Windows 549 | 550 | After downloading pcworx-info.nse you'll need to move it into the NSE Scripts directory, this will have to be done as an administrator. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 551 | 552 | move pcworx-info.nse C:\Program Files (x86)\Nmap\scripts 553 | 554 | #####Linux 555 | 556 | After Downloading pcworx-info.nse you'll need to move it into the NSE Scripts directory, this will have to be done as sudo/root. 557 | 558 | sudo mv pcworx-info.nse /usr/share/nmap/scripts 559 | 560 | 561 | ####Usage 562 | 563 | Inside a Terminal Window/Command Prompt use one of the following commands where is the target you wish you scan for Phoenix Contact PLCs. 564 | 565 | Windows: nmap -p 1962 --script pcworx-info -sV 566 | 567 | Linux: nmap -p 1962 --script pcworx-info -sV 568 | 569 | 570 | ####Notes 571 | 572 | The official version of this script is maintained at:https://github.com/digitalbond/Redpoint/pcworx-info.nse 573 | 574 | This script uses the standard PC Worx destination port of TCP 1962. 575 | 576 | == 577 | 578 | ###proconos-info.nse 579 | ![proconos-info Sample Output] (http://www.digitalbond.com/wp-content/uploads/2015/02/pcworx.png) 580 | 581 | ####Author 582 | 583 | Stephen Hilt 584 | [Digital Bond, Inc](http://www.digitalbond.com) 585 | 586 | 587 | ####Purpose and Description 588 | 589 | The purpose of proconos-info.nse is to identify and enumerate PLCs via the ProConOS/MultiProg protocol. A PLC is positively identified by querying TCP/20547 with pre-generated requests. The response messages will determine if it is a ProConOS/MultiProg Capbable PLC and lead to additional enumeration. 590 | 591 | Only one request is required to query this information from the PLC. 592 | 593 | ProConOS/MultiProg properties parsed by this script are: 594 | 595 | 1. Ladder Logic Runtime - A string that displayes the Runtime Name, Verison and Build Date. 596 | 597 | 2. PLC Type - A string of that represents the Type of the PLC, and Firmware Version 598 | 599 | 3. Project Name - A string that represents the project name that is currently running on the PLC. 600 | 601 | 4. Boot Project - A string that represents the project name set to boot on the PLC. 602 | 603 | 5. Project Source Code - A string that represents if the source code for the project is available or not. 604 | 605 | ####Installation 606 | 607 | This script requires Nmap to run. If you do not have Nmap download and Install Nmap based off the Nmap instructions. 608 | http://nmap.org/download.html 609 | 610 | #####Windows 611 | 612 | After downloading proconos-info.nse you'll need to move it into the NSE Scripts directory, this will have to be done as an administrator. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 613 | 614 | move proconos-info.nse C:\Program Files (x86)\Nmap\scripts 615 | 616 | #####Linux 617 | 618 | After Downloading proconos-info.nse you'll need to move it into the NSE Scripts directory, this will have to be done as sudo/root. 619 | 620 | sudo mv proconos-info.nse /usr/share/nmap/scripts 621 | 622 | 623 | ####Usage 624 | 625 | Inside a Terminal Window/Command Prompt use one of the following commands where is the target you wish you scan for ProConOS/MultiProg PLCs. 626 | 627 | Windows: nmap -p 20547 --script proconos-info -sV 628 | 629 | Linux: nmap -p 20547 --script proconos-info -sV 630 | 631 | 632 | ####Notes 633 | 634 | The official version of this script is maintained at:https://github.com/digitalbond/Redpoint/proconos-info.nse 635 | 636 | This script uses the standard ProConOS/MultiProg destination port of TCP 20547. 637 | 638 | == 639 | 640 | ###s7-enumerate.nse 641 | ![s7-enumerate Sample Output] (http://digibond.wpengine.netdna-cdn.com/wp-content/uploads/2014/04/S7screenshot.png) 642 | 643 | ####Author 644 | 645 | Stephen Hilt 646 | [Digital Bond, Inc](http://www.digitalbond.com) 647 | 648 | Note: This script is meant to provide the same functionality as PLCScan inside of Nmap. Some of the information that is 649 | collected by PLCScan was not ported over to this NSE, this information can be parsed out of the packets that are received. 650 | 651 | Thanks to Positive Research, and Dmitry Efanov for creating PLCScan 652 | 653 | ####Purpose and Description 654 | 655 | The purpose of s7-enumerate.nse is to identify and enumerate Siemens SIMATIC S7 PLCs. A S7 is positively identified by querying TCP/102 with a pre-generated COTP and S7COMM messages. The response messages will determine if it is a S7 PLC and lead to additional enumeration. Note: TCP/102 is used by multiple applications, one being S7COMM. 656 | 657 | Two S7 requests are sent after successful S7 communication has been established. 658 | 659 | These requests pull basic hardware, firmware information, and some descriptive information such as plant identification and system name. This information is then returned to Nmap and presented in standard output formats supported by Nmap. 660 | 661 | S7 properties parsed by this script are: 662 | 663 | 1. Module - A string that represents the identification of the module that is being queried. This identifies the S7 model, e.g. 315, 412, 1200, ... 664 | 665 | 2. Basic Hardware - A string that represents the identification of basic hardware that is being queried. 666 | 667 | 3. Version - A string that represents the identification of the basic hardware version. 668 | 669 | 4. System Name - A string that represents the system name that was given to the device. This can provide some useful intelligence if the asset owner had implemented a structured naming convention. 670 | 671 | 5. Module Type - A string that is the module type name of the inserted module. 672 | 673 | 6. Serial Number - A string that is the serial number of module. This is primarily of interest for inventory purposes. 674 | 675 | 7. Copyright - A string that is the copyright information. This usually reads "Original Siemens Equipment", but it is possible a third party implementation of the S7 protocol stack could provide additional information. 676 | 677 | 8. Plant Identification - A string that represents the plant identification that is configured on the device. This string has rarely been seen in our scanning, but it could provide useful intelligence. 678 | 679 | 680 | ####History and Background 681 | 682 | From Wikipedia article on SIMATIC http://simple.wikipedia.org/wiki/SIMATIC: 683 | 684 | > SIMATIC is the name of an automation system which was developed by the German company Siemens. The automation system controls machines used for industrial production. This system makes it possible for machines to run automatically. 685 | 686 | 687 | ####Installation 688 | 689 | This script requires Nmap to run. If you do not have Nmap download and Install Nmap based off the Nmap instructions. 690 | http://nmap.org/download.html 691 | 692 | #####Windows 693 | 694 | After downloading s7-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as an administrator. Go to Start -> Programs -> Accessories, and right click on 'Command Prompt'. Select 'Run as Administrator'. 695 | 696 | move s7-enumerate.nse C:\Program Files (x86)\Nmap\scripts 697 | 698 | #####Linux 699 | 700 | After Downloading s7-enumerate.nse you'll need to move it into the NSE Scripts directory, this will have to be done as sudo/root. 701 | 702 | sudo mv s7-enumerate.nse /usr/share/nmap/scripts 703 | 704 | 705 | ####Usage 706 | 707 | Inside a Terminal Window/Command Prompt use one of the following commands where is the target you wish you scan for S7 PLCs. 708 | 709 | Windows: nmap -p 102 --script s7-enumerate -sV 710 | 711 | Linux: sudo nmap -p 102 --script s7-enumerate -sV 712 | 713 | 714 | ####Notes 715 | 716 | The official version of this script is maintained at:https://github.com/digitalbond/Redpoint/s7-enumerate.nse 717 | 718 | This script uses the standard S7COMMS destination port of TCP 102. 719 | 720 | 721 | -------------------------------------------------------------------------------- /atg-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ This Script is designed to query the I20100 command on Guardian AST Automatic Tank Gauge 9 | products. This script sends a single query and parses the response. This response is the Tank Inventory 10 | of the ATG. Using --script-args command=I20200 you will be able to pull a diffrent report than the I20100. 11 | 12 | Based off of www.veeder.com/gold/download.cfm?doc_id=3668 13 | 14 | ]] 15 | 16 | --- 17 | -- @usage 18 | -- nmap --script atg-info -p 10001 19 | -- 20 | -- @args command If set to another command, It will do that command instead of I20100 21 | -- 22 | -- @output 23 | --10001/tcp open Guardian AST reset 24 | --| atg-info: 25 | --| I20100 26 | --| SEP 19, 2015 5:33 PM 27 | --| 28 | --| Fuel Company 29 | --| 12 Fake St 30 | --| Anytown, USA 12345 31 | --| 32 | --| 33 | --| IN-TANK INVENTORY 34 | --| 35 | --| TANK PRODUCT VOLUME TC VOLUME ULLAGE HEIGHT WATER TEMP 36 | --| 1 UNLEADED 5135 0 6647 42.71 0.00 72.01 37 | --| 2 UNLEADED 5135 0 6647 42.70 0.00 71.55 38 | --| 3 PREMIUM UNLEADED 5135 0 5350 19.27 0.00 72.52 39 | --|_ 40 | 41 | 42 | author = "Stephen J. Hilt" 43 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 44 | categories = {"discovery"} 45 | 46 | 47 | -- 48 | -- Function to define the portrule as per nmap standards 49 | portrule = shortport.port_or_service(10001, "atg") 50 | --- 51 | -- Function to set the nmap output for the host, if a valid ATG packet 52 | -- is received then the output will show that the port as ATG instead of 53 | -- tcpwrapped 54 | -- 55 | -- @param host Host that was passed in via nmap 56 | -- @param port port that ATG is running on (Default TCP/10001) 57 | function set_nmap(host, port) 58 | 59 | --set port Open 60 | port.state = "open" 61 | -- set version name to Guardian AST 62 | port.version.name = " Guardian AST" 63 | nmap.set_port_version(host, port) 64 | nmap.set_port_state(host, port, "open") 65 | 66 | end 67 | 68 | 69 | --- 70 | -- Action Function that is used to run the NSE. This function will send the initial query to the 71 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 72 | -- is a ATG device. If it is then more actions are taken to gather extra information. 73 | -- 74 | -- @param host Host that was scanned via nmap 75 | -- @param port port that was scanned via nmap 76 | action = function(host, port) 77 | local command = "I20100" 78 | local arguments = stdnse.get_script_args('command') 79 | if ( arguments ~= "I20100" and arguments ~= nil) then 80 | command = arguments 81 | end 82 | -- create new socket 83 | local sock = nmap.new_socket() 84 | -- set timeout low in case we don't get a response 85 | sock:set_timeout(1000) 86 | -- query to pull the tank inventory 87 | local tank_command = "\x01" .. command .. "\n" 88 | -- Connect to the remote host 89 | local constatus, conerr = sock:connect(host, port) 90 | if not constatus then 91 | stdnse.debug1( 92 | 'Error establishing a TCP connection for %s - %s', host, conerr 93 | ) 94 | return nil 95 | end 96 | -- send query to inventory the tanks 97 | local sendstatus, senderr = sock:send(tank_command) 98 | if not sendstatus then 99 | stdnse.debug1( 100 | 'Error sending ATG request to %s:%d - %s', 101 | host.ip, port.number, senderr 102 | ) 103 | return nil 104 | end 105 | -- receive the response for parseing 106 | local rcvstatus, response = sock:receive_bytes(1024) 107 | if(rcvstatus == false) then 108 | stdnse.debug1( "Receive error: %s", response) 109 | return nil 110 | end 111 | -- if the response was timeout, then we will return that we had a timeout 112 | --(for now add more addresses later) 113 | if (response == "TIMEOUT" or response == "EOF") then 114 | sock:close() 115 | return "TIMEOUT: No response from query" 116 | end 117 | -- if the first byte is 0x01, or 0x0a then likely the response is an ATG 118 | if(string.byte(response,1) == 0x01 or string.byte(response,1) == 0x0a) then 119 | local inventory_output = string.sub(response,2,-2) 120 | set_nmap(host, port) 121 | sock:close() 122 | return inventory_output 123 | end 124 | end 125 | 126 | -------------------------------------------------------------------------------- /codesys-v2-discover.nse: -------------------------------------------------------------------------------- 1 | local nmap = require "nmap" 2 | local comm = require "comm" 3 | local stdnse = require "stdnse" 4 | local strbuf = require "strbuf" 5 | local nsedebug = require "nsedebug" 6 | 7 | description = [[ 8 | 9 | http://digitalbond.com 10 | 11 | ]] 12 | 13 | author = "Stephen Hilt (Digital Bond)" 14 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | --- 18 | -- Script is executed for any TCP port. 19 | portrule = function( host, port ) 20 | return port.protocol == "tcp" 21 | end 22 | 23 | --- 24 | -- Function to set the nmap output for the host, if a valid CoDeSyS packet 25 | -- is received then the output will show that the port as CoDeSyS 26 | -- 27 | -- @param host Host that was passed in via nmap 28 | -- @param port port that CoDeSyS may be running on TCP/1200 or TCP/2455 29 | function set_nmap(host, port) 30 | 31 | --set port Open 32 | port.state = "open" 33 | -- set version name to CoDeSyS 34 | port.version.name = "CoDeSyS" 35 | nmap.set_port_version(host, port) 36 | nmap.set_port_state(host, port, "open") 37 | 38 | end 39 | 40 | --- 41 | -- Remove extra whitespace from the beginning and end the string 42 | -- 43 | -- @param s string to remove extra white space 44 | 45 | function trim(s) 46 | -- remove white spaces from beginning and ending of the string 47 | return (s:gsub("^%s*(.-)%s*$", "%1")) 48 | end 49 | 50 | --- 51 | -- Action Function that is used to run the NSE. This function will send the initial query to the 52 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 53 | -- is a CoDeSys device. If it is then more actions are taken to gather extra information. 54 | -- 55 | -- @param host Host that was scanned via nmap 56 | -- @param port port that was scanned via nmap 57 | action = function( host, port ) 58 | -- little endian query 59 | lile_query = bin.pack("H", "bbbb0100000001") 60 | -- big endian query 61 | bige_query = bin.pack("H", "bbbb0100000101") 62 | -- set up table for output 63 | local output = stdnse.output_table() 64 | -- create socket 65 | local sock = nmap.new_socket() 66 | -- connect to remote host 67 | local constatus, conerr = sock:connect(host, port) 68 | -- if not successful debug error message and return nil 69 | if not constatus then 70 | stdnse.print_debug(1, 71 | 'Error establishing a TCP connection for %s - %s', host, conerr 72 | ) 73 | return nil 74 | end 75 | -- send little endian query 76 | local sendstatus, senderr = sock:send(lile_query) 77 | if not sendstatus then 78 | stdnse.print_debug(1, 79 | 'Error sending CoDeSyS request to %s:%d - %s', 80 | host.ip, port.number, senderr 81 | ) 82 | return nil 83 | end 84 | -- recieve response 85 | local rcvstatus, response = sock:receive() 86 | if(rcvstatus == false) then 87 | stdnse.print_debug(1, "Receive error: %s", response) 88 | return nil 89 | end 90 | -- if there was no response, try big endian 91 | if(response == "EOF" or response == "TIMEOUT") then 92 | -- try sending big endian query 93 | local sendstatus, senderr = sock:send(bige_query) 94 | if not sendstatus then 95 | stdnse.print_debug(1, 96 | 'Error sending CoDeSyS request to %s:%d - %s', 97 | host.ip, port.number, senderr 98 | ) 99 | return nil 100 | end 101 | -- receive response 102 | local rcvstatus, response = sock:receive() 103 | if(rcvstatus == false) then 104 | stdnse.print_debug(1, "Receive error: %s", response) 105 | return nil 106 | end 107 | end 108 | -- unpack first byte to see if it is 0xbb 109 | local pos, codesys_check = bin.unpack("C", response, 1) 110 | -- is first byte 0xbb? 111 | if (codesys_check ~= 0xbb) then 112 | sock:close() 113 | return nil 114 | end 115 | 116 | local pos, os_name = bin.unpack("z", response, 65) 117 | local pos , os_type = bin.unpack("z", response, 97) 118 | local pos, product_type = bin.unpack("z", response, 129) 119 | -- close socket 120 | sock:close() 121 | -- set nmap port 122 | set_nmap(host, port) 123 | -- set output table (for future growth of information) 124 | output["OS Name"] = os_name .. " " .. os_type 125 | output["Product Type"] = product_type 126 | -- return output table to nmap 127 | return output 128 | end 129 | -------------------------------------------------------------------------------- /cspv4-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ 9 | This NSE script is used to send a CSPV4 packet to a remote device that has TCP 2222 open. This is a port used via CIP 10 | and used by CSPV4 on AB PLC5 systems. This will determine the Session ID of the remote device to verify it as a CSPV4 11 | compliant device. CSPV4 or AB/Ethernet is used by Allen Bradley inside of its software products such as RSLinx to 12 | communicate to the PLCs. This will help ideitify some Allen Bradley PLCs that do not communicate via Ethernet/IP. 13 | Example: PLC5, SLC 500 14 | 15 | ]] 16 | --- 17 | -- @usage 18 | -- nmap --script cspv4-info -p 2222 19 | -- 20 | -- 21 | -- @output 22 | --PORT STATE SERVICE 23 | --2222/tcp open CSPV4 24 | --| cspv4-info: 25 | --|_ Session ID: 65792 26 | 27 | author = "Stephen Hilt" 28 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 29 | categories = {"discovery", "intrusive"} 30 | 31 | -- 32 | -- Function to define the portrule as per nmap standards 33 | -- 34 | -- 35 | -- 36 | portrule = shortport.portnumber(2222, "tcp") 37 | 38 | --- 39 | -- Function to set the nmap output for the host, if a valid CSPV4 packet 40 | -- is received then the output will show that the port as CSPV4 instead of 41 | -- unknown 42 | -- 43 | -- @param host Host that was passed in via nmap 44 | -- @param port port that CSPV4 is running on (Default TCP/2222) 45 | function set_nmap(host, port) 46 | 47 | --set port Open 48 | port.state = "open" 49 | -- set version name to cspv4 50 | port.version.name = "CSPV4" 51 | nmap.set_port_version(host, port) 52 | nmap.set_port_state(host, port, "open") 53 | 54 | end 55 | --- 56 | -- Action Function that is used to run the NSE. 57 | -- 58 | -- @param host Host that was scanned via nmap 59 | -- @param port port that was scanned via nmap 60 | action = function(host,port) 61 | -- pack the inital communications to the PLC5 62 | local init_coms = bin.pack("H","01010000000000000000000000040005000000000000000000000000") 63 | -- create table for output 64 | local output = stdnse.output_table() 65 | -- create local vars for socket handling 66 | local socket, try, catch 67 | -- create new socket 68 | socket = nmap.new_socket() 69 | -- define the catch of the try statement 70 | catch = function() 71 | socket:close() 72 | end 73 | -- create new try 74 | try = nmap.new_try(catch) 75 | 76 | -- connect to port on host 77 | try(socket:connect(host, port)) 78 | -- send Req Identity packet 79 | try(socket:send(init_coms)) 80 | -- receive response 81 | local rcvstatus, response = socket:receive() 82 | if(rcvstatus == false) then 83 | return false, response 84 | end 85 | -- unpack the response first byte 86 | local pos, first_check = bin.unpack("C", response, 1) 87 | -- Validate the response is the response we expected 88 | if(first_check == 0x02) then 89 | -- store Session ID in output table 90 | pos, output["Session ID"] = bin.unpack("i", response, 5) 91 | -- set Nmap output 92 | set_nmap(host, port) 93 | -- close socket 94 | socket:close() 95 | -- return output table to Nmap 96 | return output 97 | -- If response is not what expcted then close connection and return nothing 98 | else 99 | socket:close() 100 | return nil 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /dnp3-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ 9 | 10 | This nmap NSE will send a command to query through the first 100 addresses of 11 | DNP3 to see if a valid response is given. If a valid response is given it will 12 | then parse the results based on function ID and other data. 13 | 14 | ]] 15 | 16 | --- 17 | -- @usage 18 | -- nmap --script dnp3-info -p 20000 19 | 20 | author = "Stephen J. Hilt" 21 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 22 | categories = {"discovery", "intrusive"} 23 | 24 | 25 | -- 26 | -- Function to define the portrule as per nmap standards 27 | portrule = shortport.port_or_service(20000, "dnp", "tcp") 28 | 29 | -- Datalink Function Codes PRM=0 30 | local function_id = { 31 | [0] = "ACK", 32 | [1] = "NACK", 33 | [11] = "Link Status", 34 | [15] = "User Data" 35 | } 36 | -- Data Link Function Codes PRM=1 37 | local alt_function_id = { 38 | [0] = "RESET Link", 39 | [1] = "Reset User Process", 40 | [2] = "TEST link", 41 | [3] = "User Data", 42 | [4] = "User Data", 43 | [9] = "Request Link Status" 44 | } 45 | -- lookup function codes based off the PRM (byte 2) 46 | function funct_lookup(id) 47 | local funct_id 48 | -- if the string is 4 bytes then was 0x0 49 | if (string.len(id) < 5) then 50 | -- look up function id in the table, if doesn't exist then its unknown 51 | funct_id = function_id[tonumber(id,2)] or "Unknown Function ID" 52 | id = tonumber(id,2) 53 | -- else byte was 0x?? 54 | else 55 | local first_value = string.byte(id, 2) % 0x10 56 | local second_value = tonumber(string.byte(id,5) % 0x10 .. string.byte(id,6) % 0x10 .. string.byte(id,7) %0x10 .. 57 | string.byte(id,8) % 0x10,2) 58 | if( first_value == 0) then 59 | -- look up function id in the table, if doesn't exist then its unknown 60 | funct_id = function_id[second_value] or "Unknown Function ID" 61 | else 62 | -- look up function id in the table, if doesn't exist then its unknown 63 | funct_id = alt_function_id[second_value] or "Unknown Function ID" 64 | end 65 | -- overwrite id to output what the value for if it was 0x?? 66 | id = second_value 67 | end 68 | return string.format("%s (%d)", funct_id, id) 69 | end 70 | --- 71 | -- Function to set the nmap output for the host, if a valid DNP3 packet 72 | -- is received then the output will show that the port as DNP3 instead of 73 | -- dnp 74 | -- 75 | -- @param host Host that was passed in via nmap 76 | -- @param port port that DNP3 is running on (Default TCP/20000) 77 | function set_nmap(host, port) 78 | 79 | --set port Open 80 | port.state = "open" 81 | -- set version name to DNP3 82 | port.version.name = "DNP3" 83 | nmap.set_port_version(host, port) 84 | nmap.set_port_state(host, port, "open") 85 | 86 | end 87 | 88 | 89 | --- 90 | -- Action Function that is used to run the NSE. This function will send the initial query to the 91 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 92 | -- is a DNP3 device. If it is then more actions are taken to gather extra information. 93 | -- 94 | -- @param host Host that was scanned via nmap 95 | -- @param port port that was scanned via nmap 96 | action = function(host, port) 97 | 98 | 99 | -- create new socket 100 | local sock = nmap.new_socket() 101 | -- set timeout low in case we don't get a response 102 | sock:set_timeout(1000) 103 | -- create output table 104 | local output = stdnse.output_table() 105 | -- query to pull the fist 100 address 106 | local first100 = bin.pack("H", "056405C900000000364C056405C901000000DE8E056405C" .. 107 | "9020000009F84056405C9030000007746056405C9040000" .. 108 | "001D90056405C905000000F552056405C906000000B4580" .. 109 | "56405C9070000005C9A056405C90800000019B9056405C9" .. 110 | "09000000F17B056405C90A000000B071056405C90B00000" .. 111 | "058B3056405C90C0000003265056405C90D000000DAA705" .. 112 | "6405C90E0000009BAD056405C90F000000736F056405C91" .. 113 | "000000011EB056405C911000000F929056405C912000000" .. 114 | "B823056405C91300000050E1056405C9140000003A37056" .. 115 | "405C915000000D2F5056405C91600000093FF056405C917" .. 116 | "0000007B3D056405C9180000003E1E056405C919000000D" .. 117 | "6DC056405C91A00000097D6056405C91B0000007F140564" .. 118 | "05C91C00000015C2056405C91D000000FD00056405C91E00" .. 119 | "0000BC0A056405C91F00000054C8056405C920000000014" .. 120 | "F056405C921000000E98D056405C922000000A887056405" .. 121 | "C9230000004045056405C9240000002A93056405C925000" .. 122 | "000C251056405C926000000835B056405C9270000006B99" .. 123 | "056405C9280000002EBA056405C929000000C678056405C" .. 124 | "92A0000008772056405C92B0000006FB0056405C92C0000" .. 125 | "000566056405C92D000000EDA4056405C92E000000ACAE0" .. 126 | "56405C92F000000446C056405C93000000026E8056405C9" .. 127 | "31000000CE2A056405C9320000008F20056405C93300000" .. 128 | "067E2056405C9340000000D34056405C935000000E5F605" .. 129 | "6405C936000000A4FC056405C9370000004C3E056405C93" .. 130 | "8000000091D056405C939000000E1DF056405C93A000000" .. 131 | "A0D5056405C93B0000004817056405C93C00000022C1056" .. 132 | "05C93D000000CA03056405C93E0000008B09056405C93F0" .. 133 | "0000063CB056405C940000000584A056405C941000000B0" .. 134 | "88056405C942000000F182056405C943000000194005640" .. 135 | "5C9440000007396056405C9450000009B54056405C94600" .. 136 | "0000DA5E056405C947000000329C056405C94800000077B" .. 137 | "F056405C9490000009F7D056405C94A000000DE77056405" .. 138 | "C94B00000036B5056405C94C0000005C63056405C94D000" .. 139 | "000B4A1056405C94E000000F5AB056405C94F0000001D69" .. 140 | "056405C9500000007FED056405C951000000972F056405C" .. 141 | "952000000D625056405C9530000003EE7056405C9540000" .. 142 | "005431056405C955000000BCF3056405C956000000FDF90" .. 143 | "56405C957000000153B056405C9580000005018056405C9" .. 144 | "59000000B8DA056405C95A000000F9D0056405C95B00000" .. 145 | "01112056405C95C0000007BC4056405C95D000000930605" .. 146 | "6405C95E000000D20C056405C95F0000003ACE056405C96" .. 147 | "00000006F49056405C961000000878B056405C962000000" .. 148 | "C681056405C9630000002E43056405C9640000004495") 149 | -- Connect to the remote host 150 | local constatus, conerr = sock:connect(host, port) 151 | if not constatus then 152 | stdnse.debug1( 153 | 'Error establishing a TCP connection for %s - %s', host, conerr 154 | ) 155 | return nil 156 | end 157 | -- send query for the first 100 addresses 158 | local sendstatus, senderr = sock:send(first100) 159 | if not sendstatus then 160 | stdnse.debug1( 161 | 'Error sending dnp3 request to %s:%d - %s', 162 | host.ip, port.number, senderr 163 | ) 164 | return nil 165 | end 166 | -- receive the response for parseing 167 | local rcvstatus, response = sock:receive() 168 | if(rcvstatus == false) then 169 | stdnse.debug1( "Receive error: %s", response) 170 | return nil 171 | end 172 | -- if the response was timeout, then we will return that we had a timeout 173 | --(for now add more addresses later) 174 | if (response == "TIMEOUT" or response == "EOF") then 175 | sock:close() 176 | return "TIMEOUT: No response from query" 177 | end 178 | -- unpack first two bytes 179 | local pos, byte1, byte2 = bin.unpack("CC", response, 1) 180 | -- check to see if it is 0x0564 181 | if( byte1 == 0x05 and byte2 == 0x64) then 182 | -- close socket 183 | sock:close() 184 | -- set nmap to reflect open DNP3 185 | set_nmap(host,port) 186 | -- unpack bit string for PRM checking as well as function codes 187 | local pos, ctrl = bin.unpack("B", response, 4) 188 | -- destination address 189 | local pos, dstadd = bin.unpack("S", response, 5) 190 | -- source address 191 | local pos, srceadd = bin.unpack("S", response, pos) 192 | -- set up output table with values 193 | output["Source Address"] = srceadd 194 | output["Destination Address"] = dstadd 195 | output["Control"] = funct_lookup(ctrl) 196 | -- return output 197 | return output 198 | -- if non 0x0564 response, then this is not a valid packet. 199 | else 200 | sock:close() 201 | return "ERROR: Non Valid DNP3 Packet Response\n\t" .. stdnse.tohex(response) 202 | end 203 | 204 | end 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /enip-enumerate.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local ipOps = require "ipOps" 3 | local nmap = require "nmap" 4 | local shortport = require "shortport" 5 | local stdnse = require "stdnse" 6 | local string = require "string" 7 | local table = require "table" 8 | 9 | description = [[ 10 | This NSE script is used to send a EtherNet/IP packet to a remote device that 11 | has TCP 44818 open. The script will send a Request Identity Packet and once a 12 | response is received, it validates that it was a proper response to the command 13 | that was sent, and then will parse out the data. Information that is parsed 14 | includes Vendor ID, Device Type, Product name, Serial Number, Product code, 15 | Revision Number, as well as the Device IP. 16 | 17 | This script was written based of information collected by using the the 18 | Wireshark dissector for CIP, and EtherNet/IP, The original information was 19 | collected by running a modified version of the ethernetip.py script ( 20 | https://github.com/paperwork/pyenip ) 21 | 22 | http://digitalbond.com 23 | 24 | ]] 25 | --- 26 | -- @usage 27 | -- nmap --script enip-enumerate -sU -p 44818 28 | -- 29 | -- 30 | -- @output 31 | --44818/tcp open EtherNet/IP 32 | --| enip-enumerate: 33 | --| Vendor: Rockwell Automation/Allen-Bradley (1) 34 | --| Product Name: 1769-L32E Ethernet Port 35 | --| Serial Number: 0x000000 36 | --| Device Type: Communications Adapter (12) 37 | --| Product Code: 158 38 | --| Revision: 3.7 39 | --|_ Device IP: 192.168.1.1 40 | -- @xmloutput 41 | --Rockwell Automation/Allen-Bradley (1) 42 | --1769-L32E Ethernet Port 43 | --0x000000 44 | --Communications Adapter (12) 45 | --158 46 | --3,7 47 | --192.168.1.1 48 | 49 | 50 | author = "Stephen Hilt (Digital Bond)" 51 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 52 | categories = {"discovery", "intrusive","digitalbond"} 53 | 54 | -- 55 | -- Function to define the portrule as per nmap standards 56 | -- 57 | -- 58 | -- 59 | portrule = shortport.portnumber(44818, "tcp") 60 | 61 | --- 62 | -- Table to look up the Vendor Name based on Vendor ID 63 | -- Returns "Unknown Vendor Number" if Vendor ID not recognized 64 | -- Table data from Wireshark dissector ( link to unofficial mirror ) 65 | -- https://github.com/avsej/wireshark/blob/master/epan/dissectors/packet-enip.c 66 | -- Fetched on 4/19/2014 67 | -- 68 | -- @key vennum Vendor number parsed out of the EtherNet/IP packet 69 | local vendor_id = { 70 | [0] = "Reserved", 71 | [1] = "Rockwell Automation/Allen-Bradley", 72 | [2] = "Namco Controls Corp.", 73 | [3] = "Honeywell Inc.", 74 | [4] = "Parker Hannifin Corp. (Veriflo Division)", 75 | [5] = "Rockwell Automation/Reliance Elec.", 76 | [6] = "Reserved", 77 | [7] = "SMC Corporation", 78 | [8] = "Molex Incorporated", 79 | [9] = "Western Reserve Controls Corp.", 80 | [10] = "Advanced Micro Controls Inc. (AMCI)", 81 | [11] = "ASCO Pneumatic Controls", 82 | [12] = "Banner Engineering Corp.", 83 | [13] = "Belden Wire & Cable Company", 84 | [14] = "Cooper Interconnect", 85 | [15] = "Reserved", 86 | [16] = "Daniel Woodhead Co. (Woodhead Connectivity)", 87 | [17] = "Dearborn Group Inc.", 88 | [18] = "Reserved", 89 | [19] = "Helm Instrument Company", 90 | [20] = "Huron Net Works", 91 | [21] = "Lumberg Inc.", 92 | [22] = "Online Development Inc.(Automation Value)", 93 | [23] = "Vorne Industries Inc.", 94 | [24] = "ODVA Special Reserve", 95 | [25] = "Reserved", 96 | [26] = "Festo Corporation", 97 | [27] = "Reserved", 98 | [28] = "Reserved", 99 | [29] = "Reserved", 100 | [30] = "Unico Inc.", 101 | [31] = "Ross Controls", 102 | [32] = "Reserved", 103 | [33] = "Reserved", 104 | [34] = "Hohner Corp.", 105 | [35] = "Micro Mo Electronics Inc.", 106 | [36] = "MKS Instruments Inc.", 107 | [37] = "Yaskawa Electric America formerly Magnetek Drives", 108 | [38] = "Reserved", 109 | [39] = "AVG Automation (Uticor)", 110 | [40] = "Wago Corporation", 111 | [41] = "Kinetics (Unit Instruments)", 112 | [42] = "IMI Norgren Limited", 113 | [43] = "BALLUFF Inc.", 114 | [44] = "Yaskawa Electric America Inc.", 115 | [45] = "Eurotherm Controls Inc", 116 | [46] = "ABB Industrial Systems", 117 | [47] = "Omron Corporation", 118 | [48] = "TURCk Inc.", 119 | [49] = "Grayhill Inc.", 120 | [50] = "Real Time Automation (C&ID)", 121 | [51] = "Reserved", 122 | [52] = "Numatics Inc.", 123 | [53] = "Lutze Inc.", 124 | [54] = "Reserved", 125 | [55] = "Reserved", 126 | [56] = "Softing GmbH", 127 | [57] = "Pepperl + Fuchs", 128 | [58] = "Spectrum Controls Inc.", 129 | [59] = "D.I.P. Inc. MKS Inst.", 130 | [60] = "Applied Motion Products Inc.", 131 | [61] = "Sencon Inc.", 132 | [62] = "High Country Tek", 133 | [63] = "SWAC Automation Consult GmbH", 134 | [64] = "Clippard Instrument Laboratory", 135 | [65] = "Reserved", 136 | [66] = "Reserved", 137 | [67] = "Reserved", 138 | [68] = "Eaton Electrical", 139 | [69] = "Reserved", 140 | [70] = "Reserved", 141 | [71] = "Toshiba International Corp.", 142 | [72] = "Control Technology Incorporated", 143 | [73] = "TCS (NZ) Ltd.", 144 | [74] = "HitachiLtd.", 145 | [75] = "ABB Robotics Products AB", 146 | [76] = "NKE Corporation", 147 | [77] = "Rockwell Software Inc.", 148 | [78] = "Escort Memory Systems (A Datalogic Group Co.)", 149 | [79] = "Reserved", 150 | [80] = "Industrial Devices Corporation", 151 | [81] = "IXXAT Automation GmbH", 152 | [82] = "Mitsubishi Electric Automation Inc.", 153 | [83] = "OPTO-22", 154 | [84] = "Reserved", 155 | [85] = "Reserved", 156 | [86] = "Horner Electric", 157 | [87] = "Burkert Werke GmbH & Co. KG", 158 | [88] = "Reserved", 159 | [89] = "Industrial Indexing Systems Inc.", 160 | [90] = "HMS Industrial Networks AB", 161 | [91] = "Robicon", 162 | [92] = "Helix Technology (Granville-Phillips)", 163 | [93] = "Arlington Laboratory", 164 | [94] = "Advantech Co. Ltd.", 165 | [95] = "Square D Company", 166 | [96] = "Digital Electronics Corp.", 167 | [97] = "Danfoss", 168 | [98] = "Reserved", 169 | [99] = "Reserved", 170 | [100] = "Bosch Rexroth Corporation] = Pneumatics", 171 | [101] = "Applied Materials Inc.", 172 | [102] = "Showa Electric Wire & Cable Co.", 173 | [103] = "Pacific Scientific (API Controls Inc.)", 174 | [104] = "Sharp Manufacturing Systems Corp.", 175 | [105] = "Olflex Wire & Cable Inc.", 176 | [106] = "Reserved", 177 | [107] = "Unitrode", 178 | [108] = "Beckhoff Automation GmbH", 179 | [109] = "National Instruments", 180 | [110] = "Mykrolis Corporations (Millipore)", 181 | [111] = "International Motion Controls Corp.", 182 | [112] = "Reserved", 183 | [113] = "SEG Kempen GmbH", 184 | [114] = "Reserved", 185 | [115] = "Reserved", 186 | [116] = "MTS Systems Corp.", 187 | [117] = "Krones Inc", 188 | [118] = "Reserved", 189 | [119] = "EXOR Electronic R & D", 190 | [120] = "SIEI S.p.A.", 191 | [121] = "KUKA Roboter GmbH", 192 | [122] = "Reserved", 193 | [123] = "SEC (Samsung Electronics Co.Ltd)", 194 | [124] = "Binary Electronics Ltd", 195 | [125] = "Flexible Machine Controls", 196 | [126] = "Reserved", 197 | [127] = "ABB Inc. (Entrelec)", 198 | [128] = "MAC Valves Inc.", 199 | [129] = "Auma Actuators Inc", 200 | [130] = "Toyoda Machine WorksLtd", 201 | [131] = "Reserved", 202 | [132] = "Reserved", 203 | [133] = "Balogh T.A.G.] = Corporation", 204 | [134] = "TR Systemtechnik GmbH", 205 | [135] = "UNIPULSE Corporation", 206 | [136] = "Reserved", 207 | [137] = "Reserved", 208 | [138] = "Conxall Corporation Inc.", 209 | [139] = "Reserved", 210 | [140] = "Reserved", 211 | [141] = "Kuramo Electric Co.Ltd.", 212 | [142] = "Creative Micro Designs", 213 | [143] = "GE Industrial Systems", 214 | [144] = "Leybold Vacuum GmbH", 215 | [145] = "Siemens Energy & Automation/Drives", 216 | [146] = "Kodensha Ltd", 217 | [147] = "Motion Engineering Inc.", 218 | [148] = "Honda Engineering Co.Ltd", 219 | [149] = "EIM Valve Controls", 220 | [150] = "Melec Inc.", 221 | [151] = "Sony Manufacturing Systems Corporation", 222 | [152] = "North American Mfg.", 223 | [153] = "WATLOW", 224 | [154] = "Japan Radio Co.Ltd", 225 | [155] = "NADEX Co.Ltd", 226 | [156] = "Ametek Automation & Process Technologies", 227 | [157] = "Reserved", 228 | [158] = "KVASER AB", 229 | [159] = "IDEC IZUMI Corporation", 230 | [160] = "Mitsubishi Heavy Industries Ltd", 231 | [161] = "Mitsubishi Electric Corporation", 232 | [162] = "Horiba-STEC Inc.", 233 | [163] = "esd electronic system design gmbh", 234 | [164] = "DAIHEN Corporation", 235 | [165] = "Tyco Valves & Controls/Keystone", 236 | [166] = "EBARA Corporation", 237 | [167] = "Reserved", 238 | [168] = "Reserved", 239 | [169] = "Hokuyo Electric Co. Ltd", 240 | [170] = "Pyramid Solutions Inc.", 241 | [171] = "Denso Wave Incorporated", 242 | [172] = "HLS Hard-Line Solutions Inc", 243 | [173] = "Caterpillar Inc.", 244 | [174] = "PDL Electronics Ltd.", 245 | [175] = "Reserved", 246 | [176] = "Red Lion Controls", 247 | [177] = "ANELVA Corporation", 248 | [178] = "Toyo Denki Seizo KK", 249 | [179] = "Sanyo Denki Co.Ltd", 250 | [180] = "Advanced Energy Japan K.K. (Aera Japan)", 251 | [181] = "Pilz GmbH & Co", 252 | [182] = "Marsh Bellofram-Bellofram PCD Division", 253 | [183] = "Reserved", 254 | [184] = "M-SYSTEM Co. Ltd", 255 | [185] = "Nissin Electric Co.Ltd", 256 | [186] = "Hitachi Metals Ltd.", 257 | [187] = "Oriental Motor Company", 258 | [188] = "A&D Co.Ltd", 259 | [189] = "Phasetronics Inc.", 260 | [190] = "Cummins Engine Company", 261 | [191] = "Deltron Inc.", 262 | [192] = "Geneer Corporation", 263 | [193] = "Anatol Automation Inc.", 264 | [194] = "Reserved", 265 | [195] = "Reserved", 266 | [196] = "Medar Inc.", 267 | [197] = "Comdel Inc.", 268 | [198] = "Advanced Energy Industries Inc", 269 | [199] = "Reserved", 270 | [200] = "DAIDEN Co.Ltd", 271 | [201] = "CKD Corporation", 272 | [202] = "Toyo Electric Corporation", 273 | [203] = "Reserved", 274 | [204] = "AuCom Electronics Ltd", 275 | [205] = "Shinko Electric Co.Ltd", 276 | [206] = "Vector Informatik GmbH", 277 | [207] = "Reserved", 278 | [208] = "Moog Inc.", 279 | [209] = "Contemporary Controls", 280 | [210] = "Tokyo Sokki Kenkyujo Co.Ltd", 281 | [211] = "Schenck-AccuRate Inc.", 282 | [212] = "The Oilgear Company", 283 | [213] = "Reserved", 284 | [214] = "ASM Japan K.K.", 285 | [215] = "HIRATA Corp.", 286 | [216] = "SUNX Limited", 287 | [217] = "Meidensha Corp.", 288 | [218] = "NIDEC SANKYO CORPORATION (Sankyo Seiki Mfg. Co.Ltd)", 289 | [219] = "KAMRO Corp.", 290 | [220] = "Nippon System Development Co.Ltd", 291 | [221] = "EBARA Technologies Inc.", 292 | [222] = "Reserved", 293 | [223] = "Reserved", 294 | [224] = "SG Co.Ltd", 295 | [225] = "Vaasa Institute of Technology", 296 | [226] = "MKS Instruments (ENI Technology)", 297 | [227] = "Tateyama System Laboratory Co.Ltd.", 298 | [228] = "QLOG Corporation", 299 | [229] = "Matric Limited Inc.", 300 | [230] = "NSD Corporation", 301 | [231] = "Reserved", 302 | [232] = "Sumitomo Wiring SystemsLtd", 303 | [233] = "Group 3 Technology Ltd", 304 | [234] = "CTI Cryogenics", 305 | [235] = "POLSYS CORP", 306 | [236] = "Ampere Inc.", 307 | [237] = "Reserved", 308 | [238] = "Simplatroll Ltd", 309 | [239] = "Reserved", 310 | [240] = "Reserved", 311 | [241] = "Leading Edge Design", 312 | [242] = "Humphrey Products", 313 | [243] = "Schneider Automation Inc.", 314 | [244] = "Westlock Controls Corp.", 315 | [245] = "Nihon Weidmuller Co.Ltd", 316 | [246] = "Brooks Instrument (Div. of Emerson)", 317 | [247] = "Reserved", 318 | [248] = " Moeller GmbH", 319 | [249] = "Varian Vacuum Products", 320 | [250] = "Yokogawa Electric Corporation", 321 | [251] = "Electrical Design Daiyu Co.Ltd", 322 | [252] = "Omron Software Co.Ltd", 323 | [253] = "BOC Edwards", 324 | [254] = "Control Technology Corporation", 325 | [255] = "Bosch Rexroth", 326 | [256] = "Turck", 327 | [257] = "Control Techniques PLC", 328 | [258] = "Hardy Instruments Inc.", 329 | [259] = "LS Industrial Systems", 330 | [260] = "E.O.A. Systems Inc.", 331 | [261] = "Reserved", 332 | [262] = "New Cosmos Electric Co.Ltd.", 333 | [263] = "Sense Eletronica LTDA", 334 | [264] = "Xycom Inc.", 335 | [265] = "Baldor Electric", 336 | [266] = "Reserved", 337 | [267] = "Patlite Corporation", 338 | [268] = "Reserved", 339 | [269] = "Mogami Wire & Cable Corporation", 340 | [270] = "Welding Technology Corporation (WTC)", 341 | [271] = "Reserved", 342 | [272] = "Deutschmann Automation GmbH", 343 | [273] = "ICP Panel-Tec Inc.", 344 | [274] = "Bray Controls USA", 345 | [275] = "Reserved", 346 | [276] = "Status Technologies", 347 | [277] = "Trio Motion Technology Ltd", 348 | [278] = "Sherrex Systems Ltd", 349 | [279] = "Adept Technology Inc.", 350 | [280] = "Spang Power Electronics", 351 | [281] = "Reserved", 352 | [282] = "Acrosser Technology Co.Ltd", 353 | [283] = "Hilscher GmbH", 354 | [284] = "IMAX Corporation", 355 | [285] = "Electronic Innovation Inc. (Falter Engineering)", 356 | [286] = "Netlogic Inc.", 357 | [287] = "Bosch Rexroth Corporation] = Indramat", 358 | [288] = "Reserved", 359 | [289] = "Reserved", 360 | [290] = "Murata Machinery Ltd.", 361 | [291] = "MTT Company Ltd.", 362 | [292] = "Kanematsu Semiconductor Corp.", 363 | [293] = "Takebishi Electric Sales Co.", 364 | [294] = "Tokyo Electron Device Ltd", 365 | [295] = "PFU Limited", 366 | [296] = "Hakko Automation Co.Ltd.", 367 | [297] = "Advanet Inc.", 368 | [298] = "Tokyo Electron Software Technologies Ltd.", 369 | [299] = "Reserved", 370 | [300] = "Shinagawa Electric Wire Co.Ltd.", 371 | [301] = "Yokogawa M&C Corporation", 372 | [302] = "KONAN Electric Co.Ltd.", 373 | [303] = "Binar Elektronik AB", 374 | [304] = "Furukawa Electric Co.", 375 | [305] = "Cooper Energy Services", 376 | [306] = "Schleicher GmbH & Co.", 377 | [307] = "Hirose Electric Co.Ltd", 378 | [308] = "Western Servo Design Inc.", 379 | [309] = "Prosoft Technology", 380 | [310] = "Reserved", 381 | [311] = "Towa Shoko Co.Ltd", 382 | [312] = "Kyopal Co.Ltd", 383 | [313] = "Extron Co.", 384 | [314] = "Wieland Electric GmbH", 385 | [315] = "SEW Eurodrive GmbH", 386 | [316] = "Aera Corporation", 387 | [317] = "STA Reutlingen", 388 | [318] = "Reserved", 389 | [319] = "Fuji Electric Co.Ltd.", 390 | [320] = "Reserved", 391 | [321] = "Reserved", 392 | [322] = "ifm efector] = inc.", 393 | [323] = "Reserved", 394 | [324] = "IDEACOD-Hohner Automation S.A.", 395 | [325] = "CommScope Inc.", 396 | [326] = "GE Fanuc Automation North America Inc.", 397 | [327] = "Matsushita Electric Industrial Co.Ltd", 398 | [328] = "Okaya Electronics Corporation", 399 | [329] = "KASHIYAMA IndustriesLtd", 400 | [330] = "JVC", 401 | [331] = "Interface Corporation", 402 | [332] = "Grape Systems Inc.", 403 | [333] = "Reserved", 404 | [334] = "Reserved", 405 | [335] = "Toshiba IT & Control Systems Corporation", 406 | [336] = "Sanyo Machine WorksLtd.", 407 | [337] = "Vansco Electronics Ltd.", 408 | [338] = "Dart Container Corp.", 409 | [339] = "Livingston & Co. Inc.", 410 | [340] = "Alfa Laval LKM as", 411 | [341] = "BF ENTRON Ltd. (British Federal)", 412 | [342] = "Bekaert Engineering NV", 413 | [343] = "Ferran Scientific Inc.", 414 | [344] = "KEBA AG", 415 | [345] = "Endress + Hauser", 416 | [346] = "Reserved", 417 | [347] = "ABB ALSTOM Power UK Ltd. (EGT)", 418 | [348] = "Berger Lahr GmbH", 419 | [349] = "Reserved", 420 | [350] = "Federal Signal Corp.", 421 | [351] = "Kawasaki Robotics (USA) Inc.", 422 | [352] = "Bently Nevada Corporation", 423 | [353] = "Reserved", 424 | [354] = "FRABA Posital GmbH", 425 | [355] = "Elsag Bailey Inc.", 426 | [356] = "Fanuc Robotics America", 427 | [357] = "Reserved", 428 | [358] = "Surface Combustion Inc.", 429 | [359] = "Reserved", 430 | [360] = "AILES Electronics Ind. Co.Ltd.", 431 | [361] = "Wonderware Corporation", 432 | [362] = "Particle Measuring Systems Inc.", 433 | [363] = "Reserved", 434 | [364] = "Reserved", 435 | [365] = "BITS Co.Ltd", 436 | [366] = "Japan Aviation Electronics Industry Ltd", 437 | [367] = "Keyence Corporation", 438 | [368] = "Kuroda Precision Industries Ltd.", 439 | [369] = "Mitsubishi Electric Semiconductor Application", 440 | [370] = "Nippon Seisen CableLtd.", 441 | [371] = "Omron ASO Co.Ltd", 442 | [372] = "Seiko Seiki Co.Ltd.", 443 | [373] = "Sumitomo Heavy IndustriesLtd.", 444 | [374] = "Tango Computer Service Corporation", 445 | [375] = "Technology Service Inc.", 446 | [376] = "Toshiba Information Systems (Japan) Corporation", 447 | [377] = "TOSHIBA Schneider Inverter Corporation", 448 | [378] = "Toyooki Kogyo Co.Ltd.", 449 | [379] = "XEBEC", 450 | [380] = "Madison Cable Corporation", 451 | [381] = "Hitati Engineering & Services Co.Ltd", 452 | [382] = "TEM-TECH Lab Co.Ltd", 453 | [383] = "International Laboratory Corporation", 454 | [384] = "Dyadic Systems Co.Ltd.", 455 | [385] = "SETO Electronics Industry Co.Ltd", 456 | [386] = "Tokyo Electron Kyushu Limited", 457 | [387] = "KEI System Co.Ltd", 458 | [388] = "Reserved", 459 | [389] = "Asahi Engineering Co.Ltd", 460 | [390] = "Contrex Inc.", 461 | [391] = "Paradigm Controls Ltd.", 462 | [392] = "Reserved", 463 | [393] = "Ohm Electric Co.Ltd.", 464 | [394] = "RKC Instrument Inc.", 465 | [395] = "Suzuki Motor Corporation", 466 | [396] = "Custom Servo Motors Inc.", 467 | [397] = "PACE Control Systems", 468 | [398] = "Reserved", 469 | [399] = "Reserved", 470 | [400] = "LINTEC Co.Ltd.", 471 | [401] = "Hitachi Cable Ltd.", 472 | [402] = "BUSWARE Direct", 473 | [403] = "Eaton Electric B.V. (former Holec Holland N.V.)", 474 | [404] = "VAT Vakuumventile AG", 475 | [405] = "Scientific Technologies Incorporated", 476 | [406] = "Alfa Instrumentos Eletronicos Ltda", 477 | [407] = "TWK Elektronik GmbH", 478 | [408] = "ABB Welding Systems AB", 479 | [409] = "BYSTRONIC Maschinen AG", 480 | [410] = "Kimura Electric Co.Ltd", 481 | [411] = "Nissei Plastic Industrial Co.Ltd", 482 | [412] = "Reserved", 483 | [413] = "Kistler-Morse Corporation", 484 | [414] = "Proteous Industries Inc.", 485 | [415] = "IDC Corporation", 486 | [416] = "Nordson Corporation", 487 | [417] = "Rapistan Systems", 488 | [418] = "LP-Elektronik GmbH", 489 | [419] = "GERBI & FASE S.p.A.(Fase Saldatura)", 490 | [420] = "Phoenix Digital Corporation", 491 | [421] = "Z-World Engineering", 492 | [422] = "Honda R&D Co.Ltd.", 493 | [423] = "Bionics Instrument Co.Ltd.", 494 | [424] = "Teknic Inc.", 495 | [425] = "R.Stahl Inc.", 496 | [426] = "Reserved", 497 | [427] = "Ryco Graphic Manufacturing Inc.", 498 | [428] = "Giddings & Lewis Inc.", 499 | [429] = "Koganei Corporation", 500 | [430] = "Reserved", 501 | [431] = "Nichigoh Communication Electric Wire Co.Ltd.", 502 | [432] = "Reserved", 503 | [433] = "Fujikura Ltd.", 504 | [434] = "AD Link Technology Inc.", 505 | [435] = "StoneL Corporation", 506 | [436] = "Computer Optical Products Inc.", 507 | [437] = "CONOS Inc.", 508 | [438] = "Erhardt + Leimer GmbH", 509 | [439] = "UNIQUE Co. Ltd", 510 | [440] = "Roboticsware Inc.", 511 | [441] = "Nachi Fujikoshi Corporation", 512 | [442] = "Hengstler GmbH", 513 | [443] = "Reserved", 514 | [444] = "SUNNY GIKEN Inc.", 515 | [445] = "Lenze Drive Systems GmbH", 516 | [446] = "CD Systems B.V.", 517 | [447] = "FMT/Aircraft Gate Support Systems AB", 518 | [448] = "Axiomatic Technologies Corp", 519 | [449] = "Embedded System Products Inc.", 520 | [450] = "Reserved", 521 | [451] = "Mencom Corporation", 522 | [452] = "Reserved", 523 | [453] = "Matsushita Welding Systems Co.Ltd.", 524 | [454] = "Dengensha Mfg. Co. Ltd.", 525 | [455] = "Quinn Systems Ltd.", 526 | [456] = "Tellima Technology Ltd", 527 | [457] = "MDT] = Software", 528 | [458] = "Taiwan Keiso Co.Ltd", 529 | [459] = "Pinnacle Systems", 530 | [460] = "Ascom Hasler Mailing Sys", 531 | [461] = "INSTRUMAR Limited", 532 | [462] = "Reserved", 533 | [463] = "Navistar International Transportation Corp", 534 | [464] = "Huettinger Elektronik GmbH + Co. KG", 535 | [465] = "OCM Technology Inc.", 536 | [466] = "Professional Supply Inc.", 537 | [467] = "Control Solutions", 538 | [468] = "Baumer IVO GmbH & Co. KG", 539 | [469] = "Worcester Controls Corporation", 540 | [470] = "Pyramid Technical Consultants Inc.", 541 | [471] = "Reserved", 542 | [472] = "Apollo Fire Detectors Limited", 543 | [473] = "Avtron Manufacturing Inc.", 544 | [474] = "Reserved", 545 | [475] = "Tokyo Keiso Co.Ltd.", 546 | [476] = "Daishowa Swiki Co.Ltd.", 547 | [477] = "Kojima Instruments Inc.", 548 | [478] = "Shimadzu Corporation", 549 | [479] = "Tatsuta Electric Wire & Cable Co.Ltd.", 550 | [480] = "MECS Corporation", 551 | [481] = "Tahara Electric", 552 | [482] = "Koyo Electronics", 553 | [483] = "Clever Devices", 554 | [484] = "GCD Hardware & Software GmbH", 555 | [485] = "Reserved", 556 | [486] = "Miller Electric Mfg Co.", 557 | [487] = "GEA Tuchenhagen GmbH", 558 | [488] = "Riken Keiki Co.] = LTD", 559 | [489] = "Keisokugiken Corporation", 560 | [490] = "Fuji Machine Mfg. Co.Ltd", 561 | [491] = "Reserved", 562 | [492] = "Nidec-Shimpo Corp.", 563 | [493] = "UTEC Corporation", 564 | [494] = "Sanyo Electric Co. Ltd.", 565 | [495] = "Reserved", 566 | [496] = "Reserved", 567 | [497] = "Okano Electric Wire Co. Ltd", 568 | [498] = "Shimaden Co. Ltd.", 569 | [499] = "Teddington Controls Ltd", 570 | [500] = "Reserved", 571 | [501] = "VIPA GmbH", 572 | [502] = "Warwick Manufacturing Group", 573 | [503] = "Danaher Controls", 574 | [504] = "Reserved", 575 | [505] = "Reserved", 576 | [506] = "American Science & Engineering", 577 | [507] = "Accutron Controls International Inc.", 578 | [508] = "Norcott Technologies Ltd", 579 | [509] = "TB Woods Inc", 580 | [510] = "Proportion-Air Inc.", 581 | [511] = "SICK Stegmann GmbH", 582 | [512] = "Reserved", 583 | [513] = "Edwards Signaling", 584 | [514] = "Sumitomo Metal IndustriesLtd", 585 | [515] = "Cosmo Instruments Co.Ltd.", 586 | [516] = "Denshosha Co.Ltd.", 587 | [517] = "Kaijo Corp.", 588 | [518] = "Michiproducts Co.Ltd.", 589 | [519] = "Miura Corporation", 590 | [520] = "TG Information Network Co.Ltd.", 591 | [521] = "Fujikin Inc.", 592 | [522] = "Estic Corp.", 593 | [523] = "GS Hydraulic Sales", 594 | [524] = "Reserved", 595 | [525] = "MTE Limited", 596 | [526] = "Hyde Park Electronics Inc.", 597 | [527] = "Pfeiffer Vacuum GmbH", 598 | [528] = "Cyberlogic Technologies", 599 | [529] = "OKUMA Corporation FA Systems Division", 600 | [530] = "Reserved", 601 | [531] = "Hitachi Kokusai Electric Co.Ltd.", 602 | [532] = "SHINKO TECHNOS Co.Ltd.", 603 | [533] = "Itoh Electric Co.Ltd.", 604 | [534] = "Colorado Flow Tech Inc.", 605 | [535] = "Love Controls Division/Dwyer Inst.", 606 | [536] = "Alstom Drives and Controls", 607 | [537] = "The Foxboro Company", 608 | [538] = "Tescom Corporation", 609 | [539] = "Reserved", 610 | [540] = "Atlas Copco Controls UK", 611 | [541] = "Reserved", 612 | [542] = "Autojet Technologies", 613 | [543] = "Prima Electronics S.p.A.", 614 | [544] = "PMA GmbH", 615 | [545] = "Shimafuji Electric Co.Ltd", 616 | [546] = "Oki Electric Industry Co.Ltd", 617 | [547] = "Kyushu Matsushita Electric Co.Ltd", 618 | [548] = "Nihon Electric Wire & Cable Co.Ltd", 619 | [549] = "Tsuken Electric Ind Co.Ltd", 620 | [550] = "Tamadic Co.", 621 | [551] = "MAATEL SA", 622 | [552] = "OKUMA America", 623 | [553] = "Control Techniques PLC-NA", 624 | [554] = "TPC Wire & Cable", 625 | [555] = "ATI Industrial Automation", 626 | [556] = "Microcontrol (Australia) Pty Ltd", 627 | [557] = "Serra Soldadura] = S.A.", 628 | [558] = "Southwest Research Institute", 629 | [559] = "Cabinplant International", 630 | [560] = "Sartorius Mechatronics T&H GmbH", 631 | [561] = "Comau S.p.A. Robotics & Final Assembly Division", 632 | [562] = "Phoenix Contact", 633 | [563] = "Yokogawa MAT Corporation", 634 | [564] = "asahi sangyo co.] = ltd.", 635 | [565] = "Reserved", 636 | [566] = "Akita Myotoku Ltd.", 637 | [567] = "OBARA Corp.", 638 | [568] = "Suetron Electronic GmbH", 639 | [569] = "Reserved", 640 | [570] = "Serck Controls Limited", 641 | [571] = "Fairchild Industrial Products Company", 642 | [572] = "ARO S.A.", 643 | [573] = "M2C GmbH", 644 | [574] = "Shin Caterpillar Mitsubishi Ltd.", 645 | [575] = "Santest Co.Ltd.", 646 | [576] = "Cosmotechs Co.Ltd.", 647 | [577] = "Hitachi Electric Systems", 648 | [578] = "Smartscan Ltd", 649 | [579] = "Woodhead Software & Electronics France", 650 | [580] = "Athena Controls Inc.", 651 | [581] = "Syron Engineering & Manufacturing Inc.", 652 | [582] = "Asahi Optical Co.Ltd.", 653 | [583] = "Sansha Electric Mfg. Co.Ltd.", 654 | [584] = "Nikki Denso Co.Ltd.", 655 | [585] = "Star Micronics] = Co.Ltd.", 656 | [586] = "Ecotecnia Socirtat Corp.", 657 | [587] = "AC Technology Corp.", 658 | [588] = "West Instruments Limited", 659 | [589] = "NTI Limited", 660 | [590] = "Delta Computer Systems Inc.", 661 | [591] = "FANUC Ltd.", 662 | [592] = "Hearn-Gu Lee", 663 | [593] = "ABB Automation Products", 664 | [594] = "Orion Machinery Co.Ltd.", 665 | [595] = "Reserved", 666 | [596] = "Wire-Pro Inc.", 667 | [597] = "Beijing Huakong Technology Co. Ltd.", 668 | [598] = "Yokoyama Shokai Co.Ltd.", 669 | [599] = "Toyogiken Co.Ltd.", 670 | [600] = "Coester Equipamentos Eletronicos Ltda.", 671 | [601] = "Reserved", 672 | [602] = "Electroplating Engineers of Japan Ltd.", 673 | [603] = "ROBOX S.p.A.", 674 | [604] = "Spraying Systems Company", 675 | [605] = "Benshaw Inc.", 676 | [606] = "ZPA-DP A.S.", 677 | [607] = "Wired Rite Systems", 678 | [608] = "Tandis Research Inc.", 679 | [609] = "SSD Drives GmbH", 680 | [610] = "ULVAC Japan Ltd.", 681 | [611] = "DYNAX Corporation", 682 | [612] = "Nor-Cal Products Inc.", 683 | [613] = "Aros Electronics AB", 684 | [614] = "Jun-Tech Co.Ltd.", 685 | [615] = "HAN-MI Co. Ltd.", 686 | [616] = "uniNtech (formerly SungGi Internet)", 687 | [617] = "Hae Pyung Electronics Reserch Institute", 688 | [618] = "Milwaukee Electronics", 689 | [619] = "OBERG Industries", 690 | [620] = "Parker Hannifin/Compumotor Division", 691 | [621] = "TECHNO DIGITAL CORPORATION", 692 | [622] = "Network Supply Co.Ltd.", 693 | [623] = "Union Electronics Co.Ltd.", 694 | [624] = "Tritronics Services PM Ltd.", 695 | [625] = "Rockwell Automation-Sprecher+Schuh", 696 | [626] = "Matsushita Electric Industrial Co.Ltd/Motor Co.", 697 | [627] = "Rolls-Royce Energy Systems Inc.", 698 | [628] = "JEONGIL INTERCOM CO.] = LTD", 699 | [629] = "Interroll Corp.", 700 | [630] = "Hubbell Wiring Device-Kellems (Delaware)", 701 | [631] = "Intelligent Motion Systems", 702 | [632] = "Reserved", 703 | [633] = "INFICON AG", 704 | [634] = "Hirschmann Inc.", 705 | [635] = "The Siemon Company", 706 | [636] = "YAMAHA Motor Co. Ltd.", 707 | [637] = "aska corporation", 708 | [638] = "Woodhead Connectivity", 709 | [639] = "Trimble AB", 710 | [640] = "Murrelektronik GmbH", 711 | [641] = "Creatrix Labs Inc.", 712 | [642] = "TopWorx", 713 | [643] = "Kumho Industrial Co.Ltd.", 714 | [644] = "Wind River Systems Inc.", 715 | [645] = "Bihl & Wiedemann GmbH", 716 | [646] = "Harmonic Drive Systems Inc.", 717 | [647] = "Rikei Corporation", 718 | [648] = "BL AutotecLtd.", 719 | [649] = "Hana Information & Technology Co.Ltd.", 720 | [650] = "Seoil Electric Co.Ltd.", 721 | [651] = "Fife Corporation", 722 | [652] = "Shanghai Electrical Apparatus Research Institute", 723 | [653] = "Reserved", 724 | [654] = "Parasense Development Centre", 725 | [655] = "Reserved", 726 | [656] = "Reserved", 727 | [657] = "Six Tau S.p.A.", 728 | [658] = "Aucos GmbH", 729 | [659] = "Rotork Controls", 730 | [660] = "Automationdirect.com", 731 | [661] = "Thermo BLH", 732 | [662] = "System ControlsLtd.", 733 | [663] = "Univer S.p.A.", 734 | [664] = "MKS-Tenta Technology", 735 | [665] = "Lika Electronic SNC", 736 | [666] = "Mettler-Toledo Inc.", 737 | [667] = "DXL USA Inc.", 738 | [668] = "Rockwell Automation/Entek IRD Intl.", 739 | [669] = "Nippon Otis Elevator Company", 740 | [670] = "Sinano Electric] = Co.Ltd.", 741 | [671] = "Sony Manufacturing Systems", 742 | [672] = "Reserved", 743 | [673] = "Contec Co.Ltd.", 744 | [674] = "Automated Solutions", 745 | [675] = "Controlweigh", 746 | [676] = "Reserved", 747 | [677] = "Fincor Electronics", 748 | [678] = "Cognex Corporation", 749 | [679] = "Qualiflow", 750 | [680] = "Weidmuller Inc.", 751 | [681] = "Morinaga Milk Industry Co.Ltd.", 752 | [682] = "Takagi Industrial Co.Ltd.", 753 | [683] = "Wittenstein AG", 754 | [684] = "Sena Technologies Inc.", 755 | [685] = "Reserved", 756 | [686] = "APV Products Unna", 757 | [687] = "Creator Teknisk Utvedkling AB", 758 | [688] = "Reserved", 759 | [689] = "Mibu Denki Industrial Co.Ltd.", 760 | [690] = "Takamastsu Machineer Section", 761 | [691] = "Startco Engineering Ltd.", 762 | [692] = "Reserved", 763 | [693] = "Holjeron", 764 | [694] = "ALCATEL High Vacuum Technology", 765 | [695] = "Taesan LCD Co.Ltd.", 766 | [696] = "POSCON", 767 | [697] = "VMIC", 768 | [698] = "Matsushita Electric WorksLtd.", 769 | [699] = "IAI Corporation", 770 | [700] = "Horst GmbH", 771 | [701] = "MicroControl GmbH & Co.", 772 | [702] = "Leine & Linde AB", 773 | [703] = "Reserved", 774 | [704] = "EC Elettronica Srl", 775 | [705] = "VIT Software HB", 776 | [706] = "Bronkhorst High-Tech B.V.", 777 | [707] = "Optex Co.Ltd.", 778 | [708] = "Yosio Electronic Co.", 779 | [709] = "Terasaki Electric Co.Ltd.", 780 | [710] = "Sodick Co.Ltd.", 781 | [711] = "MTS Systems Corporation-Automation Division", 782 | [712] = "Mesa Systemtechnik", 783 | [713] = "SHIN HO SYSTEM Co.Ltd.", 784 | [714] = "Goyo Electronics CoLtd.", 785 | [715] = "Loreme", 786 | [716] = "SAB Brockskes GmbH & Co. KG", 787 | [717] = "Trumpf Laser GmbH + Co. KG", 788 | [718] = "Niigata Electronic Instruments Co.Ltd.", 789 | [719] = "Yokogawa Digital Computer Corporation", 790 | [720] = "O.N. Electronic Co.Ltd.", 791 | [721] = "Industrial Control Communication Inc.", 792 | [722] = "ABB Inc.", 793 | [723] = "ElectroWave USA Inc.", 794 | [724] = "Industrial Network Controls] = LLC", 795 | [725] = "KDT Systems Co.Ltd.", 796 | [726] = "SEFA Technology Inc.", 797 | [727] = "Nippon POP Rivets and Fasteners Ltd.", 798 | [728] = "Yamato Scale Co.Ltd.", 799 | [729] = "Zener Electric", 800 | [730] = "GSE Scale Systems", 801 | [731] = "ISAS (Integrated Switchgear & Sys. Pty Ltd)", 802 | [732] = "Beta LaserMike Limited", 803 | [733] = "TOEI Electric Co.Ltd.", 804 | [734] = "Hakko Electronics Co.Ltd", 805 | [735] = "Reserved", 806 | [736] = "RFID Inc.", 807 | [737] = "Adwin Corporation", 808 | [738] = "Osaka VacuumLtd.", 809 | [739] = "A-Kyung Motion Inc.", 810 | [740] = "Camozzi S.P. A.", 811 | [741] = "Crevis Co.] = LTD", 812 | [742] = "Rice Lake Weighing Systems", 813 | [743] = "Linux Network Services", 814 | [744] = "KEB Antriebstechnik GmbH", 815 | [745] = "Hagiwara Electric Co.Ltd.", 816 | [746] = "Glass Inc. International", 817 | [747] = "Reserved", 818 | [748] = "DVT Corporation", 819 | [749] = "Woodward Governor", 820 | [750] = "Mosaic Systems Inc.", 821 | [751] = "Laserline GmbH", 822 | [752] = "COM-TEC Inc.", 823 | [753] = "Weed Instrument", 824 | [754] = "Prof-face European Technology Center", 825 | [755] = "Fuji Automation Co.Ltd.", 826 | [756] = "Matsutame Co.Ltd.", 827 | [757] = "Hitachi Via MechanicsLtd.", 828 | [758] = "Dainippon Screen Mfg. Co. Ltd.", 829 | [759] = "FLS Automation A/S", 830 | [760] = "ABB Stotz Kontakt GmbH", 831 | [761] = "Technical Marine Service", 832 | [762] = "Advanced Automation Associates Inc.", 833 | [763] = "Baumer Ident GmbH", 834 | [764] = "Tsubakimoto Chain Co.", 835 | [765] = "Reserved", 836 | [766] = "Furukawa Co.Ltd.", 837 | [767] = "Active Power", 838 | [768] = "CSIRO Mining Automation", 839 | [769] = "Matrix Integrated Systems", 840 | [770] = "Digitronic Automationsanlagen GmbH", 841 | [771] = "SICK STEGMANN Inc.", 842 | [772] = "TAE-Antriebstechnik GmbH", 843 | [773] = "Electronic Solutions", 844 | [774] = "Rocon L.L.C.", 845 | [775] = "Dijitized Communications Inc.", 846 | [776] = "Asahi Organic Chemicals Industry Co.Ltd.", 847 | [777] = "Hodensha", 848 | [778] = "Harting Inc. NA", 849 | [779] = "Kubler GmbH", 850 | [780] = "Yamatake Corporation", 851 | [781] = "JEOL", 852 | [782] = "Yamatake Industrial Systems Co.Ltd.", 853 | [783] = "HAEHNE Elektronische Messgerate GmbH", 854 | [784] = "Ci Technologies Pty Ltd (for Pelamos Industries)", 855 | [785] = "N. SCHLUMBERGER & CIE", 856 | [786] = "Teijin Seiki Co.Ltd.", 857 | [787] = "DAIKIN IndustriesLtd", 858 | [788] = "RyuSyo Industrial Co.Ltd.", 859 | [789] = "SAGINOMIYA SEISAKUSHO] = INC.", 860 | [790] = "Seishin Engineering Co.Ltd.", 861 | [791] = "Japan Support System Ltd.", 862 | [792] = "Decsys", 863 | [793] = "Metronix Messgerate u. Elektronik GmbH", 864 | [794] = "Reserved", 865 | [795] = "Vaccon Company Inc.", 866 | [796] = "Siemens Energy & Automation Inc.", 867 | [797] = "Ten X Technology Inc.", 868 | [798] = "Tyco Electronics", 869 | [799] = "Delta Power Electronics Center", 870 | [800] = "Denker", 871 | [801] = "Autonics Corporation", 872 | [802] = "JFE Electronic Engineering Pty. Ltd.", 873 | [803] = "Reserved", 874 | [804] = "Electro-Sensors Inc.", 875 | [805] = "Digi International Inc.", 876 | [806] = "Texas Instruments", 877 | [807] = "ADTEC Plasma Technology Co.Ltd", 878 | [808] = "SICK AG", 879 | [809] = "Ethernet Peripherals Inc.", 880 | [810] = "Animatics Corporation", 881 | [811] = "Reserved", 882 | [812] = "Process Control Corporation", 883 | [813] = "SystemV. Inc.", 884 | [814] = "Danaher Motion SRL", 885 | [815] = "SHINKAWA Sensor Technology Inc.", 886 | [816] = "Tesch GmbH & Co. KG", 887 | [817] = "Reserved", 888 | [818] = "Trend Controls Systems Ltd.", 889 | [819] = "Guangzhou ZHIYUAN Electronic Co.Ltd.", 890 | [820] = "Mykrolis Corporation", 891 | [821] = "Bethlehem Steel Corporation", 892 | [822] = "KK ICP", 893 | [823] = "Takemoto Denki Corporation", 894 | [824] = "The Montalvo Corporation", 895 | [825] = "Reserved", 896 | [826] = "LEONI Special Cables GmbH", 897 | [827] = "Reserved", 898 | [828] = "ONO SOKKI CO.,LTD.", 899 | [829] = "Rockwell Samsung Automation", 900 | [830] = "SHINDENGEN ELECTRIC MFG. CO. LTD", 901 | [831] = "Origin Electric Co. Ltd.", 902 | [832] = "Quest Technical Solutions Inc.", 903 | [833] = "LS CableLtd.", 904 | [834] = "Enercon-Nord Electronic GmbH", 905 | [835] = "Northwire Inc.", 906 | [836] = "Engel Elektroantriebe GmbH", 907 | [837] = "The Stanley Works", 908 | [838] = "Celesco Transducer Products Inc.", 909 | [839] = "Chugoku Electric Wire and Cable Co.", 910 | [840] = "Kongsberg Simrad AS", 911 | [841] = "Panduit Corporation", 912 | [842] = "Spellman High Voltage Electronics Corp.", 913 | [843] = "Kokusai Electric Alpha Co.Ltd.", 914 | [844] = "Brooks Automation Inc.", 915 | [845] = "ANYWIRE CORPORATION", 916 | [846] = "Honda Electronics Co. Ltd", 917 | [847] = "REO Elektronik AG", 918 | [848] = "Fusion UV Systems Inc.", 919 | [849] = "ASI Advanced Semiconductor Instruments GmbH", 920 | [850] = "Datalogic Inc.", 921 | [851] = "SoftPLC Corporation", 922 | [852] = "Dynisco Instruments LLC", 923 | [853] = "WEG Industrias SA", 924 | [854] = "Frontline Test Equipment Inc.", 925 | [855] = "Tamagawa Seiki Co.Ltd.", 926 | [856] = "Multi Computing Co.Ltd.", 927 | [857] = "RVSI", 928 | [858] = "Commercial Timesharing Inc.", 929 | [859] = "Tennessee Rand Automation LLC", 930 | [860] = "Wacogiken Co.Ltd", 931 | [861] = "Reflex Integration Inc.", 932 | [862] = "Siemens AG] = A&D PI Flow Instruments", 933 | [863] = "G. Bachmann Electronic GmbH", 934 | [864] = "NT International", 935 | [865] = "Schweitzer Engineering Laboratories", 936 | [866] = "ATR Industrie-Elektronik GmbH Co.", 937 | [867] = "PLASMATECH Co.Ltd", 938 | [868] = "Reserved", 939 | [869] = "GEMU GmbH & Co. KG", 940 | [870] = "Alcorn McBride Inc.", 941 | [871] = "MORI SEIKI CO.] = LTD", 942 | [872] = "NodeTech Systems Ltd", 943 | [873] = "Emhart Teknologies", 944 | [874] = "Cervis Inc.", 945 | [875] = "FieldServer Technologies (Div Sierra Monitor Corp)", 946 | [876] = "NEDAP Power Supplies", 947 | [877] = "Nippon Sanso Corporation", 948 | [878] = "Mitomi Giken Co.Ltd.", 949 | [879] = "PULS GmbH", 950 | [880] = "Reserved", 951 | [881] = "Japan Control Engineering Ltd", 952 | [882] = "Embedded Systems Korea (Former Zues Emtek Co Ltd.)", 953 | [883] = "Automa SRL", 954 | [884] = "Harms+Wende GmbH & Co KG", 955 | [885] = "SAE-STAHL GmbH", 956 | [886] = "Microwave Data Systems", 957 | [887] = "Bernecker + Rainer Industrie-Elektronik GmbH", 958 | [888] = "Hiprom Technologies", 959 | [889] = "Reserved", 960 | [890] = "Nitta Corporation", 961 | [891] = "Kontron Modular Computers GmbH", 962 | [892] = "Marlin Controls", 963 | [893] = "ELCIS s.r.l.", 964 | [894] = "Acromag Inc.", 965 | [895] = "Avery Weigh-Tronix", 966 | [896] = "Reserved", 967 | [897] = "Reserved", 968 | [898] = "Reserved", 969 | [899] = "Practicon Ltd", 970 | [900] = "Schunk GmbH & Co. KG", 971 | [901] = "MYNAH Technologies", 972 | [902] = "Defontaine Groupe", 973 | [903] = "Emerson Process Management Power & Water Solutions", 974 | [904] = "F.A. Elec", 975 | [905] = "Hottinger Baldwin Messtechnik GmbH", 976 | [906] = "Coreco Imaging Inc.", 977 | [907] = "London Electronics Ltd.", 978 | [908] = "HSD SpA", 979 | [909] = "Comtrol Corporation", 980 | [910] = "TEAM] = S.A. (Tecnica Electronica de Automatismo Y Medida)", 981 | [911] = "MAN B&W Diesel Ltd. Regulateurs Europa", 982 | [912] = "Reserved", 983 | [913] = "Reserved", 984 | [914] = "Micro Motion Inc.", 985 | [915] = "Eckelmann AG", 986 | [916] = "Hanyoung Nux", 987 | [917] = "Ransburg Industrial Finishing KK", 988 | [918] = "Kun Hung Electric Co. Ltd.", 989 | [919] = "Brimos wegbebakening b.v.", 990 | [920] = "Nitto Seiki Co.Ltd", 991 | [921] = "PPT Vision Inc.", 992 | [922] = "Yamazaki Machinery Works", 993 | [923] = "SCHMIDT Technology GmbH", 994 | [924] = "Parker Hannifin SpA (SBC Division)", 995 | [925] = "HIMA Paul Hildebrandt GmbH", 996 | [926] = "RivaTek Inc.", 997 | [927] = "Misumi Corporation", 998 | [928] = "GE Multilin", 999 | [929] = "Measurement Computing Corporation", 1000 | [930] = "Jetter AG", 1001 | [931] = "Tokyo Electronics Systems Corporation", 1002 | [932] = "Togami Electric Mfg. Co.Ltd.", 1003 | [933] = "HK Systems", 1004 | [934] = "CDA Systems Ltd.", 1005 | [935] = "Aerotech Inc.", 1006 | [936] = "JVL Industrie Elektronik A/S", 1007 | [937] = "NovaTech Process Solutions LLC", 1008 | [938] = "Reserved", 1009 | [939] = "Cisco Systems", 1010 | [940] = "Grid Connect", 1011 | [941] = "ITW Automotive Finishing", 1012 | [942] = "HanYang System", 1013 | [943] = "ABB K.K. Technical Center", 1014 | [944] = "Taiyo Electric Wire & Cable Co.Ltd.", 1015 | [945] = "Reserved", 1016 | [946] = "SEREN IPS INC", 1017 | [947] = "Belden CDT Electronics Division", 1018 | [948] = "ControlNet International", 1019 | [949] = "Gefran S.P.A.", 1020 | [950] = "Jokab Safety AB", 1021 | [951] = "SUMITA OPTICAL GLASS] = INC.", 1022 | [952] = "Biffi Italia srl", 1023 | [953] = "Beck IPC GmbH", 1024 | [954] = "Copley Controls Corporation", 1025 | [955] = "Fagor Automation S. Coop.", 1026 | [956] = "DARCOM", 1027 | [957] = "Frick Controls (div. of York International)", 1028 | [958] = "SymCom Inc.", 1029 | [959] = "Infranor", 1030 | [960] = "Kyosan CableLtd.", 1031 | [961] = "Varian Vacuum Technologies", 1032 | [962] = "Messung Systems", 1033 | [963] = "Xantrex Technology Inc.", 1034 | [964] = "StarThis Inc.", 1035 | [965] = "Chiyoda Co.Ltd.", 1036 | [966] = "Flowserve Corporation", 1037 | [967] = "Spyder Controls Corp.", 1038 | [968] = "IBA AG", 1039 | [969] = "SHIMOHIRA ELECTRIC MFG.CO.,LTD", 1040 | [970] = "Reserved", 1041 | [971] = "Siemens L&A", 1042 | [972] = "Micro Innovations AG", 1043 | [973] = "Switchgear & Instrumentation", 1044 | [974] = "PRE-TECH CO.] = LTD.", 1045 | [975] = "National Semiconductor", 1046 | [976] = "Invensys Process Systems", 1047 | [977] = "Ametek HDR Power Systems", 1048 | [978] = "Reserved", 1049 | [979] = "TETRA-K Corporation", 1050 | [980] = "C & M Corporation", 1051 | [981] = "Siempelkamp Maschinen", 1052 | [982] = "Reserved", 1053 | [983] = "Daifuku America Corporation", 1054 | [984] = "Electro-Matic Products Inc.", 1055 | [985] = "BUSSAN MICROELECTRONICS CORP.", 1056 | [986] = "ELAU AG", 1057 | [987] = "Hetronic USA", 1058 | [988] = "NIIGATA POWER SYSTEMS Co.Ltd.", 1059 | [989] = "Software Horizons Inc.", 1060 | [990] = "B3 Systems Inc.", 1061 | [991] = "Moxa Networking Co.Ltd.", 1062 | [992] = "Reserved", 1063 | [993] = "S4 Integration", 1064 | [994] = "Elettro Stemi S.R.L.", 1065 | [995] = "AquaSensors", 1066 | [996] = "Ifak System GmbH", 1067 | [997] = "SANKEI MANUFACTURING Co.,LTD.", 1068 | [998] = "Emerson Network Power Co.Ltd.", 1069 | [999] = "Fairmount Automation Inc.", 1070 | [1000] = "Bird Electronic Corporation", 1071 | [1001] = "Nabtesco Corporation", 1072 | [1002] = "AGM Electronics Inc.", 1073 | [1003] = "ARCX Inc.", 1074 | [1004] = "DELTA I/O Co.", 1075 | [1005] = "Chun IL Electric Ind. Co.", 1076 | [1006] = "N-Tron", 1077 | [1007] = "Nippon Pneumatics/Fludics System CO.,LTD.", 1078 | [1008] = "DDK Ltd.", 1079 | [1009] = "Seiko Epson Corporation", 1080 | [1010] = "Halstrup-Walcher GmbH", 1081 | [1011] = "ITT", 1082 | [1012] = "Ground Fault Systems bv", 1083 | [1013] = "Scolari Engineering S.p.A.", 1084 | [1014] = "Vialis Traffic bv", 1085 | [1015] = "Weidmueller Interface GmbH & Co. KG", 1086 | [1016] = "Shanghai Sibotech Automation Co. Ltd", 1087 | [1017] = "AEG Power Supply Systems GmbH", 1088 | [1018] = "Komatsu Electronics Inc.", 1089 | [1019] = "Souriau", 1090 | [1020] = "Baumuller Chicago Corp.", 1091 | [1021] = "J. Schmalz GmbH", 1092 | [1022] = "SEN Corporation", 1093 | [1023] = "Korenix Technology Co. Ltd", 1094 | [1024] = "Cooper Power Tools", 1095 | [1025] = "INNOBIS", 1096 | [1026] = "Shinho System", 1097 | [1027] = "Xm Services Ltd.", 1098 | [1028] = "KVC Co.Ltd.", 1099 | [1029] = "Sanyu Seiki Co.Ltd.", 1100 | [1030] = "TuxPLC", 1101 | [1031] = "Northern Network Solutions", 1102 | [1032] = "Converteam GmbH", 1103 | [1033] = "Symbol Technologies", 1104 | [1034] = "S-TEAM Lab", 1105 | [1035] = "Maguire Products Inc.", 1106 | [1036] = "AC&T", 1107 | [1037] = "MITSUBISHI HEAVY INDUSTRIES] = LTD. KOBE SHIPYARD & MACHINERY WORKS", 1108 | [1038] = "Hurletron Inc.", 1109 | [1039] = "Chunichi Denshi Co.Ltd", 1110 | [1040] = "Cardinal Scale Mfg. Co.", 1111 | [1041] = "BTR NETCOM via RIA Connect Inc.", 1112 | [1042] = "Base2", 1113 | [1043] = "ASRC Aerospace", 1114 | [1044] = "Beijing Stone Automation", 1115 | [1045] = "Changshu Switchgear Manufacture Ltd.", 1116 | [1046] = "METRONIX Corp.", 1117 | [1047] = "WIT", 1118 | [1048] = "ORMEC Systems Corp.", 1119 | [1049] = "ASATech (China) Inc.", 1120 | [1050] = "Controlled Systems Limited", 1121 | [1051] = "Mitsubishi Heavy Ind. Digital System Co.Ltd. (M.H.I.)", 1122 | [1052] = "Electrogrip", 1123 | [1053] = "TDS Automation", 1124 | [1054] = "T&C Power Conversion Inc.", 1125 | [1055] = "Robostar Co.Ltd", 1126 | [1056] = "Scancon A/S", 1127 | [1057] = "Haas Automation Inc.", 1128 | [1058] = "Eshed Technology", 1129 | [1059] = "Delta Electronic Inc.", 1130 | [1060] = "Innovasic Semiconductor", 1131 | [1061] = "SoftDEL Systems Limited", 1132 | [1062] = "FiberFin Inc.", 1133 | [1063] = "Nicollet Technologies Corp.", 1134 | [1064] = "B.F. Systems", 1135 | [1065] = "Empire Wire and Supply LLC", 1136 | [1066] = "Reserved", 1137 | [1067] = "Elmo Motion Control LTD", 1138 | [1068] = "Reserved", 1139 | [1069] = "Asahi Keiki Co.Ltd.", 1140 | [1070] = "Joy Mining Machinery", 1141 | [1071] = "MPM Engineering Ltd", 1142 | [1072] = "Wolke Inks & Printers GmbH", 1143 | [1073] = "Mitsubishi Electric Engineering Co.Ltd.", 1144 | [1074] = "COMET AG", 1145 | [1075] = "Real Time Objects & Systems] = LLC", 1146 | [1076] = "MISCO Refractometer", 1147 | [1077] = "JT Engineering Inc.", 1148 | [1078] = "Automated Packing Systems", 1149 | [1079] = "Niobrara R&D Corp.", 1150 | [1080] = "Garmin Ltd.", 1151 | [1081] = "Japan Mobile Platform Co.Ltd", 1152 | [1082] = "Advosol Inc.", 1153 | [1083] = "ABB Global Services Limited", 1154 | [1084] = "Sciemetric Instruments Inc.", 1155 | [1085] = "Tata Elxsi Ltd.", 1156 | [1086] = "TPC Mechatronics] = Co.Ltd.", 1157 | [1087] = "Cooper Bussmann", 1158 | [1088] = "Trinite Automatisering B.V.", 1159 | [1089] = "Peek Traffic B.V.", 1160 | [1090] = "Acrison Inc", 1161 | [1091] = "Applied Robotics Inc.", 1162 | [1092] = "FireBus Systems Inc.", 1163 | [1093] = "Beijing Sevenstar Huachuang Electronics", 1164 | [1094] = "Magnetek", 1165 | [1095] = "Microscan", 1166 | [1096] = "Air Water Inc.", 1167 | [1097] = "Sensopart Industriesensorik GmbH", 1168 | [1098] = "Tiefenbach Control Systems GmbH", 1169 | [1099] = "INOXPA S.A", 1170 | [1100] = "Zurich University of Applied Sciences", 1171 | [1101] = "Ethernet Direct", 1172 | [1102] = "GSI-Micro-E Systems", 1173 | [1103] = "S-Net Automation Co.Ltd.", 1174 | [1104] = "Power Electronics S.L.", 1175 | [1105] = "Renesas Technology Corp.", 1176 | [1106] = "NSWCCD-SSES", 1177 | [1107] = "Porter Engineering Ltd.", 1178 | [1108] = "Meggitt Airdynamics Inc.", 1179 | [1109] = "Inductive Automation", 1180 | [1110] = "Neural ID", 1181 | [1111] = "EEPod LLC", 1182 | [1112] = "Hitachi Industrial Equipment Systems Co.Ltd.", 1183 | [1113] = "Salem Automation", 1184 | [1114] = "port GmbH", 1185 | [1115] = "B & PLUS", 1186 | [1116] = "Graco Inc.", 1187 | [1117] = "Altera Corporation", 1188 | [1118] = "Technology Brewing Corporation", 1189 | [1121] = "CSE Servelec", 1190 | [1124] = "Fluke Networks", 1191 | [1125] = "Tetra Pak Packaging Solutions SPA", 1192 | [1126] = "Racine Federated Inc.", 1193 | [1127] = "Pureron Japan Co.Ltd.", 1194 | [1130] = "Brother IndustriesLtd.", 1195 | [1132] = "Leroy Automation", 1196 | [1134] = "THK CO.] = LTD.", 1197 | [1137] = "TR-Electronic GmbH", 1198 | [1138] = "ASCON S.p.A.", 1199 | [1139] = "Toledo do Brasil Industria de Balancas Ltda.", 1200 | [1140] = "Bucyrus DBT Europe GmbH", 1201 | [1141] = "Emerson Process Management Valve Automation", 1202 | [1142] = "Alstom Transport", 1203 | [1144] = "Matrox Electronic Systems", 1204 | [1145] = "Littelfuse", 1205 | [1146] = "PLASMART Inc.", 1206 | [1147] = "Miyachi Corporation", 1207 | [1150] = "Promess Incorporated", 1208 | [1151] = "COPA-DATA GmbH", 1209 | [1152] = "Precision Engine Controls Corporation", 1210 | [1153] = "Alga Automacao e controle LTDA", 1211 | [1154] = "U.I. Lapp GmbH", 1212 | [1155] = "ICES", 1213 | [1156] = "Philips Lighting bv", 1214 | [1157] = "Aseptomag AG", 1215 | [1158] = "ARC Informatique", 1216 | [1159] = "Hesmor GmbH", 1217 | [1160] = "Kobe SteelLtd.", 1218 | [1161] = "FLIR Systems", 1219 | [1162] = "Simcon A/S", 1220 | [1163] = "COPALP", 1221 | [1164] = "Zypcom Inc.", 1222 | [1165] = "Swagelok", 1223 | [1166] = "Elspec", 1224 | [1167] = "ITT Water & Wastewater AB", 1225 | [1168] = "Kunbus GmbH Industrial Communication", 1226 | [1170] = "Performance Controls Inc.", 1227 | [1171] = "ACS Motion ControlLtd.", 1228 | [1173] = "IStar Technology Limited", 1229 | [1174] = "Alicat Scientific Inc.", 1230 | [1176] = "ADFweb.com SRL", 1231 | [1177] = "Tata Consultancy Services Limited", 1232 | [1178] = "CXR Ltd.", 1233 | [1179] = "Vishay Nobel AB", 1234 | [1181] = "SolaHD", 1235 | [1182] = "Endress+Hauser", 1236 | [1183] = "Bartec GmbH", 1237 | [1185] = "AccuSentry Inc.", 1238 | [1186] = "Exlar Corporation", 1239 | [1187] = "ILS Technology", 1240 | [1188] = "Control Concepts Inc.", 1241 | [1190] = "Procon Engineering Limited", 1242 | [1191] = "Hermary Opto Electronics Inc.", 1243 | [1192] = "Q-Lambda", 1244 | [1194] = "VAMP Ltd", 1245 | [1195] = "FlexLink", 1246 | [1196] = "Office FA.com Co.Ltd.", 1247 | [1197] = "SPMC (Changzhou) Co. Ltd.", 1248 | [1198] = "Anton Paar GmbH", 1249 | [1199] = "Zhuzhou CSR Times Electric Co.Ltd.", 1250 | [1200] = "DeStaCo", 1251 | [1201] = "Synrad Inc", 1252 | [1202] = "Bonfiglioli Vectron GmbH", 1253 | [1203] = "Pivotal Systems", 1254 | [1204] = "TKSCT", 1255 | [1205] = "Randy Nuernberger", 1256 | [1206] = "CENTRALP", 1257 | [1207] = "Tengen Group", 1258 | [1208] = "OES Inc.", 1259 | [1209] = "Actel Corporation", 1260 | [1210] = "Monaghan Engineering Inc.", 1261 | [1211] = "wenglor sensoric gmbh", 1262 | [1212] = "HSA Systems", 1263 | [1213] = "MK Precision Co.Ltd.", 1264 | [1214] = "Tappan Wire and Cable", 1265 | [1215] = "Heinzmann GmbH & Co. KG", 1266 | [1216] = "Process Automation International Ltd.", 1267 | [1217] = "Secure Crossing", 1268 | [1218] = "SMA Railway Technology GmbH", 1269 | [1219] = "FMS Force Measuring Systems AG", 1270 | [1220] = "ABT Endustri Enerji Sistemleri Sanayi Tic. Ltd. Sti.", 1271 | [1221] = "MagneMotion Inc.", 1272 | [1222] = "STS Co.Ltd.", 1273 | [1223] = "MERAK SIC] = SA", 1274 | [1224] = "ABOUNDI Inc.", 1275 | [1225] = "Rosemount Inc.", 1276 | [1226] = "GEA FES Inc.", 1277 | [1227] = "TMG Technologie und Engineering GmbH", 1278 | [1228] = "embeX GmbH", 1279 | [1229] = "GH Electrotermia] = S.A.", 1280 | [1230] = "Tolomatic", 1281 | [1231] = "Dukane", 1282 | [1232] = "Elco (Tian Jin) Electronics Co.Ltd.", 1283 | [1233] = "Jacobs Automation", 1284 | [1234] = "Noda Radio Frequency Technologies Co.Ltd.", 1285 | [1235] = "MSC Tuttlingen GmbH", 1286 | [1236] = "Hitachi Cable Manchester", 1287 | [1237] = "ACOREL SAS", 1288 | [1238] = "Global Engineering Solutions Co.Ltd.", 1289 | [1239] = "ALTE Transportation] = S.L.", 1290 | [1240] = "Penko Engineering B.V." 1291 | } 1292 | --return vendor information 1293 | local function vendor_lookup(vennum) 1294 | return vendor_id[vennum] or "Unknown Vendor Number" 1295 | end 1296 | 1297 | --- 1298 | -- Table to look up the Device Type based on Device ID Number 1299 | -- Returns "Unknown Device Type" if Device ID Number not recognized 1300 | -- Table data from Wireshark dissector ( link to unofficial mirror ) 1301 | -- https://github.com/avsej/wireshark/blob/master/epan/dissectors/packet-enip.c 1302 | -- Fetched on 4/19/2014 1303 | -- 1304 | -- @key devtype Device ID number parsed out of the EtherNet/IP packet 1305 | local device_type = { 1306 | [0] = "Generic Device (deprecated)", 1307 | [2] = "AC Drive", 1308 | [3] = "Motor Overload", 1309 | [4] = "Limit Switch", 1310 | [5] = "Inductive Proximity Switch" , 1311 | [6] = "Photoelectric Sensor", 1312 | [7] = "General Purpose Discrete I/O", 1313 | [9] = "Resolver", 1314 | [12] = "Communications Adapter", 1315 | [14] = "Programmable Logic Controller", 1316 | [16] = "Position Controller", 1317 | [19] = "DC Drive", 1318 | [21] = "Contactor", 1319 | [22] = "Motor Starter", 1320 | [23] = "Soft Start", 1321 | [24] = "Human-Machine Interface", 1322 | [26] = "Mass Flow Controller", 1323 | [27] = "Pneumatic Valve", 1324 | [28] = "Vacuum Pressure Gauge", 1325 | [29] = "Process Control Value", 1326 | [30] = "Residual Gas Analyzer", 1327 | [31] = "DC Power Generator", 1328 | [32] = "RF Power Generator", 1329 | [33] = "Turbomolecular Vacuum Pump", 1330 | [34] = "Encoder" , 1331 | [35] = "Safety Discrete I/O Device", 1332 | [36] = "Fluid Flow Controller", 1333 | [37] = "CIP Motion Drive", 1334 | [38] = "CompoNet Repeater", 1335 | [39] = "Mass Flow Controller Enhanced", 1336 | [40] = "CIP Modbus Device", 1337 | [41] = "CIP Modbus Translator", 1338 | [42] = "Safety Analog I/O Device", 1339 | [43] = "Generic Device (keyable)", 1340 | [44] = "Managed Switch", 1341 | [59] = "ControlNet Physical Layer Component" 1342 | 1343 | } 1344 | --return device type information 1345 | function device_type_lookup (devtype) 1346 | return device_type[devtype] or "Unknown Device Type" 1347 | end 1348 | 1349 | --- 1350 | -- Function to set the nmap output for the host, if a valid EtherNet/IP packet 1351 | -- is received then the output will show that the port as EtherNet/IP instead of 1352 | -- unknown 1353 | -- 1354 | -- @param host Host that was passed in via nmap 1355 | -- @param port port that EtherNet/IP is running on (Default TCP/44818) 1356 | function set_nmap(host, port) 1357 | 1358 | --set port Open 1359 | port.state = "open" 1360 | -- set version name to EtherNet/IP 1361 | port.version.name = "EtherNet/IP" 1362 | nmap.set_port_version(host, port) 1363 | nmap.set_port_state(host, port, "open") 1364 | 1365 | end 1366 | --- 1367 | -- Action Function that is used to run the NSE. This function will send the initial query to the 1368 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 1369 | -- is a EtherNet/IP device. If it is then more actions are taken to gather extra information. 1370 | -- 1371 | -- @param host Host that was scanned via nmap 1372 | -- @param port port that was scanned via nmap 1373 | action = function(host,port) 1374 | -- pack the request identity packet (0x63) 1375 | local enip_req_ident = bin.pack("H","63000000000000000000000000000000c1debed100000000") 1376 | -- create table for output 1377 | local output = stdnse.output_table() 1378 | -- create local vars for socket handling 1379 | local socket, try, catch 1380 | -- create new socket 1381 | socket = nmap.new_socket() 1382 | -- define the catch of the try statement 1383 | catch = function() 1384 | socket:close() 1385 | end 1386 | -- create new try 1387 | try = nmap.new_try(catch) 1388 | 1389 | -- connect to port on host 1390 | try(socket:connect(host, port)) 1391 | -- send Req Identity packet 1392 | try(socket:send(enip_req_ident)) 1393 | -- receive response 1394 | local rcvstatus, response = socket:receive() 1395 | if(rcvstatus == false) then 1396 | return false, response 1397 | end 1398 | -- unpack the response command 1399 | local pos, command = bin.unpack("C", response, 1) 1400 | -- unpack the response type id 1401 | local pos, typeid = bin.unpack("C", response, 27) 1402 | -- if command is 0x63 1403 | if ( command == 0x63) then 1404 | -- if typeid == 0x0c (req ident) 1405 | if( typeid == 0x0c) then 1406 | 1407 | -- vendor number 1408 | local pos, vennum = bin.unpack(" 22 | -- 23 | -- @args aggressive - boolean value defines find all or just first sid 24 | -- 25 | -- @output 26 | -- 1911/tcp open Niagara Fox 27 | -- | fox-info: 28 | -- | Fox Version: 1.0.1 29 | -- | Host Name: xpvm-0omdc01xmy 30 | -- | Host Address: 192.168.1.1 31 | -- | Application Name: Workbench 32 | -- | Application Version: 3.7.44 33 | -- | VM Name: Java HotSpot(TM) Server VM 34 | -- | VM Version: 20.4-b02 35 | -- | OS Name: Windows XP 36 | -- | Time Zone: America/Chicago 37 | -- | Host ID: Win-99CB-D49D-5442-07BB 38 | -- | VM UUID: 8b530bc8-76c5-4139-a2ea-0fabd394d305 39 | -- |_ Brand ID: vykon 40 | -- 41 | -- @xmloutput 42 | --1.0.1 43 | --xpvm-0omdc01xmy 44 | --192.168.1.1 45 | --Workbench 46 | --3.7.44 47 | --Java HotSpot(TM) Server VM 48 | --20.4-b02 49 | --Windows XP 50 | --America/Chicago 51 | --Win-99CB-D49D-5442-07BB 52 | --8b530bc8-76c5-4139-a2ea-0fabd394d305 53 | --vykon 54 | 55 | author = "Stephen Hilt (Digital Bond)" 56 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 57 | categories = {"discovery", "intrusive"} 58 | 59 | 60 | -- 61 | -- Function to define the portrule as per nmap standards 62 | -- 63 | -- 64 | -- 65 | 66 | portrule = shortport.port_or_service(1911, "mtp", "tcp") 67 | 68 | -- 69 | -- Function to split a string based on a separator 70 | -- 71 | -- @param sep A separator to split the string upon 72 | function string:split(sep) 73 | local sep, fields = sep or ":", {} 74 | local pattern = string.format("([^%s]+)", sep) 75 | self:gsub(pattern, function(c) fields[#fields+1] = c end) 76 | return fields 77 | end 78 | 79 | --- 80 | -- Function to set the Nmap output for the host, if a valid Niagara Fox packet 81 | -- is received then the output will show that the port is open instead of 82 | -- open|filtered 83 | -- 84 | -- @param host Host that was passed in via nmap 85 | -- @param port port that Niagara Fox is running on (Default UDP/47808) 86 | function set_nmap(host, port) 87 | 88 | --set port Open 89 | port.state = "open" 90 | -- set version name to Niagara Fox 91 | port.version.name = "Niagara Fox" 92 | nmap.set_port_version(host, port) 93 | nmap.set_port_state(host, port, "open") 94 | 95 | end 96 | 97 | -- 98 | -- Function to term the length of a table/array 99 | -- 100 | -- @param t a table that is passed in 101 | function len(t) 102 | count = 0 103 | for k,v in pairs(t) do 104 | count = count + 1 105 | end 106 | return count 107 | end 108 | 109 | --- 110 | -- Action Function that is used to run the NSE. This function will send the 111 | -- initial query to the host and port that were passed in via nmap. The 112 | -- initial response is parsed to determine if host is a Niagara Fox device. If it 113 | -- is then more actions are taken to gather extra information. 114 | -- 115 | -- @param host Host that was scanned via nmap 116 | -- @param port port that was scanned via nmap 117 | action = function(host, port) 118 | --set the first query data for sending 119 | local orig_query = bin.pack( "H","666f7820612031202d3120666f782068656c6c6f0a7b0a" .. 120 | "666f782e76657273696f6e3d733a312e300a69643d693a310a686f73744e" .. 121 | "616d653d733a7870766d2d306f6d64633031786d790a686f737441646472" .. 122 | "6573733d733a3139322e3136382e312e3132350a6170702e6e616d653d73" .. 123 | "3a576f726b62656e63680a6170702e76657273696f6e3d733a332e372e34" .. 124 | "340a766d2e6e616d653d733a4a61766120486f7453706f7428544d292053" .. 125 | "657276657220564d0a766d2e76657273696f6e3d733a32302e342d623032" .. 126 | "0a6f732e6e616d653d733a57696e646f77732058500a6f732e7665727369" .. 127 | "6f6e3d733a352e310a6c616e673d733a656e0a74696d655a6f6e653d733a" .. 128 | "416d65726963612f4c6f735f416e67656c65733b2d32383830303030303b" .. 129 | "333630303030303b30323a30303a30302e3030302c77616c6c2c6d617263" .. 130 | "682c382c6f6e206f722061667465722c73756e6461792c756e646566696e" .. 131 | "65643b30323a30303a30302e3030302c77616c6c2c6e6f76656d6265722c" .. 132 | "312c6f6e206f722061667465722c73756e6461792c756e646566696e6564" .. 133 | "0a686f737449643d733a57696e2d393943422d443439442d353434322d30" .. 134 | "3742420a766d557569643d733a38623533306263382d373663352d343133" .. 135 | "392d613265612d3066616264333934643330350a6272616e6449643d733a" .. 136 | "76796b6f6e0a7d3b3b0a" ) 137 | -- output table that will be returned to nmap 138 | local to_return = stdnse.output_table() 139 | 140 | -- create new socket 141 | local sock = nmap.new_socket() 142 | -- connect to the remote host 143 | local constatus, conerr = sock:connect(host, port) 144 | if not constatus then 145 | stdnse.debug1( 146 | 'Error establishing a UDP connection for %s - %s', host, conerr 147 | ) 148 | return nil 149 | end 150 | -- send the original query to see if it is a valid Niagara Fox Device 151 | local sendstatus, senderr = sock:send(orig_query) 152 | if not sendstatus then 153 | stdnse.debug1( 154 | 'Error sending Niagara Fox request to %s:%d - %s', 155 | host.ip, port.number, senderr 156 | ) 157 | return nil 158 | end 159 | 160 | -- receive response 161 | local rcvstatus, response = sock:receive() 162 | if(rcvstatus == false) then 163 | stdnse.debug1( "Receive error: %s", response) 164 | return nil 165 | end 166 | -- split the response on 0x0a (NL char) 167 | local output = response:split("\x0a") 168 | -- for each value in side of the created array 169 | for keys,value in pairs(output) do 170 | -- if string contains hostName 171 | if ( string.match(value, "hostName") ) then 172 | local temp = value:split(":") 173 | to_return["Host Name"] = temp[2] 174 | -- if response contains hostAddress 175 | elseif (string.match(value, "hostAddress") ) then 176 | local temp = value:split(":") 177 | to_return["Host Address"] = temp[2] 178 | -- if response contains fox.version 179 | elseif ( string.match(value, "fox.version") ) then 180 | local temp = value:split(":") 181 | to_return["Fox Version"] = temp[2] 182 | -- if response contains app.name 183 | elseif ( string.match(value, "app.name") ) then 184 | local temp = value:split(":") 185 | to_return["Application Name"] = temp[2] 186 | -- if response contains app.version 187 | elseif ( string.match(value,"app.version") ) then 188 | local temp = value:split(":") 189 | to_return["Application Version"] = temp[2] 190 | -- if response contains vm.name 191 | elseif ( string.match(value, "vm.name") ) then 192 | local temp = value:split(":") 193 | to_return["VM Name"] = temp[2] 194 | -- if response contains vm.version 195 | elseif ( string.match(value, "vm.version") ) then 196 | local temp = value:split(":") 197 | to_return["VM Version"] = temp[2] 198 | --if response contains os.name 199 | elseif ( string.match(value,"os.name") ) then 200 | local temp = value:split(":") 201 | to_return["OS Name"] = temp[2] 202 | -- if response contains timeZone 203 | elseif (string.match(value,"timeZone") ) then 204 | local temp = value:split(":") 205 | -- split again just for the timezone name 206 | local temp2 = temp[2]:split(";") 207 | -- if response contains hostId 208 | elseif ( string.match(value,"hostId") ) then 209 | local temp = value:split(":") 210 | to_return["Host ID"] = temp[2] 211 | -- if response contains vmUuid 212 | elseif ( string.match(value,"vmUuid") ) then 213 | local temp = value:split(":") 214 | to_return["VM UUID"] = temp[2] 215 | -- if response contains brandId 216 | elseif ( string.match(value, "brandId") ) then 217 | local temp = value:split(":") 218 | to_return["Brand ID"] = temp[2] 219 | end 220 | -- if the length of the table is 0, then we didn't parse anything 221 | if( len(to_return) ~= 0 ) then 222 | -- set nmap output if we did parse information 223 | set_nmap(host,port) 224 | end 225 | end 226 | -- return output table to nmap 227 | return to_return 228 | end 229 | 230 | -------------------------------------------------------------------------------- /modicon-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ 9 | Modicon is a brand of Programmable Logic Controller (PLC) that is put out by 10 | Schneider Electric. This NSE is designed to use Modbus to communicate to the 11 | PLC via Normal queries that are performed via engineering software. The information 12 | that is collected via Modbus is done in two separate function codes. First, Function 13 | Code 43 is utilized to pull the Vendor Name, Network Module, and the Firmware Version. 14 | Second, Schneider uses function code 90 for communications as well. Via Function Code 90 15 | it is possible to pull information such as the CPU Module, Memory Card Model, and some 16 | information about the project that is loaded into the PLC. 17 | 18 | 19 | http://digitalbond.com 20 | ]] 21 | --- 22 | -- @usage 23 | -- nmap --script modicon-info -p 502 24 | -- 25 | -- 26 | -- @output 27 | --502/tcp open Modbus 28 | --| modicon-info: 29 | --| Vendor Name: Schneider Electric 30 | --| Network Module: BMX NOE 0100 31 | --| CPU Module: BMX P34 2000 32 | --| Firmware: V2.60 33 | --| Memory Card: BMXRMS008MP 34 | --| Project Information: Project - V4.0 35 | --| Project File Name: Project.STU 36 | --| Project Revision: 0.0.9 37 | --|_ Project Last Modified: 7/11/2013 5:55:33 38 | -- @xmloutput 39 | --Schneider Electric 40 | --BMX NOE 0100 41 | --BMX P34 2000 42 | --V2.60 43 | --BMXRMS008MP 44 | --Project - V4.0 45 | --Project.STU 46 | --0.0.9 47 | --7/11/2013 5:55:33 48 | 49 | author = "Stephen Hilt (Digital Bond)" 50 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 51 | categories = {"discovery", "intrusive","digitalbond"} 52 | 53 | -- 54 | -- Function to define the portrule as per nmap standards 55 | -- 56 | -- 57 | -- 58 | portrule = shortport.portnumber(502, "tcp") 59 | 60 | --- 61 | -- Function to trim white space off the beginning and ending of a string 62 | -- 63 | -- @param s a string passed in that needs white space trimmed off 64 | function trim(s) 65 | -- remove white spaces from beginning and ending of the string 66 | return (s:gsub("^%s*(.-)%s*$", "%1")) 67 | end 68 | --- 69 | -- Function to set the nmap output for the host, if a valid Modbus packet 70 | -- is received then the output will show that the port as Modbus. 71 | -- 72 | -- @param host Host that was passed in via nmap 73 | -- @param port port that Modbus is running on (Default TCP/502) 74 | function set_nmap(host, port) 75 | 76 | --set port Open 77 | port.state = "open" 78 | -- set version name to Modbus 79 | port.version.name = "Modbus" 80 | nmap.set_port_version(host, port) 81 | nmap.set_port_state(host, port, "open") 82 | 83 | end 84 | --- 85 | -- Function to setup the communications to the Modicon. This is where alot 86 | -- of the function code 90 information is sent and parsed for information 87 | -- about the Modicon itself. 88 | -- 89 | -- @param socket Socket passed in via Action to communicate to remote device 90 | -- @param output The output table to add information that is collected 91 | --- 92 | function init_comms(socket, output) 93 | 94 | -- decelerations 95 | local pos 96 | local payload = bin.pack("H","000100000004005a0002") 97 | socket:send(payload) 98 | -- recv packet, however not going to do anything with it 99 | local rcvstatus, response = socket:receive() 100 | -- send and receive, not going to do anything with this packet. 101 | payload = bin.pack("H","000200000005005a000100") 102 | socket:send(payload) 103 | local rcvstatus, response = socket:receive() 104 | -- create a string with 249 T (0x54) 105 | local count = 0 106 | local ice = "54" 107 | while (count < 248) do 108 | ice = ice .. "54" 109 | count = count + 1 110 | end 111 | -- send packet with 249 T's (0x54), recv packet and do nothing as well 112 | payload = bin.pack("H","0003000000fe005a00fe00" .. ice) 113 | socket:send(payload) 114 | local rcvstatus, response = socket:receive() 115 | -- send packet that request the project information 116 | payload = bin.pack("H","000400000005005a000300") 117 | socket:send(payload) 118 | local rcvstatus, response = socket:receive() 119 | -- unpack the Project Name, this is configured by the engineers 120 | local pos, project_name = bin.unpack("z", response, 50) 121 | -- unpack the year that the project was last modified 122 | -- define the next sections we are going to unpack 123 | -- Each one is to support time stamp 124 | local project_hour 125 | local project_min 126 | local project_sec 127 | local project_month 128 | local project_day 129 | -- define the 3 vars for the project revision number 130 | local project_rev_1 131 | local project_rev_2 132 | local project_rev_3 133 | -- unpack the time stamp, as well as the revision numbers 134 | -- unpack the seconds 135 | pos, project_sec = bin.unpack("C", response, 38) 136 | -- unpack the min 137 | pos, project_min = bin.unpack("C", response, pos) 138 | -- unpack the hour 139 | pos, project_hour = bin.unpack("C", response, pos) 140 | -- unpack the day 141 | pos, project_day = bin.unpack("C", response, pos) 142 | -- unpack the month 143 | pos, project_month = bin.unpack("C", response, pos) 144 | pos, project_year = bin.unpack(" 19 | -- 20 | -- 21 | -- @output 22 | --9600/tcp open OMRON FINS 23 | --| omrontcp-info: 24 | --| Controller Model: CJ2M-CPU32 02.01 25 | --| Controller Version: 02.01 26 | --| For System Use: 27 | --| Program Area Size: 20 28 | --| IOM size: 23 29 | --| No. DM Words: 32768 30 | --| Timer/Counter: 8 31 | --| Expansion DM Size: 1 32 | --| No. of steps/transitions: 0 33 | --| Kind of Memory Card: 0 34 | --|_ Memory Card Size: 0 35 | 36 | -- @xmloutput 37 | --CS1G_CPU44H 03.00 38 | --03.00 39 | -- 40 | --20 41 | --23 42 | --32768 43 | --8 44 | --1 45 | --0 46 | --0 47 | --0 48 | 49 | 50 | 51 | author = "Stephen Hilt (Digital Bond)" 52 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 53 | categories = {"discovery", "version"} 54 | 55 | -- 56 | -- Function to define the portrule as per nmap standards 57 | -- 58 | -- 59 | portrule = shortport.portnumber(9600, "tcp") 60 | 61 | --- 62 | -- Function to set the nmap output for the host, if a valid OMRON FINS packet 63 | -- is received then the output will show that the port is open. 64 | -- 65 | -- @param host Host that was passed in via nmap 66 | -- @param port port that FINS is running on (Default TCP/9600) 67 | function set_nmap(host, port) 68 | 69 | --set port Open 70 | port.state = "open" 71 | -- set version name to OMRON FINS 72 | port.version.name = "OMRON FINS" 73 | nmap.set_port_version(host, port) 74 | nmap.set_port_state(host, port, "open") 75 | 76 | end 77 | 78 | local memcard = { 79 | [0] = "No Memory Card", 80 | [1] = "SPRAM", 81 | [2] = "EPROM", 82 | [3] = "EEPROM" 83 | } 84 | 85 | function memory_card(value) 86 | local mem_card = memcard[value] or "Unknown Memory Card Type" 87 | return mem_card 88 | end 89 | 90 | 91 | --- 92 | -- Action Function that is used to run the NSE. This function will send the initial query to the 93 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 94 | -- is a FINS supported device. 95 | -- 96 | -- @param host Host that was scanned via nmap 97 | -- @param port port that was scanned via nmap 98 | action = function(host,port) 99 | -- this is the request address command 100 | local req_addr = bin.pack("H", "46494e530000000c000000000000000000000000") 101 | -- TCP requres a network address that is recived from the first request, 102 | -- The read contoller data these two strings will be joined with the address 103 | local controller_data_read = "46494e5300000015000000020000000080000200" 104 | local controller_data_read2 = "000000ef050501" 105 | 106 | -- create table for output 107 | local output = stdnse.output_table() 108 | -- create local vars for socket handling 109 | local socket, try, catch 110 | -- create new socket 111 | socket = nmap.new_socket() 112 | -- define the catch of the try statement 113 | catch = function() 114 | socket:close() 115 | end 116 | -- create new try 117 | try = nmap.new_try(catch) 118 | -- connect to port on host 119 | try(socket:connect(host, port)) 120 | -- send Request Information Packet 121 | try(socket:send(req_addr)) 122 | local rcvstatus, response = socket:receive() 123 | if(rcvstatus == false) then 124 | return false, response 125 | end 126 | local pos, header = bin.unpack("C", response, 1) 127 | if(header == 0x46) then 128 | set_nmap(host, port) 129 | local pos, address = bin.unpack("C",response,24) 130 | local controller_data = bin.pack("HCHC", controller_data_read, address, controller_data_read2, 0x00) 131 | -- send the read controller data request 132 | try(socket:send(controller_data)) 133 | local rcvstatus, response = socket:receive() 134 | if(rcvstatus == false) then 135 | return false, response 136 | end 137 | 138 | local response_code 139 | pos, response_code = bin.unpack("S", response, 111) 152 | pos, output["IOM size"] = bin.unpack("C", response, pos) 153 | pos, output["No. DM Words"] = bin.unpack(">S", response, pos) 154 | pos, output["Timer/Counter"] = bin.unpack("C", response, pos) 155 | pos, output["Expansion DM Size"] = bin.unpack("C", response, pos) 156 | pos, output["No. of steps/transitions"] = bin.unpack(">S", response, pos) 157 | local mem_card_type 158 | pos, mem_card_type = bin.unpack("C", response, pos) 159 | output["Kind of Memory Card"] = memory_card(mem_card_type) 160 | pos, output["Memory Card Size"] = bin.unpack(">S", response, pos) 161 | else 162 | output["Response Code"] = "Unknown Response Code" 163 | end 164 | -- close socket, return output 165 | socket:close() 166 | return output 167 | 168 | else 169 | -- close socket and return nil 170 | socket:close() 171 | return nil 172 | end 173 | 174 | end 175 | -------------------------------------------------------------------------------- /omronudp-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local table = require "table" 6 | 7 | description = [[ 8 | This NSE script is used to send a FINS packet to a remote device that 9 | has UDP 9600 open. The script will send a Controller Data Read Command and once a 10 | response is received, it validates that it was a proper response to the command 11 | that was sent, and then will parse out the data. 12 | 13 | http://digitalbond.com 14 | 15 | ]] 16 | --- 17 | -- @usage 18 | -- nmap --script ormonudp-info -sU -p 9600 19 | -- 20 | -- 21 | -- 22 | -- @output 23 | --9600/tcp open OMRON FINS 24 | --| omrontcp-info: 25 | --| Controller Model: CJ2M-CPU32 02.01 26 | --| Controller Version: 02.01 27 | --| For System Use: 28 | --| Program Area Size: 20 29 | --| IOM size: 23 30 | --| No. DM Words: 32768 31 | --| Timer/Counter: 8 32 | --| Expansion DM Size: 1 33 | --| No. of steps/transitions: 0 34 | --| Kind of Memory Card: 0 35 | --|_ Memory Card Size: 0 36 | 37 | -- @xmloutput 38 | --CS1G_CPU44H 03.00 39 | --03.00 40 | -- 41 | --20 42 | --23 43 | --32768 44 | --8 45 | --1 46 | --0 47 | --0 48 | --0 49 | 50 | 51 | author = "Stephen Hilt (Digital Bond)" 52 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 53 | categories = {"discovery", "version"} 54 | 55 | -- 56 | -- Function to define the portrule as per nmap standards 57 | -- 58 | -- 59 | portrule = shortport.portnumber(9600, "udp") 60 | 61 | --- 62 | -- Function to set the nmap output for the host, if a valid OMRON FINS packet 63 | -- is received then the output will show that the port is open instead of 64 | -- open|filtered 65 | -- 66 | -- @param host Host that was passed in via nmap 67 | -- @param port port that FINS is running on (Default UDP/9600) 68 | function set_nmap(host, port) 69 | 70 | --set port Open 71 | port.state = "open" 72 | -- set version name to OMRON FINS 73 | port.version.name = "OMRON FINS" 74 | nmap.set_port_version(host, port) 75 | nmap.set_port_state(host, port, "open") 76 | 77 | end 78 | 79 | local memcard = { 80 | [0] = "No Memory Card", 81 | [1] = "SPRAM", 82 | [2] = "EPROM", 83 | [3] = "EEPROM" 84 | } 85 | 86 | function memory_card(value) 87 | local mem_card = memcard[value] or "Unknown Memory Card Type" 88 | return mem_card 89 | end 90 | 91 | --- 92 | -- Action Function that is used to run the NSE. This function will send the initial query to the 93 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 94 | -- is a FINS supported device. 95 | -- 96 | -- @param host Host that was scanned via nmap 97 | -- @param port port that was scanned via nmap 98 | action = function(host,port) 99 | -- 0501 is the command to read the Controller Data 100 | -- This command via UDP will result 101 | local controller_data_read = bin.pack("H", "800002000000006300ef050100") 102 | 103 | -- create table for output 104 | local output = stdnse.output_table() 105 | -- create local vars for socket handling 106 | local socket, try, catch 107 | -- create new socket 108 | socket = nmap.new_socket() 109 | -- define the catch of the try statement 110 | catch = function() 111 | socket:close() 112 | end 113 | -- create new try 114 | try = nmap.new_try(catch) 115 | -- connect to port on host 116 | try(socket:connect(host, port)) 117 | -- send Request Information Packet 118 | try(socket:send(controller_data_read)) 119 | local rcvstatus, response = socket:receive() 120 | if(rcvstatus == false) then 121 | return false, response 122 | end 123 | local pos, header = bin.unpack("C", response, 1) 124 | if(header == 0xc0 or header == 0xc1) then 125 | set_nmap(host, port) 126 | local response_code 127 | pos, response_code = bin.unpack("S", response, 95) 141 | pos, output["IOM size"] = bin.unpack("C", response, pos) 142 | pos, output["No. DM Words"] = bin.unpack(">S", response, pos) 143 | pos, output["Timer/Counter"] = bin.unpack("C", response, pos) 144 | pos, output["Expansion DM Size"] = bin.unpack("C", response, pos) 145 | pos, output["No. of steps/transitions"] = bin.unpack(">S", response, pos) 146 | local mem_card_type 147 | pos, mem_card_type = bin.unpack("C", response, pos) 148 | output["Kind of Memory Card"] = memory_card(mem_card_type) 149 | pos, output["Memory Card Size"] = bin.unpack(">S", response, pos) 150 | 151 | else 152 | output["Response Code"] = "Unknown Response Code" 153 | end 154 | socket:close() 155 | return output 156 | 157 | else 158 | socket:close() 159 | return nil 160 | end 161 | 162 | end 163 | -------------------------------------------------------------------------------- /pcworx-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local table = require "table" 6 | 7 | description = [[ 8 | This NSE script will query and parse pcworx protocol to a remote PLC. 9 | The script will send a initial request packets and once a response is received, 10 | it validates that it was a proper response to the command that was sent, and then 11 | will parse out the data. PCWorx is a protocol and Program by Phoenix Contact. 12 | 13 | 14 | http://digitalbond.com 15 | 16 | ]] 17 | --- 18 | -- @usage 19 | -- nmap --script pcworx-info -p 1962 20 | -- 21 | -- 22 | -- @output 23 | --| pcworx-info: 24 | --1962/tcp open pcworx 25 | --| pcworx-info: 26 | --| PLC Type: ILC 330 ETH 27 | --| Model Number: 2737193 28 | --| Firmware Version: 3.95T 29 | --| Firmware Date: Mar 2 2012 30 | --|_ Firmware Time: 09:39:02 31 | 32 | -- 33 | -- 34 | -- @xmloutput 35 | --ILC 330 ETH 36 | --2737193 37 | --3.95T 38 | --Mar 2 2012 39 | --09:39:02 40 | author = "Stephen Hilt (Digital Bond)" 41 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 42 | categories = {"discovery", "version"} 43 | 44 | -- 45 | -- Function to define the portrule as per nmap standards 46 | -- 47 | -- 48 | portrule = shortport.portnumber(1962, "tcp") 49 | 50 | --- 51 | -- Function to set the nmap output for the host, if a valid pcworx Protocol packet 52 | -- is received then the output will show that the port is open instead of 53 | -- 54 | -- @param host Host that was passed in via nmap 55 | -- @param port port that pcworx Protocol is running on (Default TCP/1962) 56 | function set_nmap(host, port) 57 | 58 | --set port Open 59 | port.state = "open" 60 | -- set version name to pcworx Protocol 61 | port.version.name = "pcworx" 62 | nmap.set_port_version(host, port) 63 | nmap.set_port_state(host, port, "open") 64 | 65 | end 66 | 67 | --- 68 | -- Action Function that is used to run the NSE. This function will send the initial query to the 69 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 70 | -- is a pcworx Protocol device. If it is then more actions are taken to gather extra information. 71 | -- 72 | -- @param host Host that was scanned via nmap 73 | -- @param port port that was scanned via nmap 74 | action = function(host,port) 75 | local init_comms = bin.pack("H","0101001a0000000078800003000c494245544830314e305f4d00") 76 | 77 | -- create table for output 78 | local output = stdnse.output_table() 79 | -- create local vars for socket handling 80 | local socket, try, catch 81 | -- create new socket 82 | socket = nmap.new_socket() 83 | -- define the catch of the try statement 84 | catch = function() 85 | socket:close() 86 | end 87 | -- create new try 88 | try = nmap.new_try(catch) 89 | try(socket:connect(host, port)) 90 | try(socket:send(init_comms)) 91 | -- receive response 92 | local rcvstatus, response = socket:receive() 93 | if(rcvstatus == false) then 94 | return false, response 95 | end 96 | -- pcworx has a session ID that is generated by the PLC 97 | -- This will pull the SID so we can communicate further to the PLC 98 | local pos, sid = bin.unpack("C", response, 18) 99 | local init_comms2 = bin.pack("HCH","0105001600010000788000", sid, "00000006000402950000") 100 | try(socket:send(init_comms2)) 101 | -- receive response 102 | local rcvstatus, response = socket:receive() 103 | if(rcvstatus == false) then 104 | return false, response 105 | end 106 | -- this is the request that will pull all the information from the PLC 107 | local req_info = bin.pack("HCH","0106000e00020000000000",sid,"0400") 108 | try(socket:send(req_info)) 109 | -- receive response 110 | local rcvstatus, response = socket:receive() 111 | if(rcvstatus == false) then 112 | return false, response 113 | end 114 | local pos, check1 = bin.unpack("C",response,1) 115 | -- if the response starts with 0x81 then we will continue 116 | if(check1 == 0x81) then 117 | -- set the port information via nmap output 118 | set_nmap(host, port) 119 | -- create output table with proper data 120 | pos, output["PLC Type"] = bin.unpack("z",response,31) 121 | pos, output["Model Number"] = bin.unpack("z", response, 153) 122 | pos, output["Firmware Version"] = bin.unpack("z",response, 67) 123 | pos, output["Firmware Date"] = bin.unpack("z", response, 80) 124 | pos, output["Firmware Time"] = bin.unpack("z", response, 92) 125 | 126 | -- close socket and return output table 127 | socket:close() 128 | return output 129 | end 130 | -- close socket 131 | socket:close() 132 | -- return nil 133 | return nil 134 | end 135 | -------------------------------------------------------------------------------- /proconos-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local table = require "table" 6 | 7 | description = [[ 8 | This NSE script will query and parse ProConOs protocol to a remote PLC. 9 | The script will send a initial request packet and once a 10 | response is received, it validates that it was a proper response to the command 11 | that was sent, and then will parse out the data. 12 | 13 | http://digitalbond.com 14 | 15 | ]] 16 | --- 17 | -- @usage 18 | -- nmap --script proconos-info -p 20547 19 | -- 20 | -- 21 | -- @output 22 | --| proconos-info: 23 | --| Ladder Logic Runtime: ProConOS V3.0.1040 Oct 29 2002 24 | --| PLC Type: ADAM5510KW 1.24 Build 005 25 | --| Project Name: 510-projec 26 | --| Boot Project: 510-projec 27 | --|_ Project Source Code: Exist 28 | -- 29 | -- 30 | -- @xmloutput 31 | --ProConOS V3.0.1040 Oct 29 2002 32 | --ADAM5510KW 1.24 Build 005 33 | --510-projec 34 | --510-project 35 | --Exist 36 | author = "Stephen Hilt (Digital Bond)" 37 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 38 | categories = {"discovery", "version"} 39 | 40 | -- 41 | -- Function to define the portrule as per nmap standards 42 | -- 43 | -- 44 | portrule = shortport.portnumber(20547, "tcp") 45 | 46 | --- 47 | -- Function to set the nmap output for the host, if a valid PCPROTOCOL packet 48 | -- is received then the output will show that the port is open instead of 49 | -- open|filtered 50 | -- 51 | -- @param host Host that was passed in via nmap 52 | -- @param port port that PCPROTOCOL is running on (Default TCP/1962) 53 | function set_nmap(host, port) 54 | 55 | --set port Open 56 | port.state = "open" 57 | -- set version name to PCPROTOCOL 58 | port.version.name = "ProConOS" 59 | nmap.set_port_version(host, port) 60 | nmap.set_port_state(host, port, "open") 61 | 62 | end 63 | 64 | --- 65 | -- Action Function that is used to run the NSE. This function will send the initial query to the 66 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 67 | -- is a PCPROTOCOL device. If it is then more actions are taken to gather extra information. 68 | -- 69 | -- @param host Host that was scanned via nmap 70 | -- @param port port that was scanned via nmap 71 | action = function(host,port) 72 | local req_info = bin.pack("H","cc01000b4002000047ee") 73 | -- create table for output 74 | local output = stdnse.output_table() 75 | -- create local vars for socket handling 76 | local socket, try, catch 77 | -- create new socket 78 | socket = nmap.new_socket() 79 | -- define the catch of the try statement 80 | catch = function() 81 | socket:close() 82 | end 83 | -- create new try 84 | try = nmap.new_try(catch) 85 | try(socket:connect(host, port)) 86 | -- connect to port on host 87 | try(socket:send(req_info)) 88 | -- receive response 89 | local rcvstatus, response = socket:receive() 90 | if(rcvstatus == false) then 91 | return false, response 92 | end local pos, check1 = bin.unpack("C",response,1) 93 | -- if the fist byte is 0xcc 94 | if(check1 == 0xcc) then 95 | set_nmap(host, port) 96 | -- create output table with proper data 97 | pos, output["Ladder Logic Runtime"] = bin.unpack("z",response,13) 98 | pos, output["PLC Type"] = bin.unpack("z",response, 45) 99 | pos, output["Project Name"] = bin.unpack("z", response, 78) 100 | pos, output["Boot Project"] = bin.unpack("z", response, pos) 101 | pos, output["Project Source Code"] = bin.unpack("z", response, pos) 102 | -- close socket and return output table 103 | socket:close() 104 | return output 105 | end 106 | -- close socket 107 | socket:close() 108 | -- return nil 109 | return nil 110 | end 111 | -------------------------------------------------------------------------------- /s7-enumerate.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | 9 | description = [[ 10 | Enumerates Siemens S7 PLC Devices and collects their device information. This 11 | script is based off PLCScan that was developed by Positive Research and 12 | Scadastrangelove (https://code.google.com/p/plcscan/). This script is meant to 13 | provide the same functionality as PLCScan inside of Nmap. Some of the 14 | information that is collected by PLCScan was not ported over; this 15 | information can be parsed out of the packets that are received. 16 | 17 | Thanks to Positive Research, and Dmitry Efanov for creating PLCScan 18 | ]] 19 | 20 | author = "Stephen Hilt (Digital Bond)" 21 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 22 | categories = {"discovery", "intrusive"} 23 | 24 | --- 25 | -- @usage 26 | -- nmap --script s7-info.nse -p 102 27 | -- 28 | -- @output 29 | --102/tcp open Siemens S7 PLC 30 | --| s7-info: 31 | --| Basic Hardware: 6ES7 315-2AG10-0AB0 32 | --| System Name: SIMATIC 300(1) 33 | --| Copyright: Original Siemens Equipment 34 | --| Version: 2.6.9 35 | --| Module Type: CPU 315-2 DP 36 | --| Module: 6ES7 315-2AG10-0AB0 37 | --|_ Serial Number: S C-X4U421302009 38 | -- 39 | -- 40 | -- @xmloutput 41 | --6ES7 315-2AG10-0AB0 42 | --SIMATIC 300(1) 43 | --Original Siemens Equipment 44 | --2.6.9 45 | --SimpleServer 46 | --CPU 315-2 DP 47 | --6ES7 315-2AG10-0AB0 48 | --S C-X4U421302009 49 | -- 50 | 51 | 52 | -- port rule for devices running on TCP/102 53 | portrule = shortport.port_or_service(102, "iso-tsap", "tcp") 54 | 55 | --- 56 | -- Function to send and receive the S7COMM Packet 57 | -- 58 | -- First argument is the socket that was created inside of the main Action 59 | -- this will be utilized to send and receive the packets from the host. 60 | -- the second argument is the query to be sent, this is passed in and is created 61 | -- inside of the main action. 62 | -- @param socket the socket that was created in Action. 63 | -- @param query the specific query that you want to send/receive on. 64 | local function send_receive(socket, query) 65 | local sendstatus, senderr = socket:send(query) 66 | if(sendstatus == false) then 67 | return "Error Sending S7COMM" 68 | end 69 | -- receive response 70 | local rcvstatus, response = socket:receive() 71 | if(rcvstatus == false) then 72 | return "Error Reading S7COMM" 73 | end 74 | return response 75 | end 76 | 77 | --- 78 | -- Function to parse the first SZL Request response that was received from the S7 PLCC 79 | -- 80 | -- First argument is the socket that was created inside of the main Action 81 | -- this will be utilized to send and receive the packets from the host. 82 | -- the second argument is the query to be sent, this is passed in and is created 83 | -- inside of the main action. 84 | -- @param response Packet response that was received from S7 host. 85 | -- @param host The host hat was passed in via Nmap, this is to change output of host/port 86 | -- @param port The port that was passed in via Nmap, this is to change output of host/port 87 | -- @param output Table used for output for return to Nmap 88 | local function parse_response(response, host, port, output) 89 | -- unpack the protocol ID 90 | local pos, value = bin.unpack("C", response, 8) 91 | -- unpack the second byte of the SZL-ID 92 | local pos, szl_id = bin.unpack("C", response, 31) 93 | -- set the offset to 0 94 | local offset = 0 95 | -- if the protocol ID is 0x32 96 | if (value == 0x32) then 97 | local pos 98 | -- unpack the module information 99 | pos, output["Module"] = bin.unpack("z", response, 44) 100 | -- unpack the basic hardware information 101 | pos, output["Basic Hardware"] = bin.unpack("z", response, 72) 102 | -- set version number to 0 103 | local version = 0 104 | -- parse version number 105 | local pos, char1, char2, char3 = bin.unpack("CCC", response, 123) 106 | -- concatenate string, or if string is nil make version number 0.0 107 | output["Version"] = table.concat({char1 or "0.0", char2, char3}, ".") 108 | -- return the output table 109 | return output 110 | else 111 | return nil 112 | end 113 | end 114 | 115 | --- 116 | -- Function to parse the second SZL Request response that was received from the S7 PLC 117 | -- 118 | -- First argument is the socket that was created inside of the main Action 119 | -- this will be utilized to send and receive the packets from the host. 120 | -- the second argument is the query to be sent, this is passed in and is created 121 | -- inside of the main action. 122 | -- @param response Packet response that was received from S7 host. 123 | -- @param output Table used for output for return to Nmap 124 | local function second_parse_response(response, output) 125 | local offset = 0 126 | -- unpack the protocol ID 127 | local pos, value = bin.unpack("C", response, 8) 128 | -- unpack the second byte of the SZL-ID 129 | local pos, szl_id = bin.unpack("C", response, 31) 130 | -- if the protocol ID is 0x32 131 | if (value == 0x32) then 132 | -- if the szl-ID is not 0x1c 133 | if( szl_id ~= 0x1c ) then 134 | -- change offset to 4, this is where most of valid PLCs will fall 135 | offset = 4 136 | end 137 | -- parse system name 138 | pos, output["System Name"] = bin.unpack("z", response, 40 + offset) 139 | -- parse module type 140 | pos, output["Module Type"] = bin.unpack("z", response, 74 + offset) 141 | -- parse serial number 142 | pos, output["Serial Number"] = bin.unpack("z", response, 176 + offset) 143 | -- parse plant identification 144 | pos, output["Plant Identification"] = bin.unpack("z", response, 108 + offset) 145 | -- parse copyright 146 | pos, output["Copyright"] = bin.unpack("z", response, 142 + offset) 147 | 148 | -- for each element in the table, if it is nil, then remove the information from the table 149 | for key, value in pairs(output) do 150 | if(string.len(output[key]) == 0) then 151 | output[key] = nil 152 | end 153 | end 154 | -- return output 155 | return output 156 | else 157 | return nil 158 | end 159 | end 160 | --- 161 | -- Function to set the nmap output for the host, if a valid S7COMM packet 162 | -- is received then the output will show that the port is open 163 | -- and change the output to reflect an S7 PLC 164 | -- 165 | -- @param host Host that was passed in via nmap 166 | -- @param port port that S7COMM is running on 167 | local function set_nmap(host, port) 168 | --set port Open 169 | port.state = "open" 170 | -- set that detected an Siemens S7 171 | port.version.name = "iso-tsap" 172 | port.version.devicetype = "specialized" 173 | port.version.product = "Siemens S7 PLC" 174 | nmap.set_port_version(host, port) 175 | nmap.set_port_state(host, port, "open") 176 | 177 | end 178 | --- 179 | -- Action Function that is used to run the NSE. This function will send the initial query to the 180 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 181 | -- is a S7COMM device. If it is then more actions are taken to gather extra information. 182 | -- 183 | -- @param host Host that was scanned via nmap 184 | -- @param port port that was scanned via nmap 185 | action = function(host, port) 186 | -- COTP packet with a dst of 102 187 | local COTP = bin.pack("H", "0300001611e00000001400c1020100c2020" .. "102" .. "c0010a") 188 | -- COTP packet with a dst of 200 189 | local alt_COTP = bin.pack("H", "0300001611e00000000500c1020100c2020" .. "200" .. "c0010a") 190 | -- setup the ROSCTR Packet 191 | local ROSCTR_Setup = bin.pack("H", "0300001902f08032010000000000080000f0000001000101e0") 192 | -- setup the Read SZL information packet 193 | local Read_SZL = bin.pack("H", "0300002102f080320700000000000800080001120411440100ff09000400110001") 194 | -- setup the first SZL request (gather the basic hardware and version number) 195 | local first_SZL_Request = bin.pack("H", "0300002102f080320700000000000800080001120411440100ff09000400110001") 196 | -- setup the second SZL request 197 | local second_SZL_Request = bin.pack("H", "0300002102f080320700000000000800080001120411440100ff090004001c0001") 198 | -- response is used to collect the packet responses 199 | local response 200 | -- output table for Nmap 201 | local output = stdnse.output_table() 202 | -- create socket for communications 203 | local sock = nmap.new_socket() 204 | -- connect to host 205 | local constatus, conerr = sock:connect(host, port) 206 | if not constatus then 207 | stdnse.debug1('Error establishing connection for %s - %s', host, conerr) 208 | return nil 209 | end 210 | -- send and receive the COTP Packet 211 | response = send_receive(sock, COTP) 212 | -- unpack the PDU Type 213 | local pos, CC_connect_confirm = bin.unpack("C", response, 6) 214 | -- if PDU type is not 0xd0, then not a successful COTP connection 215 | if ( CC_connect_confirm ~= 0xd0) then 216 | sock:close() 217 | -- create socket for communications 218 | stdnse.debug1('S7INFO:: CREATING NEW SOCKET') 219 | sock = nmap.new_socket() 220 | -- connect to host 221 | local constatus, conerr = sock:connect(host, port) 222 | if not constatus then 223 | stdnse.debug1('Error establishing connection for %s - %s', host, conerr) 224 | return nil 225 | end 226 | response = send_receive(sock, alt_COTP) 227 | local pos, CC_connect_confirm = bin.unpack("C", response, 6) 228 | if ( CC_connect_confirm ~= 0xd0) then 229 | stdnse.debug1('S7 INFO:: Could not negotiate COTP') 230 | return nil 231 | end 232 | end 233 | -- send and receive the ROSCTR Setup Packet 234 | response = send_receive(sock, ROSCTR_Setup) 235 | -- unpack the protocol ID 236 | local pos, protocol_id = bin.unpack("C", response, 8) 237 | -- if protocol ID is not 0x32 then return nil 238 | if ( protocol_id ~= 0x32) then 239 | return nil 240 | end 241 | -- send and receive the READ_SZL packet 242 | response = send_receive(sock, Read_SZL) 243 | local pos, protocol_id = bin.unpack("C", response, 8) 244 | -- if protocol ID is not 0x32 then return nil 245 | if ( protocol_id ~= 0x32) then 246 | return nil 247 | end 248 | -- send and receive the first SZL Request packet 249 | response = send_receive(sock, first_SZL_Request) 250 | -- parse the response for basic hardware information 251 | output = parse_response(response, host, port, output) 252 | -- send and receive the second SZL Request packet 253 | response = send_receive(sock, second_SZL_Request) 254 | -- parse the response for more information 255 | output = second_parse_response(response, output) 256 | -- close the socket 257 | sock:close() 258 | 259 | -- If we parsed anything, then set the version info for Nmap 260 | if #output > 0 then 261 | set_nmap(host, port) 262 | end 263 | -- return output to Nmap 264 | return output 265 | 266 | end 267 | --------------------------------------------------------------------------------