NID: Difference between revisions
CelesteBlue (talk | contribs) |
|||
Line 45: | Line 45: | ||
==== Known suffixless libraries ==== | ==== Known suffixless libraries ==== | ||
Verifying | |||
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. | |||
{| class="wikitable mw-collapsible mw-collapsed" | {| class="wikitable mw-collapsible mw-collapsed" | ||
|- | |- | ||
! List of known suffixless libraries | ! List of known suffixless libraries | ||
|- | |||
| SceKblForKernel | |||
|- | |||
| ScePowerForDriver | |||
|- | |- | ||
| SceDisplayForDriver | | SceDisplayForDriver | ||
|- | |||
| SceHpremoteForDriver | |||
|- | |- | ||
| SceFt2 | | SceFt2 |
Revision as of 13:46, 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 wants 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 costy
strncmp()
. - 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 costy
Calculation
By default, NIDs are derived from a symbol's name using the following algorithm:
- Calculate 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++, 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.
Example 1: suffixless
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 |
---|
SceKblForKernel |
ScePowerForDriver |
SceDisplayForDriver |
SceHpremoteForDriver |
SceFt2 |
SceKernelForMono |
SceKernelForVM |
SceRtabi |
Example 2: plaintext suffix
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 libraries in libpaf.suprx |
PAF |
All libraries in libpaf_web_map_view.suprx |
PAF_WEB_MAP_VIEW |
Example 3: binary suffix
Used for NONAME exports.
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
The following suffixes are used by SCE for NID derivation:
//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 PS3 NONAME library NIDs derivation. const char PS3_NONAME_lib_nid_suffix[] = { 0xbc, 0x5e, 0xba, 0x9e, 0x04, 0x25, 0x04, 0x90, 0x5b, 0x64, 0x27, 0x49, 0x94, 0xd9, 0xc4, 0x1f }; //Suffix for Vita NONAME library NIDs derivation. const char vita_NONAME_lib_nid_suffix[] = { 0xc1, 0xb8, 0x86, 0xaf, 0x5c, 0x31, 0x84, 0x64, 0x67, 0xe7, 0xba, 0x5e, 0x2c, 0xff, 0xd6, 0x4a };