bbot 2.3.0.5423rc0__py3-none-any.whl → 2.3.0.5445rc0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of bbot might be problematic. Click here for more details.

bbot/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # version placeholder (replaced by poetry-dynamic-versioning)
2
- __version__ = "v2.3.0.5423rc"
2
+ __version__ = "v2.3.0.5445rc"
3
3
 
4
4
  from .scanner import Scanner, Preset
bbot/cli.py CHANGED
@@ -78,7 +78,7 @@ async def _main():
78
78
  return
79
79
 
80
80
  # if we're listing modules or their options
81
- if options.list_modules or options.list_module_options:
81
+ if options.list_modules or options.list_output_modules or options.list_module_options:
82
82
  # if no modules or flags are specified, enable everything
83
83
  if not (options.modules or options.output_modules or options.flags):
84
84
  for module, preloaded in preset.module_loader.preloaded().items():
@@ -96,7 +96,17 @@ async def _main():
96
96
  print("")
97
97
  print("### MODULES ###")
98
98
  print("")
99
- for row in preset.module_loader.modules_table(preset.modules).splitlines():
99
+ modules = sorted(set(preset.scan_modules + preset.internal_modules))
100
+ for row in preset.module_loader.modules_table(modules).splitlines():
101
+ print(row)
102
+ return
103
+
104
+ # --list-output-modules
105
+ if options.list_output_modules:
106
+ print("")
107
+ print("### OUTPUT MODULES ###")
108
+ print("")
109
+ for row in preset.module_loader.modules_table(preset.output_modules).splitlines():
100
110
  print(row)
101
111
  return
102
112
 
