Code:
.text:00000001404A7670 movsxd rax, ecx ; Move the index number into RAX
.text:00000001404A7673 lea rcx, stringTableLookup ; Load RCX with the base address of the string table array earlier mentioned
.text:00000001404A767A mov rax, [rcx+rax*8] ; Access the pointer of the ID. ( Size of a pointer on x64 processes = 8 bytes )
.text:00000001404A767E retn ; Return the address
Yay. Hopefully you understood the above ( Not my problem if you're stupid. )
Code:
void DumpFile(){
char** baseStringTable = (char**)0x14099CA00; // The base table used in the function above.
for( signed int i=0; i<3205; i++ ){
DumpToFile( "StringDump.txt", "idx: [ %x ] str: [ %s ]", i, baseStringTable[ i ] );
}
}
Now that we have these IDs, we can do simple binary strings to find where each string is referenced in your file dump.
Code:
.text:00000001403B4C88 mov ecx, 0A2Dh ; com_maxFps IDX
.text:00000001403B4C8D mov cs:off_1472458E8, rax ; This is from the previous call to RegisterDvar()
.text:00000001403B4C94 call LookupString ; Calls our lookup string function to retrieve the com_maxFPS string
.text:00000001403B4C99 lea r9d, [rdi+64h] ; Below here are parameters used for calling RegisterDvar. Ignore these
.text:00000001403B4C9D lea edx, [rdi+55h]
.text:00000001403B4CA0 xor r8d, r8d
.text:00000001403B4CA3 mov rcx, rax
.text:00000001403B4CA6 mov [rsp+38h+var_18], edi
.text:00000001403B4CAA call sub_1404A3950 ; This is our register dvar function ( Reverse this for more fun )
.text:00000001403B4CAF mov ecx, 0A2Eh ; This is some other dvar
.text:00000001403B4CB4 mov cs:off_1472452F8, rax ; This is what we want. RAX contains our pointer for our dvar registered ( Aka com_maxFPS )
So now we have our dvar pointer which will NOT change.