diff --git a/.gitignore b/.gitignore index f395ff9..d86649d 100644 --- a/.gitignore +++ b/.gitignore @@ -133,4 +133,8 @@ agents.md # Environment variables .env -.env.* \ No newline at end of file +.env.* +# Локальные дампы трафика и скрипты анализа (содержат секреты) +komet.txt +original_app.txt +fingerprint.py diff --git a/lib/backend/api.dart b/lib/backend/api.dart index c767808..8b10cf9 100644 --- a/lib/backend/api.dart +++ b/lib/backend/api.dart @@ -39,6 +39,12 @@ class Api { Map? get userAgent => _userAgent; + int? _callsSeed; + String? _deviceId; + + int? get callsSeed => _callsSeed; + String? get deviceId => _deviceId; + List? _registrationCountries; List get registrationCountries => @@ -111,6 +117,7 @@ class Api { try { final response = await sendHandshake(); if (response.isOk) { + _callsSeed = response.payload['callsSeed'] as int?; _registrationCountries = _parseRegistrationCountries(response.payload); _setSessionState(SessionState.online); _startPinging(); @@ -242,6 +249,8 @@ class Api { 'buildNumber': buildNumber, }; + _deviceId = deviceId; + final payload = { 'mt_instanceid': await DeviceIdentity.instanceId(), 'clientSessionId': DeviceIdentity.clientSessionId, diff --git a/lib/backend/modules/account.dart b/lib/backend/modules/account.dart index 70b4b9a..522901b 100644 --- a/lib/backend/modules/account.dart +++ b/lib/backend/modules/account.dart @@ -1,6 +1,8 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:typed_data'; import '../api.dart'; +import '../../core/protocol/chat_cache_fingerprint.dart'; import '../../core/protocol/opcode_map.dart'; import '../../core/protocol/packet.dart'; import '../../core/storage/app_database.dart'; @@ -1048,9 +1050,18 @@ class AccountModule { final payload = { 'token': token, 'interactive': true, - if (_api.userAgent != null) 'userAgent': _api.userAgent, + 'exp': { + 'chatsCountGroups': Uint8List.fromList([0x0b, 0x32]), + }, }; + final callsSeed = _api.callsSeed; + final deviceId = _api.deviceId; + if (callsSeed != null && deviceId != null) { + payload['chatCacheFingerprint'] = + ChatCacheFingerprint.compute(callsSeed, deviceId); + } + if (sync != null) { payload['presenceSync'] = sync.presenceSync; payload['chatsSync'] = sync.chatsSync; @@ -1060,9 +1071,6 @@ class AccountModule { payload['bannersSync'] = sync.bannersSync; payload['lastLogin'] = sync.lastLogin; if (sync.configHash != null) payload['configHash'] = sync.configHash; - if (sync.chatCacheFingerprint != null) { - payload['chatCacheFingerprint'] = sync.chatCacheFingerprint; - } } else { payload['presenceSync'] = 0; } diff --git a/lib/core/protocol/chat_cache_fingerprint.dart b/lib/core/protocol/chat_cache_fingerprint.dart new file mode 100644 index 0000000..b2ab84a --- /dev/null +++ b/lib/core/protocol/chat_cache_fingerprint.dart @@ -0,0 +1,47 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart'; + +class ChatCacheFingerprint { + static final Uint8List _signatureDigest = _hex( + '1684414033eb263e2c615f8b7df5ed8793850a07656304997fbf07e9e21e1e93', + ); + static final Uint8List _soDigest = _hex( + 'c77b89270f44bd26c218a946c18911f2b156312693ea00b419d169b71c1ed111', + ); + static final Uint8List _dexDigest = _hex( + '490a2746c7ebbff050353c575a186ca65bc708f9b6e0c1329b59a3bfab6c3924', + ); + + static Uint8List compute(int callsSeed, String deviceId) { + final seed = _int64BigEndian(callsSeed); + final device = Uint8List.fromList(utf8.encode(deviceId)); + final result = BytesBuilder(); + result.add(_sha256(_signatureDigest, seed, device)); + result.add(_sha256(_soDigest, seed, device)); + result.add(_sha256(_dexDigest, seed, device)); + return result.toBytes(); + } + + static List _sha256(Uint8List a, Uint8List b, Uint8List c) { + final builder = BytesBuilder() + ..add(a) + ..add(b) + ..add(c); + return sha256.convert(builder.toBytes()).bytes; + } + + static Uint8List _int64BigEndian(int value) { + final data = ByteData(8)..setInt64(0, value, Endian.big); + return data.buffer.asUint8List(); + } + + static Uint8List _hex(String hex) { + final out = Uint8List(hex.length ~/ 2); + for (var i = 0; i < out.length; i++) { + out[i] = int.parse(hex.substring(i * 2, i * 2 + 2), radix: 16); + } + return out; + } +} diff --git a/pubspec.lock b/pubspec.lock index 0545e63..9dab85f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -130,7 +130,7 @@ packages: source: hosted version: "0.3.5+2" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf diff --git a/pubspec.yaml b/pubspec.yaml index 6fbaeec..edae9ba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: dart_lz4: ^1.0.0 libcompress: ^1.0.0 msgpack_dart: ^1.0.1 + crypto: ^3.0.7 logger: ^2.6.2 device_info_plus: 12.3.0 flutter_timezone: ^5.0.1