Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.

Quake Champions

Featured Replies

  • Replies 97
  • Views 15
  • Created
  • Last Reply

Top Posters In This Topic

  • Author
  • Localization

coredevel, posted Sat Jun 24, 2017 2:05 pm (24275)


Has anyone look at the beta for Quake Champions? Data is stored in a unknown .pak format. Actually, I think there's two types of .pak files. One .pak format stores unrelated chromium data, which looks uncompressed.

The other .pak format stores the game data, but the format is unrecognized. It looks like there's some kind of entry list at the end of the file. All files end with the same 64-bit ID (1P.D.KS1). One of the .pak files is almost 16 GB, so they could store 64-bit offsets, but they look odd to me. From there, I can't make much of anything.

Image
  • Author
  • Localization

wattostudios, posted Wed Jul 12, 2017 11:58 am (24506)


I too would be interested in this - it's a bit beyond me though, seems to have encryption throughout the archive footer and files directory.

You can go here to get a free Beta key for the game... https://quake.bethesda.net/en/signup
This directs you how to download the game - it has a number of PAK files in the client\preload\paks directory - most are 25-200MB in size, and 1 at nearly 16GB in size.

This is the general archive structure...

Code:
// FILE DATA
  // for each file
      X - File Data
   
// DIRECTORY
  // for each file
    X - Unknown (Encrypted)
    1 - null
    2 - Unknown (4)
    4 - Unknown (4)
 
// ARCHIVE FOOTER
  2 - Header (PK)
  2 - Version? ((bytes)5,6)
  4 - null
  4 - Unknown
  4 - Directory Length
  8 - Directory Offset
  X - Unknown
  40 - Encrypted Footer Info


I suspect somewhere in the 40-byte Encrypted Footer it will contain a pointer to the "PK" field in the ARCHIVE FOOTER, after which you can find the offset and length of the DIRECTORY.

The entries in the DIRECTORY are of varying length, but are similar sized (ie. all in the range of say 80-120 bytes in length), so I suspect the encrypted part probably stores filenames and directory paths, and hopefully some length and offset information for each file.

The file data doesn't appear to be encrypted, and I don't think it's compressed either. Certainly, when downloading the data from the website at the top, it only downloaded about 10-11GB for the install, but it takes up about 17GB on my PC, so I'm pretty certain the PAK files are not compressed on my PC (but were obviously compressed when downloading from the website)

Would anyone with encryption expertise care to take a look at this?

Thanks, much appreciated.
  • Author
  • Localization

wattostudios, posted Wed Aug 16, 2017 12:34 pm (25591)


I have uploaded 3 of the archives here - if anyone can take a look at the encryption, it'd be greatly appreciated.

https://drive.google.com/open?id=0B7gEf ... TM4dmNXdVE

Somewhere in the 40-bytes at the end of the archive, it should contain a pointer to the "PK" field (which seems to be a few thousand bytes before the end of the archive). Once we can get that, we can grab the Directory Offset field.

Then, at the Directory Offset, we can clearly see a repeating pattern of file entries, of varying length, so they almost certainly contain a filename in them, as well as probably Length and Offset details.

Thanks for your help guys
  • Author
  • Localization

aluigi, posted Wed Aug 16, 2017 3:31 pm (25605)


I launched offzip -a -z -15 and it worked very well because all or almost all the files are compressed and they don't use chunks.
There are only 0x1e bytes between each compressed files and they are just zeroes, so no info there.

I tried to search the compressed sizes, uncompressed sizes and offsets in the archive but found no references so it means that the TOC is encrypted, in fact the last part of the archive is divided in 3 parts: a long sequence of "random" bytes (encrypted TOC), some 64bit numbers and the 40bytes RSA signature.
  • Author
  • Localization

wattostudios, posted Thu Aug 17, 2017 10:59 am (25621)


Thanks for trying Aluigi, at least thats better than nothing :-)

Let me know if you think it'd be useful to look at any of the EXEs for a way to crack the encryption, or if you need anything else from me.
  • Author
  • Localization

aluigi, posted Fri Aug 25, 2017 12:41 pm (25848)


Here we go :D
http://aluigi.org/bms/quake_champions.bms

The encryption algorithm is a 64bit random number generator taken from "Numerical Recipes 3rd edition" and using the first 64bit seed of the last 40 bytes and an ivec of 32 bytes still take from the last 40 bytes.
  • Author
  • Localization

