ZenHAX

Free Game Research Forum | Official QuickBMS support | twitter @zenhax | SSL HTTPS://zenhax.com
It is currently Wed May 12, 2021 8:22 pm

All times are UTC




Post new topic  Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Fri Apr 30, 2021 10:33 pm 

Joined: Thu Apr 29, 2021 7:04 pm
Posts: 3
there is a .db file that seems to contain the things i am looking for. however it seems to be encrypted and im not sure if its an sqlite database or something else just stored with the extension. if anyone is willing to help me figure out how its encrypted or how to open it it would be much appreciated

also game is MO 2 its for PC and built using UE4

the .db: https://drive.google.com/file/d/1MxvHmA ... sp=sharing
the games shipping exe: https://drive.google.com/file/d/1C9Q7Dz ... sp=sharing

any help would be really appreciated spent awhile trying to figure this out.


Last edited by froggins on Wed May 05, 2021 3:01 am, edited 1 time in total.

Top
   
PostPosted: Sat May 01, 2021 4:47 pm 

Joined: Sat Sep 28, 2019 7:00 pm
Posts: 348
I'm more into debugging stuff at runtime, but since the game is 75GB (which I'm not going to download), here is function, which most likely read such db files, which is indeed encrypted sql database, judging by relevant functions.

Deobfuscating part is "do ... while ( v9 < v16 )", where byte_14AF73848 is following byte[8] array: "2, 3, 5, 7, 0Bh, 0Dh, 11h, 13h" - but I'm not sure what exactly algorithm it is, maybe simple rotation with xoring.


Attachments:
read_func.txt [2.33 KiB]
Downloaded 13 times

_________________
You can request AES keys on rin forums (the list with keys is also there)
AES keys finder and latest UE4 bms scripts: in this post
Top
   
PostPosted: Sat May 01, 2021 8:00 pm 

Joined: Thu Apr 29, 2021 7:04 pm
Posts: 3
spiritovod wrote:
I'm more into debugging stuff at runtime, but since the game is 75GB (which I'm not going to download), here is function, which most likely read such db files, which is indeed encrypted sql database, judging by relevant functions.

Deobfuscating part is "do ... while ( v9 < v16 )", where byte_14AF73848 is following byte[8] array: "2, 3, 5, 7, 0Bh, 0Dh, 11h, 13h" - but I'm not sure what exactly algorithm it is, maybe simple rotation with xoring.

thank you for the help im going to try to figure that out.

needa do some research to understand a couple parts of that because i dont have much experience with C++


also while byte_14BD466A1 and byte_14BD466A0 have values
byte_14AF73848 is only mentioned once and is an array. how would i go about finding its value? (edit) actually i see in your response you described what this is sorry about that)

with v8 = *(_QWORD *)v7; im not quite sure what QWORD is. is this a variable or is it just giving a type to v7 which v8 then equals? feel like im looking at this part completly wrong.

when v15[0] is set to = 0i64 this means its equal to 0 but stored as a 64bit int right? so then when v7 = v15[0] it would also equal 0?

sorry for all the random questions just trying to understand the code more since i am not used to how C++ does things(signing up for a class on it during summer for sure)


Top
   
PostPosted: Sun May 02, 2021 11:04 am 

Joined: Sat Sep 28, 2019 7:00 pm
Posts: 348
@froggins: Well, I don't quite understand it either, it's much easier to observe such things at runtime for better understanding. You can do AOB search for the db header, 1D 17 DA EF, it will land you right at the spot. Also, I don't think you need variables outside mentioned cycle, the rest of function is for reading that file in blocks.

_________________
You can request AES keys on rin forums (the list with keys is also there)
AES keys finder and latest UE4 bms scripts: in this post


Top
   
PostPosted: Tue May 04, 2021 1:20 am 
User avatar

