You are on page 1of 6

NFS Undercover Save Editor v1.

2
-------------------------------
1. Disclaimer
Please notice, that this tool is provided AS IS, you are using it at your
own risk. The author of this tool is not responsible for any bugs during
the gameplay process, that may be caused directly or indirectly by using
this program and for damaged save files, which you forgot to backup.
Please, always make backups of your save game files before using this program.

2. Features
This program allows you to modify some fields of the database (DB), which
is stored in your save game file. The current version can change:
- money amount
- unlock access to all shops, thus making all cars, parts,
customizations etc. available for buying
- unlock access to all career races and jobs
- mark all types of races completed
- driver skills
There are also some optional features, for advanced users, such as:
- DB export and import (read in the following sections)
- checksum fixing
However there can be some side effects, which are covered in the next section.
Please, read it carefully to understand the logic of the program.

3. General information and usage


NFS Undercover is somewhat similar to NFS Carbon in sense of save data
management, as both store most of the gameplay related information in a
special database. In Carbon it was a simple text file, in Undercover - it is
a fully functional relational DB - SQLite (http://www.sqlite.org/), which
means, that modification of saved options and parameters is now as easy, as
executing an SQL query. You can read a bit more technical details about this
in a corresponding section.
Once the save file is opened, it is read into the memory completely and no
modifications to the original file are made until the "Save Changes" button
is pressed. The program can refuse to open the save file if it is damaged
(it doesn't mean that the checksums are wrong, but that the header or the file
itself is broken) or if there are no sufficient rights to open that file.
The DB is read upon file open - it is exported to the special file with unique
name in the temp directory, read and then deleted. When the changes are being
applied to the actual save file, the DB is exported again from the save file
currently loaded into memory, modified, imported back and only after all these
steps, the file on disk is overwritten with the new data. So, another reason
of failures during open/save process besides the file access problems (no free
space, security, etc.) are DB related problems (opening and modifying).
Actions related to checkboxes can't be undone (in this program) once they were
applied. When the file is loaded into the program, the DB data is checked and
these checkboxes get ticked again, if the corresponding options were applied
before. A special attention is needed for the last option because it will
reset the status of the event to "completed", regardless of it's previous
status.
"Fix Checksum" button is enabled only if the loaded save file has incorrect
checksums in it's header. When this button is pressed, the currently loaded
save file is written to disk with fixed checksums. Please, note the difference
with "Save Changes" button, which additionally applies currently selected
changes to the DB. Each one of these mentioned above buttons is disabled to
indicate the successful completion of the operation, no message is displayed.
"Import DB" button overwrites the DB of the currently loaded into memory save
file, then automatically overwrites it on the disk and reloads the data in
order to display an actual data from the new DB. "Export DB" button simply
writes the DB of the loaded save file to the specified location.
To edit driver skills check the last option. The dialog will open where you
can change the values. If the value was entered incorrectly, it will be just
skipped, thus will not change, no error will pop up. To open the dialog again
uncheck and than check again this option. Please, make sure that you didn't
clear check mark after you have made the changes, because the changes won't
be saved when you click on "Save Changes" in this case.

4. Technical information
I won't repeat myself about the layout of header that was described in my
previous NFS save editors, as it didn't change. Instead I just talk about
most important things.
First, this save editor assumes that the block containing the DB is not
moveable and starts at file offset 0x238. The DWORD at offset 0x21C holds the
size of DB block plus 0x14 (that's probably the header size). It turned out
that the DB can have a variable size, thus can expand. A wrong assumption was
made about the DB size constancy in version 1.0 of this editor, that could lead
to save file damage. The DB block is encrypted, the decryption key is located
right before the DB data, at file offset 0x228 and is 16 byte long, and is also
encrypted with constant master key, which is located in game exe. The
encryption is simple XOR but it is applied in block chaining mode and uses
MD5 hash function for key generation. I think code is much better than words,
so anybody interested can read the sources of CSaveFile class that I wrote for
this save editor. It can be downloaded from here:
http://www.nfstools.webhosting-for-free.com/CSaveFile.zip
For my experiments and tests with DB I used SQLite Expert Personal, a freeware
program available at: http://www.sqliteexpert.com/download.html
As you can see on the screenshot (DBEdit.png), the money value is in UserData
table, key 1076877135. The options with checkboxes in save editor operate on
CareerUnlocks and CareerEventTracking tables. The information about these
tables and their fields which I was able to figure out is listed at the end of
this section.
A couple of words about serials. Initially I thought about adding an option
to edit the serial into the save editor, but it turned out that the game allows
loading save files with the serial, that is different from the one, that is
stored in the registry, or even without it at all. Moreover, it will replace
the serial in save file with the one stored in the registry every time it
overwrites that save file (if there is no serial in the registry, the serial
buffer in save file is also filled with zeroes). So, this feature would be
useless in the save editor program.
Player name is no longer stored inside the save file, so it's easy to change it
by simply renaming the corresponding directory and save file.
Ok, now about the DB tables. CareerUnlocks table is the most interesting among
the others. It has the following fields:
Key - an unique id of an object (such as racing event or wheelman level)
Type - object type (where a value of 3 indicates shops, 2 - jobs, 1 - wheelman
level, 0 - ordinary races such as checkpoint, sprint, etc. but also
some jobs)
State - 0 means not available (locked), 1 - available, 2 - available new (will
be blinking on the GPS map)
Driver skills are stored in CareerData table as a floating point CDValue (where
a value of 0.01 represents 1%) under the following CDKey:
CDKey Skill
---------- ----------------
1048148874 Engine
3316577405 Transmission
3915205446 Nitrous
4194208498 Forced Induction
3186419145 Suspension
2493928453 Brakes
2260958773 Tires
2165616624 Earnings Bonus
3288497859 Parts Discount
2491680514 Zone Bonus
Unlocking the wheelman level is another thing, that I decided not to implement
in save editor, because it looks like the game calculates it at run-time using
some additional data, so when I've put a few 1's to the state fields to make
the level higher, it worked good only for newly created profile but 50/50 in my
real gameplay profile. Decreasing the level in real profile at level 13 brought
weird results, with level numbers of 78, 20, 53 etc. Probably the wheelman
level is somehow related to the data from CareerLogic table, but I'm not sure
about it. So I didn't put such unstable feature to the save editor.
CareerEventTracking table holds your career progress, the Rank field is the
status of the racing event (1 = winner), Flags is 4 for "completed" and 8 for
"dominated". What save editor actually does for the options with checkboxes -
it executes the following SQL queries:
1st cb: UPDATE CareerUnlocks SET State = 1 WHERE Type = 3
2nd cb: UPDATE CareerUnlocks SET State = 1 WHERE Type = 0 OR Type = 2
UPDATE CareerEventTracking SET Rank = 1, Flags = 4 WHERE Key = 222973902
1
3d cb: UPDATE CareerEventTracking SET Rank = 1, Flags = 4
4th cb: UPDATE CareerData SET CDValue = nnn.mmm WHERE CDKey = kkk
As you can see the "unlock all career events" option, the second checkbox,
executes an additional SQL query that marks one event as completed. This is
the Showdown - final career event. Not doing so will cause the game to show
only this single event as open and ready to race and others will be
unavailable, no matter that they were unlocked.
It is also possible to modify the stats, just to make some fun, because
there is no other use of it (except the money amount):
In-game Name Key Table
Career
------
Current Cash 1076877135 UserData (actual in-game money amoun
t)
Total Cost To State 2955377331 CareerData
Total Zone Points 1466039711 CareerData
Pink Slip Cars 506612467 UserData
Game
----
Total Drive Distance 3290023354 UserData (in metres)
Total Cash Earned 3128534255 UserData
Most Cost To State (1 event) 2294545711 CareerData
Highest Top Speed 1712513165 UserData (in metres per second)
Most Zone Points (1 event) 3105838030 CareerData
Total Cars Bought 358443849 UserData
Total Cars Impounded 115555055 UserData
Pursuit
-------
Longest Pursuit 2036746550 UserData (in seconds)
Shortest Pursuit 347537910 UserData (in seconds)
Pursuits Evaded 118225201 UserData
Times Busted 1190648803 UserData
Infractions 1949258289 UserData
Cops Disabled 1494668669 UserData
Cops Disabled (1 pursuit) 2032965883 UserData
Roadblocks Dodged 3378051675 UserData
Roadblocks Dodged (1 pursuit) 4055062937 UserData
Spike Strips Dodged 1385473495 UserData
Spike Strips Dodged (1 pursuit) 2724492437 UserData
Also I made a small loader program, that can run the no-Securom version of
nfs.exe by RELOADED team, that can be downloaded from
http://gf.wiretarget.com/nfs_undercover.htm
which will patch game code at run-time so that it will dump all SQL queries
being executed to the file C:\nfs.log It can be useful for analyzing what
actually the game does with DB during the gameplay process. The loader program
can be downloaded here: http://www.nfstools.webhosting-for-free.com/NFSLoader.zi
p

5. Secret codes
The secret code verification function is located at address 0x0058A6B0 in
nfs.exe. This routine takes the ascii zero-terminated string - your input,
calculates it's 32-bit hash (see SecretCodeHash()) and then searches for
that number among the 34 hard-coded secret code hashes.
int SecretCodeHash(const char *pszCode)
{
int nHash = -1;
for ( int i = 0; pszCode[i] != 0; ++i )
nHash = 33*nHash+pszCode[i];
return nHash;
}
The good news is that this hash function is very simple and produces a lot of
collisions, so it was possible to successfully bruteforce all hard-coded secret
code hashes with short length strings containing only lower case latin
characters. I've picked one of the generated secret codes for every hash,
checked the result that it produces and made the following table:
## Hash Code Result
-- -------- -------- ---------
1 0C06C9F1 zgdbyela 10000$
2 13140E79 jxkmaze 15000$
3 21748A76 aguetwia Lotus Elise from NeedForSpeed.com
4 9D3393D6 zouzzzgd 10000$
5 6C185ACF zawysied Pontiac Solstice GXP from NeedForSpeed.com
6 8324DB24 vetvlas 15000$ from T-Mobile
7 875848AE qfmytyda You are in Progressive cop team (get Police vehicle)
8 2A59FD65 deftyade Shelby Terlingua Kit
9 D631A75D ftpnkby Audi R8 from Die-Cast
10 1772D820 goosqdt BMW M3 E92 from Die-Cast
11 B39278DA nircagfa Chevrolet Camaro Concept from Die-Cast
12 A03C4CFA nsializa Dodge Viper SRT10 from Die-Cast
13 F455C6B6 jkeoqon Dodge Charger R/T from Die-Cast
14 A3D645D0 cmexlhld Ford Mustang GT from Die-Cast
15 CB649D41 gamruvld Lamborghini Murcielago LP640 from Die-Cast
16 27476579 naboatad Lexus IS F from Die-Cast
17 E2045019 awnwjnad Mazda Mazda3 MPS from Die-Cast
18 2C0958FE fexifsya Mitsubishi Lancer EVOLUTION from Die-Cast
19 4BC360A6 dotfjvvd Nissan 240SX (S13) from Die-Cast
20 EF522507 hymuueib Pontiac GTO from Die-Cast
21 47C7D523 fsmegdie Porsche 911 Turbo from Die-Cast
22 7A5DEB8B psixhfvd Volkswagen R32 from Die-Cast
23 25CDB22F tvrbylid Circuit City vinyl
24 001E6F70 tylvibsd <code disabled>
25 D5770DC7 ftfdaps Nissan GR-R (R35) from Die-Cast (police)
26 9C9E107D kodkupke Porsche 911 GT2 from Die-Cast
27 925E4841 rmoodthe Chevrolet Camaro Concept from Die-Cast (alt. paint)
28 9C0F3754 osowsubc Dodge Charger R/T from Die-Cast (alt. paint)
29 8591F3B3 orexnag Lexus IS F from Die-Cast (alt. paint)
30 F825F301 ypskdmee Mitsubishi Lancer EVOLUTION from Die-Cast (alt. paint)
31 C724A0A4 slicgs Porsche 911 GT2 from Die-Cast (alt. paint)
32 2ECEA225 xmgfoda <code disabled>
33 000ACF53 genogtp <code disabled>
34 0F803640 odkosrna <code disabled>
Some positions in this table say <code disabled> - it means that the original
secret code check function in nfs.exe explicitly skips these indices, but they
are included here for the sake of completeness. Every time you enter one of
these secret codes, the game writes 1 into the Status field in the row with
corresponding CodeKey in CheatCodes table into DB. Once the 1 value has been
put there, secret code can't be reused again for that profile.

6. Credits
This program makes use of the following libraries:
MD5 hash implementation from OpenSSL library
http://www.openssl.org/
SQLite database engine
http://www.sqlite.org/
Thanks to RELOADED team for Securom-free nfs.exe. This tool would be never
created without the ability to analyse the unprotected game code.

7. Contact
The latest version of the program can be downloaded here:
http://www.nfstools.webhosting-for-free.com/
If this free hosting is down, try to use
http://kickme.to/coderipper
It is permanent redirect to the most recent version of all these tools in
a single archive uploaded to Rapidshare.

e-mail: code_ripper@ukr.net
(C) 2008 CoDe RiPPeR

You might also like