bbot 2.1.2.5202rc0__py3-none-any.whl → 2.1.2.5217rc0__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 +1 -1
- bbot/modules/apkpure.py +15 -5
- bbot/modules/jadx.py +111 -0
- bbot/test/test_step_2/module_tests/test_module_apkpure.py +6 -4
- bbot/test/test_step_2/module_tests/test_module_jadx.py +55 -0
- {bbot-2.1.2.5202rc0.dist-info → bbot-2.1.2.5217rc0.dist-info}/METADATA +1 -1
- {bbot-2.1.2.5202rc0.dist-info → bbot-2.1.2.5217rc0.dist-info}/RECORD +10 -8
- {bbot-2.1.2.5202rc0.dist-info → bbot-2.1.2.5217rc0.dist-info}/LICENSE +0 -0
- {bbot-2.1.2.5202rc0.dist-info → bbot-2.1.2.5217rc0.dist-info}/WHEEL +0 -0
- {bbot-2.1.2.5202rc0.dist-info → bbot-2.1.2.5217rc0.dist-info}/entry_points.txt +0 -0
bbot/__init__.py
CHANGED
bbot/modules/apkpure.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from bbot.modules.base import BaseModule
|
|
3
4
|
|
|
@@ -45,9 +46,18 @@ class apkpure(BaseModule):
|
|
|
45
46
|
path = None
|
|
46
47
|
url = f"https://d.apkpure.com/b/XAPK/{app_id}?version=latest"
|
|
47
48
|
self.helpers.mkdir(self.output_dir / app_id)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
response = await self.helpers.request(url, allow_redirects=True)
|
|
50
|
+
if response:
|
|
51
|
+
attachment = response.headers.get("Content-Disposition", "")
|
|
52
|
+
if "filename" in attachment:
|
|
53
|
+
match = re.search(r'filename="?([^"]+)"?', attachment)
|
|
54
|
+
if match:
|
|
55
|
+
filename = match.group(1)
|
|
56
|
+
extension = filename.split(".")[-1]
|
|
57
|
+
content = response.content
|
|
58
|
+
file_destination = self.output_dir / app_id / f"{app_id}.{extension}"
|
|
59
|
+
with open(file_destination, "wb") as f:
|
|
60
|
+
f.write(content)
|
|
61
|
+
self.info(f'Downloaded "{app_id}" from "{url}", saved to {file_destination}')
|
|
62
|
+
path = file_destination
|
|
53
63
|
return path
|
bbot/modules/jadx.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from subprocess import CalledProcessError
|
|
3
|
+
from bbot.modules.internal.base import BaseModule
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class jadx(BaseModule):
|
|
7
|
+
watched_events = ["FILESYSTEM"]
|
|
8
|
+
produced_events = ["FILESYSTEM"]
|
|
9
|
+
flags = ["passive", "safe"]
|
|
10
|
+
meta = {
|
|
11
|
+
"description": "Decompile APKs and XAPKs using JADX",
|
|
12
|
+
"created_date": "2024-11-04",
|
|
13
|
+
"author": "@domwhewell-sage",
|
|
14
|
+
}
|
|
15
|
+
options = {
|
|
16
|
+
"threads": 4,
|
|
17
|
+
}
|
|
18
|
+
options_desc = {
|
|
19
|
+
"threads": "Maximum jadx threads for extracting apk's, default: 4",
|
|
20
|
+
}
|
|
21
|
+
deps_ansible = [
|
|
22
|
+
{
|
|
23
|
+
"name": "Install latest JRE (Debian)",
|
|
24
|
+
"package": {"name": ["default-jre"], "state": "present"},
|
|
25
|
+
"become": True,
|
|
26
|
+
"when": "ansible_facts['os_family'] == 'Debian'",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "Install latest JRE (Arch)",
|
|
30
|
+
"package": {"name": ["jre-openjdk"], "state": "present"},
|
|
31
|
+
"become": True,
|
|
32
|
+
"when": "ansible_facts['os_family'] == 'Archlinux'",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "Install latest JRE (Fedora)",
|
|
36
|
+
"package": {"name": ["which", "java-latest-openjdk-headless"], "state": "present"},
|
|
37
|
+
"become": True,
|
|
38
|
+
"when": "ansible_facts['os_family'] == 'RedHat'",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "Install latest JRE (Alpine)",
|
|
42
|
+
"package": {"name": ["openjdk11"], "state": "present"},
|
|
43
|
+
"become": True,
|
|
44
|
+
"when": "ansible_facts['os_family'] == 'Alpine'",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "Create jadx directory",
|
|
48
|
+
"file": {"path": "#{BBOT_TOOLS}/jadx", "state": "directory", "mode": "0755"},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "Download jadx",
|
|
52
|
+
"unarchive": {
|
|
53
|
+
"src": "https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zip",
|
|
54
|
+
"include": ["lib/jadx-1.5.0-all.jar", "bin/jadx"],
|
|
55
|
+
"dest": "#{BBOT_TOOLS}/jadx",
|
|
56
|
+
"remote_src": True,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
allowed_file_types = ["java archive", "android application package"]
|
|
62
|
+
|
|
63
|
+
async def setup(self):
|
|
64
|
+
self.threads = self.config.get("threads", 4)
|
|
65
|
+
return True
|
|
66
|
+
|
|
67
|
+
async def filter_event(self, event):
|
|
68
|
+
if "file" in event.tags:
|
|
69
|
+
if not event.data["magic_description"].lower() in self.allowed_file_types:
|
|
70
|
+
return False, f"Jadx is not able to decompile this file type: {event.data['magic_description']}"
|
|
71
|
+
else:
|
|
72
|
+
return False, "Event is not a file"
|
|
73
|
+
return True
|
|
74
|
+
|
|
75
|
+
async def handle_event(self, event):
|
|
76
|
+
path = Path(event.data["path"])
|
|
77
|
+
output_dir = path.parent / path.name.replace(".", "_")
|
|
78
|
+
self.helpers.mkdir(output_dir)
|
|
79
|
+
success = await self.decompile_apk(path, output_dir)
|
|
80
|
+
|
|
81
|
+
# If jadx was able to decompile the java archive, emit an event
|
|
82
|
+
if success:
|
|
83
|
+
await self.emit_event(
|
|
84
|
+
{"path": str(output_dir)},
|
|
85
|
+
"FILESYSTEM",
|
|
86
|
+
tags="folder",
|
|
87
|
+
parent=event,
|
|
88
|
+
context=f'extracted "{path}" to: {output_dir}',
|
|
89
|
+
)
|
|
90
|
+
else:
|
|
91
|
+
output_dir.rmdir()
|
|
92
|
+
|
|
93
|
+
async def decompile_apk(self, path, output_dir):
|
|
94
|
+
command = [
|
|
95
|
+
f"{self.scan.helpers.tools_dir}/jadx/bin/jadx",
|
|
96
|
+
"--threads-count",
|
|
97
|
+
self.threads,
|
|
98
|
+
"--output-dir",
|
|
99
|
+
str(output_dir),
|
|
100
|
+
str(path),
|
|
101
|
+
]
|
|
102
|
+
try:
|
|
103
|
+
output = await self.run_process(command, check=True)
|
|
104
|
+
except CalledProcessError as e:
|
|
105
|
+
self.warning(f"Error decompiling {path}. STDERR: {repr(e.stderr)}")
|
|
106
|
+
return False
|
|
107
|
+
if not Path(output_dir / "resources").exists() and not Path(output_dir / "sources").exists():
|
|
108
|
+
self.warning(f"JADX was unable to decompile {path}.")
|
|
109
|
+
self.warning(output)
|
|
110
|
+
return False
|
|
111
|
+
return True
|
|
@@ -37,6 +37,10 @@ class TestAPKPure(ModuleTestBase):
|
|
|
37
37
|
module_test.httpx_mock.add_response(
|
|
38
38
|
url="https://d.apkpure.com/b/XAPK/com.bbot.test?version=latest",
|
|
39
39
|
content=self.apk_file,
|
|
40
|
+
headers={
|
|
41
|
+
"Content-Type": "application/vnd.android.package-archive",
|
|
42
|
+
"Content-Disposition": "attachment; filename=com.bbot.test.apk",
|
|
43
|
+
},
|
|
40
44
|
)
|
|
41
45
|
|
|
42
46
|
def check(self, module_test, events):
|
|
@@ -61,9 +65,7 @@ class TestAPKPure(ModuleTestBase):
|
|
|
61
65
|
and e.data["url"] == "https://play.google.com/store/apps/details?id=com.bbot.test"
|
|
62
66
|
]
|
|
63
67
|
), "Failed to find bbot android app"
|
|
64
|
-
filesystem_event = [
|
|
65
|
-
e for e in events if e.type == "FILESYSTEM" and "com.bbot.test.xapk" in e.data["path"] and "apk" in e.tags
|
|
66
|
-
]
|
|
68
|
+
filesystem_event = [e for e in events if e.type == "FILESYSTEM" and "com.bbot.test.apk" in e.data["path"]]
|
|
67
69
|
assert 1 == len(filesystem_event), "Failed to download apk"
|
|
68
70
|
file = Path(filesystem_event[0].data["path"])
|
|
69
|
-
assert file.is_file(), "Destination
|
|
71
|
+
assert file.is_file(), "Destination apk doesn't exist"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from bbot.core.helpers.libmagic import get_magic_info
|
|
3
|
+
from bbot.test.test_step_2.module_tests.base import ModuleTestBase, tempapkfile
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestJadx(ModuleTestBase):
|
|
7
|
+
modules_overrides = ["apkpure", "google_playstore", "speculate", "jadx"]
|
|
8
|
+
apk_file = tempapkfile()
|
|
9
|
+
|
|
10
|
+
async def setup_after_prep(self, module_test):
|
|
11
|
+
await module_test.mock_dns({"blacklanternsecurity.com": {"A": ["127.0.0.99"]}})
|
|
12
|
+
module_test.httpx_mock.add_response(
|
|
13
|
+
url="https://play.google.com/store/search?q=blacklanternsecurity&c=apps",
|
|
14
|
+
text="""<!DOCTYPE html>
|
|
15
|
+
<html>
|
|
16
|
+
<head>
|
|
17
|
+
<title>"blacklanternsecurity" - Android Apps on Google Play</title>
|
|
18
|
+
</head>
|
|
19
|
+
<body>
|
|
20
|
+
<a href="/store/apps/details?id=com.bbot.test&pcampaignid=dontmatchme&pli=1"/>
|
|
21
|
+
</body>
|
|
22
|
+
</html>""",
|
|
23
|
+
)
|
|
24
|
+
module_test.httpx_mock.add_response(
|
|
25
|
+
url="https://play.google.com/store/apps/details?id=com.bbot.test",
|
|
26
|
+
text="""<!DOCTYPE html>
|
|
27
|
+
<html>
|
|
28
|
+
<head>
|
|
29
|
+
<title>BBOT</title>
|
|
30
|
+
</head>
|
|
31
|
+
<body>
|
|
32
|
+
<meta name="appstore:developer_url" content="https://www.blacklanternsecurity.com">
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</body>
|
|
36
|
+
</html>""",
|
|
37
|
+
)
|
|
38
|
+
module_test.httpx_mock.add_response(
|
|
39
|
+
url="https://d.apkpure.com/b/XAPK/com.bbot.test?version=latest",
|
|
40
|
+
content=self.apk_file,
|
|
41
|
+
headers={
|
|
42
|
+
"Content-Type": "application/vnd.android.package-archive",
|
|
43
|
+
"Content-Disposition": "attachment; filename=com.bbot.test.apk",
|
|
44
|
+
},
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def check(self, module_test, events):
|
|
48
|
+
filesystem_events = [e for e in events if e.type == "FILESYSTEM"]
|
|
49
|
+
apk_event = [e for e in filesystem_events if "file" in e.tags]
|
|
50
|
+
extension, mime_type, description, confidence = get_magic_info(apk_event[0].data["path"])
|
|
51
|
+
assert description == "Android Application Package", f"Downloaded file was detected as {description}"
|
|
52
|
+
extract_event = [e for e in filesystem_events if "folder" in e.tags]
|
|
53
|
+
assert 1 == len(extract_event), "Failed to extract apk"
|
|
54
|
+
extract_path = Path(extract_event[0].data["path"])
|
|
55
|
+
assert extract_path.is_dir(), "Destination apk doesn't exist"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
bbot/__init__.py,sha256=
|
|
1
|
+
bbot/__init__.py,sha256=bcMCe34JyyhiWa3oujbqtItGNcI12sPbMHi-V-cULyc,130
|
|
2
2
|
bbot/cli.py,sha256=7S3a4eB-Dl8yodc5WC-927Z30CNlLl9EXimGvIVypJo,10434
|
|
3
3
|
bbot/core/__init__.py,sha256=l255GJE_DvUnWvrRb0J5lG-iMztJ8zVvoweDOfegGtI,46
|
|
4
4
|
bbot/core/config/__init__.py,sha256=zYNw2Me6tsEr8hOOkLb4BQ97GB7Kis2k--G81S8vofU,342
|
|
@@ -53,7 +53,7 @@ bbot/logger.py,sha256=rLcLzNDvfR8rFj7_tZ-f5QB3Z8T0RVroact3W0ogjpA,1408
|
|
|
53
53
|
bbot/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
bbot/modules/ajaxpro.py,sha256=13T5VtzgQGSjeFs7FvCHpTO7372cA5P_0XV8yEPNXzQ,2663
|
|
55
55
|
bbot/modules/anubisdb.py,sha256=0V00Lm_1Sr_LQWkeb07-mF_530N9x5MCTXZW_aCgitY,1910
|
|
56
|
-
bbot/modules/apkpure.py,sha256=
|
|
56
|
+
bbot/modules/apkpure.py,sha256=V-bGIFV7b91kXo24OitACip8Rx5qaoI1p6iHwbICxwk,2434
|
|
57
57
|
bbot/modules/azure_realm.py,sha256=pP2PUlLy0K9KKaE8aNcznWjDW3PKHvnMejdOSc-o4ms,1612
|
|
58
58
|
bbot/modules/azure_tenant.py,sha256=cKS53GjvrplaFFYvacUmJKCdLB6h7Yp_AzHNFuKtFrU,5374
|
|
59
59
|
bbot/modules/baddns.py,sha256=jp3S3sVZW74N9zMCEfy_J5XtnnsrRvHGtWQCBu874RY,6375
|
|
@@ -126,6 +126,7 @@ bbot/modules/internetdb.py,sha256=Edg0Z84dH8dPTZMd7RlzvYBYNq8JHs_ns_ldnFxwRKo,54
|
|
|
126
126
|
bbot/modules/ip2location.py,sha256=yGivX9fzvwvLpnqmYCP2a8SPjTarzrZxfRluog-nkME,2628
|
|
127
127
|
bbot/modules/ipneighbor.py,sha256=Gr-HGtyZRDp_fPjpw-Mq1al7ocFdiZbKsAoAit-EUlA,1591
|
|
128
128
|
bbot/modules/ipstack.py,sha256=j_S8WMNqQuSQgBT7AX4tO70fgbWuRYrpsS3tVsu_hn4,2200
|
|
129
|
+
bbot/modules/jadx.py,sha256=a5RrFiXglgNQpXkRHZM6i_fqCP1GPBB_UVZZk9BrehY,3946
|
|
129
130
|
bbot/modules/leakix.py,sha256=KkqhlBHhKxYGcWfGdrXzJPYXFIshp2oCY6FRHhsI8mY,1547
|
|
130
131
|
bbot/modules/myssl.py,sha256=yypGgAwkPAsoo9_eUFx1TO7qdE4UAUPW24Ca6G0z76M,936
|
|
131
132
|
bbot/modules/newsletters.py,sha256=5PfkzYmnrP2Pbqsch5z575Isck5TG4RJPH8vPr_vM2c,2632
|
|
@@ -260,7 +261,7 @@ bbot/test/test_step_2/module_tests/test_module_affiliates.py,sha256=d6uAzb_MF4oN
|
|
|
260
261
|
bbot/test/test_step_2/module_tests/test_module_aggregate.py,sha256=hjxbMxAEFhS7W8RamBrM1t6T-tsLHq95MmQVfrYsock,487
|
|
261
262
|
bbot/test/test_step_2/module_tests/test_module_ajaxpro.py,sha256=0sPzcm0O3mmeqcOb8BUPijdAwt5TJvyaGDdbJdDMgYI,2789
|
|
262
263
|
bbot/test/test_step_2/module_tests/test_module_anubisdb.py,sha256=aQHUUswX2VJYoUWFm3cInXnUK4lkU-ah3b2BnxWgWcQ,546
|
|
263
|
-
bbot/test/test_step_2/module_tests/test_module_apkpure.py,sha256=
|
|
264
|
+
bbot/test/test_step_2/module_tests/test_module_apkpure.py,sha256=8KM-JCir0doUupwN3JwV5OPaPE_Jq_hz2-96-ZKGpRI,2823
|
|
264
265
|
bbot/test/test_step_2/module_tests/test_module_asn.py,sha256=qIbitSAEAmYyxhpxvdFDsQrHaaxfgKsFox9Q3jTmvgI,10616
|
|
265
266
|
bbot/test/test_step_2/module_tests/test_module_asset_inventory.py,sha256=S21Wuwwg2U4pM5G4KZI4-rDp4V654rZTl_GZG-mPjjY,3879
|
|
266
267
|
bbot/test/test_step_2/module_tests/test_module_azure_realm.py,sha256=uCNeyKmlC26tcyQGyasnTqzzVWo_oKy_EHKEVVh8W9o,1287
|
|
@@ -332,6 +333,7 @@ bbot/test/test_step_2/module_tests/test_module_internetdb.py,sha256=3FRiC2ktEC7u
|
|
|
332
333
|
bbot/test/test_step_2/module_tests/test_module_ip2location.py,sha256=VRuXQelBc3hTNXiAJZD0ow5R4t6L8xAi_tS62TFLJKA,1123
|
|
333
334
|
bbot/test/test_step_2/module_tests/test_module_ipneighbor.py,sha256=Bc5xaiIpleC7j5Lz2Y8S9i6PHETOg4KmwiLNJ9HeMx8,608
|
|
334
335
|
bbot/test/test_step_2/module_tests/test_module_ipstack.py,sha256=BgCeE9Bef2RM6akluq0XVzr4G23kpP0Nqfydm_RoTXU,2767
|
|
336
|
+
bbot/test/test_step_2/module_tests/test_module_jadx.py,sha256=qTBfDc_Iv03n8iGdyLm6kBaKeEdSxFYeKj5xL1PmyF0,2391
|
|
335
337
|
bbot/test/test_step_2/module_tests/test_module_json.py,sha256=gmlqge5ZJpjVMGs7OLZBsNlSFTTrKnKjIZMIU23o8VQ,3350
|
|
336
338
|
bbot/test/test_step_2/module_tests/test_module_leakix.py,sha256=MxlanzyTi2oypYqw54RVA0kH55w_PWNLHMIWElkNFEc,1641
|
|
337
339
|
bbot/test/test_step_2/module_tests/test_module_myssl.py,sha256=dweSmwUYEcC3DapozRSpHvvvdbw54HVlc_L2pC7ILew,1532
|
|
@@ -400,8 +402,8 @@ bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt,sha256=ruUQwVfia1_m2u
|
|
|
400
402
|
bbot/wordlists/top_open_ports_nmap.txt,sha256=LmdFYkfapSxn1pVuQC2LkOIY2hMLgG-Xts7DVtYzweM,42727
|
|
401
403
|
bbot/wordlists/valid_url_schemes.txt,sha256=VciB-ww0y-O8Ii1wpTR6rJzGDiC2r-dhVsIJApS1ZYU,3309
|
|
402
404
|
bbot/wordlists/wordninja_dns.txt.gz,sha256=DYHvvfW0TvzrVwyprqODAk4tGOxv5ezNmCPSdPuDUnQ,570241
|
|
403
|
-
bbot-2.1.2.
|
|
404
|
-
bbot-2.1.2.
|
|
405
|
-
bbot-2.1.2.
|
|
406
|
-
bbot-2.1.2.
|
|
407
|
-
bbot-2.1.2.
|
|
405
|
+
bbot-2.1.2.5217rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
|
|
406
|
+
bbot-2.1.2.5217rc0.dist-info/METADATA,sha256=xPAP-jaJXyObldRPFdKgbFfvFFzf9bLlOOj9AQhkqMk,17109
|
|
407
|
+
bbot-2.1.2.5217rc0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
408
|
+
bbot-2.1.2.5217rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
|
|
409
|
+
bbot-2.1.2.5217rc0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|