Quote:
Originally Posted by Forgetest
I've been trying to make memory patches on this, only to get crashes on both games on Windows, but it seems to work on Linux L4D2.
...
So I aimed to patch those calls of Holster, SetActiveWeapon and Deploy to NOPs. However as mentioned above, it's crashing on Windows.
|
Patching out function calls with NOPs on Windows isn't sufficient most of the time. Even if you patch out the entire instruction (which is almost always needed on Windows), it won't work most of the time and you'll have to worry about patching a lot of bytes. You can instead try patching with unconditional jumps.
If you don't know how those work:
Basically, your patch should jump from one instruction to another (while skipping any other instruction between your source and your destination). The destination of the jump depends on which part(s) of the function you want to skip over.
For example, if you want to skip the function call for
CTerrorGun::Holster, you'll want to start at the first byte of that function's call instruction. Since an unconditional jump (E9 ? ? ? ?) takes 5 bytes, the length of your jump will be calculated by the following equation:
Let a1 = Address of the patch location + 5 bytes (because the patch itself takes five bytes)
Let a2 = Address of the start of the instruction after the
CTerrorGun::Holster's call instruction.
Equation: a2 - a1 = JMP instruction length
Here is
CTerrorGun::Holster's call instruction on Windows:
Code:
.text:103E4712 8B 10 mov edx, [eax]
.text:103E4714 8B C8 mov ecx, eax
.text:103E4716 8B 82 24 04 00 00 mov eax, [edx+424h]
.text:103E471C 6A 00 push 0
.text:103E471E FF D0 call eax
Your patch will start at the first byte (8B). The offset for that is 172h (370). Your patch length is 5 bytes so
a1 will be
103E4717 (82).
Here's the next instruction:
Code:
.text:103E4720 56 push esi
.text:103E4721 8B CB mov ecx, ebx
.text:103E4723 E8 C8 F9 C5 FF call sub_100440F0
Your
a2 will be
103E4720. Now you can use the equation and get
9. Your patch bytes will now be
\xE9\x09\x00\x00\x00.
Since I like to be consistent on both platforms and both games as much as possible, I used the unconditional jump method for Linux as well. These are my offsets and sigs:
PHP Code:
"Games"
{
"#default"
{
"Offsets"
{
"OS"
{
"linux" "1"
"windows" "0"
}
}
}
"left4dead"
{
"MemPatches"
{
"EquipSecondWeapon_StopHolster"
{
"signature" "CTerrorGun_EquipSecondWeapon"
"linux"
{
"offset" "297"
"verify" "\x8B"
"patch" "\xE9\x0E\x00\x00\x00"
}
"windows"
{
"offset" "403"
"verify" "\x8B"
"patch" "\xE9\x09\x00\x00\x00"
}
}
"EquipSecondWeapon_SetActiveWeapon"
{
"signature" "CTerrorGun_EquipSecondWeapon"
"linux"
{
"offset" "316"
"verify" "\x89"
"patch" "\xE9\x0B\x00\x00\x00"
}
"windows"
{
"offset" "417"
"verify" "\x56"
"patch" "\xE9\x03\x00\x00\x00"
}
}
"EquipSecondWeapon_Deploy"
{
"signature" "CTerrorGun_EquipSecondWeapon"
"linux"
{
"offset" "332"
"verify" "\x8B"
"patch" "\xE9\x06\x00\x00\x00"
}
"windows"
{
"offset" "425"
"verify" "\x8B"
"patch" "\xE9\x07\x00\x00\x00"
}
}
}
"Signatures"
{
/**
* CTerrorGun::Use(CBaseEntity *, CBaseEntity *, USE_TYPE, float)
*
* How to find on Windows:
* 1. Find the function's offsets with asherkin's VTable dump.
* 2. Use IDA to get the VTable dump for the "CTerrorGun" class on Windows.
* 3. Compare your dump's offsets with asherkin's dump's offsets to find the target function.
* 4. Look for the target function in the Windows binary.
**/
"CTerrorGun_Use"
{
"library" "server"
"linux" "@_ZN10CTerrorGun3UseEP11CBaseEntityS1_8USE_TYPEf"
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x85\x2A\x8B\x2A\x0F\x84\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x90\x2A\x2A\x2A\x2A\x8B\x2A\xFF\x2A\x84\x2A\x0F\x84\x2A\x2A\x2A\x2A\x8B\x2A\x8B"
/* ? ? ? ? ? ? ? ? ? 85 ? 8B ? 0F 84 ? ? ? ? 8B ? 8B 90 ? ? ? ? 8B ? FF ? 84 ? 0F 84 ? ? ? ? 8B ? 8B */
}
/**
* CTerrorGun::EquipSecondWeapon()
*
* How to find on Windows:
* 1a. Search for the "Player.PickupWeapon" string.
* 2a. One of the functions that references that string should be this function.
*
* 1b. Find the function's offsets with asherkin's VTable dump.
* 2b. Use IDA to get the VTable dump for the "CTerrorGun" class on Windows.
* 3b. Compare your dump's offsets with asherkin's dump's offsets to find the target function.
* 4b. Look for the target function in the Windows binary.
**/
"CTerrorGun_EquipSecondWeapon"
{
"library" "server"
"linux" "@_ZN10CTerrorGun17EquipSecondWeaponEv"
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x80\xBE\x2A\x2A\x2A\x2A\x2A\x8D\x9E\x2A\x2A\x2A\x2A\x74\x2A\x5E"
/* ? ? ? ? ? ? ? 80 BE ? ? ? ? ? 8D 9E ? ? ? ? 74 ? 5E */
}
/**
* CWeaponSpawn::Use(CBaseEntity *, CBaseEntity *, USE_TYPE, float)
*
* How to find on Windows:
* 1a. Search for the "spawner_give_item" string.
* 2a. The string can only be found in this function.
*
* 1b. Find the function's offsets with asherkin's VTable dump.
* 2b. In IDA Pro, go to the ".rdata" section of the Windows binary.
* 3b. Search for "CWeaponSpawn::`vftable'" to jump to the "CWeaponSpawn" vtable.
* 4b. Compare your dump's offsets with asherkin's dump's offsets to find the target function.
* 5b. Look for the target function in the Windows binary.
**/
"CWeaponSpawn::Use"
{
"library" "server"
"linux" "@_ZN12CWeaponSpawn3UseEP11CBaseEntityS1_8USE_TYPEf"
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x85\x2A\x8B\x2A\x89\x2A\x2A\x2A\x0F\x84\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x90\x2A\x2A\x2A\x2A\x8B\x2A\xFF\x2A\x84\x2A\x0F\x84\x2A\x2A\x2A\x2A\x8B"
/* ? ? ? ? ? ? ? ? ? 85 ? 8B ? 89 ? ? ? 0F 84 ? ? ? ? 8B ? 8B 90 ? ? ? ? 8B ? FF ? 84 ? 0F 84 ? ? ? ? 8B */
}
}
}
"left4dead2"
{
"MemPatches"
{
"EquipSecondWeapon_StopHolster"
{
"signature" "CTerrorGun_EquipSecondWeapon"
"linux"
{
"offset" "294"
"verify" "\x8B"
"patch" "\xE9\x0E\x00\x00\x00"
}
"windows"
{
"offset" "370"
"verify" "\x8B"
"patch" "\xE9\x09\x00\x00\x00"
}
}
"EquipSecondWeapon_SetActiveWeapon"
{
"signature" "CTerrorGun_EquipSecondWeapon"
"linux"
{
"offset" "313"
"verify" "\x89"
"patch" "\xE9\x07\x00\x00\x00"
}
"windows"
{
"offset" "384"
"verify" "\x56"
"patch" "\xE9\x03\x00\x00\x00"
}
}
"EquipSecondWeapon_Deploy"
{
"signature" "CTerrorGun_EquipSecondWeapon"
"linux"
{
"offset" "325"
"verify" "\x8B"
"patch" "\xE9\x06\x00\x00\x00"
}
"windows"
{
"offset" "392"
"verify" "\x8B"
"patch" "\xE9\x07\x00\x00\x00"
}
}
}
"Signatures"
{
/**
* CTerrorGun::Use(CBaseEntity *, CBaseEntity *, USE_TYPE, float)
*
* How to find on Windows:
* 1. Find the function's offsets with asherkin's VTable dump.
* 2. Use IDA to get the VTable dump for the "CTerrorGun" class on Windows.
* 3. Compare your dump's offsets with asherkin's dump's offsets to find the target function.
* 4. Look for the target function in the Windows binary.
**/
"CTerrorGun_Use"
{
"library" "server"
"linux" "@_ZN10CTerrorGun3UseEP11CBaseEntityS1_8USE_TYPEf"
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x56\x57\x8B\x2A\x2A\x8B\x2A\x85\x2A\x0F\x84\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x90\x2A\x2A\x2A\x2A\x8B\x2A\xFF\x2A\x84\x2A\x0F\x84\x2A\x2A\x2A\x2A\x8B\x2A\x8B"
/* ? ? ? ? ? ? 56 57 8B ? ? 8B ? 85 ? 0F 84 ? ? ? ? 8B ? 8B 90 ? ? ? ? 8B ? FF ? 84 ? 0F 84 ? ? ? ? 8B ? 8B */
}
/**
* CTerrorGun::EquipSecondWeapon()
*
* How to find on Windows:
* 1a. Search for the "Player.PickupWeapon" string.
* 2a. One of the functions that references that string should be this function.
*
* 1b. Find the function's offsets with asherkin's VTable dump.
* 2b. Use IDA to get the VTable dump for the "CTerrorGun" class on Windows.
* 3b. Compare your dump's offsets with asherkin's dump's offsets to find the target function.
* 4b. Look for the target function in the Windows binary.
**/
"CTerrorGun_EquipSecondWeapon"
{
"library" "server"
"linux" "@_ZN10CTerrorGun17EquipSecondWeaponEv"
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x56\x8B\x2A\x80\xBE\x2A\x2A\x2A\x2A\x2A\x74\x2A\x32\x2A\x5E\x8B"
/* ? ? ? ? ? ? 56 8B ? 80 BE ? ? ? ? ? 74 ? 32 ? 5E 8B */
}
/**
* CWeaponSpawn::Use(CBaseEntity *, CBaseEntity *, USE_TYPE, float)
*
* How to find on Windows:
* 1a. Search for the "spawner_give_item" string.
* 2a. The string can only be found in this function.
*
* 1b. Find the function's offsets with asherkin's VTable dump.
* 2b. In IDA Pro, go to the ".rdata" section of the Windows binary.
* 3b. Search for "CWeaponSpawn::`vftable'" to jump to the "CWeaponSpawn" vtable.
* 4b. Compare your dump's offsets with asherkin's dump's offsets to find the target function.
* 5b. Look for the target function in the Windows binary.
**/
"CWeaponSpawn::Use"
{
"library" "server"
"linux" "@_ZN12CWeaponSpawn3UseEP11CBaseEntityS1_8USE_TYPEf"
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x53\x57\x8B\x2A\x2A\x8B\x2A\x85\x2A\x0F\x84\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x90\x2A\x2A\x2A\x2A\x8B\x2A\xFF\x2A\x84\x2A\x0F\x84\x2A\x2A\x2A\x2A\x8B"
/* ? ? ? ? ? ? 53 57 8B ? ? 8B ? 85 ? 0F 84 ? ? ? ? 8B ? 8B 90 ? ? ? ? 8B ? FF ? 84 ? 0F 84 ? ? ? ? 8B */
}
}
}
}
I've tested both games on Windows and the patches work as intended without any crashes.
__________________