anais-apk-forensic 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +249 -0
- package/anais.sh +669 -0
- package/analysis_tools/__pycache__/apk_basic_info.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/apk_basic_info.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/check_zip_encryption.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/check_zip_encryption.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/detect_obfuscation.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/detect_obfuscation.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/dex_payload_hunter.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/entropy_analyzer.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/error_logger.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/error_logger.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/find_encrypted_payload.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/fix_apk_headers.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/fix_apk_headers.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/manifest_analyzer.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/manifest_analyzer.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/network_analyzer.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/network_analyzer.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/report_generator.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/report_generator.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/report_generator_modular.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/sast_scanner.cpython-313.pyc +0 -0
- package/analysis_tools/__pycache__/sast_scanner.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/so_string_analyzer.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/yara_enhanced_analyzer.cpython-314.pyc +0 -0
- package/analysis_tools/__pycache__/yara_results_processor.cpython-314.pyc +0 -0
- package/analysis_tools/apk_basic_info.py +85 -0
- package/analysis_tools/check_zip_encryption.py +142 -0
- package/analysis_tools/detect_obfuscation.py +650 -0
- package/analysis_tools/dex_payload_hunter.py +734 -0
- package/analysis_tools/entropy_analyzer.py +335 -0
- package/analysis_tools/error_logger.py +75 -0
- package/analysis_tools/find_encrypted_payload.py +485 -0
- package/analysis_tools/fix_apk_headers.py +154 -0
- package/analysis_tools/manifest_analyzer.py +214 -0
- package/analysis_tools/network_analyzer.py +287 -0
- package/analysis_tools/report_generator.py +506 -0
- package/analysis_tools/report_generator_modular.py +885 -0
- package/analysis_tools/sast_scanner.py +412 -0
- package/analysis_tools/so_string_analyzer.py +406 -0
- package/analysis_tools/yara_enhanced_analyzer.py +330 -0
- package/analysis_tools/yara_results_processor.py +368 -0
- package/analyzer_config.json +113 -0
- package/apkid/__init__.py +32 -0
- package/apkid/__pycache__/__init__.cpython-313.pyc +0 -0
- package/apkid/__pycache__/__init__.cpython-314.pyc +0 -0
- package/apkid/__pycache__/apkid.cpython-313.pyc +0 -0
- package/apkid/__pycache__/apkid.cpython-314.pyc +0 -0
- package/apkid/__pycache__/main.cpython-313.pyc +0 -0
- package/apkid/__pycache__/main.cpython-314.pyc +0 -0
- package/apkid/__pycache__/output.cpython-313.pyc +0 -0
- package/apkid/__pycache__/rules.cpython-313.pyc +0 -0
- package/apkid/apkid.py +266 -0
- package/apkid/main.py +98 -0
- package/apkid/output.py +177 -0
- package/apkid/rules/apk/common.yara +68 -0
- package/apkid/rules/apk/obfuscators.yara +118 -0
- package/apkid/rules/apk/packers.yara +1197 -0
- package/apkid/rules/apk/protectors.yara +301 -0
- package/apkid/rules/dex/abnormal.yara +104 -0
- package/apkid/rules/dex/anti-vm.yara +568 -0
- package/apkid/rules/dex/common.yara +60 -0
- package/apkid/rules/dex/compilers.yara +434 -0
- package/apkid/rules/dex/obfuscators.yara +602 -0
- package/apkid/rules/dex/packers.yara +761 -0
- package/apkid/rules/dex/protectors.yara +520 -0
- package/apkid/rules/dll/common.yara +38 -0
- package/apkid/rules/dll/obfuscators.yara +43 -0
- package/apkid/rules/elf/anti-vm.yara +43 -0
- package/apkid/rules/elf/common.yara +54 -0
- package/apkid/rules/elf/obfuscators.yara +991 -0
- package/apkid/rules/elf/packers.yara +1128 -0
- package/apkid/rules/elf/protectors.yara +794 -0
- package/apkid/rules/res/common.yara +43 -0
- package/apkid/rules/res/obfuscators.yara +46 -0
- package/apkid/rules/res/protectors.yara +46 -0
- package/apkid/rules.py +77 -0
- package/bin/anais +3 -0
- package/dist/cli.js +82 -0
- package/dist/index.js +123 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/index.js +21 -0
- package/dist/utils/output.js +44 -0
- package/dist/utils/paths.js +107 -0
- package/docs/ARCHITECTURE.txt +353 -0
- package/docs/Workflow and Reference.md +445 -0
- package/package.json +70 -0
- package/rules/yara_general_rules.yar +323 -0
- package/scripts/dynamic_analysis_helper.sh +334 -0
- package/scripts/frida/dpt_dex_dumper.js +145 -0
- package/scripts/frida/frida_dex_dump.js +145 -0
- package/scripts/frida/frida_hooks.js +437 -0
- package/scripts/frida/frida_websocket_extractor.js +154 -0
- package/scripts/setup.sh +206 -0
- package/scripts/validate_framework.sh +224 -0
- package/src/cli.ts +91 -0
- package/src/index.ts +123 -0
- package/src/types/index.ts +44 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/output.ts +50 -0
- package/src/utils/paths.ts +72 -0
- package/tsconfig.json +14 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
APK Basic Information Extractor using Androguard
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from androguard.core.bytecodes.apk import APK
|
|
12
|
+
except ImportError:
|
|
13
|
+
print("Warning: androguard not installed. Run: pip3 install androguard")
|
|
14
|
+
sys.exit(0)
|
|
15
|
+
|
|
16
|
+
def extract_apk_info(apk_path):
|
|
17
|
+
"""Extract comprehensive APK information"""
|
|
18
|
+
try:
|
|
19
|
+
apk = APK(apk_path)
|
|
20
|
+
|
|
21
|
+
info = {
|
|
22
|
+
'package_name': apk.get_package(),
|
|
23
|
+
'app_name': apk.get_app_name(),
|
|
24
|
+
'version_name': apk.get_androidversion_name(),
|
|
25
|
+
'version_code': apk.get_androidversion_code(),
|
|
26
|
+
'min_sdk': apk.get_min_sdk_version(),
|
|
27
|
+
'target_sdk': apk.get_target_sdk_version(),
|
|
28
|
+
'permissions': apk.get_permissions(),
|
|
29
|
+
'activities': apk.get_activities(),
|
|
30
|
+
'services': apk.get_services(),
|
|
31
|
+
'receivers': apk.get_receivers(),
|
|
32
|
+
'providers': apk.get_providers(),
|
|
33
|
+
'libraries': apk.get_libraries(),
|
|
34
|
+
'main_activity': apk.get_main_activity(),
|
|
35
|
+
'is_signed': apk.is_signed(),
|
|
36
|
+
'is_signed_v1': apk.is_signed_v1(),
|
|
37
|
+
'is_signed_v2': apk.is_signed_v2(),
|
|
38
|
+
'is_signed_v3': apk.is_signed_v3(),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Get certificate info if signed
|
|
42
|
+
if apk.is_signed():
|
|
43
|
+
try:
|
|
44
|
+
certs = apk.get_certificates_der_v1()
|
|
45
|
+
if certs:
|
|
46
|
+
from cryptography import x509
|
|
47
|
+
from cryptography.hazmat.backends import default_backend
|
|
48
|
+
|
|
49
|
+
cert = x509.load_der_x509_certificate(certs[0], default_backend())
|
|
50
|
+
info['certificate'] = {
|
|
51
|
+
'subject': str(cert.subject),
|
|
52
|
+
'issuer': str(cert.issuer),
|
|
53
|
+
'serial': str(cert.serial_number),
|
|
54
|
+
'not_before': str(cert.not_valid_before),
|
|
55
|
+
'not_after': str(cert.not_valid_after),
|
|
56
|
+
}
|
|
57
|
+
except:
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
return info
|
|
61
|
+
|
|
62
|
+
except Exception as e:
|
|
63
|
+
return {'error': str(e)}
|
|
64
|
+
|
|
65
|
+
def main():
|
|
66
|
+
if len(sys.argv) < 3:
|
|
67
|
+
print("Usage: apk_basic_info.py <apk_path> <output_json>")
|
|
68
|
+
sys.exit(1)
|
|
69
|
+
|
|
70
|
+
apk_path = sys.argv[1]
|
|
71
|
+
output_json = sys.argv[2]
|
|
72
|
+
|
|
73
|
+
info = extract_apk_info(apk_path)
|
|
74
|
+
|
|
75
|
+
with open(output_json, 'w') as f:
|
|
76
|
+
json.dump(info, f, indent=2)
|
|
77
|
+
|
|
78
|
+
print(f"APK Info extracted successfully")
|
|
79
|
+
if 'package_name' in info:
|
|
80
|
+
print(f"Package: {info['package_name']}")
|
|
81
|
+
print(f"Version: {info['version_name']} ({info['version_code']})")
|
|
82
|
+
print(f"Permissions: {len(info.get('permissions', []))}")
|
|
83
|
+
|
|
84
|
+
if __name__ == '__main__':
|
|
85
|
+
main()
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
ZIP Encryption and Protection Checker
|
|
4
|
+
Detects various ZIP protection mechanisms including encryption and header manipulation
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import struct
|
|
9
|
+
import json
|
|
10
|
+
import zipfile
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
class ZipProtectionChecker:
|
|
14
|
+
def __init__(self, apk_path):
|
|
15
|
+
self.apk_path = Path(apk_path)
|
|
16
|
+
self.results = {
|
|
17
|
+
'encrypted': False,
|
|
18
|
+
'password_protected': False,
|
|
19
|
+
'encrypted_files': [],
|
|
20
|
+
'corrupted_headers': False,
|
|
21
|
+
'protection_type': 'none',
|
|
22
|
+
'details': {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
def check_zip_encryption(self):
|
|
26
|
+
"""Check if ZIP file is encrypted or password protected"""
|
|
27
|
+
try:
|
|
28
|
+
with zipfile.ZipFile(self.apk_path, 'r') as zf:
|
|
29
|
+
for info in zf.infolist():
|
|
30
|
+
# Check encryption flag (bit 0 of flag_bits)
|
|
31
|
+
if info.flag_bits & 0x1:
|
|
32
|
+
self.results['encrypted'] = True
|
|
33
|
+
self.results['password_protected'] = True
|
|
34
|
+
self.results['encrypted_files'].append(info.filename)
|
|
35
|
+
self.results['protection_type'] = 'password_protected'
|
|
36
|
+
except zipfile.BadZipFile:
|
|
37
|
+
self.results['corrupted_headers'] = True
|
|
38
|
+
self.results['protection_type'] = 'corrupted_zip'
|
|
39
|
+
except Exception as e:
|
|
40
|
+
self.results['details']['error'] = str(e)
|
|
41
|
+
|
|
42
|
+
def check_local_file_header(self):
|
|
43
|
+
"""Check local file headers for manipulation"""
|
|
44
|
+
try:
|
|
45
|
+
with open(self.apk_path, 'rb') as f:
|
|
46
|
+
data = f.read(1024) # Read first KB
|
|
47
|
+
|
|
48
|
+
# Check for ZIP signature
|
|
49
|
+
if data[:4] != b'PK\x03\x04':
|
|
50
|
+
self.results['corrupted_headers'] = True
|
|
51
|
+
self.results['details']['header_issue'] = 'Invalid ZIP signature'
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
# Parse local file header
|
|
55
|
+
signature = struct.unpack('<I', data[0:4])[0]
|
|
56
|
+
version = struct.unpack('<H', data[4:6])[0]
|
|
57
|
+
flags = struct.unpack('<H', data[6:8])[0]
|
|
58
|
+
|
|
59
|
+
self.results['details']['local_header'] = {
|
|
60
|
+
'signature': hex(signature),
|
|
61
|
+
'version': version,
|
|
62
|
+
'flags': hex(flags)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Check encryption bit
|
|
66
|
+
if flags & 0x1:
|
|
67
|
+
self.results['encrypted'] = True
|
|
68
|
+
|
|
69
|
+
return True
|
|
70
|
+
|
|
71
|
+
except Exception as e:
|
|
72
|
+
self.results['details']['header_error'] = str(e)
|
|
73
|
+
return False
|
|
74
|
+
|
|
75
|
+
def check_central_directory(self):
|
|
76
|
+
"""Check central directory for manipulation"""
|
|
77
|
+
try:
|
|
78
|
+
with open(self.apk_path, 'rb') as f:
|
|
79
|
+
# Search for End of Central Directory signature
|
|
80
|
+
f.seek(-22, 2) # Minimum EOCD size is 22 bytes
|
|
81
|
+
data = f.read()
|
|
82
|
+
|
|
83
|
+
# Look for EOCD signature (PK\x05\x06)
|
|
84
|
+
eocd_offset = data.find(b'PK\x05\x06')
|
|
85
|
+
if eocd_offset == -1:
|
|
86
|
+
# Try reading more data
|
|
87
|
+
f.seek(-1024, 2)
|
|
88
|
+
data = f.read()
|
|
89
|
+
eocd_offset = data.find(b'PK\x05\x06')
|
|
90
|
+
|
|
91
|
+
if eocd_offset != -1:
|
|
92
|
+
eocd_data = data[eocd_offset:]
|
|
93
|
+
cd_offset = struct.unpack('<I', eocd_data[16:20])[0]
|
|
94
|
+
|
|
95
|
+
self.results['details']['central_directory'] = {
|
|
96
|
+
'offset': cd_offset,
|
|
97
|
+
'found': True
|
|
98
|
+
}
|
|
99
|
+
else:
|
|
100
|
+
self.results['corrupted_headers'] = True
|
|
101
|
+
self.results['details']['central_directory'] = {
|
|
102
|
+
'found': False
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
except Exception as e:
|
|
106
|
+
self.results['details']['cd_error'] = str(e)
|
|
107
|
+
|
|
108
|
+
def analyze(self):
|
|
109
|
+
"""Run all checks"""
|
|
110
|
+
self.check_zip_encryption()
|
|
111
|
+
self.check_local_file_header()
|
|
112
|
+
self.check_central_directory()
|
|
113
|
+
|
|
114
|
+
return self.results
|
|
115
|
+
|
|
116
|
+
def main():
|
|
117
|
+
if len(sys.argv) < 3:
|
|
118
|
+
print("Usage: check_zip_encryption.py <apk_path> <output_json>")
|
|
119
|
+
sys.exit(1)
|
|
120
|
+
|
|
121
|
+
apk_path = sys.argv[1]
|
|
122
|
+
output_json = sys.argv[2]
|
|
123
|
+
|
|
124
|
+
checker = ZipProtectionChecker(apk_path)
|
|
125
|
+
results = checker.analyze()
|
|
126
|
+
|
|
127
|
+
# Save results
|
|
128
|
+
with open(output_json, 'w') as f:
|
|
129
|
+
json.dump(results, f, indent=2)
|
|
130
|
+
|
|
131
|
+
# Print summary
|
|
132
|
+
print(f"Encryption Check Results:")
|
|
133
|
+
print(f" Encrypted: {results['encrypted']}")
|
|
134
|
+
print(f" Password Protected: {results['password_protected']}")
|
|
135
|
+
print(f" Protection Type: {results['protection_type']}")
|
|
136
|
+
print(f" Corrupted Headers: {results['corrupted_headers']}")
|
|
137
|
+
|
|
138
|
+
if results['encrypted_files']:
|
|
139
|
+
print(f" Encrypted Files: {len(results['encrypted_files'])}")
|
|
140
|
+
|
|
141
|
+
if __name__ == '__main__':
|
|
142
|
+
main()
|