wattostudios, posted Sat Aug 26, 2017 11:53 am (25921)


Wow, awesome work, I won't even begin to fathom how you worked that one out, what a nice complicated bit of work :-) Think you'll find lots of people happy to have access to these files.
  • Author
  • Localization

coredevel, posted Sat Sep 02, 2017 2:04 am (26159)


Amazing work. Thanks for the help!
  • Author
  • Localization

OXOTHuK, posted Tue Mar 20, 2018 6:15 pm (33477)


Hi 2 all.
Now this script does not work?
  • Author
  • Localization

aluigi, posted Sun Apr 22, 2018 8:08 am (34228)


@OXOTHuK
What error you get from quickbms?
Nobody else has reported any problem.
  • Author
  • Localization

madsnark, posted Sat Apr 28, 2018 6:11 am (34445)


aluigi wrote:
@OXOTHuK
What error you get from quickbms?
Nobody else has reported any problem.

Image
  • Author
  • Localization

aluigi, posted Sat Apr 28, 2018 8:41 am (34449)


Upload the archive.
  • Author
  • Localization

aluigi, posted Mon Apr 30, 2018 3:32 pm (34531)


I analyzed the file you provided and noticed that now the "PK\x05\x06" entry has been replaced with a "PK\x06\x06" entry having the following custom format:
Code:
get ZERO byte
get central_entries longlong
get central_size longlong
get central_offset longlong
get DUMMY_offset longlong
Unfortunately there is something small changed in the encryption algorithm because the first byte every 8 is partially invalid.
In my opinion it's something related to NextUInt64().
  • Author
  • Localization

Rev3n4nt, posted Wed Jun 06, 2018 8:02 pm (35658)


Is there anything new about encrypting renewed PAK format? If it's NextUInt64(), is there a way meybe to bruteforce invalid first byte every 8 ? I'm not a coder really, but I hope there will be solution soon for this, so communities like "Garry's mod", "XNALara", and "Quake1 models mods" can get some models from QC for them asap :)
  • Author
  • Localization

buk0wski, posted Sat Jun 16, 2018 11:06 pm (35961)


Hey luigi, good to see that you're still doing great work after all this years. :)
However, bump?! What happened here, did they change the init vectors? Do you think there is any practical way to solve this issue?

And besides, how did you even find the correct NextUInt64() function in the first place?
  • Author
  • Localization

buk0wski, posted Sat Jun 16, 2018 11:28 pm (35962)


Image

This is what I get from changing "PK\x05\x06" to "PK\x06\x06" in lines 69 and 71 of the .bms file.
central_offset is wrong I suppose? (line 81, goto)

EDIT:
Image

It's somewhat evolving. I updated the header format and added prints to keep track of everything. The dummy doesn't look legit tho

I'll continue tomorrow, it's already quite late. However this isn't hopeless I think
  • Author
  • Localization

aluigi, posted Sun Jun 17, 2018 6:56 am (35966)


buk0wski wrote:
Do you think there is any practical way to solve this issue?

Sure, buy the game, find NextUInt64 with the help of the constant numbers used in the algorithm, spot the differences and give me the result :)
  • Author
  • Localization

buk0wski, posted Sun Jun 17, 2018 1:10 pm (35989)


I did it with literally every constant (as hex ofc), but without any success. Seems like the switched the entire RNG process, while leaving the decrypt function itself technically the same.
But in fact the exe doesn't even disassemble properly (with IDA Free v7). All that I realized is that my capabilities and knowledge are not yet sufficient for this kind of nuisance.
  • Author
  • Localization

aluigi, posted Sun Jun 17, 2018 3:20 pm (35994)


Try searching the constants in hex for NextUInt64:
2862933555777941757ULL = 0x27bb2ee687b0b0fd
7046029254386353087ULL = 0x61c8864680b583bf
4294957665U = 0xffffda61
21 and 35

The only other constant available is the one of NrRandom:
4101842887655102017ULL = 0x38ecac5fb3251641

Locating these functions should be really very easy. If you need to make some practice this is the perfect occasion.

It's perfectly possible that the exe is encrypted, being on Steam you probably need to use steamless to decrypt it first:
https://github.com/atom0s/Steamless/releases