@@ -293,6 +293,7 @@ names = [
293
293
  "alyssa",
294
294
  "amanda",
295
295
  "amber",
296
+ "amir",
296
297
  "amy",
297
298
  "andrea",
298
299
  "andrew",
bbot/modules/base.py CHANGED
@@ -51,7 +51,7 @@ class BaseModule:
51
51
 
52
52
  target_only (bool): Accept only the initial target event(s). Default is False.
53
53
 
54
- in_scope_only (bool): Accept only explicitly in-scope events. Default is False.
54
+ in_scope_only (bool): Accept only explicitly in-scope events, regardless of the scan's search distance. Default is False.
55
55
 
56
56
  options (Dict): Customizable options for the module, e.g., {"api_key": ""}. Empty dict by default.
57
57
 
@@ -112,7 +112,7 @@ def extract_text(file_path):
112
112
  result = ""
113
113
  buffer = reader.read(4096)
114
114
  while len(buffer) > 0:
115
- result += buffer.decode("utf-8")
115
+ result += buffer.decode("utf-8", errors="ignore")
116
116
  buffer = reader.read(4096)
117
117
 
118
118
  return result.strip()
bbot/modules/httpx.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import re
2
- import json
2
+ import orjson
3
3
  import tempfile
4
4
  import subprocess
5
5
  from pathlib import Path
@@ -142,11 +142,11 @@ class httpx(BaseModule):
142
142
  proxy = self.scan.http_proxy
143
143
  if proxy:
144
144
  command += ["-http-proxy", proxy]
145
- async for line in self.run_process_live(command, input=list(stdin), stderr=subprocess.DEVNULL):
145
+ async for line in self.run_process_live(command, text=False, input=list(stdin), stderr=subprocess.DEVNULL):
146
146
  try:
147
- j = json.loads(line)
148
- except json.decoder.JSONDecodeError:
149
- self.debug(f"Failed to decode line: {line}")
147
+ j = await self.helpers.run_in_executor(orjson.loads, line)
148
+ except orjson.JSONDecodeError:
149
+ self.warning(f"httpx failed to decode line: {line}")
150
150
  continue
151
151
 
152
152
  url = j.get("url", "")
@@ -5,7 +5,11 @@ from bbot.modules.base import BaseInterceptModule
5
5
 
6
6
  class CloudCheck(BaseInterceptModule):
7
7
  watched_events = ["*"]
8
- meta = {"description": "Tag events by cloud provider, identify cloud resources like storage buckets"}
8
+ meta = {
9
+ "description": "Tag events by cloud provider, identify cloud resources like storage buckets",
10
+ "created_date": "2024-07-07",
11
+ "author": "@TheTechromancer",
12
+ }
9
13
  scope_distance_modifier = 1
10
14
  _priority = 3
11
15
 
@@ -68,9 +72,10 @@ class CloudCheck(BaseInterceptModule):
68
72
  base_kwargs["event_type"] = event_type
69
73
  for sig in sigs:
70
74
  matches = []
71
- if event.type == "HTTP_RESPONSE":
72
- matches = await self.helpers.re.findall(sig, event.data.get("body", ""))
73
- elif event.type.startswith("DNS_NAME"):
75
+ # TODO: convert this to an excavate YARA hook
76
+ # if event.type == "HTTP_RESPONSE":
77
+ # matches = await self.helpers.re.findall(sig, event.data.get("body", ""))
78
+ if event.type.startswith("DNS_NAME"):
74
79
  for host in str_hosts_to_check:
75
80
  match = sig.match(host)
76
81
  if match:
@@ -9,6 +9,8 @@ from bbot.modules.base import BaseInterceptModule, BaseModule
9
9
 
10
10
  class DNSResolve(BaseInterceptModule):
11
11
  watched_events = ["*"]
12
+ produced_events = ["DNS_NAME", "IP_ADDRESS", "RAW_DNS_RECORD"]
13
+ meta = {"description": "Perform DNS resolution", "created_date": "2022-04-08", "author": "@TheTechromancer"}
12
14
  _priority = 1
13
15
  scope_distance_modifier = None
14
16
 
@@ -104,7 +104,7 @@ class speculate(BaseInternalModule):
104
104
  # don't act on unresolved DNS_NAMEs
105
105
  usable_dns = False
106
106
  if event.type == "DNS_NAME":
107
- if self.dns_disable or ("a-record" in event.tags or "aaaa-record" in event.tags):
107
+ if self.dns_disable or event.resolved_hosts:
108
108
  usable_dns = True
109
109
 
110
110
  if event.type == "IP_ADDRESS" or usable_dns:
@@ -3,7 +3,7 @@ from bbot.modules.templates.sql import SQLTemplate
3
3
 
4
4
  class MySQL(SQLTemplate):
5
5
  watched_events = ["*"]
6
- meta = {"description": "Output scan data to a MySQL database"}
6
+ meta = {"description": "Output scan data to a MySQL database", "created_date": "2024-11-13", "author": "@TheTechromancer"}
7
7
  options = {
8
8
  "username": "root",
9
9
  "password": "bbotislife",
@@ -0,0 +1,171 @@
1
+ import sys
2
+ from xml.dom import minidom
3
+ from datetime import datetime
4
+ from xml.etree.ElementTree import Element, SubElement, tostring
5
+
6
+ from bbot import __version__
7
+ from bbot.modules.output.base import BaseOutputModule
8
+
9
+
10
+ class NmapHost:
11
+ __slots__ = ["hostnames", "open_ports"]
12
+
13
+ def __init__(self):
14
+ self.hostnames = set()
15
+ # a dict of {port: {protocol: banner}}
16
+ self.open_ports = dict()
17
+
18
+
19
+ class Nmap_XML(BaseOutputModule):
20
+ watched_events = ["OPEN_TCP_PORT", "DNS_NAME", "IP_ADDRESS", "PROTOCOL", "HTTP_RESPONSE"]
21
+ meta = {"description": "Output to Nmap XML", "created_date": "2024-11-16", "author": "@TheTechromancer"}
22
+ output_filename = "output.nmap.xml"
23
+ in_scope_only = True
24
+
25
+ async def setup(self):
26
+ self.hosts = {}
27
+ self._prep_output_dir(self.output_filename)
28
+ return True
29
+
30
+ async def handle_event(self, event):
31
+ event_host = event.host
32
+
33
+ # we always record by IP
34
+ ips = []
35
+ for ip in event.resolved_hosts:
36
+ try:
37
+ ips.append(self.helpers.make_ip_type(ip))
38
+ except ValueError:
39
+ continue
40
+ if not ips and self.helpers.is_ip(event_host):
41
+ ips = [event_host]
42
+
43
+ for ip in ips:
44
+ try:
45
+ nmap_host = self.hosts[ip]
46
+ except KeyError:
47
+ nmap_host = NmapHost()
48
+ self.hosts[ip] = nmap_host
49
+
50
+ event_port = getattr(event, "port", None)
51
+ if event.type == "OPEN_TCP_PORT":
52
+ if event_port not in nmap_host.open_ports:
53
+ nmap_host.open_ports[event.port] = {}
54
+ elif event.type in ("PROTOCOL", "HTTP_RESPONSE"):
55
+ if event_port is not None:
56
+ try:
57
+ existing_services = nmap_host.open_ports[event.port]
58
+ except KeyError:
59
+ existing_services = {}
60
+ nmap_host.open_ports[event.port] = existing_services
61
+ if event.type == "PROTOCOL":
62
+ protocol = event.data["protocol"].lower()
63
+ banner = event.data.get("banner", None)
64
+ elif event.type == "HTTP_RESPONSE":
65
+ protocol = event.parsed_url.scheme.lower()
66
+ banner = event.http_title
67
+ if protocol not in existing_services:
68
+ existing_services[protocol] = banner
69
+
70
+ if self.helpers.is_ip(event_host):
71
+ if str(event.module) == "PTR":
72
+ nmap_host.hostnames.add(event.parent.data)
73
+ else:
74
+ nmap_host.hostnames.add(event_host)
75
+
76
+ async def report(self):
77
+ scan_start_time = str(int(self.scan.start_time.timestamp()))
78
+ scan_start_time_str = self.scan.start_time.strftime("%a %b %d %H:%M:%S %Y")
79
+ scan_end_time = datetime.now()
80
+ scan_end_time_str = scan_end_time.strftime("%a %b %d %H:%M:%S %Y")
81
+ scan_end_time_timestamp = str(scan_end_time.timestamp())
82
+ scan_duration = scan_end_time - self.scan.start_time
83
+ num_hosts_up = len(self.hosts)
84
+
85
+ # Create the root element
86
+ nmaprun = Element(
87
+ "nmaprun",
88
+ {
89
+ "scanner": "bbot",
90
+ "args": " ".join(sys.argv),
91
+ "start": scan_start_time,
92
+ "startstr": scan_start_time_str,
93
+ "version": str(__version__),
94
+ "xmloutputversion": "1.05",
95
+ },
96
+ )
97
+
98
+ ports_scanned = []
99
+ speculate_module = self.scan.modules.get("speculate", None)
100
+ if speculate_module is not None:
101
+ ports_scanned = speculate_module.ports
102
+ portscan_module = self.scan.modules.get("portscan", None)
103
+ if portscan_module is not None:
104
+ ports_scanned = self.helpers.parse_port_string(str(portscan_module.ports))
105
+ num_ports_scanned = len(sorted(ports_scanned))
106
+ ports_scanned = ",".join(str(x) for x in sorted(ports_scanned))
107
+
108
+ # Add scaninfo
109
+ SubElement(
110
+ nmaprun,
111
+ "scaninfo",
112
+ {"type": "syn", "protocol": "tcp", "numservices": str(num_ports_scanned), "services": ports_scanned},
113
+ )
114
+
115
+ # Add host information
116
+ for ip, nmap_host in self.hosts.items():
117
+ hostnames = sorted(nmap_host.hostnames)
118
+ ports = sorted(nmap_host.open_ports)
119
+
120
+ host_elem = SubElement(nmaprun, "host")
121
+ SubElement(host_elem, "status", {"state": "up", "reason": "user-set", "reason_ttl": "0"})
122
+ SubElement(host_elem, "address", {"addr": str(ip), "addrtype": f"ipv{ip.version}"})
123
+
124
+ if hostnames:
125
+ hostnames_elem = SubElement(host_elem, "hostnames")
126
+ for hostname in hostnames:
127
+ SubElement(hostnames_elem, "hostname", {"name": hostname, "type": "user"})
128
+
129
+ ports = SubElement(host_elem, "ports")
130
+ for port, protocols in nmap_host.open_ports.items():
131
+ port_elem = SubElement(ports, "port", {"protocol": "tcp", "portid": str(port)})
132
+ SubElement(port_elem, "state", {"state": "open", "reason": "syn-ack", "reason_ttl": "0"})
133
+ # <port protocol="tcp" portid="443"><state state="open" reason="syn-ack" reason_ttl="53"/><service name="http" product="AkamaiGHost" extrainfo="Akamai&apos;s HTTP Acceleration/Mirror service" tunnel="ssl" method="probed" conf="10"/></port>
134
+ for protocol, banner in protocols.items():
135
+ attrs = {"name": protocol, "method": "probed", "conf": "10"}
136
+ if banner is not None:
137
+ attrs["product"] = banner
138
+ attrs["extrainfo"] = banner
139
+ SubElement(port_elem, "service", attrs)
140
+
141
+ # Add runstats
142
+ runstats = SubElement(nmaprun, "runstats")
143
+ SubElement(
144
+ runstats,
145
+ "finished",
146
+ {
147
+ "time": scan_end_time_timestamp,
148
+ "timestr": scan_end_time_str,
149
+ "summary": f"BBOT done at {scan_end_time_str}; {num_hosts_up} scanned in {scan_duration} seconds",
150
+ "elapsed": str(scan_duration.total_seconds()),
151
+ "exit": "success",
152
+ },
153
+ )
154
+ SubElement(runstats, "hosts", {"up": str(num_hosts_up), "down": "0", "total": str(num_hosts_up)})
155
+
156
+ # make backup of the file
157
+ self.helpers.backup_file(self.output_file)
158
+
159
+ # Pretty-format the XML
160
+ rough_string = tostring(nmaprun, encoding="utf-8")
161
+ reparsed = minidom.parseString(rough_string)
162
+
163
+ # Create a new document with the doctype
164
+ doctype = minidom.DocumentType("nmaprun")
165
+ reparsed.insertBefore(doctype, reparsed.documentElement)
166
+
167
+ pretty_xml = reparsed.toprettyxml(indent=" ")
168
+
169
+ with open(self.output_file, "w") as f:
170
+ f.write(pretty_xml)
171
+ self.info(f"Saved Nmap XML output to {self.output_file}")
@@ -3,7 +3,11 @@ from bbot.modules.templates.sql import SQLTemplate
3
3
 
4
4
  class Postgres(SQLTemplate):
5
5
  watched_events = ["*"]
6
- meta = {"description": "Output scan data to a SQLite database"}
6
+ meta = {
7
+ "description": "Output scan data to a SQLite database",
8
+ "created_date": "2024-11-08",
9
+ "author": "@TheTechromancer",
10
+ }
7
11
  options = {
8
12
  "username": "postgres",
9
13
  "password": "bbotislife",
@@ -5,7 +5,11 @@ from bbot.modules.templates.sql import SQLTemplate
5
5
 
6
6
  class SQLite(SQLTemplate):
7
7
  watched_events = ["*"]
8
- meta = {"description": "Output scan data to a SQLite database"}
8
+ meta = {
9
+ "description": "Output scan data to a SQLite database",
10
+ "created_date": "2024-11-07",
11
+ "author": "@TheTechromancer",
12
+ }
9
13
  options = {
10
14
  "database": "",
11
15
  }
@@ -6,7 +6,7 @@ from bbot.modules.output.base import BaseOutputModule
6
6
 
7
7
  class Stdout(BaseOutputModule):
8
8
  watched_events = ["*"]
9
- meta = {"description": "Output to text"}
9
+ meta = {"description": "Output to text", "created_date": "2024-04-03", "author": "@TheTechromancer"}
10
10
  options = {"format": "text", "event_types": [], "event_fields": [], "in_scope_only": False, "accept_dupes": True}
11
11
  options_desc = {
12
12
  "format": "Which text format to display, choices: text,json",
@@ -5,7 +5,7 @@ from bbot.modules.output.base import BaseOutputModule
5
5
 
6
6
  class TXT(BaseOutputModule):
7
7
  watched_events = ["*"]
8
- meta = {"description": "Output to text"}
8
+ meta = {"description": "Output to text", "created_date": "2024-04-03", "author": "@TheTechromancer"}
9
9
  options = {"output_file": ""}
10
10
  options_desc = {"output_file": "Output to file"}
11
11
 
@@ -52,6 +52,11 @@ class BBOTArgs:
52
52
  "",
53
53
  "bbot -l",
54
54
  ),
55
+ (
56
+ "List output modules",
57
+ "",
58
+ "bbot -lo",
59
+ ),
55
60
  (
56
61
  "List presets",
57
62
  "",
@@ -290,12 +295,6 @@ class BBOTArgs:
290
295
  )
291
296
 
292
297
  output = p.add_argument_group(title="Output")
293
- output.add_argument(
294
- "-o",
295
- "--output-dir",
296
- help="Directory to output scan results",
297
- metavar="DIR",
298
- )
299
298
  output.add_argument(
300
299
  "-om",
301
300
  "--output-modules",
@@ -304,6 +303,13 @@ class BBOTArgs:
304
303
  help=f'Output module(s). Choices: {",".join(sorted(self.preset.module_loader.output_module_choices))}',
305
304
  metavar="MODULE",
306
305
  )
306
+ output.add_argument("-lo", "--list-output-modules", action="store_true", help="List available output modules")
307
+ output.add_argument(
308
+ "-o",
309
+ "--output-dir",
310
+ help="Directory to output scan results",
311
+ metavar="DIR",
312
+ )
307
313
  output.add_argument("--json", "-j", action="store_true", help="Output scan data in JSON format")
308
314
  output.add_argument("--brief", "-br", action="store_true", help="Output only the data itself")
309
315
  output.add_argument("--event-types", nargs="+", default=[], help="Choose which event types to display")
@@ -150,11 +150,23 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
150
150
  out, err = capsys.readouterr()
151
151
  # internal modules
152
152
  assert "| excavate " in out
153
- # output modules
154
- assert "| csv " in out
153
+ # no output modules
154
+ assert not "| csv " in out
155
155
  # scan modules
156
156
  assert "| wayback " in out
157
157
 
158
+ # list output modules
159
+ monkeypatch.setattr("sys.argv", ["bbot", "--list-output-modules"])
160
+ result = await cli._main()
161
+ assert result == None
162
+ out, err = capsys.readouterr()
163
+ # no internal modules
164
+ assert not "| excavate " in out
165
+ # output modules
166
+ assert "| csv " in out
167
+ # no scan modules
168
+ assert not "| wayback " in out
169
+
158
170
  # output dir and scan name
159
171
  output_dir = bbot_test_dir / "bbot_cli_args_output"
160
172
  scan_name = "bbot_cli_args_scan_name"
@@ -156,17 +156,15 @@ async def test_modules_basic_checks(events, httpx_mock):
156
156
  assert not (
157
157
  "web-basic" in flags and "web-thorough" in flags
158
158
  ), f'module "{module_name}" should have either "web-basic" or "web-thorough" flags, not both'
159
- meta = preloaded.get("meta", {})
160
- # make sure every module has a description
161
- assert meta.get("description", ""), f"{module_name} must have a description"
162
- # make sure every module has an author
163
- assert meta.get("author", ""), f"{module_name} must have an author"
164
- # make sure every module has a created date
165
- created_date = meta.get("created_date", "")
166
- assert created_date, f"{module_name} must have a created date"
167
- assert created_date_regex.match(
168
- created_date
169
- ), f"{module_name}'s created_date must match the format YYYY-MM-DD"
159
+ meta = preloaded.get("meta", {})
160
+ # make sure every module has a description
161
+ assert meta.get("description", ""), f"{module_name} must have a description"
162
+ # make sure every module has an author
163
+ assert meta.get("author", ""), f"{module_name} must have an author"
164
+ # make sure every module has a created date
165
+ created_date = meta.get("created_date", "")
166
+ assert created_date, f"{module_name} must have a created date"
167
+ assert created_date_regex.match(created_date), f"{module_name}'s created_date must match the format YYYY-MM-DD"
170
168
 
171
169
  # attribute checks
172
170
  watched_events = preloaded.get("watched_events")
@@ -8,7 +8,7 @@ class TestCloudCheck(ModuleTestBase):
8
8
  modules_overrides = ["httpx", "excavate", "cloudcheck"]
9
9
 
10
10
  async def setup_after_prep(self, module_test):
11
- module_test.set_expect_requests({"uri": "/"}, {"response_data": "<a href='asdf.s3.amazonaws.com'/>"})
11
+ module_test.set_expect_requests({"uri": "/"}, {"response_data": "<a href='http://asdf.s3.amazonaws.com'/>"})
12
12
 
13
13
  scan = Scanner(config={"cloudcheck": True})
14
14
  await scan._prep()
@@ -0,0 +1,85 @@
1
+ import xml.etree.ElementTree as ET
2
+
3
+ from bbot.modules.base import BaseModule
4
+ from .base import ModuleTestBase
5
+
6
+
7
+ class TestNmap_XML(ModuleTestBase):
8
+ modules_overrides = ["nmap_xml", "speculate"]
9
+ targets = ["blacklanternsecurity.com", "127.0.0.3"]
10
+ config_overrides = {"dns": {"minimal": False}}
11
+
12
+ class DummyModule(BaseModule):
13
+ watched_events = ["OPEN_TCP_PORT"]
14
+ _name = "dummy_module"
15
+
16
+ async def handle_event(self, event):
17
+ if event.port == 80:
18
+ await self.emit_event(
19
+ {"host": str(event.host), "port": event.port, "protocol": "http", "banner": "Apache"},
20
+ "PROTOCOL",
21
+ parent=event,
22
+ )
23
+ elif event.port == 443:
24
+ await self.emit_event(
25
+ {"host": str(event.host), "port": event.port, "protocol": "https"}, "PROTOCOL", parent=event
26
+ )
27
+
28
+ async def setup_before_prep(self, module_test):
29
+ self.dummy_module = self.DummyModule(module_test.scan)
30
+ module_test.scan.modules["dummy_module"] = self.dummy_module
31
+ await module_test.mock_dns(
32
+ {
33
+ "blacklanternsecurity.com": {"A": ["127.0.0.1", "127.0.0.2"]},
34
+ "3.0.0.127.in-addr.arpa": {"PTR": ["www.blacklanternsecurity.com"]},
35
+ "www.blacklanternsecurity.com": {"A": ["127.0.0.1"]},
36
+ }
37
+ )
38
+
39
+ def check(self, module_test, events):
40
+ nmap_xml_file = module_test.scan.modules["nmap_xml"].output_file
41
+ nmap_xml = open(nmap_xml_file).read()
42
+
43
+ # Parse the XML
44
+ root = ET.fromstring(nmap_xml)
45
+
46
+ # Expected IP addresses
47
+ expected_ips = {"127.0.0.1", "127.0.0.2", "127.0.0.3"}
48
+ found_ips = set()
49
+
50
+ # Iterate over each host in the XML
51
+ for host in root.findall("host"):
52
+ # Get the IP address
53
+ address = host.find("address").get("addr")
54
+ found_ips.add(address)
55
+
56
+ # Get hostnames if available
57
+ hostnames = sorted([hostname.get("name") for hostname in host.findall(".//hostname")])
58
+
59
+ # Get open ports and services
60
+ ports = []
61
+ for port in host.findall(".//port"):
62
+ port_id = port.get("portid")
63
+ state = port.find("state").get("state")
64
+ if state == "open":
65
+ service_name = port.find("service").get("name")
66
+ service_product = port.find("service").get("product", "")
67
+ service_extrainfo = port.find("service").get("extrainfo", "")
68
+ ports.append((port_id, service_name, service_product, service_extrainfo))
69
+
70
+ # Sort ports for consistency
71
+ ports.sort()
72
+
73
+ # Assertions
74
+ if address == "127.0.0.1":
75
+ assert hostnames == ["blacklanternsecurity.com", "www.blacklanternsecurity.com"]
76
+ assert ports == sorted([("80", "http", "Apache", "Apache"), ("443", "https", "", "")])
77
+ elif address == "127.0.0.2":
78
+ assert hostnames == sorted(["blacklanternsecurity.com"])
79
+ assert ports == sorted([("80", "http", "Apache", "Apache"), ("443", "https", "", "")])
80
+ elif address == "127.0.0.3":
81
+ assert hostnames == [] # No hostnames for this IP
82
+ assert ports == sorted([("80", "http", "Apache", "Apache"), ("443", "https", "", "")])
83
+
84
+ # Assert that all expected IPs were found
85
+ assert found_ips == expected_ips
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bbot
3
- Version: 2.3.0.5423rc0
3
+ Version: 2.3.0.5445rc0
4
4
  Summary: OSINT automation for hackers.
5
5
  Home-page: https://github.com/blacklanternsecurity/bbot
6
6
  License: GPL-3.0
@@ -29,6 +29,7 @@ Requires-Dist: jinja2 (>=3.1.3,<4.0.0)
29
29
  Requires-Dist: lxml (>=4.9.2,<6.0.0)
30
30
  Requires-Dist: mmh3 (>=4.1,<6.0)
31
31
  Requires-Dist: omegaconf (>=2.3.0,<3.0.0)
32
+ Requires-Dist: orjson (>=3.10.12,<4.0.0)
32
33
  Requires-Dist: psutil (>=5.9.4,<7.0.0)
33
34
  Requires-Dist: puremagic (>=1.28,<2.0)
34
35
  Requires-Dist: pycryptodome (>=3.17,<4.0)
@@ -1,5 +1,5 @@
1
- bbot/__init__.py,sha256=LdP06wn7DHX_800M7nQMUIA8LKbluosrRSK4gYZ1bqM,130
2
- bbot/cli.py,sha256=xPTXsZr8FGmI3N6e3gjo9i9E2u-Ih2Sr4MQU6RTxnj8,10434
1
+ bbot/__init__.py,sha256=JG68O_TRR-d3_m2mYrlMbXECV7BE7Shu8Dw0HiS3jeU,130
2
+ bbot/cli.py,sha256=Qlgqabm8N6r6uO1RuwGaM7-VXDSP_NH-YUnDUTsDYPM,10877
3
3
  bbot/core/__init__.py,sha256=l255GJE_DvUnWvrRb0J5lG-iMztJ8zVvoweDOfegGtI,46
4
4
  bbot/core/config/__init__.py,sha256=zYNw2Me6tsEr8hOOkLb4BQ97GB7Kis2k--G81S8vofU,342
5
5
  bbot/core/config/files.py,sha256=zANvrTRLJQIOWSNkxd9MpWmf9cQFr0gRZLUxeIbTwQc,1412
@@ -30,7 +30,7 @@ bbot/core/helpers/helper.py,sha256=eD9yJUhrFUmmoXm4pyi31dulJ5W2eyS-YLGXmx7AyDQ,8
30
30
  bbot/core/helpers/interactsh.py,sha256=VBYYH6-rWBofRsgemndK6iZNmyifOps8vgQOw2mac4k,12624
31
31
  bbot/core/helpers/libmagic.py,sha256=QMHyxjgDLb2jyjBvK1MQ-xt6WkGXhKcHu9ZP1li-sik,3460
32
32
  bbot/core/helpers/misc.py,sha256=156tWmNGZ0I1X537hQ8cAlShVq8D2dQVGz3DxaLh5d0,87734
33
- bbot/core/helpers/names_generator.py,sha256=Sj_Q-7KQyElEpalzlUadSwaniESqrIVVEle9ycPIiho,10322
33
+ bbot/core/helpers/names_generator.py,sha256=x6nZfEPKMwv3qR_RI4U6TBNbo6PgCF4fqbldtwilvpw,10334
34
34
  bbot/core/helpers/ntlm.py,sha256=P2Xj4-GPos2iAzw4dfk0FJp6oGyycGhu2x6sLDVjYjs,2573
35
35
  bbot/core/helpers/process.py,sha256=00uRpLMFi3Pt3uT8qXwAIhsXdoa7h-ifoXh0sGYgwqs,1702
36
36
  bbot/core/helpers/ratelimiter.py,sha256=K8qFIyJPJtfdb9kSW6_lL6ahWqxR2uWyCBkDlg6uJgo,1990
@@ -61,7 +61,7 @@ bbot/modules/baddns.py,sha256=SP-o0M2dq5QIkaQZUKl9YZiOXdZasty-fHPxTJJAeR0,6378
61
61
  bbot/modules/baddns_direct.py,sha256=pe_seO74XI4b6w4Q_IBDNvtBjmD-7it5ts0Z-FB0L6k,3818
62
62
  bbot/modules/baddns_zone.py,sha256=IcewDBtA_-64NCNFojEFd9jt2YBek6ltB2mmqdDH6LE,1034
63
63
  bbot/modules/badsecrets.py,sha256=JSukBYdD3yuvVy84DkyX48428R_LgQ7P39tjTRAD_Mo,5107
64
- bbot/modules/base.py,sha256=zNjF1-174Svg8SW07J7QahLVkVyCyEBxi7k2YF4FIUk,71101
64
+ bbot/modules/base.py,sha256=Ala_jLu3I2iEadn_NNiOb4RnFdJPwlrtywASDvd-P6c,71143
65
65
  bbot/modules/bevigil.py,sha256=0VLIxmeXRUI2-EoR6IzuHJMcX8KCHNNta-WYa3gVlDg,2862
66
66
  bbot/modules/binaryedge.py,sha256=5F9LnZwRM_rZnzTv29hLJLI2GEQdzOwSpahPFC1kJC0,1397
67
67
  bbot/modules/bucket_amazon.py,sha256=mwjYeEAcdfOpjbOa1sD8U9KBMMVY_c8FoHjSGR9GQbg,730
@@ -98,7 +98,7 @@ bbot/modules/docker_pull.py,sha256=T_xObzExDTZF-_HfgZSfrU199QgCME3rYmkVs1HigXQ,9
98
98
  bbot/modules/dockerhub.py,sha256=yHKxV-uVubAUvYrIXizSZoLUiPKArTH2mCh5FjY4sas,3486
99
99
  bbot/modules/dotnetnuke.py,sha256=rw_EchDg49VyQj5JiUh0AqUqtsuqLrhc-nwrybdzhZ8,10537
100
100
  bbot/modules/emailformat.py,sha256=RLPJW-xitYB-VT4Lp08qVzFkXx_kMyV_035JT_Yf4fM,1082
101
- bbot/modules/extractous.py,sha256=_9tJsQRqhYIaPFmMByc2NiyvPhcPgs-KGQ8-XhtkSyc,4546
101
+ bbot/modules/extractous.py,sha256=qE4h0reR51t9NSIcR4-VMMjc5t3H03bpW3fO0A6nb9c,4563
102
102
  bbot/modules/ffuf_shortnames.py,sha256=9Kh0kJsw7XXpXmCkiB5eAhG4h9rSo8Y-mB3p0EDa_l0,12624
103
103
  bbot/modules/filedownload.py,sha256=x2LmLcLD1FD2L9O6p58l21WYoqyxD5HgHg6P1g1RyxU,8180
104
104
  bbot/modules/fingerprintx.py,sha256=rdlR9d64AntAhbS_eJzh8bZCeLPTJPSKdkdKdhH_qAo,3269
@@ -114,17 +114,17 @@ bbot/modules/google_playstore.py,sha256=N4QjzQag_bgDXfX17rytBiiWA-SQtYI2N0J_ZNEO
114
114
  bbot/modules/gowitness.py,sha256=nLV2AFFK6hiQrQSoYlqY1Eo2BE3rAjYiiOKCtqAoRDc,11277
115
115
  bbot/modules/hackertarget.py,sha256=IsKs9PtxUHdLJKZydlRdW_loBE2KphQYi3lKDAd4odc,1029
116
116
  bbot/modules/host_header.py,sha256=uDjwidMdeNPMRfzQ2YW4REEGsZqnGOZHbOS6GgdNd9s,7686
117
- bbot/modules/httpx.py,sha256=VaHpdfMsnEGkJlSUfRrM4DppgqEsDxC1MBqOgKhEL18,7588
117
+ bbot/modules/httpx.py,sha256=sNvtjIek2Io9BTle3MQUOj-0QYZvbsKL4et1Xd9vY1I,7642
118
118
  bbot/modules/hunt.py,sha256=5giYoCuXWVCzxuHwF6DvA9UlJcenokZJU2-fsou_9zg,5933
119
119
  bbot/modules/hunterio.py,sha256=Vp_QnxHSHLYmlUxPYozFVs1u-50UzRybq7Q7dWvCbFM,2638
120
120
  bbot/modules/iis_shortnames.py,sha256=bIlmC21a0eK_cjMu1UQkDl9EfpfCN1SAggDqJL8LJfE,14493
121
121
  bbot/modules/internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
122
  bbot/modules/internal/aggregate.py,sha256=csWYIt2fUp9K_CRxP3bndUMIjpNIh8rmBubp5Fr1-nc,395
123
123
  bbot/modules/internal/base.py,sha256=BXO4Hc7XKaAOaLzolF3krJX1KibPxtek2GTQUgnCHk0,387
124
- bbot/modules/internal/cloudcheck.py,sha256=WVW5gQQhnJmTb1_wl4MjM_HUNQIKS8kIQFNKdaAGJiY,4754
125
- bbot/modules/internal/dnsresolve.py,sha256=643r5hJ6KRGuwn3ldIVOiyUNEex0Mfvp1Y4t_GgPnSI,15499
124
+ bbot/modules/internal/cloudcheck.py,sha256=sr1_dj4eqcD3x8MigZkjf0AxZZWSJFzvRjYGl5uxVdk,4913
125
+ bbot/modules/internal/dnsresolve.py,sha256=1fwWChIGpSEIIkswueiIhEwIahQ7YngZ-njFK-RIsfU,15679
126
126
  bbot/modules/internal/excavate.py,sha256=IazekmFOnjrqghTf9YhBbMM4dohv27vIEvfNZXJSZvg,51529
127
- bbot/modules/internal/speculate.py,sha256=1UX5YKCfUnJ4EV8suHSAdq1Y2decEjIV88LQ8-VQcRQ,9260
127
+ bbot/modules/internal/speculate.py,sha256=NolqW2s8tokibc6gVM960KlrABkjhLB-7YlCdVx4O9s,9223
128
128
  bbot/modules/internetdb.py,sha256=Edg0Z84dH8dPTZMd7RlzvYBYNq8JHs_ns_ldnFxwRKo,5415
129
129
  bbot/modules/ip2location.py,sha256=yGivX9fzvwvLpnqmYCP2a8SPjTarzrZxfRluog-nkME,2628
130
130
  bbot/modules/ipneighbor.py,sha256=b_0IhorihFLtXJZEz57EGXjXW30gIOEzzVgz2GFvM3A,1591
@@ -144,17 +144,18 @@ bbot/modules/output/discord.py,sha256=BzZW0T-DgZHo3xwaQbZ6DAA59wKIvCDV1LK82ev7A2
144
144
  bbot/modules/output/emails.py,sha256=mzZideMCNfB8-naQANO5g8Y9HdgviAihRsdY_xPQjbQ,1095
145
145
  bbot/modules/output/http.py,sha256=4UWKpbQx3EHpi24VIem6oSvXr0W0NZ3lDpJOmQ3Mwik,2582
146
146
  bbot/modules/output/json.py,sha256=zvM2NwWScGk3pN4wF0mm-OqVW_0ADYy95Am4T02VVD4,1289
147
- bbot/modules/output/mysql.py,sha256=iq_VRvuarEZJHR8_OWB2Z76-yQrxWqNGfPrPHOi9oiI,1884
147
+ bbot/modules/output/mysql.py,sha256=mdIdu17otSuElA-_1OwnB3DV31lL0WcMrti38vqGsrY,1944
148
148
  bbot/modules/output/neo4j.py,sha256=u950eUwu8YMql_WaBA38TN2bUhx7xnZdIIvYfR3xVcY,6114
149
- bbot/modules/output/postgres.py,sha256=2JdEF6mU-VmVqPrgEh5L2MGv-s0BoNwoz8EnG5i3u2s,1847
149
+ bbot/modules/output/nmap_xml.py,sha256=RZx3LFNi_OWxd0lJXY6Nk-_sSQBRidRnoWKyZEaUXrQ,7048
150
+ bbot/modules/output/postgres.py,sha256=vsz3Gl9SKoWKhDidMFczksJzTeM0TZ7G9qY2rIYETF0,1938
150
151
  bbot/modules/output/python.py,sha256=RvK2KN-Zp0Vy_1zGSNioE5eeL5hIh6Z_riFtaTymyIM,270
151
152
  bbot/modules/output/slack.py,sha256=Ir_z11VYBdXDx8DwntWCv33Ic43vO1UIbxcp9gj0vvk,1181
152
153
  bbot/modules/output/splunk.py,sha256=TjTCUmDwRwKOFKBJw-Xbjku64U77OauHjtR56gyaAPs,1952
153
- bbot/modules/output/sqlite.py,sha256=GCtm1UoKfewtEKE79gBcj_UlTXO7jNHEEEuhqQ_iUnQ,888
154
- bbot/modules/output/stdout.py,sha256=d05QB4V4Rpw9dIZBwKlQsmdX8lSjeCt3uqkPPJYI5rY,3024
154
+ bbot/modules/output/sqlite.py,sha256=N0p6RRUcuCqGd4HIP0nG6JOPMs88LDQx4ImkdZVBM5E,979
155
+ bbot/modules/output/stdout.py,sha256=aLUtODqStdxmhh4lg7PRUsPEwTPLzdp3Hx7ZwbUvP_c,3084
155
156
  bbot/modules/output/subdomains.py,sha256=3KZz4vD0itmqpo56uCyk43Z_zN1Q0Q_nyXjdnEublPA,1515
156
157
  bbot/modules/output/teams.py,sha256=I2d52LqDC7e_oboLHoYBaRK6UpN0nkJ0uRnBXrhZf9E,4628
157
- bbot/modules/output/txt.py,sha256=_cQaa8oK0MAdF1YhWaZh_8szNneRpDqzFETta13HPB8,916
158
+ bbot/modules/output/txt.py,sha256=I4zGvsFvqYZtruiCLg5spAYwR-wqjxCU0FRkPhqBUJo,976
158
159
  bbot/modules/output/web_report.py,sha256=lZ0FqRZ7Jz1lljI9JMhH9gjtWLaTCSpSnAKQGAcPx-Q,3720
159
160
  bbot/modules/output/websocket.py,sha256=sDTtHU-Ey_tvS0gMi6PVPV9L4qAmGyWeccxAKfEWCac,2278
160
161
  bbot/modules/paramminer_cookies.py,sha256=q1PzftHQpCHLz81_VgLZsO6moia7ZtnU32igfcySi2w,1816
@@ -220,7 +221,7 @@ bbot/scanner/__init__.py,sha256=gCyAAbkNm8_KozNpDENCKqO3E3ZCgseplnz40AtiJ1U,56
220
221
  bbot/scanner/dispatcher.py,sha256=_hsIegfUDrt8CUdXqgRvp1J0UwwzqVSDxjQmiviO41c,793
221
222
  bbot/scanner/manager.py,sha256=_5FBfxOmSMUeGp_-ryyGGl0pxb_eu-NSWft-lH1Pyog,10466
222
223
  bbot/scanner/preset/__init__.py,sha256=Jf2hWsHlTFtWNXL6gXD8_ZbKPFUM564ppdSxHFYnIJU,27
223
- bbot/scanner/preset/args.py,sha256=KnFoQveKiSbNOSWr5dpa9lS3vP3Jnhk1FiyBLeaqFpI,16054
224
+ bbot/scanner/preset/args.py,sha256=pMJ0PfQDbLwOnggaKJl_CHz1SpQpqhhQQPvVWQaoIKA,16269
224
225
  bbot/scanner/preset/conditions.py,sha256=hFL9cSIWGEsv2TfM5UGurf0c91cyaM8egb5IngBmIjA,1569
225
226
  bbot/scanner/preset/environ.py,sha256=9KbEOLWkUdoAf5Ez_2A1NNm6QduQElbnNnrPi6VDhZs,4731
226
227
  bbot/scanner/preset/path.py,sha256=Q29MO8cOEn690yW6bB08P72kbZ3C-H_TOEoXuwWnFM8,2274
@@ -242,7 +243,7 @@ bbot/test/test_step_1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
242
243
  bbot/test/test_step_1/test__module__tests.py,sha256=uwuROxdXI52D-V9z3Q9VNslvBfaduj6MQS5tQ_UOqXA,1460
243
244
  bbot/test/test_step_1/test_bbot_fastapi.py,sha256=FNGvlax4lFZVd0T3HvV9SJh1lsngOX58GrUnJVzoy20,2531
244
245
  bbot/test/test_step_1/test_bloom_filter.py,sha256=GodseGF98sarWXZ5C3JCVWblnycS4BA75HEAzhx4xXg,2139
245
- bbot/test/test_step_1/test_cli.py,sha256=JIBpAMpr2Zmg_cM0AOoyWLbwtF6JVhgp83Mxc1ZgPUs,25935
246
+ bbot/test/test_step_1/test_cli.py,sha256=osCnJFA5S7NpGeAukVFTx3EkmLZPX6vITectU062Rsg,26299
246
247
  bbot/test/test_step_1/test_command.py,sha256=5IeGV6TKB0xtFEsfsU_0mNrOmEdIQiQ3FHkUmsBNoOI,6485
247
248
  bbot/test/test_step_1/test_config.py,sha256=Q38hygpke2GDcv8OguVZuiSOnfDJxEMrRy20dN5Qsn0,887
248
249
  bbot/test/test_step_1/test_depsinstaller.py,sha256=zr9f-wJDotD1ZvKXGEuDRWzFYMAYBI6209mI_PWPtTQ,703
@@ -254,7 +255,7 @@ bbot/test/test_step_1/test_files.py,sha256=5Q_3jPpMXULxDHsanSDUaj8zF8bXzKdiJZHOm
254
255
  bbot/test/test_step_1/test_helpers.py,sha256=6WG2rqnI7Jt0Z7Dc5AyqTDcL16QM0_WJ3CXE1M-xSMc,39506
255
256
  bbot/test/test_step_1/test_manager_deduplication.py,sha256=hZQpDXzg6zvzxFolVOcJuY-ME8NXjZUsqS70BRNXp8A,15594
256
257
  bbot/test/test_step_1/test_manager_scope_accuracy.py,sha256=JV1bQHt9EIM0GmGS4T4Brz_L2lfcwTxtNC06cfv7r64,79763
257
- bbot/test/test_step_1/test_modules_basic.py,sha256=PtY8plupy-eOAr3YHWAZtgKqNRZt2eYtJljY8Zf3Cuo,20055
258
+ bbot/test/test_step_1/test_modules_basic.py,sha256=hxXdsrBwme5elGQtvyvA52-KzahyQC3FlWQZ3T0EheA,19989
258
259
  bbot/test/test_step_1/test_presets.py,sha256=CCwXb0gxTd8lSYtp0a_2PkfrwfdD5f9VngetbCLecL0,38211
259
260
  bbot/test/test_step_1/test_python_api.py,sha256=GM5Kp2AAFl92ozo1kL6axsM87F8Gdq2_mWQvRnbXW_0,5503
260
261
  bbot/test/test_step_1/test_regexes.py,sha256=34-BHzDE5qdltE-sQIzkrTmJTL49QUYoTn2uT1DZLwI,14356
@@ -293,7 +294,7 @@ bbot/test/test_step_2/module_tests/test_module_c99.py,sha256=F-46Kkwxe29xPZ-3kxC
293
294
  bbot/test/test_step_2/module_tests/test_module_censys.py,sha256=RoFfLS0hgASdSoctJEzaKrHVqqRkuPRKPTYVCX2rZLo,4177
294
295
  bbot/test/test_step_2/module_tests/test_module_certspotter.py,sha256=60jCOeK1yaUEgtTxYW-T47kZgKt9XxP2qBH9w-0MDBk,636
295
296
  bbot/test/test_step_2/module_tests/test_module_chaos.py,sha256=9JRgtDEnnJgmEMCTB2bqRJRkBavLys-6ypHPxrM_hXk,956
296
- bbot/test/test_step_2/module_tests/test_module_cloudcheck.py,sha256=XWAkCpq0PMEGXksnK4tNR1IyPkjRd_anhCoT5tWmLU4,4074
297
+ bbot/test/test_step_2/module_tests/test_module_cloudcheck.py,sha256=9DVhJfXaM42JXz577T0LdrrmArvhFXNdhICZP8aLLFU,4081
297
298
  bbot/test/test_step_2/module_tests/test_module_code_repository.py,sha256=i02Tgvr_F9_E4d6aEaXrfdk71NkoDvjzP4C98l2rNGg,2414
298
299
  bbot/test/test_step_2/module_tests/test_module_columbus.py,sha256=6CpIJCsykUfsn0CqxQWciIiNdM3Z73-HTnpBnVtS-L8,563
299
300
  bbot/test/test_step_2/module_tests/test_module_credshed.py,sha256=ipkCFL7YmZBLWWoGyGr98saL_yh3E99EnLtagHqdY1g,3360
@@ -350,6 +351,7 @@ bbot/test/test_step_2/module_tests/test_module_mysql.py,sha256=4wAPjbjhlxmOkEhQn
350
351
  bbot/test/test_step_2/module_tests/test_module_myssl.py,sha256=zRJ1sOEespWtBx2jA07bW5sHD1XQ9pV0PtHtGogo7Gs,1531
351
352
  bbot/test/test_step_2/module_tests/test_module_neo4j.py,sha256=pUUaqxBsF6s11dEDhrETpvlR2pqiUcc0uvH8Z5GvVUQ,1332
352
353
  bbot/test/test_step_2/module_tests/test_module_newsletters.py,sha256=uf5t2oRqxhNToPjEfkY9vMdOUzrSocvx8w5itS6HUaM,2295
354
+ bbot/test/test_step_2/module_tests/test_module_nmap_xml.py,sha256=KbUAjhARvtERv7Jx666n2hkuLOmK8Zah8RpLZqNyAuE,3548
353
355
  bbot/test/test_step_2/module_tests/test_module_ntlm.py,sha256=tPUrsOnq8iV0l_qiD_4xkqp0-o_T2uI1e-yH22oNveA,1132
354
356
  bbot/test/test_step_2/module_tests/test_module_nuclei.py,sha256=rLCTuKWnGWiGDcVnMjk4D7x6RGftEj3D4Woqpam-cgQ,7050
355
357
  bbot/test/test_step_2/module_tests/test_module_oauth.py,sha256=pN1o0DmcwGCa985FrIhUuX1jIGriDjaxMzWozuv8pR0,9481
@@ -414,8 +416,8 @@ bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt,sha256=ZSIVebs7ptMvHx
414
416
  bbot/wordlists/top_open_ports_nmap.txt,sha256=LmdFYkfapSxn1pVuQC2LkOIY2hMLgG-Xts7DVtYzweM,42727
415
417
  bbot/wordlists/valid_url_schemes.txt,sha256=0B_VAr9Dv7aYhwi6JSBDU-3M76vNtzN0qEC_RNLo7HE,3310
416
418
  bbot/wordlists/wordninja_dns.txt.gz,sha256=DYHvvfW0TvzrVwyprqODAk4tGOxv5ezNmCPSdPuDUnQ,570241
417
- bbot-2.3.0.5423rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
418
- bbot-2.3.0.5423rc0.dist-info/METADATA,sha256=Xijs0MQx3HBuMhNV53hM89g8TXQmOP5JsOI4y33U6mE,17949
419
- bbot-2.3.0.5423rc0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
420
- bbot-2.3.0.5423rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
421
- bbot-2.3.0.5423rc0.dist-info/RECORD,,
419
+ bbot-2.3.0.5445rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
420
+ bbot-2.3.0.5445rc0.dist-info/METADATA,sha256=TG1MVpP1_xg79xoc_MNMJtE8VrRLIGHNIHAq8oy9VW4,17990
421
+ bbot-2.3.0.5445rc0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
422
+ bbot-2.3.0.5445rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
423
+ bbot-2.3.0.5445rc0.dist-info/RECORD,,