mirror of
https://github.com/InstanceBrick/nightcap.git
synced 2026-10-17 17:00:55 +02:00
roblox 2.736.1408 (2998)
This commit is contained in:
1 parent
2f80333c5d
commit
569980ecf2
8 files changed
+273
-47
No files matched your search
@@ -62,6 +62,26 @@
|
||||
"select_method_rva": "0x32734a6"
|
||||
},
|
||||
"reason": "Verified 2026-08-28 on the current host: the machine-derived exact-Build-ID profile passed two isolated no-recovery Tier C Vulkan canaries; fullscreen state synchronization and Build-ID-scoped FmodAudioDevice output interposition were re-derived for the current payload; legacy executable patches and signal recovery remain disabled."
|
||||
},
|
||||
{
|
||||
"version_name": "2.736.1408",
|
||||
"version_code": 2998,
|
||||
"elf_build_id": "ade08266c67aee88ec9c1d00902150e1684dad3a",
|
||||
"status": "supported",
|
||||
"default_allowed": true,
|
||||
"allow_legacy_binary_patches": false,
|
||||
"allow_host_abi_bridges": true,
|
||||
"allow_host_constructor_replay": true,
|
||||
"user_game_settings_fullscreen_setter_rva": "0x45ad8aa",
|
||||
"fmod_output_device_bridge": {
|
||||
"vtable_rva": "0x6c58040",
|
||||
"string_constructor_rva": "0x1d32df8",
|
||||
"count_method_rva": "0x32d0ee0",
|
||||
"info_method_rva": "0x32d0f80",
|
||||
"current_method_rva": "0x32d0f30",
|
||||
"select_method_rva": "0x32d0cb4"
|
||||
},
|
||||
"reason": "Verified 2026-09-06: exact Build-ID profile passed two isolated no-recovery Tier C Vulkan canaries and real game sessions, including fullscreen state synchronization and host FMOD output-device interposition; legacy executable patches and signal recovery remain disabled."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,64 +1,64 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"elf_build_id": "63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"payload_sha256": "72c3b1a5c151b5ac0bfc5394ce3a91775884fbd777589ccab8ac1c4f9885f739",
|
||||
"payload_id": "2908-63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"payload_path": "payloads/2908-63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"elf_build_id": "ade08266c67aee88ec9c1d00902150e1684dad3a",
|
||||
"payload_sha256": "4343a6a900d1fca27ff8e10b9d9c86bee40a5d0ba547cb29903b7769f4f42a9d",
|
||||
"payload_id": "2998-ade08266c67aee88ec9c1d00902150e1684dad3a",
|
||||
"payload_path": "payloads/2998-ade08266c67aee88ec9c1d00902150e1684dad3a",
|
||||
"reference": {
|
||||
"elf_build_id": "1686400865ae0e408cd7bd67de7a439625c6fd13",
|
||||
"payload_sha256": "3e9c26c81186f93458ff65d8a8bc240c220974db02b8388b91340b77b336997d"
|
||||
"elf_build_id": "63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"payload_sha256": "72c3b1a5c151b5ac0bfc5394ce3a91775884fbd777589ccab8ac1c4f9885f739"
|
||||
},
|
||||
"profile": {
|
||||
"elf_build_id": "63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"elf_build_id": "ade08266c67aee88ec9c1d00902150e1684dad3a",
|
||||
"bridge_entries": [
|
||||
{
|
||||
"rva": "0x1cf69e2",
|
||||
"rva": "0x1d2c1e2",
|
||||
"kind": "allocate",
|
||||
"label": "small-allocate"
|
||||
},
|
||||
{
|
||||
"rva": "0x1cf9c3a",
|
||||
"rva": "0x1d2f43a",
|
||||
"kind": "usable_size",
|
||||
"label": "usable-size"
|
||||
},
|
||||
{
|
||||
"rva": "0x21af33f",
|
||||
"rva": "0x21e68bf",
|
||||
"kind": "reallocate",
|
||||
"label": "reallocate"
|
||||
},
|
||||
{
|
||||
"rva": "0x1cf677e",
|
||||
"rva": "0x1d2bf82",
|
||||
"kind": "allocate",
|
||||
"label": "allocate"
|
||||
},
|
||||
{
|
||||
"rva": "0x1d12197",
|
||||
"rva": "0x1d47a63",
|
||||
"kind": "aligned_allocate",
|
||||
"label": "aligned-allocate-direct"
|
||||
},
|
||||
{
|
||||
"rva": "0x1cfa1d9",
|
||||
"rva": "0x1d2f9d9",
|
||||
"kind": "free",
|
||||
"label": "free"
|
||||
}
|
||||
],
|
||||
"data_seeds": {
|
||||
"allocator_object_slot": "0x7571570",
|
||||
"empty_string_slot": "0x767e428",
|
||||
"jni_singleton_slot": "0x7ad47e8",
|
||||
"allocator_object_slot": "0x7652e70",
|
||||
"empty_string_slot": "0x775fd28",
|
||||
"jni_singleton_slot": "0x7bb4340",
|
||||
"jni_singleton_bytes": 1024,
|
||||
"arena_initializer": "0x1cf6df8",
|
||||
"allocator_thread_initializer": "0x1d82be7",
|
||||
"arena_guard_slot": "0x7a10730",
|
||||
"arena_table_slot": "0x7a107c0",
|
||||
"arena_initializer": "0x1d2c5f8",
|
||||
"allocator_thread_initializer": "0x1db7b57",
|
||||
"arena_guard_slot": "0x7af0430",
|
||||
"arena_table_slot": "0x7af04c0",
|
||||
"arena_table_slot_count": 4194304
|
||||
},
|
||||
"native_allocator": {
|
||||
"allocate": "0x1cf677e",
|
||||
"deallocate": "0x1cfa1d9"
|
||||
"allocate": "0x1d2bf82",
|
||||
"deallocate": "0x1d2f9d9"
|
||||
},
|
||||
"init_array_offset": "0x6f78a18",
|
||||
"init_array_count": 3556,
|
||||
"init_array_offset": "0x7057818",
|
||||
"init_array_count": 3570,
|
||||
"constructor_run_ranges": [
|
||||
{
|
||||
"begin": 2,
|
||||
@@ -66,32 +66,32 @@
|
||||
},
|
||||
{
|
||||
"begin": 5,
|
||||
"end_exclusive": 3556
|
||||
"end_exclusive": 3570
|
||||
}
|
||||
],
|
||||
"native_mimalloc_constructor_run_ranges": [
|
||||
{
|
||||
"begin": 2,
|
||||
"end_exclusive": 3556
|
||||
"end_exclusive": 3570
|
||||
}
|
||||
],
|
||||
"native_mimalloc_thread_initializer_after_constructor": 2,
|
||||
"native_pre_jni_bootstrap": {
|
||||
"registry_initializer": "0x21b1889",
|
||||
"registry_slot": "0x7a14898"
|
||||
"registry_initializer": "0x21e8e09",
|
||||
"registry_slot": "0x7af4598"
|
||||
},
|
||||
"default_allocator_strategy": "native_mimalloc"
|
||||
},
|
||||
"derivation_anchors": {
|
||||
"signature_version": 1,
|
||||
"allocator_object_initializer_rva": "0x2186a91",
|
||||
"empty_string_initializer_rva": "0x2192669",
|
||||
"jni_singleton_initializer_rva": "0x1cf6309",
|
||||
"allocator_object_initializer_rva": "0x21bde7d",
|
||||
"empty_string_initializer_rva": "0x21c9a86",
|
||||
"jni_singleton_initializer_rva": "0x1d2aec0",
|
||||
"constructor_rvas": {
|
||||
"2": "0x1cf9f31",
|
||||
"3": "0x1cf5680",
|
||||
"4": "0x1cf63c8",
|
||||
"5": "0x1cf6309"
|
||||
"2": "0x1d2f731",
|
||||
"3": "0x1d2af84",
|
||||
"4": "0x1d2bc08",
|
||||
"5": "0x1d2aec0"
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-11
@@ -1,23 +1,24 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"package": "com.roblox.client",
|
||||
"version_name": "2.725.1142",
|
||||
"version_code": 2546,
|
||||
"version_name": "2.736.1408",
|
||||
"version_code": 2998,
|
||||
"abi": "x86_64",
|
||||
"elf_build_id": "d0cb1fa0deb3d9161b4cd77530cbcd2e50de3a21",
|
||||
"elf_build_id": "ade08266c67aee88ec9c1d00902150e1684dad3a",
|
||||
"sha256": {
|
||||
"libroblox": "92ca0e4d8bc4e1c7a37fc2b52544869299ec8b9a40ea8da96ebac66660e0b1af",
|
||||
"base_apk": "eba476fec3020eaceb28436c1d160eb35d6689d8ffb060e09678535584babc7a",
|
||||
"x86_64_split_apk": "5c4193c9700481079cee958b38ba9cbb97768b0a130b7f704ed084753f01ce2b"
|
||||
"libroblox": "4343a6a900d1fca27ff8e10b9d9c86bee40a5d0ba547cb29903b7769f4f42a9d",
|
||||
"base_apk": "a4a71ec39df6619a56ab7adce0959d1d60354835485b53806f4026914287ea86",
|
||||
"x86_64_split_apk": "a4a71ec39df6619a56ab7adce0959d1d60354835485b53806f4026914287ea86"
|
||||
},
|
||||
"signing_certificates_sha256": [
|
||||
"2bebd189e8d3106401347056c93d045b61e20e22d0c3cbed85474aeb00a3d12a",
|
||||
"44932ea35a17a267372d71b54d1a0cb3da0dca5113e94406ae2fe18090ba1477"
|
||||
],
|
||||
"assets": {
|
||||
"file_count": 1837
|
||||
"file_count": 1836,
|
||||
"sha256_tree": "caee48e11c194bc11852493f53ff67d5e2bb233172f12b87ea5fca97c0c10840"
|
||||
},
|
||||
"source": "sober-update-service",
|
||||
"imported_at": "2026-07-09T19:12:54Z",
|
||||
"compatibility_status": "supported"
|
||||
"source": "apk-pure-native",
|
||||
"imported_at": "2026-08-31T16:30:19Z",
|
||||
"compatibility_status": "supported",
|
||||
"apk_layout": "monolithic"
|
||||
}
|
||||
@@ -6,6 +6,29 @@ namespace mocktail::compat {
|
||||
namespace {
|
||||
|
||||
constexpr HostAbiProfile kProfiles[] = {
|
||||
// Roblox 2.736.1408. Derived from the verified 2908 profile and validated
|
||||
// by two isolated no-recovery Vulkan canaries and real game sessions.
|
||||
{"ade08266c67aee88ec9c1d00902150e1684dad3a",
|
||||
{{{0x1d2c1e2, HostBridgeKind::kAllocate, "small-allocate"},
|
||||
{0x1d2f43a, HostBridgeKind::kUsableSize, "usable-size"},
|
||||
{0x21e68bf, HostBridgeKind::kReallocate, "reallocate"},
|
||||
{0x1d2bf82, HostBridgeKind::kAllocate, "allocate"},
|
||||
{0x1d47a63, HostBridgeKind::kAlignedAllocate,
|
||||
"aligned-allocate-direct"},
|
||||
{0x1d2f9d9, HostBridgeKind::kFree, "free"}}},
|
||||
6,
|
||||
{0x7652e70, 0x775fd28, 0x7bb4340, 0x400, 0x1d2c5f8, 0x1db7b57,
|
||||
0x7af0430, 0x7af04c0, 0x400000},
|
||||
{0x1d2bf82, 0x1d2f9d9},
|
||||
0x7057818,
|
||||
3570,
|
||||
{{{2, 3}, {5, 3570}}},
|
||||
2,
|
||||
{{{2, 3570}}},
|
||||
1,
|
||||
2,
|
||||
{0x21e8e09, 0x7af4598},
|
||||
HostAllocatorStrategy::kNativeMimalloc},
|
||||
// Roblox 2.734.917. This exact Build-ID profile was machine-derived from
|
||||
// the verified reference and passed two isolated no-recovery Tier C Vulkan
|
||||
// canaries with native constructors, JNI startup, presentation, and
|
||||
|
||||
@@ -102,6 +102,38 @@ TEST(BuildProfileTest, ReportsUnknownBuildWithoutInventingProfile) {
|
||||
EXPECT_FALSE(result.profile.has_value());
|
||||
}
|
||||
|
||||
TEST(BuildProfileTest, Payload2998SupportsFullscreenAndHostAudioByDefault) {
|
||||
const ProfileLookupResult result = FindBuildProfile(
|
||||
kManifestPath, "ade08266c67aee88ec9c1d00902150e1684dad3a");
|
||||
|
||||
ASSERT_TRUE(result) << result.error;
|
||||
ASSERT_TRUE(result.profile.has_value());
|
||||
EXPECT_EQ(result.profile->version_name, "2.736.1408");
|
||||
EXPECT_EQ(result.profile->version_code, 2998);
|
||||
EXPECT_EQ(result.profile->status, BuildStatus::kSupported);
|
||||
EXPECT_TRUE(result.profile->default_allowed);
|
||||
EXPECT_FALSE(result.profile->allow_legacy_binary_patches);
|
||||
EXPECT_TRUE(result.profile->allow_host_abi_bridges);
|
||||
EXPECT_TRUE(result.profile->allow_host_constructor_replay);
|
||||
ASSERT_TRUE(
|
||||
result.profile->user_game_settings_fullscreen_setter_rva.has_value());
|
||||
EXPECT_EQ(*result.profile->user_game_settings_fullscreen_setter_rva,
|
||||
0x45ad8aaU);
|
||||
ASSERT_TRUE(result.profile->fmod_output_device_bridge.has_value());
|
||||
EXPECT_EQ(result.profile->fmod_output_device_bridge->vtable_rva,
|
||||
0x6c58040U);
|
||||
EXPECT_EQ(result.profile->fmod_output_device_bridge->string_constructor_rva,
|
||||
0x1d32df8U);
|
||||
EXPECT_EQ(result.profile->fmod_output_device_bridge->count_method_rva,
|
||||
0x32d0ee0U);
|
||||
EXPECT_EQ(result.profile->fmod_output_device_bridge->info_method_rva,
|
||||
0x32d0f80U);
|
||||
EXPECT_EQ(result.profile->fmod_output_device_bridge->current_method_rva,
|
||||
0x32d0f30U);
|
||||
EXPECT_EQ(result.profile->fmod_output_device_bridge->select_method_rva,
|
||||
0x32d0cb4U);
|
||||
}
|
||||
|
||||
TEST(BuildProfileTest, RejectsInvalidBuildId) {
|
||||
const ProfileLookupResult result = FindBuildProfile(kManifestPath, "oops");
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ import unittest
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
ANALYZER_PATH = PROJECT_ROOT / "scripts" / "derive_roblox_host_abi_profile.py"
|
||||
REFERENCE_PROFILE_PATH = PROJECT_ROOT / "config" / "roblox_host_abi_reference.json"
|
||||
# Keep the upgrade fixture independent of the project's current reference.
|
||||
REFERENCE_PROFILE_PATH = PROJECT_ROOT / "tests" / "fixtures" / "roblox_host_abi_2908.json"
|
||||
REFERENCE_PAYLOAD_ID = "2908-63c5109637b7d7b2bdb8ed8f858023ff5ef49326"
|
||||
CANDIDATE_PAYLOAD_ID = "2998-ade08266c67aee88ec9c1d00902150e1684dad3a"
|
||||
PAYLOAD_ROOT = Path.home() / ".local" / "share" / "mocktail" / "payloads"
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"elf_build_id": "63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"payload_sha256": "72c3b1a5c151b5ac0bfc5394ce3a91775884fbd777589ccab8ac1c4f9885f739",
|
||||
"payload_id": "2908-63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"payload_path": "payloads/2908-63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"reference": {
|
||||
"elf_build_id": "1686400865ae0e408cd7bd67de7a439625c6fd13",
|
||||
"payload_sha256": "3e9c26c81186f93458ff65d8a8bc240c220974db02b8388b91340b77b336997d"
|
||||
},
|
||||
"profile": {
|
||||
"elf_build_id": "63c5109637b7d7b2bdb8ed8f858023ff5ef49326",
|
||||
"bridge_entries": [
|
||||
{
|
||||
"rva": "0x1cf69e2",
|
||||
"kind": "allocate",
|
||||
"label": "small-allocate"
|
||||
},
|
||||
{
|
||||
"rva": "0x1cf9c3a",
|
||||
"kind": "usable_size",
|
||||
"label": "usable-size"
|
||||
},
|
||||
{
|
||||
"rva": "0x21af33f",
|
||||
"kind": "reallocate",
|
||||
"label": "reallocate"
|
||||
},
|
||||
{
|
||||
"rva": "0x1cf677e",
|
||||
"kind": "allocate",
|
||||
"label": "allocate"
|
||||
},
|
||||
{
|
||||
"rva": "0x1d12197",
|
||||
"kind": "aligned_allocate",
|
||||
"label": "aligned-allocate-direct"
|
||||
},
|
||||
{
|
||||
"rva": "0x1cfa1d9",
|
||||
"kind": "free",
|
||||
"label": "free"
|
||||
}
|
||||
],
|
||||
"data_seeds": {
|
||||
"allocator_object_slot": "0x7571570",
|
||||
"empty_string_slot": "0x767e428",
|
||||
"jni_singleton_slot": "0x7ad47e8",
|
||||
"jni_singleton_bytes": 1024,
|
||||
"arena_initializer": "0x1cf6df8",
|
||||
"allocator_thread_initializer": "0x1d82be7",
|
||||
"arena_guard_slot": "0x7a10730",
|
||||
"arena_table_slot": "0x7a107c0",
|
||||
"arena_table_slot_count": 4194304
|
||||
},
|
||||
"native_allocator": {
|
||||
"allocate": "0x1cf677e",
|
||||
"deallocate": "0x1cfa1d9"
|
||||
},
|
||||
"init_array_offset": "0x6f78a18",
|
||||
"init_array_count": 3556,
|
||||
"constructor_run_ranges": [
|
||||
{
|
||||
"begin": 2,
|
||||
"end_exclusive": 3
|
||||
},
|
||||
{
|
||||
"begin": 5,
|
||||
"end_exclusive": 3556
|
||||
}
|
||||
],
|
||||
"native_mimalloc_constructor_run_ranges": [
|
||||
{
|
||||
"begin": 2,
|
||||
"end_exclusive": 3556
|
||||
}
|
||||
],
|
||||
"native_mimalloc_thread_initializer_after_constructor": 2,
|
||||
"native_pre_jni_bootstrap": {
|
||||
"registry_initializer": "0x21b1889",
|
||||
"registry_slot": "0x7a14898"
|
||||
},
|
||||
"default_allocator_strategy": "native_mimalloc"
|
||||
},
|
||||
"derivation_anchors": {
|
||||
"signature_version": 1,
|
||||
"allocator_object_initializer_rva": "0x2186a91",
|
||||
"empty_string_initializer_rva": "0x2192669",
|
||||
"jni_singleton_initializer_rva": "0x1cf6309",
|
||||
"constructor_rvas": {
|
||||
"2": "0x1cf9f31",
|
||||
"3": "0x1cf5680",
|
||||
"4": "0x1cf63c8",
|
||||
"5": "0x1cf6309"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "compat/build_profile.h"
|
||||
#include "compat/host_abi_profile.h"
|
||||
#include "update/apkpure_provider.h"
|
||||
#include "update/compatibility_catalog.h"
|
||||
#include "update/host_abi_deriver.h"
|
||||
@@ -545,6 +546,57 @@ TEST(ShippedMetadataTest, ReferenceSidecarDescribesASupportedProfile) {
|
||||
EXPECT_TRUE(runtime.profile->fmod_output_device_bridge.has_value());
|
||||
}
|
||||
|
||||
TEST(ShippedMetadataTest, DefaultPayloadHasABuiltinProfileAndMatchingReference) {
|
||||
const std::filesystem::path root = MOCKTAIL_TEST_SOURCE_DIR;
|
||||
const auto catalog =
|
||||
LoadCompatibilityCatalog(root / "config/roblox_compatibility.json");
|
||||
ASSERT_TRUE(catalog) << catalog.error;
|
||||
const auto preferred = PreferredSupportedProfile(catalog.profiles);
|
||||
ASSERT_TRUE(preferred.has_value());
|
||||
EXPECT_EQ(preferred->version_name, "2.736.1408");
|
||||
EXPECT_EQ(preferred->version_code, 2998U);
|
||||
|
||||
const auto payload = nlohmann::json::parse(
|
||||
ReadFile(root / "config/roblox_payload.json"));
|
||||
EXPECT_EQ(payload.at("version_name"), preferred->version_name);
|
||||
EXPECT_EQ(payload.at("version_code"), preferred->version_code);
|
||||
EXPECT_EQ(payload.at("elf_build_id"), preferred->elf_build_id);
|
||||
EXPECT_EQ(payload.at("compatibility_status"), "supported");
|
||||
|
||||
const auto reference = nlohmann::json::parse(
|
||||
ReadFile(root / "config/roblox_host_abi_reference.json"));
|
||||
EXPECT_EQ(reference.at("payload_sha256"),
|
||||
payload.at("sha256").at("libroblox"));
|
||||
const auto* builtin = compat::FindHostAbiProfile(preferred->elf_build_id);
|
||||
ASSERT_NE(builtin, nullptr);
|
||||
const auto& profile = reference.at("profile");
|
||||
const auto rva = [](const nlohmann::json& value) {
|
||||
return std::stoull(value.get<std::string>(), nullptr, 16);
|
||||
};
|
||||
EXPECT_EQ(builtin->init_array_offset, rva(profile.at("init_array_offset")));
|
||||
EXPECT_EQ(builtin->init_array_count, profile.at("init_array_count"));
|
||||
ASSERT_EQ(builtin->bridge_entry_count, profile.at("bridge_entries").size());
|
||||
for (std::size_t i = 0; i < builtin->bridge_entry_count; ++i) {
|
||||
EXPECT_EQ(builtin->bridge_entries[i].rva,
|
||||
rva(profile.at("bridge_entries").at(i).at("rva")));
|
||||
}
|
||||
EXPECT_EQ(builtin->native_allocator.allocate,
|
||||
rva(profile.at("native_allocator").at("allocate")));
|
||||
EXPECT_EQ(builtin->native_allocator.deallocate,
|
||||
rva(profile.at("native_allocator").at("deallocate")));
|
||||
EXPECT_EQ(builtin->native_pre_jni_bootstrap.registry_initializer,
|
||||
rva(profile.at("native_pre_jni_bootstrap")
|
||||
.at("registry_initializer")));
|
||||
EXPECT_EQ(builtin->native_pre_jni_bootstrap.registry_slot,
|
||||
rva(profile.at("native_pre_jni_bootstrap").at("registry_slot")));
|
||||
EXPECT_TRUE(builtin->HasValidConstructorRanges());
|
||||
EXPECT_TRUE(builtin->HasValidNativeMimallocConstructorRanges());
|
||||
EXPECT_EQ(builtin->NativeMimallocConstructorRangeEndExclusive(),
|
||||
builtin->init_array_count);
|
||||
EXPECT_EQ(builtin->default_allocator_strategy,
|
||||
compat::HostAllocatorStrategy::kNativeMimalloc);
|
||||
}
|
||||
|
||||
std::string ActivationManifestFixture(const std::string& payload_id) {
|
||||
return nlohmann::json({{"schema_version", 1},
|
||||
{"payload_id", payload_id},
|
||||
|
||||
Reference in new issue
Block a user