Worst case scenario dump the memory and do it the raw way :)
  • Author
  • Localization

buk0wski, posted Sun Jun 17, 2018 6:26 pm (35998)


Thanks for your help mate, highly appreciated. But even after successfully removing the steam encryption w/ steamless (nice hint btw, didn't know this exists), the mentioned constants are nowhere to find :( Well, except for a heckton of 0x15 and 0x23 matches that didn't really get me any further

If they changed all those values, I guess I would have to find the algorithm only by recognizing the corresponding assembly op codes. Which (besides sounding crazy) I doubt is even possible since they depend on the used compiler and its settings, if I am not mistaken?

aluigi wrote:
Worst case scenario dump the memory and do it the raw way :)

Will do this.
I think there could be an additional reverse engineering protection because the disassembled steamless output still has some "random byte" areas that shouldn't be there.

Can you recommend a decent memdump debugging tool? I didn't really like the few I "worked" with so far and the windows-implemented techniques are not that practical either

-----------------------------------------------------

EDIT: Windows task manager DMP file of the process didn't include the values either.... something strange is going on here
  • Author
  • Localization

buk0wski, posted Mon Jun 18, 2018 4:35 pm (36012)


Found it in the ram! Finally.

This is the actual nextUInt64() func:
(The comments are refering to the the code in http://aluigi.org/bms/quake_champions.bms)

Code:
mov r8,rcx                  
mov rcx,27BB2EE687B0B0FD { -2018463491 }   
mov rax,[r8]      // ulong U
imul rax,rcx         // U *= 2862933555777941757ULL   
mov rcx,61C8864680B583BF    
add rax,rcx         // U = 7046029254386353087ULL
mov [r8],rax      // save U                  
mov rdx,[r8 08]      // RDX = ulong V
shr rdx,11          // V >> 17
xor rdx,[r8 08]      // ^= V
mov rcx,rdx               
shl rcx,1F         // V << 31   
xor rcx,rdx         // ^= V
mov edx,FFFFDA61    // 4294957665U   
mov rax,rcx               
shr rax,08 { 8 }      // V >> 8
xor rax,rcx         // ^= V
mov [r8 08],rax      // save V
mov rcx,[r8 10]      // RCX = ulong W
mov eax,ecx
imul rdx,rax         // ???!!!!
shr rcx,20 { 32 }      // W >> 32   
add rdx,rcx         // W ?!
mov [r8 10],rdx      // save W
mov rcx,[r8]      // RCX = ulong X (= U)                  
shl rcx,15 { 21 }      // U << 21               
xor rcx,[r8]         // ^ U = X
mov rax,rcx         // RAX = X               
shr rax,23 { 35 }      // X >> 35
xor rcx,rax         // ^= X
mov rax,rcx         // RAX = RCX   
shl rax,04 { 4 }      // X << 4
xor rax,rcx         // ^= X
add rax,[r8 08]      // (x v)
xor rax,rdx         // ^ w
ret

I tried to analyze it as good as I possibly could. I am lacking a lot of practice tho, as you may see

If I am not mistaken, they changed the line
Code:
w = 4294957665U * (w & 0xffffffff)   (w >> 32);

to something like
Code:
v ^= v >> 17; 
ulong a = v;      // rdx?
v ^= v << 31;
v ^= v >> 8;
ulong b = v;       // rax?
w = (a * b) (w >> 32);   // a * b -> imul rdx, rax??

But what is happing to the 4294957665U constant?

This is a bit over my head actually, can someone back me up here please?

EDIT: This is the NrRandom() function, which contains iterations of NextUInt64() since NrRandom() calls it a few times:
Code:
mov rax,38ECAC5FB3251641 { -1289415103 }
mov r8,rcx
mov [rcx 08],rax
mov qword ptr [rcx 10],00000001 { 1 }
mov rax,[QuakeChampions.NvOptimusEnablement 4A77E0] { [148F2BB98F0] }
test rax,rax
je QuakeChampions.apProcessExceptionDllCall 1D99A8
xor rdx,[rax]
mov rax,[rcx 08]
mov r11,27BB2EE687B0B0FD { -2018463491 }
xor rax,rdx
mov r10,61C8864680B583BF { -2135587905 }
imul rax,r11
mov r9d,FFFFDA61 { -9631 }
add rax,r10
mov [rcx],rax
mov rcx,[rcx 08]
shr rcx,11 { 17 }
xor rcx,[r8 08]
mov rdx,rcx
shl rdx,1F { 31 }
xor rdx,rcx
mov rax,rdx
shr rax,08 { 8 }
xor rax,rdx
mov [r8 08],rax
mov rcx,[r8 10]
mov eax,ecx
imul rax,r9
shr rcx,20 { 32 }
add rax,rcx
mov [r8 10],rax
mov rax,[r8]
mov [r8 08],rax
mov rax,[r8]
imul rax,r11
add rax,r10
mov [r8],rax
mov rcx,[r8 08]
shr rcx,11 { 17 }
xor rcx,[r8 08]
mov rdx,rcx
shl rdx,1F { 31 }
xor rdx,rcx
mov rax,rdx
shr rax,08 { 8 }
xor rax,rdx
mov [r8 08],rax
mov rcx,[r8 10]
mov eax,ecx
imul rax,r9
shr rcx,20 { 32 }
add rax,rcx
mov [r8 10],rax
mov rax,[r8 08]
mov [r8 10],rax
mov rax,[r8]
imul rax,r11
add rax,r10
mov [r8],rax
mov rcx,[r8 08]
shr rcx,11 { 17 }
xor rcx,[r8 08]
mov rdx,rcx
shl rdx,1F { 31 }
xor rdx,rcx
mov rax,rdx
shr rax,08 { 8 }
xor rax,rdx
mov [r8 08],rax
mov rcx,[r8 10]
mov eax,ecx
imul rax,r9
shr rcx,20 { 32 }
add rax,rcx
mov [r8 10],rax
ret

I've recently learned that r9 = r9d, so 4294957665U is in fact multiplied with W?

EDIT2: Here's everything I found in the memory (each function seperated, still messy): https://pastebin.com/5TMBEQWS
  • Author
  • Localization

throwaway6346435, posted Sun Jul 08, 2018 12:56 pm (36586)


Encryption pseudocode:
Code:
signed __int64 __fastcall sub_141562250(__int64 a1, __int64 a2)
{
  __int64 v2; // r8@1
  __int64 v3; // rcx@3
  signed __int64 result; // rax@3

  v2 = a1;
  *(_QWORD *)(a1 8) = 4101842887655102017i64;
  *(_QWORD *)(a1 16) = 1i64;
  if ( qword_142F99BE8 )
    a2 ^= *(_QWORD *)qword_142F99BE8;
  *(_QWORD *)a1 = 2862933555777941757i64 * (a2 ^ *(_QWORD *)(a1 8)) 7046029254386353087i64;
  v3 = *(_QWORD *)(a1 8) ^ (*(_QWORD *)(a1 8) >> 17);
  *(_QWORD *)(v2 8) = v3 ^ (v3 << 31) ^ ((v3 ^ (unsigned __int64)(v3 << 31)) >> 8);
  *(_QWORD *)(v2 16) = (*(_QWORD *)(v2 16) >> 32) 4294957665i64 * (unsigned int)*(_QWORD *)(v2 16);
  *(_QWORD *)(v2 8) = *(_QWORD *)v2;
  *(_QWORD *)v2 = 2862933555777941757i64 * *(_QWORD *)v2 7046029254386353087i64;
  *(_QWORD *)(v2 8) ^= (*(_QWORD *)(v2 8) >> 17) ^ ((*(_QWORD *)(v2 8) ^ (*(_QWORD *)(v2 8) >> 17)) << 31) ^ ((*(_QWORD *)(v2 8) ^ (*(_QWORD *)(v2 8) >> 17) ^ ((*(_QWORD *)(v2 8) ^ (*(_QWORD *)(v2 8) >> 17)) << 31)) >> 8);
  *(_QWORD *)(v2 16) = (*(_QWORD *)(v2 16) >> 32) 4294957665i64 * (unsigned int)*(_QWORD *)(v2 16);
  *(_QWORD *)(v2 16) = *(_QWORD *)(v2 8);
  *(_QWORD *)v2 = 2862933555777941757i64 * *(_QWORD *)v2 7046029254386353087i64;
  *(_QWORD *)(v2 8) ^= (*(_QWORD *)(v2 8) >> 17) ^ ((*(_QWORD *)(v2 8) ^ (*(_QWORD *)(v2 8) >> 17)) << 31) ^ ((*(_QWORD *)(v2 8) ^ (*(_QWORD *)(v2 8) >> 17) ^ ((*(_QWORD *)(v2 8) ^ (*(_QWORD *)(v2 8) >> 17)) << 31)) >> 8);
  result = (*(_QWORD *)(v2 16) >> 32) 4294957665i64 * (unsigned int)*(_QWORD *)(v2 16);
  *(_QWORD *)(v2 16) = result;
  return result;
}
int __fastcall sub_141561CB0(__int64 a1, signed __int64 a2)
{
  unsigned __int64 v2; // rdi@1
  __int64 v3; // rbx@1
  __int64 v4; // rax@2
  unsigned __int64 v5; // r10@2
  __int64 v6; // r8@2
  unsigned __int64 v7; // rdx@2
  signed __int64 v8; // r9@2
  unsigned __int64 v9; // rdx@3
  __int128 v10; // xmm1@6
  __int64 v11; // rdx@6
  __int64 v13; // [sp 0h] [bp-48h]@6
  __int64 v14; // [sp 20h] [bp-28h]@2
  unsigned __int64 v15; // [sp 28h] [bp-20h]@2
  unsigned __int64 v16; // [sp 30h] [bp-18h]@2
  __int64 v17; // [sp 38h] [bp-10h]@6

  v2 = 0i64;
  v3 = a1;
  *(_DWORD *)(a1 184) = 0;
  if ( a2 )
  {
    v6 = a1 112;
    *(_OWORD *)v6 = *(_OWORD *)a2;
    *(_OWORD *)(v6 16) = *(_OWORD *)(a2 16);
  }
  else
  {
    LODWORD(v4) = time64(0i64);
    sub_141562250((__int64)&v14, v4);
    v5 = v16;
    v6 = v3 112;
    v7 = v15;
    v8 = v14;
    do
    {
      v5 = 4294957665i64 * (unsigned int)v5 (v5 >> 32);
      v9 = (((v7 >> 17) ^ v7) << 31) ^ (v7 >> 17) ^ v7;
      v7 = (v9 >> 8) ^ v9;
      v8 = 2862933555777941757i64 * v8 7046029254386353087i64;
      *(_BYTE *)(v6 v2 ) = v5 ^ (v7
                                  (((v8 ^ (unsigned __int64)(v8 << 21)) >> 35) ^ v8 ^ 16
                                                                                      * (((v8 ^ (unsigned __int64)(v8 << 21)) >> 35) ^ v8)));
    }
    while ( v2 < 0x20 );
    a2 = v3 112;
  }
  *(_OWORD *)(v3 144) = *(_OWORD *)a2;
  v10 = *(_OWORD *)(a2 16);
  v11 = *(_QWORD *)v6;
  *(_QWORD *)(v3 176) = *(_QWORD *)v6;
  *(_OWORD *)(v3 160) = v10;
  sub_141562250(v3 192, v11);
  return sub_14211B3B0((unsigned __int64)&v13 ^ v17);
}


Tried cleaning it a little bit, still a long way to go, got bored, may be it will help someone:
Code:
signed __int64 __fastcall sub_141562250(__int64 a1, __int64 a2)
{
  __int64 u; // r8@1
  __int64 v3; // rcx@3
  signed __int64 result; // rax@3

  u = a1;
  v = 4101842887655102017i64;
  w = 1i64;
  if ( qword_142F99BE8 )
    a2 ^= qword_142F99BE8;
  u = 2862933555777941757i64 * (a2 ^ 4101842887655102017i64) 7046029254386353087i64;
  v3 = 4101842887655102017i64 ^ (4101842887655102017i64 >> 17);
  v = v3 ^ (v3 << 31) ^ ((v3 ^ (v3 << 31)) >> 8);
  w = (w >> 32) 4294957665i64 * (w & 0xffffffff);
  v = u;
  u = 2862933555777941757i64 * u 7046029254386353087i64;
  v ^= (v >> 17) ^ ((v ^ (v >> 17)) << 31) ^ ((v ^ (v >> 17) ^ ((v ^ (v >> 17)) << 31)) >> 8);
  w = (w >> 32) 4294957665i64 * (w & 0xffffffff);
  w = v;
  u = 2862933555777941757i64 * u 7046029254386353087i64;
  v ^= (v >> 17) ^ ((v ^ (v >> 17)) << 31) ^ ((v ^ (v >> 17) ^ ((v ^ (v >> 17)) << 31)) >> 8);
  result = (w >> 32) 4294957665i64 * (w & 0xffffffff);
  w = result;
  return result;
}
int __fastcall sub_141561CB0(__int64 a1, signed __int64 a2)
{
  unsigned __int64 v2; // rdi@1
  __int64 v3; // rbx@1
  __int64 now; // rax@2
  unsigned __int64 v5; // r10@2
  __int64 v6; // r8@2
  unsigned __int64 v7; // rdx@2
  signed __int64 v8; // r9@2
  unsigned __int64 v9; // rdx@3
  __int128 v10; // xmm1@6
  __int64 v11; // rdx@6
  __int64 v13; // [sp 0h] [bp-48h]@6
  __int64 v14; // [sp 20h] [bp-28h]@2
  unsigned __int64 v15; // [sp 28h] [bp-20h]@2
  unsigned __int64 v16; // [sp 30h] [bp-18h]@2
  __int64 v17; // [sp 38h] [bp-10h]@6

  v2 = 0i64;
  v3 = a1;
  *(_DWORD *)(a1 184) = 0;
  if ( a2 )
  {
    v6 = a1 112;
    *(_OWORD *)v6 = *(_OWORD *)a2;
    *(_OWORD *)(v6 16) = *(_OWORD *)(a2 16);
  }
  else
  {
    LODWORD(now) = time64(0i64);
    sub_141562250((__int64)&v14, now);
    w = v16;
    v6 = v3 112;
    v = v15;
    u = v14;
    do
    {
      w = 4294957665i64 * (w & 0xffffffff) (w >> 32);
      v9 = (((v >> 17) ^ v) << 31) ^ (v >> 17) ^ v;
      v = (v9 >> 8) ^ v9;
      u = 2862933555777941757i64 * u 7046029254386353087i64;
      *(_BYTE *)(v6 v2 ) = w ^ (v (((u ^ (u << 21)) >> 35) ^ u ^ 16 * (((u ^ (u << 21)) >> 35) ^ u)));
    }
    while ( v2 < 0x20 );
    a2 = v3 112;
  }
  *(_OWORD *)(v3 144) = *(_OWORD *)a2;
  v10 = *(_OWORD *)(a2 16);
  v11 = *(_QWORD *)v6;
  *(_QWORD *)(v3 176) = *(_QWORD *)v6;
  *(_OWORD *)(v3 160) = v10;
  sub_141562250(v3 192, v11);
  return sub_14211B3B0((unsigned __int64)&v13 ^ v17);
}
  • Author
  • Localization

buk0wski, posted Fri Jul 13, 2018 2:39 pm (36716)


I already went through all of this. Regarding the constants and the u,v,w variables, everything is exactly the same, but they added a function call in the decryption code:
Quote:
if( qc_seed_idx == 8) {
qc_seed = NextUInt64();
qc_seed_idx = 0;
}
//somewhere here they added....

E8 B699BB00 - call QuakeChampions.Scaleform::Render::Matrix4x4::Transpose 3D4490 // this

and maybe some other Init Vector stuff (I guess) beforehand, including a time function and "security cookie" calls (which are not included in my pastebin since I found them later). The 4x4Matrix appears to be a shifting substitution box of some kind, obviously returning a double.

There are in fact several variations of this RNG where constant floats/doubles are multiplied to the NextUInt64() output, but I found none that includes a 4x4 matrix and thus a variable double value.

However it COULD be possible to reverse engineer the happenings in the box as well of course, but that's where my motivation, spare time and also capabilities reached its limits.

-> Probably easier to hook the running exe and go from there, reading out buffers or memcpy seeds, whatever. Maybe even call the matrix function from the outside. I am not that experienced in this field, but you get my point I guess

ah and those pointer dereferences to NvOptimusEnablement are also questionable. I dont even remember where it led to, as some weeks has passed
QuakeChampions.apProcessExceptionDllCall 1D9999 - 48 8B 05 5843A301 - mov rax,[QuakeChampions.NvOptimusEnablement 4A77E0] { [148F2BB98F0] }


//no guarantee of correctness
Guest
This topic is now closed to further replies.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.