|
| 1 | +#-*- coding:utf8 -*- |
| 2 | +from burp import IBurpExtender |
| 3 | +from burp import IContextMenuFactory |
| 4 | + |
| 5 | +from javax.swing import JMenuItem |
| 6 | +from java.util import List, ArrayList |
| 7 | +from java.net import URL |
| 8 | + |
| 9 | +import re |
| 10 | +from datetime import datetime |
| 11 | +from HTMLParser import HTMLParser |
| 12 | + |
| 13 | +# |
| 14 | +class TagStripper(HTMLParser): |
| 15 | + def __init__(self): |
| 16 | + HTMLParser.__init__(self) |
| 17 | + self.page_text = [] |
| 18 | + # 遇到两个标签之间的数据时调用 |
| 19 | + def handle_data(self, data): |
| 20 | + self.page_text.append(data) |
| 21 | + # 遇到注释时调用 |
| 22 | + def handle_comment(self, data): |
| 23 | + self.handle_data(data) |
| 24 | + |
| 25 | + def strip(self,html): |
| 26 | + # 会调用上面的两个函数 |
| 27 | + self.feed(html) |
| 28 | + return "".join(self.page_text) |
| 29 | + |
| 30 | +class BurpExtender(IBurpExtender, IContextMenuFactory): |
| 31 | + def registerExtenderCallbacks(self,callbacks): |
| 32 | + self._callbacks = callbacks |
| 33 | + self._helpers = callbacks.getHelpers() |
| 34 | + self.context = None |
| 35 | + self.hosts = set() |
| 36 | + |
| 37 | + # 按部就班,先设定一个非常常见的密码,因为是字典,不能重复最好,所以用集合 |
| 38 | + self.wordlist = set(["password"]) |
| 39 | + |
| 40 | + # 建立起我们的扩展工具 |
| 41 | + callbacks.setExtensionName("Build Wordlist") |
| 42 | + callbacks.registerContextMenuFactory(self) |
| 43 | + |
| 44 | + return |
| 45 | + |
| 46 | + # 添加菜单 |
| 47 | + def createMenuItems(self, context_menu): |
| 48 | + self.context = context_menu |
| 49 | + menu_list = ArrayList() |
| 50 | + menu_list.add(JMenuItem("Bulid Wordlist", actionPerformed=self.wordlist_menu)) |
| 51 | + |
| 52 | + return menu_list |
| 53 | + |
| 54 | + def wordlist_menu(self, event): |
| 55 | + |
| 56 | + # 抓取用户点击细节 |
| 57 | + http_traffic = self.context.getSelectedMessages() |
| 58 | + |
| 59 | + # 获取ip或主机名(域名) |
| 60 | + for traffic in http_traffic: |
| 61 | + http_service = traffic.getHttpService() |
| 62 | + host = http_service.getHost() |
| 63 | + |
| 64 | + self.hosts.add(host) |
| 65 | + # 获取网站的返回信息 |
| 66 | + http_response = traffic.getResponse() |
| 67 | + # 若有回应就调用get_word |
| 68 | + if http_response: |
| 69 | + self.get_words(http_response) |
| 70 | + |
| 71 | + self.display_wordlist() |
| 72 | + return |
| 73 | + |
| 74 | + def get_words(self, http_response): |
| 75 | + |
| 76 | + headers, body = http_response.tostring().split("\r\n\r\n", 1) |
| 77 | + |
| 78 | + # 忽略下一个请求 |
| 79 | + if headers.lower().find("content-type: text") == -1: |
| 80 | + return |
| 81 | + |
| 82 | + # 获取标签中的文本 |
| 83 | + tag_stripper = TagStripper() |
| 84 | + page_text = tag_stripper.strip(body) |
| 85 | + |
| 86 | + # 匹配第一个是字母的,后面跟着的是两个以上的字母,数字或下划线/ |
| 87 | + words = re.findall("[a-zA-Z]\w{2,}", page_text) |
| 88 | + |
| 89 | + # 感觉这里的长度有点短啊,作者是12,我改成15了 |
| 90 | + for word in words: |
| 91 | + # 过滤长字符串 |
| 92 | + if len(word) <= 15: |
| 93 | + self.wordlist.add(word.lower()) |
| 94 | + |
| 95 | + return |
| 96 | + |
| 97 | + # 再后面添加更多的猜测 |
| 98 | + def mangle(self, word): |
| 99 | + year = datetime.now().year |
| 100 | + suffixes = ["", "1", "!", year] |
| 101 | + mangled = [] |
| 102 | + |
| 103 | + for password in (word, word.capitalize()): |
| 104 | + for suffix in suffixes: |
| 105 | + mangled.append("%s%s" % (password, suffix)) |
| 106 | + |
| 107 | + return mangled |
| 108 | + |
| 109 | + def display_wordlist(self): |
| 110 | + |
| 111 | + print "#!comment: BHP Wordlist for site(s) %s" % ", ".join(self.hosts) |
| 112 | + |
| 113 | + for word in sorted(self.wordlist): |
| 114 | + for password in self.mangle(word): |
| 115 | + print password |
| 116 | + |
| 117 | + return |
0 commit comments