Alright folks. Time to post some information and how I got to it.
The game seems to be using
[Link]. For example, I went to Coach Fred to buy some stuff. Scanned for my current $ and found an address. Set a breakpoint to see what writes to it and found this piece of code almost everyone else has tripped over by now:
Code: Select all
Cyberpunk2077.exe+17CFE60 - 48 89 5C 24 08 - mov [rsp+08],rbx
Cyberpunk2077.exe+17CFE65 - 57 - push rdi
Cyberpunk2077.exe+17CFE66 - 48 83 EC 20 - sub rsp,20
Cyberpunk2077.exe+17CFE6A - 48 8B 01 - mov rax,[rcx]
Cyberpunk2077.exe+17CFE6D - 8B DA - mov ebx,edx
Cyberpunk2077.exe+17CFE6F - BA 99020000 - mov edx,00000299
Cyberpunk2077.exe+17CFE74 - 48 8B F9 - mov rdi,rcx
Cyberpunk2077.exe+17CFE77 - FF 90 68010000 - call qword ptr [rax+00000168]
Cyberpunk2077.exe+17CFE7D - 8B 4F 78 - mov ecx,[rdi+78]
Cyberpunk2077.exe+17CFE80 - BA 01000000 - mov edx,00000001
Cyberpunk2077.exe+17CFE85 - F3 48 0F2C C0 - cvttss2si rax,xmm0
Cyberpunk2077.exe+17CFE8A - 3B C2 - cmp eax,edx
Cyberpunk2077.exe+17CFE8C - 0F43 D0 - cmovae edx,eax
Cyberpunk2077.exe+17CFE8F - 33 C0 - xor eax,eax
Cyberpunk2077.exe+17CFE91 - 03 CB - add ecx,ebx
Cyberpunk2077.exe+17CFE93 - 48 8B 5C 24 30 - mov rbx,[rsp+30]
Cyberpunk2077.exe+17CFE98 - 0F49 C1 - cmovns eax,ecx
Cyberpunk2077.exe+17CFE9B - 3B C2 - cmp eax,edx
Cyberpunk2077.exe+17CFE9D - 0F4E D0 - cmovle edx,eax
Cyberpunk2077.exe+17CFEA0 - 89 57 78 - mov [rdi+78],edx << write
Cyberpunk2077.exe+17CFEA3 - 48 83 C4 20 - add rsp,20
Cyberpunk2077.exe+17CFEA7 - 5F - pop rdi
Cyberpunk2077.exe+17CFEA8 - C3 - ret
Upon checking my RDI pointer (000001FEC20AE8A0) in x64dbg, I found the following stuff:
Then looked at the list of functions:
All those you see with "?Reserve@WriteBytesCount@AK@@UEAA_NJ@Z" are RET 0 functions, meaning functions that do nothing.
And picked the first one, which shows this:
* * *
I then looked at that pointer and found it's leading to a RTTI structure:
How do I know this? By inspecting the member-functions in this block:
Function at offset 0x28 tells you which type of RTTI you're looking at. It's using the value read through function at 0x20, which, in this case is:
So 0x2 used in this
case leads to:
So we're looking at a
Class. There are other RTTI-related member-functions in this table which might give more insight:
0x0008:
Code: Select all
00007FF760F03D30 | 48:8B41 18 | MOV RAX,QWORD PTR DS:[RCX+18] |
00007FF760F03D34 | 48:8902 | MOV QWORD PTR DS:[RDX],RAX |
00007FF760F03D37 | 48:8BC2 | MOV RAX,RDX |
00007FF760F03D3A | C3 | RET |
In my case:
0x0030:
Code: Select all
00007FF760F03FF0 | 48:8B41 20 | MOV RAX,QWORD PTR DS:[RCX+20] |
00007FF760F03FF4 | 48:8902 | MOV QWORD PTR DS:[RDX],RAX |
00007FF760F03FF7 | 48:8BC2 | MOV RAX,RDX |
00007FF760F03FFA | C3 | RET |
In my case:
* * *
Back to our $ structure, I looked at the other member-functions to see what I can pick-up. Found at 0x120 some piece of code that checks up a hash value and if not valid, it computes it, from what I could gather:
Code: Select all
00007FF7624BF7B2 | 48:83EC 20 | SUB RSP,20 |
00007FF7624BF7B6 | 803D 77B0BF02 00 | CMP BYTE PTR DS:[7FF7650BA834],0 |
00007FF7624BF7BD | 48:8BFA | MOV RDI,RDX |
00007FF7624BF7C0 | 4C:8BF1 | MOV R14,RCX |
00007FF7624BF7C3 | 48:BB 0659A2AC5B18169B | MOV RBX,9B16185BACA25906 |
00007FF7624BF7CD | 75 16 | JNE cyberpunk2077.7FF7624BF7E5 |
00007FF7624BF7CF | 48:8D15 3A49A701 | LEA RDX,QWORD PTR DS:[7FF763F34110] | 00007FF763F34110:"itemData"
00007FF7624BF7D6 | 48:8BCB | MOV RCX,RBX |
00007FF7624BF7D9 | E8 42D89EFE | CALL <cyberpunk2077.hashMe> |
00007FF7624BF7DE | C605 4FB0BF02 01 | MOV BYTE PTR DS:[7FF7650BA834],1 |
00007FF7624BF7E5 | 48:8B07 | MOV RAX,QWORD PTR DS:[RDI] |
Called it "hashMe"
There are over 65k references to that function. In short, if BYTE in that pointer is != 0, then hashMe( "itemData" ). But I think it's more of a "give me Class hash and RTTI name and I'll find it for you" function. Rather than some hashing mechanism.
Then the function at
0x0140 in this vftable is the WRITE one we started from. 0x0138 is another type of write, I think for float type (while 0x0140 is for integer, or vice-versa):
And 0x0140 is the READ function:
Code: Select all
00007FF7624B1BB0 | 8B41 78 | MOV EAX,DWORD PTR DS:[RCX+78] |
00007FF7624B1BB3 | C3 | RET |