Following the initial PS4 NIDs, additional PlayStation 4 NIDs, his recent PS4 PUP Unpacker Rewrite and the PS4LibDoc updates today PlayStation 4 developer Zer0xFF released PS4 NID to Function Name Resolver source code for use in IDA Pro 7.0 resolving Bin / Lib Function Names by developers.
Download: PS4 NID Resolver IDA Plugin (compiled to work with IDA 7.0) / ps4_nid_resolver_ida-master.zip / GIT
From the related Tweets below, to quote: "2 weeks ago I posted this picture, today I'm posting up the source, this will be helpful for anyone working with PS4 and RE sprx, currently it's missing game bin/sprx support but that will be added in due time"
And to quote from the README.md file: PS4 NID to Function Name Resolver
Resolves PS4 Bin/Lib Function Names
Requirement
How-To-Build
Note: on windows you'd need to change --idaq C:\Users\USERNAME\AppData\Hex-Rays\IDA Pro\
How-To-Use
At this moment, the plugin will only attempt to resolve libraries that have been defined in ps4libdoc by idc. In the future I plan on supporting any PS4 bin/lib/sprx (such as those found inside games containers)
Special Thanks
To @idc for his work on ps4libdoc and ps4-uplift which made this project possible.
And from his Blog, to quote: PS4 NID Resolver - IDA Plugin
One of the joys of Reverse Engineering PS4 files is having to deal with nameless functions, since Sony have come up with an ingenious (?) way to create shared libraries without including any symbol names, but still have a way to resolve functions, using Name Identifier (NID).
What is an NID?
That, it's just a form of ID that can be used to identify a function, the way it works is, when devs build apps, the write the code and use the function name, but when the app is built the names are stripped out and instead NIDs and address locations are used to identify which function to call and where.
So what do we need to resolver NID into function names?
There are 3 main parts to this:
we can deduce from this snippet that SUB_260 is sceSysmoduleUnloadModuleByNameInternal since the error being printed is clearly from SUB_260, and since we can associate function address (0x260) to it's NID, we can associate NID to a name.
"but that sounds laborious", you say!! well ya it is but thanks to the work of @idc we have a database of over 10,000 functions!! As for the plugin you can find the source on github.
If you're not using IDA, building the source would generate an executable that will printout NID, symbol address and it's associated name, just so, I tried to break all the functionality into manageable bits so it can be easily ported to other tools (contact me if you need help).
NIDs Explained
What are they:
Function names, variables, etc, but obfuscated. Known as (N)ame(ID)entifiers.
How to get a nid from:
PSP
sha1 hash of string of function name or variable , grab first 4 bytes, endian swap 32
Warning: Some nids have to be manually guessed! From 3.70 at least. there is no solution to find the suffix (yet)
PSVita
sha1 hash of string of function name or variable , grab first 4 bytes, endian swap 32
Warning: Some nids have to be manually guessed! there is no solution to find the suffix (yet)
Warning2: nids like module_start, etc(NONAME) have suffix c1b886af5c31846467e7ba5e2cffd64a as key
PS3
sha1 hash of string of function name plus binary key 6759659904250490566427499489741A in hex,
grab first 4 bytes, endian swap 32
Warning: nids like module_start, etc (NONAME) have suffix bc5eba9e042504905b64274994d9c41f as binary key
PS4
sha1 hash of string of function name or variable plus binary key 518D64A635DED8C1E6B039B1C3E55230
grab first 8 bytes?, endian swap 64? and finally convert to sony's special base64
(i believe replace - with = for charset)
Bruteforcing:
Using custom hashcat.
Algos:
Download: PS4 NID Resolver IDA Plugin (compiled to work with IDA 7.0) / ps4_nid_resolver_ida-master.zip / GIT
From the related Tweets below, to quote: "2 weeks ago I posted this picture, today I'm posting up the source, this will be helpful for anyone working with PS4 and RE sprx, currently it's missing game bin/sprx support but that will be added in due time"
And to quote from the README.md file: PS4 NID to Function Name Resolver
Resolves PS4 Bin/Lib Function Names
Requirement
How-To-Build
Code:
git clone --recurse-submodules https://github.com/Thunder07/ps4_nid_resolver_ida.git
cd ps4_nid_resolver_ida
./extern/ida-cmake/build.py -t 7.0 -i ~/idasdk70/ --idaq ~/.idapro/
How-To-Use
- Ctrl+Alt+F10: Basic Settings Panel
- Ctrl+F10: Resolve Function Names (Note: this action is none reversible, make sure you've a copy of your ida database before applying this)
At this moment, the plugin will only attempt to resolve libraries that have been defined in ps4libdoc by idc. In the future I plan on supporting any PS4 bin/lib/sprx (such as those found inside games containers)
Special Thanks
To @idc for his work on ps4libdoc and ps4-uplift which made this project possible.
And from his Blog, to quote: PS4 NID Resolver - IDA Plugin
One of the joys of Reverse Engineering PS4 files is having to deal with nameless functions, since Sony have come up with an ingenious (?) way to create shared libraries without including any symbol names, but still have a way to resolve functions, using Name Identifier (NID).
What is an NID?
Code:
b+uAV89IlxE#M#N
qLpSK75lXI4#M#N
ekNvsT22rsY#M#N
QOQtbeDqsT4#M#N
VjhsmxpcezI#N#O
h5jSB2QIDV0#N#O
fMP5NHUOaMk#A#B
6Vf9WTLDoss#N#O
Tp+ZEy69mLk#N#O
So what do we need to resolver NID into function names?
There are 3 main parts to this:
- String table offset
- contain names of libraries and modules that are used in sprx/bin but it also contains the actual NIDs
- Symbol table offset
- contains function/symbol address and it's associated String id
- This table contains only the address of internal functions only
- contains function/symbol address and it's associated String id
- Runtime/Dynamic relocation table offset
- contains function/symbol address and it's associated String id
- This table contains the addresses of external functions
- contains function/symbol address and it's associated String id
Code:
result = SUB_260(unk_252D64, 0LL, 0LL, 0LL, 0LL);
if ( (_DWORD)result )
result = printf("sceSysmoduleUnloadModuleByNameInternal Error:ret=%08x\n", (unsigned int)result);
"but that sounds laborious", you say!! well ya it is but thanks to the work of @idc we have a database of over 10,000 functions!! As for the plugin you can find the source on github.
If you're not using IDA, building the source would generate an executable that will printout NID, symbol address and it's associated name, just so, I tried to break all the functionality into manageable bits so it can be easily ported to other tools (contact me if you need help).
NIDs Explained
What are they:
Function names, variables, etc, but obfuscated. Known as (N)ame(ID)entifiers.
How to get a nid from:
PSP
sha1 hash of string of function name or variable , grab first 4 bytes, endian swap 32
Warning: Some nids have to be manually guessed! From 3.70 at least. there is no solution to find the suffix (yet)
PSVita
sha1 hash of string of function name or variable , grab first 4 bytes, endian swap 32
Warning: Some nids have to be manually guessed! there is no solution to find the suffix (yet)
Warning2: nids like module_start, etc(NONAME) have suffix c1b886af5c31846467e7ba5e2cffd64a as key
PS3
sha1 hash of string of function name plus binary key 6759659904250490566427499489741A in hex,
grab first 4 bytes, endian swap 32
Warning: nids like module_start, etc (NONAME) have suffix bc5eba9e042504905b64274994d9c41f as binary key
PS4
sha1 hash of string of function name or variable plus binary key 518D64A635DED8C1E6B039B1C3E55230
grab first 8 bytes?, endian swap 64? and finally convert to sony's special base64
(i believe replace - with = for charset)
Bruteforcing:
Using custom hashcat.
Algos:
- PS3, Python
Code:import sys, os import struct from hashlib import sha1 import hashlib from base64 import b64encode as base64enc from binascii import unhexlify as uhx #ref https://github.com/SocraticBliss/ps4_name2nid_plugin NEW_NIDS = {} AEROLIB = 'nids.txt' NAMES = 'ps3_names.txt' def name2nid(name): symbol = sha1(name.encode() + uhx(b'6759659904250490566427499489741A')).digest() nid = struct.unpack('<I', symbol[:4])[0] NEW_NIDS[nid]=name def save_nids(NIDS): csvFile=open(AEROLIB,"w") for nid, name in sorted(NIDS.items(), key=lambda x: x[1]): csvFile.writelines('0x%08X %s\n' % (nid, name)) csvFile.close() f = open(NAMES,"r") for line in f.readlines(): line = line.strip() name2nid(line) f.close() save_nids(NEW_NIDS)
- PS4, Python
Code:import sys, os import struct #from hashlib import sha1 import hashlib from base64 import b64encode as base64enc from binascii import unhexlify as uhx #ref https://github.com/SocraticBliss/ps4_name2nid_plugin NEW_NIDS = {} AEROLIB = 'aerolib.csv' NAMES = 'ps4_names.txt' def name2nid(name): symbol = hashlib.sha1(name.encode() + uhx('518D64A635DED8C1E6B039B1C3E55230')).digest() id = struct.unpack('<Q', symbol[:8])[0] nid = base64enc(uhx('%016x' % id), b'+-').rstrip(b'=') NEW_NIDS[nid]=name def save_nids(NIDS): csvFile=open(AEROLIB,"w") for nid, name in sorted(NIDS.items(), key=lambda x: x[1]): csvFile.writelines('%s %s\n' % (str(nid,'utf-8'), name)) csvFile.close() f = open(NAMES,"r") for line in f.readlines(): line = line.strip() name2nid(line) f.close() save_nids(NEW_NIDS)
- nidcracker (also excellent bruter but for psp)
- nid-explained
- ps4_module_loader (aerolib.csv)
- ps4libdoc
- Ps3GhidraScripts (nids.txt)
- vita-headers (db folder)