Results 1 to 10 of 10
  1. #1
    殺す必要がある唯一のものは殺されるために準備され人 々である。
    Premium Member
    Hitokiri~'s Avatar
    Join Date
    Oct 2012
    Gender
    female
    Location
    Cancer.
    Posts
    1,195
    Reputation
    24
    Thanks
    863
    My Mood
    Bitchy

    Learning To Make Call of Duty Advanced Warfare Hacks

    I'm using the term "hack" very loosely here. Essentially, I'm going to show you how to make external memory based C++ "trainers" for Advanced Warfare.

    Requirements:
    - Basic knowledge of C++ and Pointers
    - Basic knowledge of Windows ( Process IDs etc. )
    - Basic assembly knowledge
    - A decompiler or Cheat Engine ( It's up to you )
    - A brain. ( This is the most important part )

    Step 1: You'll need to do a memory dump of Advanced Warfare. I described how to do it in the first 2 paragraphs in this post.

    Step 2: Now that you have your memory dump, you'll need to open it in your debugger. If you're using cheat engine, a memory dump isn't required since you can just find offsets the old fashioned way. For this tutorial however, I'm going to show you how you can create a trainer to edit dvars by name from an external application.

    Step 3: Since every CoD game, dvar-related functions can always be found by a string reference. The particular string is:

    "Can't create dvar '%s': %i dvars already exist"

    So let's do a string search for this. I'm using IDA.



    The cross reference to this string is always present in the RegisterDvar function.
    Let's go to that. We'll see the below code.

    Code:
    .text:00000001404A3AC3                 lea     rdx, aCanTCreateDvar ; "Can't create dvar '%s': %i dvars alread"... - Our error string
    .text:00000001404A3ACA                 mov     r9d, 2000h      ; _QWORD ; Maximum number of dvars the game can use
    .text:00000001404A3AD0                 mov     r8, rsi         ; _QWORD   ; Dvar name
    .text:00000001404A3AD3                 xor     ecx, ecx        ; type        ; Type = 0 = Fatal error
    .text:00000001404A3AD5                 call    Com_ErrorMessage          ; Calls the error function message to alert the user
    Right so this function registers dvars but that doesn't really help us, does it? We want to know how to edit dvars, not create them. So for that, we'll need to find out what functions call this "RegisterDvar" function. So let's go to the top of our subroutine:



    Now select a cross reference. ( X button in IDA while the cursor is on "sub_xxxx" )


    As we can see, there's several cross references. Let's try the first function. Ideally, we're looking for a short function that functions as a "wrapper" ( I.E. It mainly checks if a dvar has been registered with a name identical to one in the array of registered dvars. )

    Scrolling up or down we can see that the first function well exceeds over 300 bytes. That's way too much for a simple "If dvar already exists" function.
     






    Let's try the second function:
    Code:
    .text:00000001404A34B0 ; int __fastcall Dvar_RegisterBool(char *dvarName, QWORD defaultValue, QWORD maxValue)
    .text:00000001404A34B0 Dvar_RegisterBool proc near             ; CODE XREF: sub_14000EDF0+80p
    .text:00000001404A34B0                                         ; sub_14000EDF0+9Fp ...
    .text:00000001404A34B0
    .text:00000001404A34B0 var_38          = qword ptr -38h
    .text:00000001404A34B0 var_30          = qword ptr -30h
    .text:00000001404A34B0 var_28          = xmmword ptr -28h
    .text:00000001404A34B0 var_18          = xmmword ptr -18h
    .text:00000001404A34B0 arg_0           = qword ptr  8
    .text:00000001404A34B0 arg_8           = qword ptr  10h
    .text:00000001404A34B0
    .text:00000001404A34B0                 mov     [rsp+arg_0], rbx
    .text:00000001404A34B5                 mov     [rsp+arg_8], rsi
    .text:00000001404A34BA                 push    rdi
    .text:00000001404A34BB                 sub     rsp, 50h
    .text:00000001404A34BF                 xor     eax, eax
    .text:00000001404A34C1                 mov     rdi, rcx
    .text:00000001404A34C4                 mov     ecx, 34h
    .text:00000001404A34C9                 mov     qword ptr [rsp+58h+var_28], rax
    .text:00000001404A34CE                 mov     qword ptr [rsp+58h+var_28+8], rax
    .text:00000001404A34D3                 mov     rax, gs:58h
    .text:00000001404A34DC                 mov     ebx, r8d
    .text:00000001404A34DF                 mov     dword ptr [rsp+58h+var_18], 0
    .text:00000001404A34E7                 mov     byte ptr [rsp+58h+var_18], dl
    .text:00000001404A34EB                 mov     edx, cs:TlsIndex
    .text:00000001404A34F1                 mov     rax, [rax+rdx*8]
    .text:00000001404A34F5                 or      [rax+rcx], ebx
    .text:00000001404A34F8                 mov     rcx, rdi
    .text:00000001404A34FB                 call    Dvar_FindByString
    .text:00000001404A3500                 mov     rsi, rax
    .text:00000001404A3503                 test    rax, rax
    .text:00000001404A3506                 lea     rax, [rsp+58h+var_28]
    .text:00000001404A350B                 movaps  xmm0, [rsp+58h+var_28]
    .text:00000001404A3510                 movaps  xmm1, [rsp+58h+var_18]
    .text:00000001404A3515                 movdqa  [rsp+58h+var_28], xmm0
    .text:00000001404A351B                 movdqa  [rsp+58h+var_18], xmm1
    .text:00000001404A3521                 jnz     short loc_1404A354A
    .text:00000001404A3523                 lea     r9, [rsp+58h+var_18]
    .text:00000001404A3528                 mov     r8d, ebx
    .text:00000001404A352B                 xor     edx, edx
    .text:00000001404A352D                 mov     rcx, rdi
    .text:00000001404A3530                 mov     [rsp+58h+var_38], rax
    .text:00000001404A3535                 call    RegisterDvar
    .text:00000001404A353A                 mov     rbx, [rsp+58h+arg_0]
    .text:00000001404A353F                 mov     rsi, [rsp+58h+arg_8]
    .text:00000001404A3544                 add     rsp, 50h
    .text:00000001404A3548                 pop     rdi
    .text:00000001404A3549                 retn
    .text:00000001404A354A ; ---------------------------------------------------------------------------
    .text:00000001404A354A
    .text:00000001404A354A loc_1404A354A:                          ; CODE XREF: Dvar_RegisterBool+71j
    .text:00000001404A354A                 mov     [rsp+58h+var_30], rax
    .text:00000001404A354F                 lea     rax, [rsp+58h+var_18]
    .text:00000001404A3554                 mov     r9d, ebx
    .text:00000001404A3557                 xor     r8d, r8d
    .text:00000001404A355A                 mov     rdx, rdi
    .text:00000001404A355D                 mov     rcx, rsi
    .text:00000001404A3560                 mov     [rsp+58h+var_38], rax
    .text:00000001404A3565                 call    sub_1404A41D0
    .text:00000001404A356A                 mov     rbx, [rsp+58h+arg_0]
    .text:00000001404A356F                 mov     rax, rsi
    .text:00000001404A3572                 mov     rsi, [rsp+58h+arg_8]
    .text:00000001404A3577                 add     rsp, 50h
    .text:00000001404A357B                 pop     rdi
    .text:00000001404A357C                 retn
    .text:00000001404A357C Dvar_RegisterBool endp
    This seems much shorter.
    The interesting part in this function is the following code:
    Code:
    .text:00000001404A34FB                 call    Dvar_FindByString         ; Calls Dvar_FindByString ( I've reversed this. It'll appear as sub_xxx to you )
    .text:00000001404A3500                 mov     rsi, rax                      ; Dvar_FindByString returns a pointer to the string passed
    .text:00000001404A3503                 test    rax, rax                       ; If it returns NULL ( 0 ) no dvar was found. This checks for that.
    .text:00000001404A3506                 lea     rax, [rsp+58h+var_28]   ; Below prepares for registering the dvar, ignore these if you want
    .text:00000001404A350B                 movaps  xmm0, [rsp+58h+var_28]
    .text:00000001404A3510                 movaps  xmm1, [rsp+58h+var_18]
    .text:00000001404A3515                 movdqa  [rsp+58h+var_28], xmm0
    .text:00000001404A351B                 movdqa  [rsp+58h+var_18], xmm1
    .text:00000001404A3521                 jnz     short loc_1404A354A      ; If the test rax,rax above returns 1 ( Aka the dvar exists ) it leaves the function
    So we basically have our function we want. Jump to Dvar_FindByString
    Code:
    .text:00000001404A20E0 Dvar_FindByString proc near             ; CODE XREF: sub_1404A0DC0+83p
    .text:00000001404A20E0                                         ; sub_1404A1770+33p ...
    .text:00000001404A20E0
    .text:00000001404A20E0 arg_0           = qword ptr  8 ; This is the dvar name. Eg. "com_maxfps"
    .text:00000001404A20E0
    .text:00000001404A20E0                 mov     [rsp+arg_0], rbx
    .text:00000001404A20E5                 push    rdi      ; Prologue function. Allocate 0x20 bytes on the stack for local variables.
    .text:00000001404A20E6                 sub     rsp, 20h
    .text:00000001404A20EA                 mov     rdi, rcx ; The below is to avoid deadlocks ( google ) during dvar registration. Ignore this.
    .text:00000001404A20ED                 lock inc cs:DvarLock
    .text:00000001404A20F4                 mov     eax, cs:dword_14A90E1B4
    .text:00000001404A20FA                 test    eax, eax
    .text:00000001404A20FC                 jz      short loc_1404A2111  ; This is where the fun begins
    .text:00000001404A20FE                 xchg    ax, ax
    .text:00000001404A2100
    .text:00000001404A2100 loc_1404A2100:                          ; CODE XREF: Dvar_FindByString+2Fj
    .text:00000001404A2100                 xor     ecx, ecx        ; dwMilliseconds
    .text:00000001404A2102                 call    j_Sleep
    .text:00000001404A2107                 mov     eax, cs:dword_14A90E1B4
    .text:00000001404A210D                 test    eax, eax
    .text:00000001404A210F                 jnz     short loc_1404A2100
    .text:00000001404A2111
    .text:00000001404A2111 loc_1404A2111:                          ; CODE XREF: Dvar_FindByString+1Cj - Aka "Fun"
    .text:00000001404A2111                 mov     rcx, rdi          ; Move the dvar name pointer into RCX
    .text:00000001404A2114                 call    HashString       ; Calls a function that hashes the string
    .text:00000001404A2119                 movsxd  rbx, eax      ; The result is a DWORD stored in EAX
    .text:00000001404A211C                 lea     rax, DvarArrayPtr ; This is an array pointer of hashes strings
    .text:00000001404A2123                 mov     rbx, [rax+rbx*8]  ; The dvar pointer is stored at ( HashArray[ HashValue ] )
    .text:00000001404A2127                 test    rbx, rbx          ; Check if a dvar exists at this index
    .text:00000001404A212A                 jz      short loc_1404A2148 ; If no dvar exists, return 0
    .text:00000001404A212C                 nop     dword ptr [rax+00h] ; Ignore this. Activision brainfarted here.
    .text:00000001404A2130
    .text:00000001404A2130 loc_1404A2130:                          ; CODE XREF: Dvar_FindByString+66j
    .text:00000001404A2130                 mov     rdx, [rbx]      ; Compare the dvar name stored at the hash value array index
    .text:00000001404A2133                 mov     rcx, rdi        ; to our provided name ( rcx )
    .text:00000001404A2136                 call    stricmp          ; String compare function
    .text:00000001404A213B                 test    eax, eax       ; If it returns NULL ( Aka EAX == 0 )
    .text:00000001404A213D                 jz      short loc_1404A215C  ; Then we found our dvar -> Return the pointer
    .text:00000001404A213F                 mov     rbx, [rbx+58h] ; The bottom of the dvar struct contains a single linked-list pointing to the next dvar
    .text:00000001404A2143                 test    rbx, rbx ; If this value is not zero, it iterates to the next dvar.
    .text:00000001404A2146                 jnz     short loc_1404A2130 ; And performs the stricmp() again
    .text:00000001404A2148
    .text:00000001404A2148 loc_1404A2148:                          ; CODE XREF: Dvar_FindByString+4Aj
    .text:00000001404A2148                 lock dec cs:DvarLock
    .text:00000001404A214F                 xor     eax, eax                ; This returns 0
    .text:00000001404A2151                 mov     rbx, [rsp+28h+arg_0]
    .text:00000001404A2156                 add     rsp, 20h
    .text:00000001404A215A                 pop     rdi
    .text:00000001404A215B                 retn
    .text:00000001404A215C ; ---------------------------------------------------------------------------
    .text:00000001404A215C
    .text:00000001404A215C loc_1404A215C:                          ; CODE XREF: Dvar_FindByString+5Dj
    .text:00000001404A215C                 lock dec cs:DvarLock
    .text:00000001404A2163                 mov     rax, rbx            ; This returns our found dvar pointer.
    .text:00000001404A2166                 mov     rbx, [rsp+28h+arg_0]
    .text:00000001404A216B                 add     rsp, 20h
    .text:00000001404A216F                 pop     rdi
    .text:00000001404A2170                 retn
    .text:00000001404A2170 Dvar_FindByString endp
    So from the above code, we can gather that our dvar structure looks like this:

    Code:
    struct dvar_s{
             char* dvarName;  // 0x0000 - Pointer to the dvar name
             struct dvar_s* next; // 0x0058
    }; // Size: [ 0x60 ]
    From common knowledge, we know for AW, the value is stored at dvar_s + 0x10 ( 16 )
    So basically:

    Code:
    struct dvar_s{
             char* dvarName;  // 0x0000 - Pointer to the dvar name
             char _unk[ 8 ];     // 0x0008
             enum{                // 0x0010
                int iValue;
                float fValue;
                double dblValue;
                float flVec2[2];
                float flVec3[3];
                float flVec4[4];
             }
             char _unk2[0x38];    // 0x0020
             struct dvar_s* next; // 0x0058
    }; // Size: [ 0x60 ]
    So how do we edit dvars? Well we have the dvar structure and the HashValue function.
    All we need to do is emulate the above Dvar_FindByString() and we can edit the dvars with the structure.

  2. The Following 5 Users Say Thank You to Hitokiri~ For This Useful Post:

    Cosmo_ (05-04-2015),i4mTh3Fr34kPr0 (04-09-2015),Izochor (03-02-2015),[MPGH]Minnesota Dabs (03-02-2015),SammyDoge1 (03-21-2015)

  3. #2
    Minnesota Dabs's Avatar
    Join Date
    Nov 2013
    Gender
    male
    Location
    VOTE TRUMP
    Posts
    4,208
    Reputation
    615
    Thanks
    1,066
    My Mood
    Relaxed
    Thanks for this, I'm sure a lot of people will make use of it .
    Successful Trades: 52

    Scammed Trades: 6

    Vouch Profile!



    Consider donating to my PayPal!

  4. #3
    [NEWACCOUNT]Yano's Avatar
    Join Date
    Dec 2014
    Gender
    male
    Location
    CL_WritePacket();
    Posts
    329
    Reputation
    13
    Thanks
    3,425
    My Mood
    Relaxed
    Nice tut!:-)

    If I had AW I would release so much tools ... :/
    Code:
    __asm mov [RecoilVec], 0

  5. #4
    heathbar's Avatar
    Join Date
    Mar 2015
    Gender
    male
    Posts
    0
    Reputation
    10
    Thanks
    0
    can someone make a full vid from scratch ( for people with no programming skill) step by step

  6. #5
    SammyDoge1's Avatar
    Join Date
    Apr 2009
    Gender
    male
    Location
    Tried looking behind you...?
    Posts
    2,179
    Reputation
    59
    Thanks
    2,086
    My Mood
    Tired
    Quote Originally Posted by heathbar View Post
    ( for people with no programming skill)
    I think you're wrong here then.
    Following a tut will only get you so far.





  7. The Following User Says Thank You to SammyDoge1 For This Useful Post:

    TonyMane() (03-20-2015)

  8. #6
    heathbar's Avatar
    Join Date
    Mar 2015
    Gender
    male
    Posts
    0
    Reputation
    10
    Thanks
    0
    how do you learn then? it would be amazing to do this stuff man

  9. #7
    Threadstarter
    殺す必要がある唯一のものは殺されるために準備され人 々である。
    Premium Member
    Hitokiri~'s Avatar
    Join Date
    Oct 2012
    Gender
    female
    Location
    Cancer.
    Posts
    1,195
    Reputation
    24
    Thanks
    863
    My Mood
    Bitchy
    Quote Originally Posted by heathbar View Post
    how do you learn then? it would be amazing to do this stuff man
    Code:
    http://bit . ly/1F975EV
    Careful now, use this with responsibility.
    Last edited by Hitokiri~; 03-19-2015 at 11:07 AM.

  10. #8
    heathbar's Avatar
    Join Date
    Mar 2015
    Gender
    male
    Posts
    0
    Reputation
    10
    Thanks
    0
    what language?

  11. #9
    Max5623's Avatar
    Join Date
    Mar 2015
    Gender
    male
    Location
    Badajoz
    Posts
    25
    Reputation
    10
    Thanks
    1
    My Mood
    Amused
    so much tools, very complex oO

  12. #10
    StonedEngine's Avatar
    Join Date
    Feb 2014
    Gender
    male
    Location
    Germany?
    Posts
    69
    Reputation
    10
    Thanks
    48
    My Mood
    Amused
    Quote Originally Posted by heathbar View Post
    what language?
    Requirements:
    - Basic knowledge of C++ and Pointers
    - Basic knowledge of Windows ( Process IDs etc. )
    - Basic assembly knowledge
    - A decompiler or Cheat Engine ( It's up to you )
    - A brain. ( This is the most important part )

    Did you even read the post?
    HK

Similar Threads

  1. [Info] Call of Duty Advanced Warfare Multiplayer Reveal
    By Horror in forum Call of Duty Hacks & Cheats
    Replies: 11
    Last Post: 09-10-2014, 07:33 PM
  2. [Info] Call of Duty: ADVANCED WARFARE
    By Thriksaw in forum Call of Duty Hacks & Cheats
    Replies: 18
    Last Post: 08-08-2014, 06:16 PM
  3. [WTS] Call of Duty: Advanced Warfare STEAM GIFT
    By NazyProspekt in forum Selling Accounts/Keys/Items
    Replies: 5
    Last Post: 06-26-2014, 01:23 AM
  4. Replies: 3
    Last Post: 05-26-2014, 08:15 AM
  5. Call of Duty®: Advanced Warfare
    By 12qwerty34 in forum Call of Duty Ghosts Discussions & Help
    Replies: 10
    Last Post: 05-10-2014, 11:23 PM