teamstelemetry 0.0.1-security → 9.2.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.

Potentially problematic release.


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

@@ -0,0 +1,72 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ // Tên tệp JSON bạn tải về từ Interact.sh
5
+ const jsonExportFileName = 'interactsh-export.json';
6
+
7
+ console.log('Bắt đầu chẩn đoán dữ liệu từ tệp export của Interact.sh...');
8
+
9
+ try {
10
+ // Đọc tệp JSON export
11
+ const jsonFilePath = path.join(__dirname, jsonExportFileName);
12
+ const fileContent = fs.readFileSync(jsonFilePath, 'utf8');
13
+
14
+ // Phân tích cú pháp tệp JSON (có thể lồng nhau)
15
+ let interactData;
16
+ try {
17
+ const outerData = JSON.parse(fileContent);
18
+ interactData = typeof outerData.app === 'string' ? JSON.parse(outerData.app) : outerData;
19
+ } catch (e) {
20
+ interactData = JSON.parse(fileContent);
21
+ }
22
+
23
+ console.log(`Phát hiện tên miền gốc: ${interactData.host}`);
24
+
25
+ // Trích xuất và giải mã từng chunk
26
+ const chunks = {};
27
+ const dnsRequests = interactData.data.filter(req => req.protocol === 'dns');
28
+ const regex = new RegExp(`^(\\d+)\\.([0-9a-fA-F]+)`);
29
+
30
+ for (const request of dnsRequests) {
31
+ const fullId = request['full-id'] || '';
32
+ const match = fullId.match(regex);
33
+ if (match) {
34
+ const index = parseInt(match[1], 10);
35
+ const hexChunk = match[2];
36
+ // Giải mã ngay lập tức từng chunk HEX thành text
37
+ const decodedChunk = Buffer.from(hexChunk, 'hex').toString('utf8');
38
+ chunks[index] = decodedChunk;
39
+ }
40
+ }
41
+
42
+ const collectedChunksCount = Object.keys(chunks).length;
43
+ if (collectedChunksCount === 0) {
44
+ throw new Error('Không trích xuất được mảnh dữ liệu nào từ tệp export.');
45
+ }
46
+
47
+ console.log(`✅ Đã tìm thấy và xử lý ${collectedChunksCount} mảnh dữ liệu.\n`);
48
+
49
+ // Sắp xếp các chunks theo đúng thứ tự chỉ số (index)
50
+ const sortedKeys = Object.keys(chunks).sort((a, b) => parseInt(a) - parseInt(b));
51
+
52
+ console.log('--- NỘI DUNG CỦA TỪNG CHUNK ĐÃ ĐƯỢC GIẢI MÃ ---');
53
+ // In ra nội dung của từng chunk một
54
+ for (const key of sortedKeys) {
55
+ console.log(`Chunk [${key}]: ${chunks[key]}`);
56
+ }
57
+ console.log('--------------------------------------------');
58
+
59
+ // Ghép lại để xem trước chuỗi đầy đủ (có thể bị lỗi hoặc thiếu)
60
+ const fullDecodedString = sortedKeys.map(key => chunks[key]).join('');
61
+ console.log('\n--- DỮ LIỆU TỔNG HỢP (để tham khảo) ---');
62
+ console.log(fullDecodedString);
63
+ console.log('-----------------------------------------');
64
+
65
+
66
+ } catch (error) {
67
+ if (error.code === 'ENOENT') {
68
+ console.error(`\n❌ Lỗi: Không tìm thấy tệp '${jsonExportFileName}'. Hãy đảm bảo tệp JSON đã tải về nằm cùng thư mục.`);
69
+ } else {
70
+ console.error(`\n❌ Đã xảy ra lỗi nghiêm trọng:`, error.message);
71
+ }
72
+ }
@@ -0,0 +1,129 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * Hàm này quét chuỗi JSON bị lỗi và cố gắng trích xuất các cặp key-value đơn giản.
6
+ * Rất hữu ích khi dữ liệu bị mất mát do gói tin DNS không đến được theo đúng thứ tự hoặc bị thiếu.
7
+ * @param {string} brokenJsonString - Chuỗi JSON bị lỗi, không hoàn chỉnh.
8
+ * @returns {object} - Một đối tượng chứa các dữ liệu đã được khôi phục.
9
+ */
10
+ function bestEffortParse(brokenJsonString) {
11
+ const recoveredData = {};
12
+ // Các trường đơn giản, quan trọng thường xuất hiện ở đầu và dễ cứu nhất
13
+ const simpleKeysToRecover = ['ip', 'username', 'hostname', 'platform', 'arch', 'home'];
14
+
15
+ console.log('\n--- BẮT ĐẦU CỨU DỮ LIỆU TỪNG PHẦN ---');
16
+
17
+ for (const key of simpleKeysToRecover) {
18
+ // Regex để tìm một cặp "key": "value"
19
+ const regex = new RegExp(`"${key}"\\s*:\\s*"(.*?)"`, 'i');
20
+ const match = brokenJsonString.match(regex);
21
+
22
+ if (match && match[1]) {
23
+ recoveredData[key] = match[1];
24
+ console.log(`[+] Cứu thành công: ${key}`);
25
+ }
26
+ }
27
+
28
+ // Cố gắng tìm và trích xuất toàn bộ đối tượng "env"
29
+ // Regex này tìm chuỗi bắt đầu bằng "env": { và kết thúc ở cuối chuỗi
30
+ const envMatch = brokenJsonString.match(/"env"\s*:\s*({.*)/s);
31
+ if (envMatch && envMatch[1]) {
32
+ console.log('[+] Tìm thấy đối tượng "env" có thể bị lỗi. Đang thử phục hồi...');
33
+ let envString = envMatch[1];
34
+ // Cố gắng đóng đối tượng một cách an toàn
35
+ // Thêm dấu '}' vào cuối nếu nó bị thiếu, nhưng chỉ khi chuỗi không kết thúc bằng '}'
36
+ if (!envString.trim().endsWith('}')) {
37
+ envString += '}';
38
+ }
39
+
40
+ try {
41
+ // Thử phân tích cú pháp riêng cho đối tượng env
42
+ recoveredData.env = JSON.parse(envString);
43
+ console.log('[+] Cứu thành công toàn bộ đối tượng "env".');
44
+ } catch (e) {
45
+ // Nếu thất bại, chỉ hiển thị phần đã trích xuất được để người dùng tự phân tích
46
+ console.log('[-] Không thể phân tích cú pháp đối tượng "env" hoàn chỉnh. Hiển thị một phần.');
47
+ recoveredData.env_partial = envString;
48
+ }
49
+ }
50
+
51
+ return recoveredData;
52
+ }
53
+
54
+
55
+ // --- Bắt đầu logic chính ---
56
+
57
+ // Lấy tên tệp từ đối số dòng lệnh.
58
+ const logFileName = process.argv[2];
59
+
60
+ if (!logFileName) {
61
+ console.error('❌ Lỗi: Vui lòng cung cấp tên tệp log làm đối số.');
62
+ console.log(' Ví dụ: node ten_script_cua_ban.js interactsh-log.txt');
63
+ process.exit(1); // Thoát với mã lỗi
64
+ }
65
+
66
+ console.log(`Bắt đầu giải mã dữ liệu từ tệp '${logFileName}'...`);
67
+ try {
68
+ const logFilePath = path.join(__dirname, logFileName);
69
+ const fileContent = fs.readFileSync(logFilePath, 'utf8');
70
+
71
+ const chunks = {};
72
+ // Regex để trích xuất chỉ số (group 1) và chuỗi hex (group 2) từ mỗi dòng
73
+ // Ví dụ: [0.7b22...a75.d20b...m59h] -> group 1: '0', group 2: '7b22...a75'
74
+ const lineRegex = /\[(\d+)\.(.*?)\.[a-z0-9]+\]/i;
75
+
76
+ const lines = fileContent.split('\n');
77
+
78
+ for (const line of lines) {
79
+ const match = line.match(lineRegex);
80
+ if (match && match[1] && match[2]) {
81
+ const index = parseInt(match[1], 10);
82
+ // Loại bỏ các dấu chấm có thể tồn tại trong chuỗi hex do giới hạn độ dài subdomain
83
+ const hexData = match[2].replace(/\./g, '');
84
+ chunks[index] = hexData;
85
+ }
86
+ }
87
+
88
+ if (Object.keys(chunks).length === 0) {
89
+ throw new Error('Không trích xuất được mảnh dữ liệu nào từ tệp log. Hãy kiểm tra định dạng tệp.');
90
+ }
91
+
92
+ console.log(`✅ Đã xử lý ${Object.keys(chunks).length} mảnh dữ liệu.`);
93
+
94
+ // Sắp xếp các mảnh theo đúng thứ tự và ghép lại thành chuỗi HEX đầy đủ
95
+ const sortedKeys = Object.keys(chunks).sort((a, b) => parseInt(a) - parseInt(b));
96
+ const fullHexString = sortedKeys.map(key => chunks[key]).join('');
97
+
98
+ // Giải mã chuỗi HEX thành chuỗi JSON (có thể bị lỗi)
99
+ const decodedJsonString = Buffer.from(fullHexString, 'hex').toString('utf8');
100
+
101
+ // Cố gắng phân tích chuỗi JSON đã giải mã
102
+ try {
103
+ const finalData = JSON.parse(decodedJsonString);
104
+ console.log('\n--- DỮ LIỆU ĐÃ GIẢI MÃ HOÀN CHỈNH ---');
105
+ console.log(JSON.stringify(finalData, null, 2));
106
+ } catch (jsonError) {
107
+ // Nếu thất bại, chuyển sang chế độ cứu dữ liệu
108
+ console.log('\n⚠️ Lỗi phân tích JSON (có thể do mất gói tin). Chuyển sang chế độ cứu dữ liệu...');
109
+
110
+ const recovered = bestEffortParse(decodedJsonString);
111
+
112
+ console.log('\n--- KẾT QUẢ CỨU DỮ LIỆU ---');
113
+ if (Object.keys(recovered).length > 0) {
114
+ console.log(JSON.stringify(recovered, null, 2));
115
+ } else {
116
+ console.log('Không thể cứu được dữ liệu nào một cách tự động.');
117
+ }
118
+
119
+ console.log('\n--- DỮ LIỆU GỐC BỊ LỖI (để tham khảo) ---');
120
+ console.log(decodedJsonString);
121
+ }
122
+
123
+ } catch (error) {
124
+ if (error.code === 'ENOENT') {
125
+ console.error(`\n❌ Lỗi: Không tìm thấy tệp '${logFileName}'.`);
126
+ } else {
127
+ console.error(`\n❌ Đã xảy ra lỗi nghiêm trọng:`, error.message);
128
+ }
129
+ }
@@ -0,0 +1,67 @@
1
+ import json
2
+ import sys
3
+
4
+ def parse_nested_oast_data(file_content):
5
+ """
6
+ Phân tích file log chứa JSON lồng nhau (double-encoded).
7
+ Trích xuất danh sách các interaction từ key 'data'.
8
+ """
9
+ try:
10
+ # Bước 1: Giải mã đối tượng JSON bên ngoài
11
+ outer_data = json.loads(file_content)
12
+
13
+ # Bước 2: Lấy giá trị của key 'app', đây là một chuỗi chứa JSON khác
14
+ app_json_string = outer_data.get('app')
15
+ if not app_json_string:
16
+ print("[-] Lỗi: Không tìm thấy key 'app' trong dữ liệu đầu vào.", file=sys.stderr)
17
+ return None
18
+
19
+ # Bước 3: Giải mã chuỗi JSON bên trong để có được đối tượng dữ liệu thực sự
20
+ inner_data = json.loads(app_json_string)
21
+
22
+ # Bước 4: Trích xuất danh sách các interaction từ key 'data'
23
+ interactions = inner_data.get('data', []) # Mặc định trả về list rỗng nếu không có key 'data'
24
+
25
+ return interactions
26
+
27
+ except json.JSONDecodeError as e:
28
+ print(f"[!] Lỗi giải mã JSON: {e}", file=sys.stderr)
29
+ return None
30
+ except KeyError as e:
31
+ print(f"[!] Lỗi: Không tìm thấy key cần thiết trong JSON: {e}", file=sys.stderr)
32
+ return None
33
+
34
+ def main():
35
+ """
36
+ Hàm chính để chạy script từ dòng lệnh.
37
+ """
38
+ if len(sys.argv) != 3:
39
+ print("Sử dụng: python extract_oast_data.py <file_log_dau_vao.json> <file_json_dau_ra.json>")
40
+ sys.exit(1)
41
+
42
+ input_file = sys.argv[1]
43
+ output_file = sys.argv[2]
44
+
45
+ print(f"[*] Đang xử lý file: {input_file}")
46
+
47
+ try:
48
+ # Đọc toàn bộ nội dung file vì đây là một object JSON duy nhất
49
+ with open(input_file, 'r', encoding='utf-8') as f:
50
+ content = f.read()
51
+ except FileNotFoundError:
52
+ print(f"[!] Lỗi: Không tìm thấy file '{input_file}'", file=sys.stderr)
53
+ sys.exit(1)
54
+
55
+ parsed_data = parse_nested_oast_data(content)
56
+
57
+ if parsed_data is not None:
58
+ try:
59
+ with open(output_file, 'w', encoding='utf-8') as f:
60
+ # Ghi danh sách các interaction đã trích xuất ra file JSON
61
+ json.dump(parsed_data, f, indent=2, ensure_ascii=False)
62
+ print(f"[+] Hoàn thành! Dữ liệu tương tác đã được trích xuất và lưu vào: {output_file}")
63
+ except IOError as e:
64
+ print(f"[!] Lỗi khi ghi file: {e}", file=sys.stderr)
65
+
66
+ if __name__ == "__main__":
67
+ main()
@@ -0,0 +1,129 @@
1
+ import re
2
+ import json
3
+ import sys
4
+ import argparse
5
+
6
+ # Các hàm parse_nested_oast_data, extract_question_lines, và process_extracted_lines không thay đổi
7
+ def parse_nested_oast_data(file_content):
8
+ try:
9
+ outer_data = json.loads(file_content)
10
+ app_json_string = outer_data.get('app')
11
+ if not app_json_string:
12
+ print("[-] Lỗi: Không tìm thấy key 'app' trong dữ liệu đầu vào.", file=sys.stderr)
13
+ return None
14
+ inner_data = json.loads(app_json_string)
15
+ return inner_data.get('data', [])
16
+ except (json.JSONDecodeError, KeyError) as e:
17
+ print(f"[!] Lỗi khi phân tích JSON ban đầu: {e}", file=sys.stderr)
18
+ return None
19
+
20
+ def extract_question_lines(interactions):
21
+ if not interactions:
22
+ return []
23
+ extracted_lines = []
24
+ pattern = re.compile(
25
+ r";; QUESTION SECTION:.*?\n"
26
+ r"([^\n]*oast\.fun[^\n]*)",
27
+ re.IGNORECASE | re.DOTALL
28
+ )
29
+ for interaction in interactions:
30
+ raw_request = interaction.get("raw-request", "")
31
+ if not raw_request:
32
+ continue
33
+ match = pattern.search(raw_request)
34
+ if match:
35
+ line = match.group(1).strip()
36
+ extracted_lines.append(line)
37
+ return extracted_lines
38
+
39
+ def process_extracted_lines(lines):
40
+ unique_items = {}
41
+ for line in lines:
42
+ cleaned_line = line.lstrip(';').strip()
43
+ parts = cleaned_line.split('.', 2)
44
+ if len(parts) >= 2:
45
+ try:
46
+ index = int(parts[0])
47
+ data = parts[1]
48
+ identifier_key = (index, data.lower())
49
+ if identifier_key not in unique_items:
50
+ unique_items[identifier_key] = {"index": index, "data": data}
51
+ except ValueError:
52
+ print(f"[-] Bỏ qua dòng không có index hợp lệ: {line}", file=sys.stderr)
53
+ unique_data = list(unique_items.values())
54
+ return sorted(unique_data, key=lambda item: item['index'])
55
+
56
+ def write_ascii_data_file(sorted_data, ascii_output_path):
57
+ """
58
+ CẬP NHẬT: Chuyển đổi giá trị 'data' (chuỗi hex) sang ASCII và ghi ra file.
59
+ Mỗi giá trị đã được giải mã sẽ nằm trên một dòng riêng.
60
+ """
61
+ print(f"[*] Đang chuyển đổi data sang ASCII và lưu tại: {ascii_output_path}")
62
+ try:
63
+ with open(ascii_output_path, 'w', encoding='utf-8') as f:
64
+ for item in sorted_data:
65
+ hex_string = item['data']
66
+ try:
67
+ # Chuyển đổi chuỗi hex thành bytes
68
+ byte_data = bytes.fromhex(hex_string)
69
+ # Giải mã bytes thành chuỗi ký tự (sử dụng utf-8 cho an toàn)
70
+ # errors='replace' sẽ thay thế các ký tự không hợp lệ bằng ''
71
+ ascii_string = byte_data.decode('utf-8', errors='replace')
72
+ f.write(ascii_string + '\n')
73
+ except ValueError:
74
+ # Xảy ra khi chuỗi hex không hợp lệ (vd: chứa ký tự lạ, hoặc có số lượng ký tự lẻ)
75
+ print(f"[-] Cảnh báo: Không thể chuyển đổi chuỗi hex, bỏ qua: '{hex_string}'", file=sys.stderr)
76
+
77
+ print(f"[+] Đã lưu file ASCII thành công.")
78
+ except IOError as e:
79
+ print(f"[!] Lỗi khi ghi file ASCII: {e}", file=sys.stderr)
80
+
81
+ def main():
82
+ """
83
+ Hàm chính để chạy script, sử dụng argparse để xử lý tham số dòng lệnh.
84
+ """
85
+ parser = argparse.ArgumentParser(
86
+ description="Xử lý log OAST, trích xuất, xóa trùng, sắp xếp và lưu kết quả.",
87
+ formatter_class=argparse.RawTextHelpFormatter
88
+ )
89
+
90
+ parser.add_argument("input_file", help="Đường dẫn tới file log JSON đầu vào.")
91
+ parser.add_argument("output_file", help="Đường dẫn tới file JSON đầu ra chính (chứa index và data).")
92
+ parser.add_argument(
93
+ "--data-only",
94
+ metavar="PATH",
95
+ help="(Tùy chọn) Đường dẫn để lưu file văn bản sau khi chuyển đổi các giá trị 'data' từ hex sang ASCII."
96
+ )
97
+
98
+ args = parser.parse_args()
99
+
100
+ print(f"[*] Đang xử lý file: {args.input_file}")
101
+
102
+ try:
103
+ with open(args.input_file, 'r', encoding='utf-8') as f:
104
+ content = f.read()
105
+ except FileNotFoundError:
106
+ print(f"[!] Lỗi: Không tìm thấy file '{args.input_file}'", file=sys.stderr)
107
+ sys.exit(1)
108
+
109
+ interactions_data = parse_nested_oast_data(content)
110
+
111
+ if interactions_data:
112
+ question_lines = extract_question_lines(interactions_data)
113
+ final_sorted_data = process_extracted_lines(question_lines)
114
+
115
+ # Luôn tạo file output chính
116
+ try:
117
+ with open(args.output_file, 'w', encoding='utf-8') as f:
118
+ json.dump(final_sorted_data, f, indent=2, ensure_ascii=False)
119
+ print(f"[+] Hoàn thành! Dữ liệu chính đã được lưu vào: {args.output_file}")
120
+ except IOError as e:
121
+ print(f"[!] Lỗi khi ghi file chính: {e}", file=sys.stderr)
122
+
123
+ # Nếu người dùng cung cấp tham số --data-only, tạo thêm file đã giải mã
124
+ if args.data_only:
125
+ # Gọi hàm đã được sửa đổi
126
+ write_ascii_data_file(final_sorted_data, args.data_only)
127
+
128
+ if __name__ == "__main__":
129
+ main()