NID: Difference between revisions
CelesteBlue (talk | contribs) |
CelesteBlue (talk | contribs) No edit summary |
||
Line 1: | Line 1: | ||
Abbreviation of '''N'''umeric '''Id'''entifier. | Abbreviation of '''N'''umeric '''Id'''entifier. | ||
= Usage = | |||
Dynamic linking of modules (by [[SceKernelModulemgr]]) is performed based on NIDs of functions/variables instead of names. | Dynamic linking of modules (by [[SceKernelModulemgr]]) is performed based on NIDs of functions/variables instead of names. | ||
For example, a module that | For example, a module that needs to import [[SceDisplay#sceDisplayGetFrameBufForDriver|sceDisplayGetFrameBuf]] will indicate that it needs <code>SceDisplayForDriver:0xEEDA2E54</code> in [[Modules#Imports|its libstub structures]]. | ||
This solution provides multiple benefits: | This solution provides multiple benefits: | ||
* Names of functions and variables are not included in modules | * Names of functions and variables are not included in modules. This reveals much less information to attackers. | ||
* Lookup inside a NID table is faster | * Lookup inside a NID table is faster. | ||
** Equality testing is a simple 32-bit comparison instead of a | ** Equality testing is a simple 32-bit comparison instead of a costly <code>strncmp()</code> of length <code>strlen(name)</code>. | ||
** A dichotomic search can be performed in <code>O(log2(n))</code> if NID tables are sorted. | ** A dichotomic search can be performed in <code>O(log2(n))</code> if NID tables are sorted. | ||
*** While NID tables appear to be sorted, this optimization is seemingly not used by SCE. | *** While NID tables appear to be sorted, this optimization is seemingly not used by SCE. | ||
= Calculation = | |||
By default, NIDs are derived from a symbol's name using the following algorithm: | By default, NIDs are derived from a symbol's name using the following algorithm: | ||
# | # Compute the SHA-1 hash of the (optionally salted) name: <code>hash = sha1(name + suffix) = ZZ YY XX WW VV UU TT SS RR QQ PP OO NN MM LL KK JJ II HH GG </code> | ||
#* <code>suffix</code> acts as salt and may be a string or raw binary data | #* <code>suffix</code> acts as salt and may be a string or raw binary data | ||
#* <code>name + suffix</code> corresponds to concatenation in this context | #* <code>name + suffix</code> corresponds to concatenation in this context | ||
Line 24: | Line 25: | ||
Notes: | Notes: | ||
* For C++, derivation is performed using the symbol's mangled name. | * For C++ symbols, derivation is performed using the symbol's mangled name. | ||
* <code>libname_nid</code> is derived using the same suffix as the rest of the library. | * <code>libname_nid</code> is derived using the same suffix as the rest of the library. | ||
** Since library names are always known, this makes it (in theory) possible to bruteforce the suffix used for NID derivation of any library. | ** Since library names are always known, this makes it (in theory) possible to bruteforce the suffix used for NID derivation of any library. | ||
Line 31: | Line 32: | ||
* The [https://creepnt.stream/vita/nid_help.html following online tool] can be used for NID calculations. | * The [https://creepnt.stream/vita/nid_help.html following online tool] can be used for NID calculations. | ||
=== Example | == Suffixless NIDs == | ||
=== Example === | |||
[[SceDisplay#sceDisplayGetFrameBufForDriver|sceDisplayGetFrameBuf]] | [[SceDisplay#sceDisplayGetFrameBufForDriver|sceDisplayGetFrameBuf]] | ||
Line 44: | Line 47: | ||
</source> | </source> | ||
=== Known suffixless libraries === | |||
Verifying that a library does not use a suffix for NID derivation is trivial: derive a NID based on the library name and check if it matches the <code>libname_nid</code> field of the [[Modules#Exports|libent]] structure of that library. | Verifying that a library does not use a suffix for NID derivation is trivial: derive a NID based on the library name and check if it matches the <code>libname_nid</code> field of the [[Modules#Exports|libent]] structure of that library. | ||
Line 51: | Line 54: | ||
|- | |- | ||
! List of known suffixless libraries | ! List of known suffixless libraries | ||
|- | |||
| Most PSP libraries before some System Software version around 3.50 | |||
|- | |- | ||
| SceKblForKernel | | SceKblForKernel | ||
Line 69: | Line 74: | ||
|} | |} | ||
=== Example | == Plaintext Suffix NIDs == | ||
=== Example === | |||
The [[SceShellSvc#SceIpmi|SceIpmi]] library uses <code>libipmi</code> as suffix. | The [[SceShellSvc#SceIpmi|SceIpmi]] library uses <code>libipmi</code> as suffix. | ||
Line 93: | Line 100: | ||
The NID of IPMI::Client::Config::estimateClientMemorySize() is 0x4E255C31. | The NID of IPMI::Client::Config::estimateClientMemorySize() is 0x4E255C31. | ||
</source> | </source> | ||
=== Known plaintext suffixes === | |||
Plaintext suffixes follow patterns across some modules. | Plaintext suffixes follow patterns across some modules. | ||
Line 160: | Line 168: | ||
|- | |- | ||
! colspan="2" | Others | ! colspan="2" | Others | ||
|- | |||
| All PS3 libraries except NONAME ones || 0xbc5eba9e042504905b64274994d9c41f | |||
|- | |- | ||
| All libraries in <code>libpaf.suprx</code> || PAF | | All libraries in <code>libpaf.suprx</code> || PAF | ||
Line 166: | Line 176: | ||
|} | |} | ||
== | == Binary Suffix NIDs == | ||
Used for PS Vita [[Modules#NONAME_exports|NONAME exports]] and PS3 named exports. | |||
=== Example === | |||
<source lang="c"> | <source lang="c"> | ||
Line 179: | Line 191: | ||
</source> | </source> | ||
=== Known binary suffixes === | |||
<source lang="c"> | <source lang="c"> | ||
//Default suffix for all PS3 NIDs derivations, except NONAME library. | // Default suffix for all PS3 NIDs derivations, except NONAME library. | ||
const char PS3_default_nid_suffix[] = { | const char PS3_default_nid_suffix[] = { | ||
0x67, 0x59, 0x65, 0x99, 0x04, 0x25, 0x04, 0x90, 0x56, 0x64, 0x27, 0x49, 0x94, 0x89, 0x74, 0x1a | 0x67, 0x59, 0x65, 0x99, 0x04, 0x25, 0x04, 0x90, 0x56, 0x64, 0x27, 0x49, 0x94, 0x89, 0x74, 0x1a | ||
}; | }; | ||
//Suffix for | // Suffix for PSP2 NONAME library NIDs derivation. | ||
const char | const char PSP2_NONAME_lib_nid_suffix[] = { | ||
0xc1, 0xb8, 0x86, 0xaf, 0x5c, 0x31, 0x84, 0x64, 0x67, 0xe7, 0xba, 0x5e, 0x2c, 0xff, 0xd6, 0x4a | 0xc1, 0xb8, 0x86, 0xaf, 0x5c, 0x31, 0x84, 0x64, 0x67, 0xe7, 0xba, 0x5e, 0x2c, 0xff, 0xd6, 0x4a | ||
}; | }; | ||
</source> | </source> |
Revision as of 14:19, 24 March 2024
Abbreviation of Numeric Identifier.
Usage
Dynamic linking of modules (by SceKernelModulemgr) is performed based on NIDs of functions/variables instead of names.
For example, a module that needs to import sceDisplayGetFrameBuf will indicate that it needs SceDisplayForDriver:0xEEDA2E54
in its libstub structures.
This solution provides multiple benefits:
- Names of functions and variables are not included in modules. This reveals much less information to attackers.
- Lookup inside a NID table is faster.
- Equality testing is a simple 32-bit comparison instead of a costly
strncmp()
of lengthstrlen(name)
. - A dichotomic search can be performed in
O(log2(n))
if NID tables are sorted.- While NID tables appear to be sorted, this optimization is seemingly not used by SCE.
- Equality testing is a simple 32-bit comparison instead of a costly
Calculation
By default, NIDs are derived from a symbol's name using the following algorithm:
- Compute the SHA-1 hash of the (optionally salted) name:
hash = sha1(name + suffix) = ZZ YY XX WW VV UU TT SS RR QQ PP OO NN MM LL KK JJ II HH GG
suffix
acts as salt and may be a string or raw binary dataname + suffix
corresponds to concatenation in this context- For example,
name="sceFunc"
andsuffix="MySuffix"
results inhash = sha1("sceFuncMySuffix")
- For example,
- Truncate the result to 32 bits:
tr = truncate32(hash) = 0xZZYYXXWW
- Reverse endianness of the truncated result:
NID = swap32(tr) = 0xWWXXYYZZ
Notes:
- For C++ symbols, derivation is performed using the symbol's mangled name.
libname_nid
is derived using the same suffix as the rest of the library.- Since library names are always known, this makes it (in theory) possible to bruteforce the suffix used for NID derivation of any library.
- The NID of functions and variables can be set to arbitrary values.
- It is possible to encounter NIDs that do not match the "expected" NID found by deriving using this algorithm.
- The following online tool can be used for NID calculations.
Suffixless NIDs
Example
sha1("sceDisplayGetFrameBuf") = 54 2E DA EE DA 61 8E 3F 07 9A C7 46 92 24 6D F1 2A A8 F7 C7 Truncate to 32 bits: 0x542EDAEE Reverse endianness: 0xEEDA2E54 The NID of sceDisplayGetFrameBuf is 0xEEDA2E54.
Known suffixless libraries
Verifying that a library does not use a suffix for NID derivation is trivial: derive a NID based on the library name and check if it matches the libname_nid
field of the libent structure of that library.
List of known suffixless libraries |
---|
Most PSP libraries before some System Software version around 3.50 |
SceKblForKernel |
ScePowerForDriver |
SceDisplayForDriver |
SceHpremoteForDriver |
SceFt2 |
SceKernelForMono |
SceKernelForVM |
SceRtabi |
Plaintext Suffix NIDs
Example
The SceIpmi library uses libipmi
as suffix.
//N.B. "SceIpmilibipmi" is "SceIpmi" + "libipmi sha1("SceIpmilibipmi") = DB 4E E3 F4 E9 A8 6C 3F 79 4B 5A 28 CF 26 07 36 14 42 70 B0 Truncate to 32 bits: 0xDB4EE3F4 Reverse endianness: 0xF4E34EDB NID of the SceIpmi library is 0xF4E34EDB.
For C++ exports, the NID is derived from the mangled name.
//IPMI::Client::Config::estimateClientMemorySize() =mangling=> _ZN4IPMI6Client6Config24estimateClientMemorySizeEv sha1("_ZN4IPMI6Client6Config24estimateClientMemorySizeEvlibipmi") = 31 5C 25 4E FE AE B4 34 CA B5 9F 43 03 3D 62 BC 11 6F FC AB Truncate to 32 bits: 0x315C254E Reverse endianness: 0x4E255C31 The NID of IPMI::Client::Config::estimateClientMemorySize() is 0x4E255C31.
Known plaintext suffixes
Plaintext suffixes follow patterns across some modules.
List of libraries with a known plaintext suffix | |
---|---|
Library name | Suffix |
Library name | |
SceAvcdecForPlayer | SceAvcdecForPlayer |
SceAudiodecUser | SceAudiodecUser |
SceAudioencUser | SceAudioencUser |
SceCodecEngineUser | SceCodecEngineUser |
SceJpegUser | SceJpegUser |
SceJpegEncUser | SceJpegEncUser |
SceLibMonoBridge | SceLibMonoBridge |
SceVideodecUser | SceVideodecUser |
SceVideodecAsyncUser | SceVideodecAsyncUser |
SceVideodecLowDelayUser | SceVideodecLowDelayUser |
SceVideodecRecoveryPointUser | SceVideodecRecoveryPointUser |
SceVideoencUser | SceVideoencUser |
Library name + User | |
SceAtrac | SceAtracUser |
SceG729 | SceG729User |
Library name without Sce | |
SceWebUIPlugin | WebUIPlugin |
SceAppSettings | AppSettings |
SceBackupRestore | BackupRestore |
SceDbRecovery | DbRecovery |
SceLibLocationPermission | LibLocationPermission |
libXXX | |
SceLibMtp | libmtp |
SceIpmi | libipmi |
lib + Library name | |
ScePsp2Compat | libScePsp2Compat |
SceWebKit | libSceWebKit |
Others | |
All PS3 libraries except NONAME ones | 0xbc5eba9e042504905b64274994d9c41f |
All libraries in libpaf.suprx |
PAF |
All libraries in libpaf_web_map_view.suprx |
PAF_WEB_MAP_VIEW |
Binary Suffix NIDs
Used for PS Vita NONAME exports and PS3 named exports.
Example
sha1("module_start" + vita_NONAME_lib_nid_suffix) = 96 D1 5C 93 65 10 32 1C 7D 60 7B 4D FC 06 BC 73 06 3E 25 61 Truncate to 32 bits: 0x96D15C93 Reverse endianness: 0x935CD196 The NID of module_start is 0x935CD196.
Known binary suffixes
// Default suffix for all PS3 NIDs derivations, except NONAME library. const char PS3_default_nid_suffix[] = { 0x67, 0x59, 0x65, 0x99, 0x04, 0x25, 0x04, 0x90, 0x56, 0x64, 0x27, 0x49, 0x94, 0x89, 0x74, 0x1a }; // Suffix for PSP2 NONAME library NIDs derivation. const char PSP2_NONAME_lib_nid_suffix[] = { 0xc1, 0xb8, 0x86, 0xaf, 0x5c, 0x31, 0x84, 0x64, 0x67, 0xe7, 0xba, 0x5e, 0x2c, 0xff, 0xd6, 0x4a };