Reject v24.0 metadata instead of silently decoding wrong offsets

This commit is contained in:
pancake committed 2026-04-17 19:17:59 +02:00
1 parent b276df7e87
commit a4e6446d16
3 files changed
+54 -2

No files matched your search

+4
View File
@@ -119,12 +119,16 @@ if (version < 24 || version > 31) return NULL;
if (version < 27) header_size = sizeof (v24);
else if (version < 29) header_size = sizeof (v27);
else header_size = sizeof (v29); /* 29, 30, 31 */
/* After normalizing header fields, reject v24.0 via image-stride probe. */
if (version == 24 && is_v24_0 (meta)) return NULL;
```
| Wire version | Status | Reality |
|--------------|-----------------------------------|--------------------------------------------------------------------------------------------|
| 16, 19, 20 | Rejected | Pre-Unity-5.5 builds, effectively extinct. |
| 21, 22, 23 | Rejected | Unity 5.3 – 5.5 IPAs exist but are rare. |
| 24.0 | Rejected after sub-version probe | On-disk `version` is 24 for both v24.0 and v24.1+. The parser probes image-row stride (32 B vs 40 B) and rejects v24.0 with an explicit error; TypeDefinition/MethodDefinition/ImageDefinition rows would otherwise decode at wrong offsets. |
| 24.1 – 24.5 | Accepted via `_v24` header struct | Row decoders target the v24.1+ strides. |
| 27 | Accepted via `_v27` header struct | Header correct. Row decoders still assume the v24.1+ layout; v27.2 RGCTX widening not handled (only affects RGCTX which is unused). |
| 29 | Accepted via `_v29` header struct | Header correct. Method rows decoded as 32 B. Reverse-P/Invoke BLOB path is the only v29-specific code. |
| 30 | Accepted | Never shipped on disk; dead slot, safe. |
+6 -2
View File
@@ -917,9 +917,13 @@ Unity-release → wire-version → sub-version mapping.
`Il2CppMethodDefinition`, aligning with ECMA-335's return-value
param-row model.
r2unity's current acceptance band is **v24..v31**, with dedicated
r2unity's current acceptance band is **v24.1..v31**, with dedicated
handling only for the v24.1+ table strides and the v31
`returnParameterToken` insertion.
`returnParameterToken` insertion. Since the on-disk `version` field is
`24` for both v24.0 and v24.1+, the parser probes the image-row stride
(32 B on v24.0, 40 B on v24.1+) and rejects v24.0 explicitly to avoid
silent mis-decoding of TypeDefinition/MethodDefinition/ImageDefinition
rows.
## 5. How the parser is wired in r2unity
+44
View File
@@ -14,6 +14,43 @@ R_API bool r2unity_is_debug (void) {
}
/* Detect v24.0 vs v24.1+ (both land on disk as version==24).
*
* At v24.1 the ImageDefinition row grew by 8 bytes (added
* customAttributeStart/Count), so imagesSize is a multiple of 40 on v24.1+
* and 32 on v24.0. When imagesSize is divisible by both (a multiple of 160),
* probe the 4 bytes at offset 40: under v24.1+ that is row 1's nameIndex
* (a valid string-pool offset); under v24.0 it is mid-row.
*
* Fixing row layouts for v24.0 (larger TypeDefinition, MethodDefinition,
* ImageDefinition) is tracked separately; reject for now so decoders don't
* silently return wrong offsets. */
static bool is_v24_0 (R2UnityMetadata *meta) {
ut64 ioff = meta->header.v24.imagesOffset;
ut64 isize = meta->header.v24.imagesSize;
if (!isize) {
return false;
}
bool div40 = (isize % 40) == 0;
bool div32 = (isize % 32) == 0;
if (div40 && !div32) {
return false;
}
if (div32 && !div40) {
return true;
}
if (isize >= 44) {
ut8 probe[4];
if (r_buf_read_at (meta->buf, ioff + 40, probe, 4) == 4) {
uint32_t name_idx = r_read_le32 (probe);
if (name_idx < (uint32_t) meta->stringSize) {
return false;
}
}
}
return true;
}
R_API R2UnityMetadata *r2unity_parse_metadata (RBuffer *buf) {
if (!buf) {
return NULL;
@@ -97,6 +134,13 @@ R_API R2UnityMetadata *r2unity_parse_metadata (RBuffer *buf) {
meta->typeDefinitionsOffset = meta->header.v29.typeDefinitionsOffset;
meta->typeDefinitionsSize = meta->header.v29.typeDefinitionsSize;
}
if (meta->version == 24 && is_v24_0 (meta)) {
R_LOG_ERROR ("v24.0 metadata (Unity 5.6..2018.2) not supported: "
"TypeDefinition/MethodDefinition/ImageDefinition row layouts "
"differ from v24.1+ and would silently decode wrong offsets");
r2unity_free_metadata (meta);
return NULL;
}
meta->strings = r_buf_new_slice (buf, meta->stringOffset, meta->stringSize);
meta->string_literals = r_buf_new_slice (buf, meta->stringLiteralOffset, meta->stringLiteralSize);
if (g_debug) {