MLT

python - halycon, webapp fingerprinting/static file analysis

MLT
Nov 10th, 2013
384
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.65 KB | None | 0 0
  1. #!/usr/bin/python
  2. import os
  3. import sys
  4. import re
  5. import hashlib
  6. import argparse
  7. import operator
  8. from subprocess import Popen
  9. from subprocess import PIPE
  10.  
  11.  
  12. def parse_show(commit, search_file):
  13.   p = Popen("git show %s:%s" % (commit, search_file), shell=True, stdout=PIPE, stderr=PIPE)
  14.   (out, err) = p.communicate()
  15.   if err != "":
  16.     return ""
  17.   return out
  18.  
  19. def parse_log(search_file, string, omit_directory, top):
  20.   p = Popen("git log --stat --stat-width=10000 --pretty=oneline --format='\x11%H\x12'", shell=True, stdout=PIPE)
  21.   (log, _) = p.communicate()
  22.  
  23.   files = {}
  24.   commits = []
  25.   version = {}
  26.   changed = 0
  27.   commit = ""
  28.   current_version = ""
  29.  
  30.   for i in log.split('\n'):
  31.     if re.match('\x11.*\x12', i):
  32.       if changed == 0:
  33.         version[commit] = current_version
  34.       changed = 0
  35.       commit = re.sub('[\x11\x12]', '', i)
  36.       commits.append(commit)
  37.  
  38.     elif '|' in i:
  39.       file = i.split()[0]
  40.       if file == search_file:
  41.         try:
  42.           current_version = '-'.join(re.search(string, parse_show(commit, search_file)).groups()) + "-commitid-" + commit
  43.           version[commit] = current_version
  44.           changed = 1
  45.         except:
  46.           pass
  47.  
  48.       else:
  49.         if files.has_key(file):
  50.           files[file][commit] = []
  51.         else:
  52.           files[file] = {}
  53.           files[file][commit] = []
  54.  
  55.   tmp = {}
  56.   for file in files:
  57.     if not re.match("^.*\.(php|asp|xml|sql|ini)$", file) and re.search(omit_directory, file) == None:
  58.       tmp[file] = files[file]
  59.   files = tmp
  60.  
  61.   if top != 0:
  62.     files = dict(list(reversed(sorted(files.iteritems(), key=operator.itemgetter(1))))[:top])
  63.  
  64.   for file in files:
  65.     for commit in files[file]:
  66.       p = Popen("git show %s:%s" % (commit, file), shell=True, stdout=PIPE, stderr=PIPE)
  67.       (out, err) = p.communicate()
  68.       if err != "":
  69.         continue
  70.  
  71.       files[file][commit] = hashlib.md5(out).hexdigest()
  72.  
  73.   return files, commits, version
  74.  
  75. def clone(url):
  76.   path = url.split('/')[-1].split(".")[0]
  77.   p = Popen("git clone %s" % url, shell=True, stdout=PIPE, stderr=PIPE)
  78.   (out, err) = p.communicate()
  79.   os.chdir(path)
  80.   return path
  81.  
  82. if __name__ == "__main__":
  83.   parser = argparse.ArgumentParser()
  84.   parser.add_argument("-c", "--clone", help="Clone the repo first.", action="store_true")
  85.   parser.add_argument("-u", "-p", "--url", "--path", help="Path or URL to the repository.", required=True)
  86.   parser.add_argument("-f", "--file", help="File to search", required=True)
  87.   parser.add_argument("-m", "--match", help="Regex to match line with version number (ie: '^\\\\\\$wp_version = \\x27([^']+)\\x27;$')", required=True)
  88.   parser.add_argument("--omit-directory", help="Comma separated list of directories to omit.", default="")
  89.   parser.add_argument("-t", "--top", help="Top 'n' files to use. (0 for unlimited)", default=10, type=int)
  90.   args=parser.parse_args()
  91.  
  92.   if args.clone:
  93.     print "Cloning: %s" % args.url
  94.     path = clone(args.url)
  95.   else:
  96.     os.chdir(args.url)
  97.     path = args.url
  98.  
  99.   (files, commits, version) = parse_log(args.file, args.match, "(" + '|'.join(args.omit_directory.split(",")) + ")", args.top)
  100.  
  101.   os.chdir("..")
  102.  
  103.   try:
  104.     os.stat("sigs")
  105.   except:
  106.     os.mkdir("sigs")
  107.  
  108.   for file in files:
  109.     f = open("sigs/%s-%s" % (path, file.rstrip("/").split("/")[-1]), "w")
  110.     f.write("---\n")
  111.     f.write("config:\n")
  112.     f.write("  app_name: " + path + "\n")
  113.     f.write("  check_file: " + file + "\n")
  114.     f.write("sigs:\n")
  115.     for revision in files[file]:
  116.       try:
  117.         f.write("  " + version[revision] + ": " + files[file][revision] + "\n")
  118.       except:
  119.         pass
  120.     f.close()
Advertisement
Comments
  • Comment was deleted
Add Comment
Please, Sign In to add comment