Mafia: Definitive Edition
Mafia: Definitive Edition
Game Name: Mafia: Definitive Edition
Game Vendor: Steam
Game Version: 1.0
Game Process: mafiadefinitiveedition.exe
Game File Version: 1.0.0.1
Hello folks. Yet another new game with a different engine. Don't know if there's a name for it, but noticed it kinda resembles Ubisoft's Anvil a bit, given the internal data structure and member-functions. Couldn't find any RTTI methods in use, though there is a GetClassName function available in the vftable
I'm going to fill this puppy as I progress.
Game Vendor: Steam
Game Version: 1.0
Game Process: mafiadefinitiveedition.exe
Game File Version: 1.0.0.1
Hello folks. Yet another new game with a different engine. Don't know if there's a name for it, but noticed it kinda resembles Ubisoft's Anvil a bit, given the internal data structure and member-functions. Couldn't find any RTTI methods in use, though there is a GetClassName function available in the vftable
I'm going to fill this puppy as I progress.
- sebastianyyz
- Expert Cheater
- Posts: 332
- Joined: Sun Jul 09, 2017 3:33 am
- Reputation: 59
Re: Mafia: Definitive Edition
Great, another great table incoming. Thank you
Re: Mafia: Definitive Edition
Alright.
l0wb1t contacted me regarding his No Reload script, then I realized he's already posted a table. So instead of the usual me wasting time through the Engine, finding this and that, I decided to start from his table. Mainly this part:
The goal here is to find out where the various hunted-for structures are and what they are called (if there are any leads in the structures or member-functions regarding naming). I'm doing this cuz most of the names you see in game-hackers' tables come from the interpretation of what you're getting from debugging or structure content, but almost never named with the original, developer-given, intended names.
Setting a breakpoint at that address, in my current game session, shows this:
So not much to lead with, as RBX isn't really some structure pointer, but something adjusted to then read that (float)100.0 value from 0xC offset. But if I set a breakpoint at the function's prologue (maybe you learn some new words today, eh?) and check RCX, I might find a lead:
I saw a pointer there, at [RCX] basically. And I decided to investigate it. Entered its memory and saw this:
Looks like the kind of structure I'm looking for, whereas the indicated spot is the pointer to the member-functions table (also called 'vftable' - virtual functions table). So.. just like in the other topic about Marvel's Avengers I decided to check out these member-functions. Browsed 0000000144E83638's memory and saw this:
So at 0x10 we see a function that might lead to a Name, similar to what I saw in Anvil games (Assassin's Creed series), Decima (Horizon Zero Dawn), etc. Let's see if I'm right. Browsing that address in hex dump shows this:
So.. we're looking at C_Player2 And [[C_Player2]+0x10] == GetName.
Cool.. now I wanted to figure out if there's a direct pointer, static one, leading to that structure (C_Player2), whose address is 00000000E3010D30:
Then I debugged the 2 static addresses when doing LOAD LAST CHECKPOINT. And found that the pointer is written to these spots:
As well as here:
So.. pick the one you want, both work
-> "mafiadefinitiveedition.exe+63DA8F0" + 0x28 == mafiadefinitiveedition.exe+63DA918 -> [mafiadefinitiveedition.exe+63DA918] == 00000000E3010D30 (C_Player2)
-> "mafiadefinitiveedition.exe+63A3110" + 0xAB0 == mafiadefinitiveedition.exe+63A3BC0 -> [mafiadefinitiveedition.exe+63A3BC0] ==
00000000E3010D30 (C_Player2)
We've now got a way to get directly to the Player structure. Let's see now how to get from here to the Player's Health. Let's check that prologue again:
The address in RBX is read from [R9]. Now.. where's that R9 taken from is what we wanna find out..
BR,
Sun
l0wb1t contacted me regarding his No Reload script, then I realized he's already posted a table. So instead of the usual me wasting time through the Engine, finding this and that, I decided to start from his table. Mainly this part:
Code: Select all
aobscanmodule(_InfiniteHealth,mafiadefinitiveedition.exe,F3 0F 10 4B 0C 0F 28 E6)
Setting a breakpoint at that address, in my current game session, shows this:
So not much to lead with, as RBX isn't really some structure pointer, but something adjusted to then read that (float)100.0 value from 0xC offset. But if I set a breakpoint at the function's prologue (maybe you learn some new words today, eh?) and check RCX, I might find a lead:
I saw a pointer there, at [RCX] basically. And I decided to investigate it. Entered its memory and saw this:
Looks like the kind of structure I'm looking for, whereas the indicated spot is the pointer to the member-functions table (also called 'vftable' - virtual functions table). So.. just like in the other topic about Marvel's Avengers I decided to check out these member-functions. Browsed 0000000144E83638's memory and saw this:
So at 0x10 we see a function that might lead to a Name, similar to what I saw in Anvil games (Assassin's Creed series), Decima (Horizon Zero Dawn), etc. Let's see if I'm right. Browsing that address in hex dump shows this:
So.. we're looking at C_Player2 And [[C_Player2]+0x10] == GetName.
Cool.. now I wanted to figure out if there's a direct pointer, static one, leading to that structure (C_Player2), whose address is 00000000E3010D30:
Then I debugged the 2 static addresses when doing LOAD LAST CHECKPOINT. And found that the pointer is written to these spots:
Code: Select all
0000000142C07F43 | 48:8D0D A6297D03 | LEA RCX,QWORD PTR DS:[1463DA8F0] | rcx <- 00000001463DA8F0
0000000142C07F4A | E8 81462F00 | CALL mafiadefinitiveedition.142EFC5D0 |
-->
0000000142EFC5D0 | E9 3BEE7421 | JMP mafiadefinitiveedition.16464B410 |
<--
000000016464B410 | 48:8951 28 | MOV QWORD PTR DS:[RCX+28],RDX | rdx == 00000000E3010D30
000000016464B414 | C3 | RET |
Code: Select all
0000000142C07F56 | 48:8D0D B3B17903 | LEA RCX,QWORD PTR DS:[1463A3110] | rcx <- 00000001463A3110
0000000142C07F5D | 48:8BD7 | MOV RDX,RDI |
0000000142C07F60 | E8 9B74F0FF | CALL mafiadefinitiveedition.142B0F400 |
-->
0000000142B0F455 | 48:89BE B00A0000 | MOV QWORD PTR DS:[RSI+AB0],RDI | rdi == 00000000E3010D30
..
-> "mafiadefinitiveedition.exe+63DA8F0" + 0x28 == mafiadefinitiveedition.exe+63DA918 -> [mafiadefinitiveedition.exe+63DA918] == 00000000E3010D30 (C_Player2)
-> "mafiadefinitiveedition.exe+63A3110" + 0xAB0 == mafiadefinitiveedition.exe+63A3BC0 -> [mafiadefinitiveedition.exe+63A3BC0] ==
00000000E3010D30 (C_Player2)
We've now got a way to get directly to the Player structure. Let's see now how to get from here to the Player's Health. Let's check that prologue again:
The address in RBX is read from [R9]. Now.. where's that R9 taken from is what we wanna find out..
BR,
Sun
Re: Mafia: Definitive Edition
Then let's focus on the member-functions of C_Player2 Set a hardware breakpoint on the pointer to the vftable and see which functions are accessed, as well as try to interpret what's going on. I got these:
The first 5 are accessed when out to Desktop. The moment you go back in, this happens:
I checked the first one: 140985613.
This leads to this piece of code:
And from testing, I can tell you that's the C_Player2's position on the mini-map. If you freeze the 3 floats (or the array altogether), you will see the mini-map flickering, trying to move you back to the frozen position
I then looked at the member-function at offset 0x60:
The CALL leads to this:
I was then curious to know what's being read here So [14635E9B8] == 000000004428C020; then [000000004428C020+8] == 0000000044290010. And then I checked that one in dump and saw this:
Aside from the string references, there's a member-functions pointer there. Ding-ding-ding-ding! So I checked it out, the function at 0x10 offset:
Ta-daaa So.. [mafiadefinitiveedition.exe+635E9B8]+0x8 == C_Game.
Code: Select all
140985613 - 4C 8B 00 - mov r8,[rax]
142E422E5 - 48 8B 00 - mov rax,[rax]
1421DE00D - 4C 8B 00 - mov r8,[rax]
1421DE029 - 4C 8B 03 - mov r8,[rbx]
142DA8D97 - 48 8B 01 - mov rax,[rcx]
142437FB5 - 49 8B 06 - mov rax,[r14]
Code: Select all
142A95FA3 - 4C 8B 00 - mov r8,[rax]
142A016C9 - 48 8B 06 - mov rax,[rsi]
142A01B24 - 48 8B 06 - mov rax,[rsi]
142A028A2 - 49 8B 06 - mov rax,[r14]
142A028D2 - 49 8B 06 - mov rax,[r14]
142A028E4 - 49 8B 06 - mov rax,[r14]
142A02966 - 49 8B 06 - mov rax,[r14]
142A0298B - 49 8B 06 - mov rax,[r14]
142A02A99 - 49 8B 06 - mov rax,[r14]
142A02B01 - 49 8B 06 - mov rax,[r14]
142E44EB5 - 4C 8B 00 - mov r8,[rax]
142D49373 - 48 8B 01 - mov rax,[rcx]
142C0CD83 - 48 8B 01 - mov rax,[rcx]
142C15679 - 4C 8B 00 - mov r8,[rax]
142C156BF - 48 8B 06 - mov rax,[rsi]
14170E9E0 - 48 8B 01 - mov rax,[rcx]
142B01035 - 48 8B 16 - mov rdx,[rsi]
142B01056 - 48 8B 06 - mov rax,[rsi]
142B0106A - 48 8B 06 - mov rax,[rsi]
142C149D3 - 48 8B 07 - mov rax,[rdi]
142C56A3A - 48 8B 01 - mov rax,[rcx]
142CC28D2 - 48 8B 01 - mov rax,[rcx]
142CBD7E5 - 48 8B 01 - mov rax,[rcx]
142CBD8A1 - 48 8B 01 - mov rax,[rcx]
142C85C6B - 48 8B 01 - mov rax,[rcx]
142D20704 - 48 8B 07 - mov rax,[rdi]
142D0525D - 48 8B 01 - mov rax,[rcx]
142C57C86 - 48 8B 01 - mov rax,[rcx]
142C8EE8D - 48 8B 01 - mov rax,[rcx]
142CD0A22 - 48 8B 01 - mov rax,[rcx]
142C4195C - 48 8B 11 - mov rdx,[rcx]
142BD4141 - 48 8B 11 - mov rdx,[rcx]
142BC1661 - 48 8B 01 - mov rax,[rcx]
142BD2F81 - 48 8B 01 - mov rax,[rcx]
142BD2F9E - 48 8B 01 - mov rax,[rcx]
142D490A5 - 48 8B 07 - mov rax,[rdi]
142D0039A - 48 8B 10 - mov rdx,[rax]
142D003B8 - 49 8B 16 - mov rdx,[r14]
142D0DC6B - 48 8B 01 - mov rax,[rcx]
1426B84C5 - 4C 8B 00 - mov r8,[rax]
142EEE9C2 - 4C 8B 00 - mov r8,[rax]
141BEF66A - 48 8B 00 - mov rax,[rax]
142DE71C1 - 4C 8B 00 - mov r8,[rax]
14256CA02 - 48 8B 00 - mov rax,[rax]
142D44B20 - 49 8B 06 - mov rax,[r14]
142CCE02C - 48 8B 01 - mov rax,[rcx]
1417108A0 - 48 8B 01 - mov rax,[rcx]
142D1FED5 - 48 8B 03 - mov rax,[rbx]
142B80C8D - 48 8B 07 - mov rax,[rdi]
1428D68A6 - 48 8B 03 - mov rax,[rbx]
142BD4FDB - 48 8B 01 - mov rax,[rcx]
142D08018 - 48 8B 01 - mov rax,[rcx]
142D08255 - 48 8B 03 - mov rax,[rbx]
142D082B3 - 4C 8B 03 - mov r8,[rbx]
142B806C2 - 48 8B 01 - mov rax,[rcx]
142ADF3CA - 48 8B 01 - mov rax,[rcx]
142AE4C06 - 48 8B 10 - mov rdx,[rax]
142B04015 - 4C 8B 10 - mov r10,[rax]
142B0402F - 48 8B 17 - mov rdx,[rdi]
142B0404D - 48 8B 07 - mov rax,[rdi]
142ADE0A5 - 48 8B 01 - mov rax,[rcx]
142AF6AD5 - 48 8B 01 - mov rax,[rcx]
142AEAF6B - 48 8B 10 - mov rdx,[rax]
142AFD008 - 48 8B 02 - mov rax,[rdx]
1425EF1CD - 4C 8B 00 - mov r8,[rax]
1425EE626 - 48 8B 03 - mov rax,[rbx]
14227BC73 - 4C 8B 00 - mov r8,[rax]
1422856FF - 4C 8B 00 - mov r8,[rax]
142AF5702 - 4C 8B 00 - mov r8,[rax]
142AEFA3F - 48 8B 10 - mov rdx,[rax]
142AEFABF - 48 8B 10 - mov rdx,[rax]
142AEFB3F - 48 8B 10 - mov rdx,[rax]
142D44FB1 - 48 8B 10 - mov rdx,[rax]
14255F23B - 4C 8B 06 - mov r8,[rsi]
1425F4D71 - 48 8B 06 - mov rax,[rsi]
1425F508F - 49 8B 45 00 - mov rax,[r13+00]
14261DC73 - 4C 8B 01 - mov r8,[rcx]
142D588D9 - 48 8B 10 - mov rdx,[rax]
142D5872B - 48 8B 00 - mov rax,[rax]
142438B71 - 48 8B 07 - mov rax,[rdi]
142438D4B - 4C 8B 06 - mov r8,[rsi]
142438D7E - 48 8B 06 - mov rax,[rsi]
1424388EB - 48 8B 07 - mov rax,[rdi]
142438CBD - 48 8B 00 - mov rax,[rax]
142436ACC - 49 8B 07 - mov rax,[r15]
142D22D05 - 48 8B 06 - mov rax,[rsi]
142A0189D - 48 8B 06 - mov rax,[rsi]
142A98517 - 48 8B 10 - mov rdx,[rax]
142A9852A - 4C 8B 03 - mov r8,[rbx]
142A98540 - 4C 8B 03 - mov r8,[rbx]
142A96F4A - 49 8B 04 24 - mov rax,[r12]
142B7AE2E - 4C 8B 00 - mov r8,[rax]
142CBA3E0 - 48 8B 01 - mov rax,[rcx]
142266E27 - 4C 8B 00 - mov r8,[rax]
142D866FC - 49 8B 00 - mov rax,[r8]
142DE44EB - 4C 8B 08 - mov r9,[rax]
142371B47 - 4C 8B 00 - mov r8,[rax]
142A01901 - 48 8B 06 - mov rax,[rsi]
Code: Select all
mafiadefinitiveedition.exe+985610 - 48 8B C8 - mov rcx,rax
mafiadefinitiveedition.exe+985613 - 4C 8B 00 - mov r8,[rax]
mafiadefinitiveedition.exe+985616 - 41 FF 90 20010000 - call qword ptr [r8+00000120]
Code: Select all
mafiadefinitiveedition.exe+2B4A450 - 48 8B 81 48030000 - mov rax,[rcx+00000348]
mafiadefinitiveedition.exe+2B4A457 - 48 8B 88 98020000 - mov rcx,[rax+00000298]
mafiadefinitiveedition.exe+2B4A45E - 8B 41 08 - mov eax,[rcx+08]
mafiadefinitiveedition.exe+2B4A461 - F2 0F10 01 - movsd xmm0,[rcx]
mafiadefinitiveedition.exe+2B4A465 - F2 0F11 02 - movsd [rdx],xmm0
mafiadefinitiveedition.exe+2B4A469 - 89 42 08 - mov [rdx+08],eax
mafiadefinitiveedition.exe+2B4A46C - 48 8B C2 - mov rax,rdx
mafiadefinitiveedition.exe+2B4A46F - C3 - ret
I then looked at the member-function at offset 0x60:
The CALL leads to this:
Code: Select all
000000014170E789 | E8 22A7C200 | CALL mafiadefinitiveedition.142338EB0 |
-->
0000000142338EB0 | 48:8B05 015B0204 | MOV RAX,QWORD PTR DS:[14635E9B8] |
0000000142338EB7 | 48:8B40 08 | MOV RAX,QWORD PTR DS:[RAX+8] |
0000000142338EBB | C3 | RET |
<--
Aside from the string references, there's a member-functions pointer there. Ding-ding-ding-ding! So I checked it out, the function at 0x10 offset:
Ta-daaa So.. [mafiadefinitiveedition.exe+635E9B8]+0x8 == C_Game.
Re: Mafia: Definitive Edition
So instead of using the hardcoded static adress we could use it like that based on what you was showing. May saves time after update
Code: Select all
[ENABLE]
aobscanmodule(C_Player,mafiadefinitiveedition.exe,49 8B 75 28 48 3B 1F) // should be unique
alloc(newmem,$1000,"mafiadefinitiveedition.exe"+2F1C3E4)
alloc(pC_Player,8)
newmem:
push rdx
push r11
lea rdx,[r13+28]
mov r11,[RDX]
mov [pC_Player],r11
code:
pop r11
pop rdx
mov rsi,[r13+28]
cmp rbx,[rdi]
jmp return
C_Player:
jmp newmem
nop
nop
return:
registersymbol(C_Player,pC_Player)
[DISABLE]
C_Player:
db 49 8B 75 28 48 3B 1F
unregistersymbol(C_Player,pC_Player)
dealloc(pC_Player)
dealloc(newmem)
Re: Mafia: Definitive Edition
Code: Select all
[ENABLE]
aobscanmodule( aob, mafiadefinitiveedition.exe, 488D0D????????E8????????83A7????????FD48 )
label( C_Player2 )
registersymbol( C_Player2 )
//aob+(DWORD)[aob+3]+7+28:
C_Player2:
[DISABLE]
unregistersymbol( C_Player2 )
Code: Select all
-> "mafiadefinitiveedition.exe+63DA8F0" + 0x28 == mafiadefinitiveedition.exe+63DA918 -> [mafiadefinitiveedition.exe+63DA918] == 00000000E3010D30 (C_Player2)
P.S.: Thanks Zanzer for the assist; forgot that CE can automatically do calculus for you directly
Re: Mafia: Definitive Edition
Hacker hacks
Re: Mafia: Definitive Edition
If you want to get C_Player2 from C_Game, you can do so this way
Ta-daaa -> [[mafiadefinitiveedition.exe+635E9B8]+0x8]+0x98 == C_Player2. You can name the 0x90 member-function Game::GetPlayer
Code: Select all
0000000142BFABCD | E8 DEE273FF | CALL mafiadefinitiveedition.142338EB0 |
-->
0000000142338EB0 | 48:8B05 015B0204 | MOV RAX,QWORD PTR DS:[14635E9B8] |
0000000142338EB7 | 48:8B40 08 | MOV RAX,QWORD PTR DS:[RAX+8] | rax <- C_Game
0000000142338EBB | C3 | RET |
<--
0000000142BFABD2 | 48:8BC8 | MOV RCX,RAX |
0000000142BFABD5 | 48:8B10 | MOV RDX,QWORD PTR DS:[RAX] |
0000000142BFABD8 | FF92 90000000 | CALL QWORD PTR DS:[RDX+90] | vftable
-->
0000000142331F60 | 48:8B81 98000000 | MOV RAX,QWORD PTR DS:[RCX+98] | rax <- C_Player2
0000000142331F67 | C3 | RET |
<--
Ta-daaa -> [[mafiadefinitiveedition.exe+635E9B8]+0x8]+0x98 == C_Player2. You can name the 0x90 member-function Game::GetPlayer
Re: Mafia: Definitive Edition
SunBeam wrote: ↑Wed Sep 30, 2020 7:40 pmAdd the above script to your table. Then open the script, uncomment "//aob+(DWORD)[aob+3]+7+28:" line and click OK. Ignore the warning. Then enable the script and add to your list C_Player2 as a pointer You won't need then a hook to get the Player In your code, you can use something like this: "cmp rax,[C_Player2]" (if rax is a Player you check for).
I'm going to check that
Re: Mafia: Definitive Edition
..and if you check the member-function at 0xD8 in C_Game, you will see this:
Once a map loads up, setting the BYTE at that offset in C_Game to 1 will RELOAD LAST CHECKPOINT Fun!
[C_Game+0x7B519] -> 0x1 = reload last checkpoint automatically
Code: Select all
000000014234F560 | 0FB681 19B50700 | MOVZX EAX,BYTE PTR DS:[RCX+7B519] |
000000014234F567 | C3 | RET |
[C_Game+0x7B519] -> 0x1 = reload last checkpoint automatically
Re: Mafia: Definitive Edition
Then searching for the # of bullets in memory, as a DWORD, leads to this spot where bullets are being written as you fire:
Looking at RCX and its member-functions shows that this is called C_WeaponItem (in my case, 0000004E6CB50BF0).
That "jmp [rax+18]" leads to here:
I'm assuming this is the "is firing" piece of code, a status BYTE. Cuz that write happens just as you fired. Or maybe it's "barrel's empty, do some lag till next shot is fired". Hence the delay between shots. I wonder what happens if you NOP it so it stays 0. Will you get fast fire?
EDIT: Nah, just a status BOOL.
So how do we get from C_WeaponItem to C_Player2? Is there any intermediate pointer in-between the relationship or not? Like a C_Inventory, perhaps? Cuz that's the usual logic: Player -> Inventory -> Weapons -> Bullets.
I did a bit of back-tracing and found this out:
Then back-tracing one more step out of this function, I saw that..
So the logic goes like this:
[C_Player2 + 0x128] = C_InventoryWrapper
[C_InventoryWrapper + 0x58 ] = id of the selected item (in this case, for Pistol, the value is 0x21)
With this id and RCX set to C_InventoryWrapper, we go into the CALL @ 1425CC1B0. Where this happens:
The above is a look-up function that returns the pointer to the Inventory-related item based on its ID. Not any ID, but the ID that's stored @ [C_InventoryWrapper+0x58].. which is the ID of the active/current item/weapon. How do I know this? Well.. if you holster the weapon, 0x21 becomes 0x01. Watch:
Then at [C_WeaponItem + 0x8] you have another pointer: C_ItemDataWeapon. This holds these:
What's interesting about the picture above is you can clearly see the Property offsets. Not sure if you've noticed.. but.. when I fired the weapon, this is the spot that writes to clip:
Offset is 0x18. Now.. back to the picture above:
Pimp, eh? So:
- m_Ammo is at C_ItemDataWeapon + 0x18
- m_AmmoAUX is at C_ItemDataWeapon + 0x1C
- m_Upgrades is at C_ItemDataWeapon + 0x20
Furthermore, the address that's below the string points to the data type Watch this:
So.. m_Ammo is a property that's located at 0x18 in C_ItemDataWeapon. Its data type is "u32" which is a 0x4 (DWORD).
If we check m_Upgrades' data type memory block, we see this:
So.. offset 0x20 in C_ItemDataWeapon should contain a POINTER to a table of upgrades. That's what the vector translates to. Let's check:
Nada, no upgrades
Found out that [C_InventoryWrapper+0x5C] holds the id of the previously selected/active item/weapon In my case, 0x1, as in the Holster "item"
Recap:
[C_Player2 + 0x128] = C_InventoryWrapper
[C_InventoryWrapper + 0x58 ] = id of the selected item (in this case, for Pistol, the value is 0x21)
--> C_WeaponItem
[C_WeaponItem + 0x8 ] = C_ItemDataWeapon
[C_ItemDataWeapon + 0x18] = m_Ammo
[C_ItemDataWeapon + 0x1C] = m_AmmoAUX
[C_ItemDataWeapon + 0x20] = m_Upgrades
Code: Select all
00000001425EBB30 | 48:8B41 08 | MOV RAX,QWORD PTR DS:[RCX+8] |
00000001425EBB34 | 45:33C0 | XOR R8D,R8D |
00000001425EBB37 | 85D2 | TEST EDX,EDX |
00000001425EBB39 | 44:0F4FC2 | CMOVG R8D,EDX |
00000001425EBB3D | 44:8940 18 | MOV DWORD PTR DS:[RAX+18],R8D | <--
00000001425EBB41 | 48:8B01 | MOV RAX,QWORD PTR DS:[RCX] |
00000001425EBB44 | 48:FF60 18 | JMP QWORD PTR DS:[RAX+18] |
That "jmp [rax+18]" leads to here:
Code: Select all
mafiadefinitiveedition.exe+25EB990 - C6 41 11 01 - mov byte ptr [rcx+11],01
mafiadefinitiveedition.exe+25EB994 - C3 - ret
EDIT: Nah, just a status BOOL.
So how do we get from C_WeaponItem to C_Player2? Is there any intermediate pointer in-between the relationship or not? Like a C_Inventory, perhaps? Cuz that's the usual logic: Player -> Inventory -> Weapons -> Bullets.
I did a bit of back-tracing and found this out:
Code: Select all
0000000142B185A0 | 40:57 | PUSH RDI |
0000000142B185A2 | 41:56 | PUSH R14 |
0000000142B185A4 | 41:57 | PUSH R15 |
0000000142B185A6 | 48:83EC 50 | SUB RSP,50 |
0000000142B185AA | 8B51 58 | MOV EDX,DWORD PTR DS:[RCX+58] | 0000004E6D71A420 == C_InventoryWrapper
0000000142B185AD | 48:8BF9 | MOV RDI,RCX |
0000000142B185B0 | E8 FB3BABFF | CALL mafiadefinitiveedition.1425CC1B0 |
0000000142B185B5 | 8B57 5C | MOV EDX,DWORD PTR DS:[RDI+5C] | RAX == 0000004E6CB50BF0 == C_WeaponItem
Code: Select all
0000000142BB40E3 | 48:8B89 28010000 | MOV RCX,QWORD PTR DS:[RCX+128] | rcx == 00000000E3010D30 == C_Player2
0000000142BB40EA | E8 B144F6FF | CALL mafiadefinitiveedition.142B185A0 |
[C_Player2 + 0x128] = C_InventoryWrapper
[C_InventoryWrapper + 0x58 ] = id of the selected item (in this case, for Pistol, the value is 0x21)
With this id and RCX set to C_InventoryWrapper, we go into the CALL @ 1425CC1B0. Where this happens:
Code: Select all
00000001425CC1B0 | 48:8B41 40 | MOV RAX,QWORD PTR DS:[RCX+40] |start
00000001425CC1B4 | 4C:8B49 48 | MOV R9,QWORD PTR DS:[RCX+48] |end
00000001425CC1B8 | 49:3BC1 | CMP RAX,R9 |if start == end
00000001425CC1BB | 74 19 | JE mafiadefinitiveedition.1425CC1D6 |exit
00000001425CC1BD | 0F1F00 | NOP DWORD PTR DS:[RAX],EAX |else
00000001425CC1C0 | 48:8B08 | MOV RCX,QWORD PTR DS:[RAX] |read_placeholder
00000001425CC1C3 | 4C:8B41 08 | MOV R8,QWORD PTR DS:[RCX+8] |read_item
00000001425CC1C7 | 41:3950 0C | CMP DWORD PTR DS:[R8+C],EDX |check id (stored at item+0xC)
00000001425CC1CB | 74 0C | JE mafiadefinitiveedition.1425CC1D9 |if equal, we found it
00000001425CC1CD | 48:83C0 08 | ADD RAX,8 |else, move to next placeholder
00000001425CC1D1 | 49:3BC1 | CMP RAX,R9 |did we finish the table?
00000001425CC1D4 | 75 EA | JNE mafiadefinitiveedition.1425CC1C0 |if not, return to read_loop
00000001425CC1D6 | 33C0 | XOR EAX,EAX |if not found, 0
00000001425CC1D8 | C3 | RET |exit
00000001425CC1D9 | 48:8BC1 | MOV RAX,RCX |move found ptr to RAX
00000001425CC1DC | C3 | RET |exit
Then at [C_WeaponItem + 0x8] you have another pointer: C_ItemDataWeapon. This holds these:
What's interesting about the picture above is you can clearly see the Property offsets. Not sure if you've noticed.. but.. when I fired the weapon, this is the spot that writes to clip:
Code: Select all
00000001425EBB3D | 44:8940 18 | MOV DWORD PTR DS:[RAX+18],R8D | <--
Pimp, eh? So:
- m_Ammo is at C_ItemDataWeapon + 0x18
- m_AmmoAUX is at C_ItemDataWeapon + 0x1C
- m_Upgrades is at C_ItemDataWeapon + 0x20
Furthermore, the address that's below the string points to the data type Watch this:
So.. m_Ammo is a property that's located at 0x18 in C_ItemDataWeapon. Its data type is "u32" which is a 0x4 (DWORD).
If we check m_Upgrades' data type memory block, we see this:
So.. offset 0x20 in C_ItemDataWeapon should contain a POINTER to a table of upgrades. That's what the vector translates to. Let's check:
Nada, no upgrades
Found out that [C_InventoryWrapper+0x5C] holds the id of the previously selected/active item/weapon In my case, 0x1, as in the Holster "item"
Recap:
[C_Player2 + 0x128] = C_InventoryWrapper
[C_InventoryWrapper + 0x58 ] = id of the selected item (in this case, for Pistol, the value is 0x21)
--> C_WeaponItem
[C_WeaponItem + 0x8 ] = C_ItemDataWeapon
[C_ItemDataWeapon + 0x18] = m_Ammo
[C_ItemDataWeapon + 0x1C] = m_AmmoAUX
[C_ItemDataWeapon + 0x20] = m_Upgrades
Re: Mafia: Definitive Edition
I think clip ammo can be stopped from decreating if the TEST in this code checks out and the JE below it doesn't jump:
Yup, it works
Infinite Clip / No Reload:
Code: Select all
0000000142C9D350 | 40:53 | PUSH RBX | rcx == 0000003409DF0420 (??)
0000000142C9D352 | 57 | PUSH RDI |
0000000142C9D353 | 41:54 | PUSH R12 |
0000000142C9D355 | 41:56 | PUSH R14 |
0000000142C9D357 | 41:57 | PUSH R15 |
0000000142C9D359 | 48:83EC 50 | SUB RSP,50 |
0000000142C9D35D | 48:8B41 28 | MOV RAX,QWORD PTR DS:[RCX+28] | == 00000000E3010D30 (C_Player2)
0000000142C9D361 | 4C:8BF1 | MOV R14,RCX | r14 <- 0000003409DF0420
0000000142C9D364 | 0F297424 40 | MOVAPS XMMWORD PTR SS:[RSP+40],XMM6 |
0000000142C9D369 | 0F28F1 | MOVAPS XMM6,XMM1 |
0000000142C9D36C | 48:8B88 38010000 | MOV RCX,QWORD PTR DS:[RAX+138] | == 0000004E6D71A678
0000000142C9D373 | 48:8B89 C0000000 | MOV RCX,QWORD PTR DS:[RCX+C0] | == 000000336F243AA0
..
0000000142C9D37F | 49:8B46 28 | MOV RAX,QWORD PTR DS:[R14+28] | == 00000000E3010D30 (C_Player2)
..
0000000142C9D386 | 4C:8BB8 48010000 | MOV R15,QWORD PTR DS:[RAX+148] | == 0000004E6D71A7D8
0000000142C9D38D | 49:8B46 50 | MOV RAX,QWORD PTR DS:[R14+50] | 0
..
0000000142C9D418 | 49:8B46 28 | MOV RAX,QWORD PTR DS:[R14+28] | == 00000000E3010D30 (C_Player2)
0000000142C9D41C | 49:8BCF | MOV RCX,R15 |
0000000142C9D41F | 8078 18 09 | CMP BYTE PTR DS:[RAX+18],9 | [00000000E3010D30+18] == 9
..
0000000142BB2A00 | 48:8BC4 | MOV RAX,RSP | rcx == 0000004E6D71A7D8
..
0000000142BB40AD | 41:80BD 7C030000 80 | CMP BYTE PTR DS:[R13+37C],80 | r13 == 0000004E6D71A7D8
0000000142BB40B5 | 73 38 | JAE mafiadefinitiveedition.142BB40EF |
0000000142BB40B7 | 49:8B8D 70020000 | MOV RCX,QWORD PTR DS:[R13+270] | == 000000007BF8DBF0
0000000142BB40BE | 48:6341 04 | MOVSXD RAX,DWORD PTR DS:[RCX+4] | == 0000000000003074
0000000142BB40C2 | F78408 68020000 00001000 | TEST DWORD PTR DS:[RAX+RCX+268],100000 | == 0000000320200020
0000000142BB40CD | 74 0D | JE mafiadefinitiveedition.142BB40DC | <- jumps
0000000142BB40CF | 49:8B85 B0010000 | MOV RAX,QWORD PTR DS:[R13+1B0] |
0000000142BB40D6 | 8078 18 09 | CMP BYTE PTR DS:[RAX+18],9 | 9
0000000142BB40DA | 74 13 | JE mafiadefinitiveedition.142BB40EF |
0000000142BB40DC | 49:8B8D B0010000 | MOV RCX,QWORD PTR DS:[R13+1B0] | r13 == 0000004E6D71A7D8; rcx <- 00000000E3010D30 (C_Player2)
0000000142BB40E3 | 48:8B89 28010000 | MOV RCX,QWORD PTR DS:[RCX+128] | rcx <- 0000004E6D71A420 (C_InventoryWrapper)
0000000142BB40EA | E8 B144F6FF | CALL mafiadefinitiveedition.142B185A0 | <-- subtract
Infinite Clip / No Reload:
Code: Select all
local C_Player2 = readQword( getAddressSafe( process ) + 0x63DA8F0 + 0x28 )
local p = readQword( C_Player2 + 0x148 )
p = readQword( p + 0x270 )
local q = readInteger( p + 0x4 )
local r = readInteger( p + q + 0x268 )
r = r | 0x100000
writeInteger( p + q + 0x268, r )
Re: Mafia: Definitive Edition
Getting from C_Player2 to Health is done via this code:
[[C_Player2 + 0xD30] + 0x18] = p == 00000000E44D5A60
Then here, before l0wb1t's hook spot:
So then:
[[p]] == pHealth; pHealth + 0xC = Health float value Like so:
BR,
Sun
Code: Select all
0000000142BFAB90 | 48:83EC 28 | SUB RSP,28 |
0000000142BFAB94 | 8B81 00010000 | MOV EAX,DWORD PTR DS:[RCX+100] | rcx == 000000336635AF30
0000000142BFAB9A | A8 04 | TEST AL,4 |
0000000142BFAB9C | 74 0D | JE mafiadefinitiveedition.142BFABAB |
0000000142BFAB9E | F3:0F1081 F0010000 | MOVSS XMM0,DWORD PTR DS:[RCX+1F0] |
0000000142BFABA6 | 48:83C4 28 | ADD RSP,28 |
0000000142BFABAA | C3 | RET |
0000000142BFABAB | A8 02 | TEST AL,2 |
0000000142BFABAD | 74 0D | JE mafiadefinitiveedition.142BFABBC |
0000000142BFABAF | F3:0F1081 EC010000 | MOVSS XMM0,DWORD PTR DS:[RCX+1EC] |
0000000142BFABB7 | 48:83C4 28 | ADD RSP,28 |
0000000142BFABBB | C3 | RET |
0000000142BFABBC | A8 01 | TEST AL,1 |
0000000142BFABBE | 74 0D | JE mafiadefinitiveedition.142BFABCD |
0000000142BFABC0 | F3:0F1081 E8010000 | MOVSS XMM0,DWORD PTR DS:[RCX+1E8] |
0000000142BFABC8 | 48:83C4 28 | ADD RSP,28 |
0000000142BFABCC | C3 | RET |
0000000142BFABCD | E8 DEE273FF | CALL mafiadefinitiveedition.142338EB0 | C_Game
0000000142BFABD2 | 48:8BC8 | MOV RCX,RAX |
0000000142BFABD5 | 48:8B10 | MOV RDX,QWORD PTR DS:[RAX] |
0000000142BFABD8 | FF92 90000000 | CALL QWORD PTR DS:[RDX+90] | C_Player2
0000000142BFABDE | 48:8B88 300D0000 | MOV RCX,QWORD PTR DS:[RAX+D30] | 0000004E6857F130
0000000142BFABE5 | 48:8B41 18 | MOV RAX,QWORD PTR DS:[RCX+18] | 00000000E44D5A60
0000000142BFABE9 | 8078 64 00 | CMP BYTE PTR DS:[RAX+64],0 |
0000000142BFABED | 74 0D | JE mafiadefinitiveedition.142BFABFC |
0000000142BFABEF | F3:0F1080 9C000000 | MOVSS XMM0,DWORD PTR DS:[RAX+9C] |
0000000142BFABF7 | 48:83C4 28 | ADD RSP,28 |
0000000142BFABFB | C3 | RET |
0000000142BFABFC | F3:0F1080 98000000 | MOVSS XMM0,DWORD PTR DS:[RAX+98] |
0000000142BFAC04 | 48:83C4 28 | ADD RSP,28 |
0000000142BFAC08 | C3 | RET |
Then here, before l0wb1t's hook spot:
Code: Select all
0000000142C17C94 | 48:8B41 08 | MOV RAX,QWORD PTR DS:[RCX+8] | rax <- 00000000E44D5A60 (p)
0000000142C17C98 | 4C:8B08 | MOV R9,QWORD PTR DS:[RAX] | r9 <- 0000004E74820E70
0000000142C17C9B | 48:8B01 | MOV RAX,QWORD PTR DS:[RCX] |
0000000142C17C9E | 49:8B19 | MOV RBX,QWORD PTR DS:[R9] | rbx <- 000000010EAF8020 (pHealth)
0000000142C17CA1 | 48:8BA8 980D0000 | MOV RBP,QWORD PTR DS:[RAX+D98] |
0000000142C17CA8 | 48:8BD3 | MOV RDX,RBX |
0000000142C17CAB | E8 50060000 | CALL mafiadefinitiveedition.142C18300 |
0000000142C17CB0 | F3:0F1047 3C | MOVSS XMM0,DWORD PTR DS:[RDI+3C] |
0000000142C17CB5 | F3:0F5E43 04 | DIVSS XMM0,DWORD PTR DS:[RBX+4] |
0000000142C17CBA | 48:8B4F 40 | MOV RCX,QWORD PTR DS:[RDI+40] |
0000000142C17CBE | F3:0F1035 BE9CF001 | MOVSS XMM6,DWORD PTR DS:[144B21984] |
0000000142C17CC6 | 0F28CE | MOVAPS XMM1,XMM6 |
0000000142C17CC9 | F3:0F5CC8 | SUBSS XMM1,XMM0 |
0000000142C17CCD | E8 7EBEFEFF | CALL mafiadefinitiveedition.142C03B50 |
0000000142C17CD2 | F3:0F104B 0C | MOVSS XMM1,DWORD PTR DS:[RBX+C] | <- l0wb1t's hook spot
[[p]] == pHealth; pHealth + 0xC = Health float value Like so:
BR,
Sun
Re: Mafia: Definitive Edition
Accesses to Weapon Data (rcx+r9 = WeaponDataBase)
Fire Rate
Code: Select all
"mafiadefinitiveedition.exe"+2BBFB90: 4C 8B 89 70 02 00 00 - mov r9,[rcx+00000270]
"mafiadefinitiveedition.exe"+2BBFB97: 49 63 49 04 - movsxd rcx,dword ptr [r9+04]
// ---------- INJECTING HERE ----------
"mafiadefinitiveedition.exe"+2BBFB9B: 42 8B 84 09 34 01 00 00 - mov eax,[rcx+r9+00000134]
// ---------- DONE INJECTING ----------
"mafiadefinitiveedition.exe"+2BBFBA3: 89 02 - mov [rdx],eax
"mafiadefinitiveedition.exe"+2BBFBA5: 42 8B 84 09 38 01 00 00 - mov eax,[rcx+r9+00000138]
"mafiadefinitiveedition.exe"+2BBFBAD: 41 89 00 - mov [r8],eax
"mafiadefinitiveedition.exe"+2BBFBB0: C3 - ret
Code: Select all
"mafiadefinitiveedition.exe"+2CD66E8: 75 15 - jne mafiadefinitiveedition.exe+2CD66FF
// ---------- INJECTING HERE ----------
"mafiadefinitiveedition.exe"+2CD66EA: 41 0F 2F B6 64 01 00 00 - comiss xmm6,[r14+00000164] // change it to -0.01
// ---------- DONE INJECTING ----------
"mafiadefinitiveedition.exe"+2CD66F2: 73 0B - jae mafiadefinitiveedition.exe+2CD66FF
Who is online
Users browsing this forum: No registered users