Joined: Sat Dec 27, 2014 8:49 pm
Posts: 206
spiritovod has the right function, it's just a matter of following what it does in the proper order. This does use SQLite3 (specifically revision hash: 042a1abb030a0711386add7eb6e10832cc8b0f57) but is custom encrypted as SQLite3 does not give you encryption by default unless you add on SQLiteCypher which this doesn't use. Instead, they implemented their own on-open encryption.

Here's a rundown of what the function is doing:

Code:
  result = fopen(a1, "rb");
  v2 = result;
  if ( result )
  {
    if ( (unsigned int)fread(&v18, 4i64, 1i64, result) == 1
      && v18 == -270919907
      && (unsigned int)fread(&v17, 4i64, 1i64, v2)
      && v17 != 1766609235
      && (fread(&v16, 4i64, 1i64, v2),
          sub_1435B4550(":memory:", v15, 6i64),
          v3 = v15[0],
          v4 = **(_QWORD **)(*(_QWORD *)(*(_QWORD *)(v15[0] + 16) + 8i64) + 8i64),
          (v5 = (char *)malloc(v16)) != 0i64) )
    {


First, the file is being opened and validated based on their own custom header setup. This expects their custom header otherwise it's simply closed and ignored.

The first 4 bytes are checked for: 0xEFDA171D
The next 4 bytes are checked for: 0x694C5153 (This is SQLites default header being checked, to see if this is encrypted.)

Based on that info, it does look like they have intentions to support unencrypted database files with their custom header prefixing the file later on.

Next, a blank database instance is opened in memory via the sqlite3_openDatabase call here:
Code:
sub_1435B4550(":memory:", v15, 6i64),


Following that, they grab the block of memory the database is at and allocate the initial page of memory to be used while walking the file to decrypt it:
Code:
          v4 = **(_QWORD **)(*(_QWORD *)(*(_QWORD *)(v15[0] + 16) + 8i64) + 8i64),
          (v5 = (char *)malloc(v16)) != 0i64)


The header of the file is in the following format if the 2nd uint32_t is not the normal SQLite3 header:
Code:
struct header_t
{
    uint32_t Signature;
    uint32_t Parts;
    uint32_t PartSize;
};


Parts is the number of 'chunks' inside of the file to decrypt individually, while PartSize is the size of each chunk.
In the example you gave, the file is:
- Parts: 5444
- PartSize: 1024

This info can also be used to validate the file.
Take (Parts * PartsSize) + 0x0C and it should equal the total file size.

v15 at this point is pointing to an empty initialized instance of the sqlite3 object structure. You can see that here:
https://github.com/sqlite/sqlite/blob/m ... nt.h#L1493

(Note, this is not the same revision so it may not align to the one in this program.)

Next:

Code:
      v6 = 0;
      byte_14BD466A1 = 97;
      byte_14BD466A0 = 37;


v6 is the parts step count while the other two byte values here are the xor keys initial values.

Code:
        while ( 1 )
        {
          ++v6;
          v15[0] = 0i64;
          sub_1435D7010(v4, (unsigned int)v6, v15, 1);
          v7 = v15[0];
          sub_1435D8890(v15[0]);
          ++*(_WORD *)(v7 + 42);
          if ( fread(v5, v16, 1i64, v2) != 1 )
            break;


This is where the game is allocating memory and updating the initialized database object returned in v15. They are creating pages of memory from the file based on the Parts and PartSize information as they step over each part. These are populating the sqlite3 structures 'pVdbe' variable information from what it looks like as its stepping through each part and updating the memory blocks.

The initial block of memory used each time we read in a new part is first read into v5, which was allocated when the file header was validated.

Then that data is copied into in-memory database information as its processed with 'sub_1435D7010' and 'sub_1435D8890'.

The fread here is reading the current part from the file. (v16 being 1024 from the header's PartSize value.)

The next part is where the actual decryption and processing happens:

Code:
          v8 = *(_QWORD *)v7;
          v9 = 0;
          if ( v16 > 0 )
          {
            v10 = &v5[-v8];
            do
            {
              ++v9;
              v11 = v10[v8++];
              v12 = byte_14BD466A0 & 7;
              v13 = byte_14BD466A1 ^ byte_14BD466A0++ ^ v11;
              byte_14BD466A1 += byte_14AF73848[v12] + 1;
              *(_BYTE *)(v8 - 1) = v13;
            }
            while ( v9 < v16 );
          }
          v14 = *(_QWORD *)(v7 + 32);
          sub_1435D91F0(v7);
          sub_1435B52C0(v14);
          if ( v6 >= v17 )
            goto LABEL_13;


The first part is preparing the in-memory database page to align to the part being processed so that when completed, the pages are all prepared and ready for use as an actual decrypted database.


Code:
            v10 = &v5[-v8];
            do
            {
              ++v9;
              v11 = v10[v8++];
              v12 = byte_14BD466A0 & 7;
              v13 = byte_14BD466A1 ^ byte_14BD466A0++ ^ v11;
              byte_14BD466A1 += byte_14AF73848[v12] + 1;
              *(_BYTE *)(v8 - 1) = v13;
            }
            while ( v9 < v16 );


This is the actual decryption part and is walking over a set of 3 keys to mutate the xor as each byte is processed.

The first value is taken from the encrypted part read from the file, as it steps each byte from this read block. It then does some basic xoring while mutating the keys and then writes the xor'd value to the current pages memory for the in-memory database.

The keys are:
- byte_14BD466A0: 0x25
- byte_14BD466A1: 0x61
- byte_14AF73848: { 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11, 0x13 }

These keys ARE NOT reset when stepping to the next part of the file, it is kept from the previous mutation.

The last part during the loop is:

Code:
          v14 = *(_QWORD *)(v7 + 32);
          sub_1435D91F0(v7);
          sub_1435B52C0(v14);
          if ( v6 >= v17 )
            goto LABEL_13;


This is cleaning up the temp information, adjusting the linked list of the in-memory database pages and checking if we've hit the part count to stop iterating and close the file.

When completed, the database is decrypted and rebuilt, part by part, in-memory to be used by the game to avoid any on-disk resources, I/O or potential information leak. Based on how this works, you can dump the database from memory as well right after it's done looping the pages. Simply walk the database objects pages that are exposed inside of the virtual link list being used in the 'pVdbe' field and you should be able to see all of it decrypted too.

Attached is the decrypted database. If you want to donate since you put a bounty on this, my Paypal is:
https://paypal.me/atom0s

You can use the latest version of SQLite Browser to open and view it.


Attachments:
Content.dec.db.zip [2.04 MiB]
Downloaded 8 times

_________________
My personal site: http://atom0s.com
Donations can be made via Paypal: Click Here
Top
   
PostPosted: Wed May 05, 2021 2:24 am 
User avatar

Joined: Sat Dec 27, 2014 8:49 pm
Posts: 206
Since I didn't really look at the db after decrypting it, it was brought to my attention that the data inside of it is also encrypted. The inner encryption is done differently with a different mutation/key setup. I won't post about that for now since the game is new and I'm sure a bunch of people are going to want to just try to sell information for the game. However, I will post a fully decrypted version of the db.

The database attached is ~1MB smaller than the previous due to being imported into a newer SQLite version and dumped with that newer version. So there's a lot of overhead from the old version removed. (The game uses 3.7.x while the latest is 3.35.5)

The latest version of SQLite Browser should be able to open and view the file without issue. The file is rebuilt via a tool I wrote to dump, decrypt and rebuild the original db with. Both the table creation and indexes should align properly etc. Just the fields are decrypted in this version.


Attachments:
Content.db.dump.decrypted.by.atom0s.db.7z [595.15 KiB]
Downloaded 3 times

_________________
My personal site: http://atom0s.com
Donations can be made via Paypal: Click Here
Top
   
PostPosted: Wed May 05, 2021 7:51 am 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 12183
@froggins
Please don't change the title of the topic.
If it's solved for you, it isn't for others who are searching the same.
This is a forum.
Thanks


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 7 posts ] 

All times are UTC


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Limited