Mafia: Definitive Edition

Add topics here with methods, analysis, code snippets, mods etc. for a certain game that normally won't make it in the Tables or Requests sections.
Post Reply
User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Mafia: Definitive Edition

Post by SunBeam »

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.

User avatar
sebastianyyz
Expert Cheater
Expert Cheater
Posts: 179
Joined: Sun Jul 09, 2017 3:33 am
Reputation: 16

Re: Mafia: Definitive Edition

Post by sebastianyyz »

Great, another great table incoming. Thank you

User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Re: Mafia: Definitive Edition

Post by SunBeam »

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:

Code: Select all

aobscanmodule(_InfiniteHealth,mafiadefinitiveedition.exe,F3 0F 10 4B 0C 0F 28 E6)
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:

Image

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:

Image

I saw a pointer there, at [RCX] basically. And I decided to investigate it. Entered its memory and saw this:

Image

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:

Image

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:

Image

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:

Image

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                                   |
As well as here:

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
..
So.. pick the one you want, both work :P

-> "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:

Image

The address in RBX is read from [R9]. Now.. where's that R9 taken from is what we wanna find out..

BR,
Sun

User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Re: Mafia: Definitive Edition

Post by SunBeam »

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:

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]
The first 5 are accessed when out to Desktop. The moment you go back in, this happens:

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]
I checked the first one: 140985613.

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]
This leads to this piece of code:

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 
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:

Image

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                                   |
<--
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:

Image

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:

Image

Image

Ta-daaa :) So.. [mafiadefinitiveedition.exe+635E9B8]+0x8 == C_Game.

User avatar
l0wb1t
RCE Fanatics
RCE Fanatics
Posts: 411
Joined: Mon May 29, 2017 4:16 pm
Reputation: 272

Re: Mafia: Definitive Edition

Post by l0wb1t »

SunBeam wrote:
Wed Sep 30, 2020 6:08 pm
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:
...
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)

User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Re: Mafia: Definitive Edition

Post by SunBeam »

l0wb1t wrote:
Wed Sep 30, 2020 7:09 pm
...

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 )
I used this part from my explanation:

Code: Select all

-> "mafiadefinitiveedition.exe+63DA8F0" + 0x28 == mafiadefinitiveedition.exe+63DA918 -> [mafiadefinitiveedition.exe+63DA918] == 00000000E3010D30 (C_Player2)
Add 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 :P 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).

P.S.: Thanks Zanzer for the assist; forgot that CE can automatically do calculus for you directly ;)

Zanzer
RCE Fanatics
RCE Fanatics
Posts: 445
Joined: Fri Mar 03, 2017 10:48 pm
Reputation: 889

Re: Mafia: Definitive Edition

Post by Zanzer »

Hacker hacks

User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Re: Mafia: Definitive Edition

Post by SunBeam »

If you want to get C_Player2 from C_Game, you can do so this way ;)

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                                   |
<--
Image

Ta-daaa :) -> [[mafiadefinitiveedition.exe+635E9B8]+0x8]+0x98 == C_Player2. You can name the 0x90 member-function Game::GetPlayer :P

User avatar
l0wb1t
RCE Fanatics
RCE Fanatics
Posts: 411
Joined: Mon May 29, 2017 4:16 pm
Reputation: 272

Re: Mafia: Definitive Edition

Post by l0wb1t »

SunBeam wrote:
Wed Sep 30, 2020 7:40 pm
Add 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 :P 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

User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Re: Mafia: Definitive Edition

Post by SunBeam »

..and if you check the member-function at 0xD8 in C_Game, you will see this:

Code: Select all

000000014234F560 | 0FB681 19B50700 | MOVZX EAX,BYTE PTR DS:[RCX+7B519] |
000000014234F567 | C3              | RET                               |
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

User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Re: Mafia: Definitive Edition

Post by SunBeam »

Then searching for the # of bullets in memory, as a DWORD, leads to this spot where bullets are being written as you fire:

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]     |
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:

Code: Select all

mafiadefinitiveedition.exe+25EB990 - C6 41 11 01           - mov byte ptr [rcx+11],01
mafiadefinitiveedition.exe+25EB994 - C3                    - ret 
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:

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
Then back-tracing one more step out of this function, I saw that..

Code: Select all

0000000142BB40E3 | 48:8B89 28010000 | MOV RCX,QWORD PTR DS:[RCX+128]        | rcx == 00000000E3010D30 == C_Player2
0000000142BB40EA | E8 B144F6FF      | CALL mafiadefinitiveedition.142B185A0 |
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:

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
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:

Image

Image

Then at [C_WeaponItem + 0x8] you have another pointer: C_ItemDataWeapon. This holds these:

Image

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 | <--
Offset is 0x18. Now.. back to the picture above:

Image

Pimp, eh? :D 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:

Image

Image

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:

Image

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:

Image

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" :P

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

User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Re: Mafia: Definitive Edition

Post by SunBeam »

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:

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
Yup, it works :D

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 )

User avatar
SunBeam
Administration
Administration
Posts: 3022
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 2156

Re: Mafia: Definitive Edition

Post by SunBeam »

Getting from C_Player2 to Health is done via this code:

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                                   |
[[C_Player2 + 0xD30] + 0x18] = p == 00000000E44D5A60

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
So then:

[[p]] == pHealth; pHealth + 0xC = Health float value :P Like so:

Image

BR,
Sun

User avatar
l0wb1t
RCE Fanatics
RCE Fanatics
Posts: 411
Joined: Mon May 29, 2017 4:16 pm
Reputation: 272

Re: Mafia: Definitive Edition

Post by l0wb1t »

Accesses to Weapon Data (rcx+r9 = WeaponDataBase)
Image

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 
Fire Rate

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

Post Reply

Who is online

Users browsing this forum: No registered users