How to update offsets and signatures for reverts dependent on MemoryPatching (UNDER CONSTRUCTION!) - rsedxcftvgyhbujnkiqwe/castaway-plugins GitHub Wiki

Written by: VerdiusArcana

Editing and proofreading by: protons oppai

How to Find Memory Patch Revert Functions in Ghidra (Windows) for TF2

This guide assumes you are already familiar with basic Ghidra operations such as:

  • Navigating the Listing view
  • Navigating the Decompile view
  • Using the String search ("Defined Strings")
  • That you have computer knowledge and programming knowledge in general

The following instructions walk through how to locate the functions in the Team Fortress 2 Windows Server binary using Ghidra, this will be necessary to update signatures and/or offsets for the reverts for the Weapon Reverts Plugin.

After this section, we will go through what needs to be done to accomplish each revert.

A quick look at CodeBrowser

CodeBrowser

  1. Save Disk, should be pressed whenever after you are done analyzing and decompiling a binary on first run, thereafter it should be pressed whenever you find and name a function, change plate comments, or when you update any Global Var.
  2. This is where you filter for functions. On Linux the symbols are already in, but it can be hard to directly type in something
    like CTFWeaponBaseMelee::OnSwingHit because on Linux they look typically like this: _ZN18CTFWeaponBaseMelee10OnSwingHitER10CGameTrace as the so called "Mangled name" contains the var types too. So you will have to make do with just inputting the function name. Such as OnSwingHit
  3. Output of any scripts you run. Typically the makesig output appears here. (See section: makesig.py script)
  4. Decompile Window. Whenever you see "Decompile Window" in the instructions of this How to, this is the tab meant.
  5. Defined Strings. Whenever you are told to search for a string, this is where you do it.

!!!STRONGLY RECOMMENDED!!!

  1. First: Copy the .so and .dll from their respective folders (Dedicated server install folders typically found in /tf/bin/) to a new folder.

    • Name the folder something like tf2_serverbinaries_DATEOFTF2UPDATE
      • For example: tf2_serverbinaries_13May2025
    • After running Ghidra, click on File>New Project...
    • Make sure "Non-Shared Project" is selected.
    • For Project directory, choose the directory you placed the .so and .dll files in, which in our example is tf2_serverbinaries_13May2025
    • For name, it would be appropriate to name if something like TF2-Server-Date, which for our example could be TF2-Server-13May2025
  2. Press Finish.

    • Now it should say "Active Project: TF2-Server-Date"
    • Now click File>Import File.
    • Unless you intend to make new memorypatches entirely, you can just choose .dll first, but I recommend having both of them decompiled.
    • So begin with choosing the .so file and just follow Ghidra's instructions. DO NOT CHANGE ANYTHING!!!
  3. Once it's done, press OK.

    • Now when you double click on the file in your project, it will open a window called CodeBrowser.
    • It will also immediately ask you if you want to analyze the file. Just press "Analyze" or "OK".
    • And just press OK until no more dialog pops up, you will see a processing bar doing stuff in the CodeBrowser window at the bottom right. And your computer fans will probably speed up.
    • This is quite a heavy operation, depending on your computer it can take anywhere from 15 minutes to 45 minutes. So lean back and relax or go do something else. DO NOT CLOSE ANY GHIDRA WINDOWS DURING THIS.
  4. After it's done and you see no more stuff happening in the bottom right.

    • Click the little Save Disk icon at the top left of CodeBrowser if it's not already greyed out.
  5. Now close the CodeBrowser Window and proceed to the Ghidra window where you have your project.

    • Proceed to import the server.dlland repeat the process.
  6. Once you have both the .so and .dll files analyzed and decompiled, you can go to File>Open...to open the other file (if you are following along, the
    latest decompile you will have open in the CodeBrowser Window is the .dll file, so just choose the .so file).

    • This makes it so you don't need to have several CodeBrowser Windows open.

Before we begin: FUN_******** is a function that Ghidra has discovered, but since the Windows binary does not contain debug information, Ghidra has labeled it according to it's starting address. I'm not gonna go into technical depth about this. When you see things like Double-Click on the FUN_ and similar mentions in this guide as I don't write out the full FUN_ name, it's because it's pointless for me to write out the address that comes attached, like FUN_106ac67a because you might see something different.


What to do when you find a function (also strongly recommended)

  • When you find and have verified a function, name it for future usage and to make it easier to cross reference stuff.

  • Rightclick the FUN_ in the Decompile window and pick "Edit Function Signature".

  • Look at the field Function Name.

  • In here, copy and paste the function name from this document to this field, then press OK. DO NOT CHANGE ANYTHING ELSE!!!

  • I also tend to copy over the "plate comment" from the .so binary (Linux) and adding it too onto discovered functions in the Windows binary.

  • For example for CObjectSentrygun::OnWrenchHit function.

    • The plate comment in the .so at the top of Decompile window says CObjectSentrygun::OnWrenchHit(CTFPlayer*, CTFWrench*, Vector)
    • Select it with the cursor and CTRL+C, then go back to the server.dll Listing Window, then go to the function you discovered (in this case CObjectSentrygun::OnWrenchHit), again right click the function name in the Decompile window.
  • But this time, hover the mouse over Comments and choose Set Plate Comment.

  • Make sure the Plate Comment tab is selected. Paste in the CObjectSentrygun::OnWrenchHit(CTFPlayer*, CTFWrench*, Vector) and change nothing else, just press OK.

  • Once you are done, press that tiny save disk to the very top-left of the CodeBrowser Window.

The Functions we need to hunt down.


Note: CTFMinigun::GetProjectileDamage and CTFMinigun::GetWeaponSpread were originally located by sheer dumb luck. These instructions are not going to work if Valve messes to much. Pray Valve doesn’t touch these functions ever again so you can just plop in the already found signatures and be happy.


CTFMinigun::GetProjectileDamage

Signatures (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x51\x56\x8B\xF1\xE8\x2A\x2A\x2A\x2A\xF3\x0F\x10\x8E\x2A\x2A\x2A\x2A\x0F\x57\xD2\x0F\x2F\xCA\xA1\x2A\x2A\x2A\x2A\xD9\x55\x2A\x72\x2A\xF3\x0F\x10\x40\x2A\xF3\x0F\x5C\xC1\xEB\x2A\x0F\x28\xC2\xF3\x0F\x10\x9E\x2A\x2A\x2A\x2A\x0F\x2F\xDA\x5E\xF3\x0F\x5C\x05\x2A\x2A\x2A\x2A\x72\x2A\xF3\x0F\x10\x48\x2A\xF3\x0F\x5C\xCB\xEB\x2A\x0F\x28\xCA\x0F\x2F\xC1\x77\x2A\x0F\x28\xC1\xF3\x0F\x10\x1D\x2A\x2A\x2A\x2A\x0F\x2F\xD8\x76\x2A\xF3\x0F\x5C\x05" 
"linux"   "@_ZN10CTFMinigun19GetProjectileDamageEv"

Finding It Without a Signature

You need to find CTFWeaponBase::GetProjectileDamage first to help verify that you have found CTFMinigun::GetProjectileDamage!

  • Search for the string:
mult_dmg_disguised
  • Look at its cross-references (XREFs) in the Listing Window.
    You should see a single FUN_ there. Double-Click it.
  • Rename the FUN_ to CTFWeaponBase::GetProjectileDamage

Now with CTFWeaponBase::GetProjectileDamage discovered. We can make a attempt at finding CTFMinigun::GetProjectileDamage

  1. Search for the string:

    ring_of_fire_while_aiming
    
  2. Look at its cross-references (XREFs).
    Ignore any that are within FUN_ labeled functions — you're looking for one that isn't automatically named with a FUN_

  3. If you're in the right spot, the disassembly (listing view) should resemble this:

        1061c675 68 1c 5f    PUSH    s_ring_of_fire_while_aiming_108d5f1c = "ring_of_fire_while_aiming"
                 8d 10
        1061c67a 6a 00       PUSH    0x0
        1061c67c e8 6f 05    CALL    CALL_ATTRIB_HOOK_INT    int CALL_ATTRIB_HOOK_INT(int par
                 bc ff
        1061c681 83 c4 14    ADD     ESP,0x14

Navigating From There

If you see the above, you're likely in the correct spot. Scroll down slightly:

  • You should see a FLDZ instruction.
  • You should also see a RET shortly after.
  • After a small gap of undefined bytes (??), a new function should begin.

In Ghidra (In the Windows Binary of TF2), a function (That is not Undefined) could look like this: function in ghidra
(Just took a random function to show what it can look like
the function in the image is NOT CTFMinigun::GetProjectileDamage)

That new function after the bunch of ?? is very likely CTFMinigun::GetProjectileDamage.

Immediately following that function in memory should be a new function. which is very very likely to be CTFMinigun::GetWeaponSpread.

Verifying

You can cross-check your find like this:

  • Make sure you already found and labeled:

    • CTFWeaponBase::GetProjectileDamage
    • CTFWeaponBase::GetWeaponSpread
  • In the function you believe is CTFMinigun::GetProjectileDamage, you should see an early call to CTFWeaponBase::GetProjectileDamage.

Also, if you look in the Decompile window to your right, you should see something that looks like this code snippet in it with values such as
0.75,1.0,1.25 and so on:

fVar3 = fVar2 - 0.75; if (fVar2 - 0.75 <= fVar4) { fVar3 = fVar4; } if (fVar3 < 1.0) { fVar2 = (fVar3 - 0.2) * 1.25; if (fVar2 <= 0.0) { fVar2 = 0.0; } if (1.0 <= fVar2) { fVar2 = 1.0; } fVar1 = (float10)((fVar2 + 1.0) * 0.5 * (float)fVar1); }


CTFMinigun::GetWeaponSpread

Signature (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x51\x56\x8B\xF1\xE8\x2A\x2A\x2A\x2A\xF3\x0F\x10\x8E\x2A\x2A\x2A\x2A\x0F\x57\xD2\x0F\x2F\xCA\xA1\x2A\x2A\x2A\x2A\xD9\x55\x2A\x72\x2A\xF3\x0F\x10\x40\x2A\xF3\x0F\x5C\xC1\xEB\x2A\x0F\x28\xC2\xF3\x0F\x10\x9E\x2A\x2A\x2A\x2A\x0F\x2F\xDA\x5E\xF3\x0F\x5C\x05\x2A\x2A\x2A\x2A\x72\x2A\xF3\x0F\x10\x48\x2A\xF3\x0F\x5C\xCB\xEB\x2A\x0F\x28\xCA\x0F\x2F\xC1\x77\x2A\x0F\x28\xC1\xF3\x0F\x10\x1D\x2A\x2A\x2A\x2A\x0F\x2F\xD8\x76\x2A\x0F\x57\xC9"
"linux"   "@_ZN10CTFMinigun15GetWeaponSpreadEv"

Finding It Without a Signature

You need to find CTFWeaponBase::GetWeaponSpread first to help verify that you have found CTFMinigun::GetWeaponSpread!

  • Search for the string:
mult_spread_scales_consecutive
  • Look at its cross-references (XREFs) in the Listing Window.
    You should see a single FUN_ there. Double-Click it.
  • Rename the FUN_ to CTFWeaponBase::GetWeaponSpread

Now with CTFWeaponBase::GetWeaponSpread discovered. We can make a attempt at finding CTFMinigun::GetWeaponSpread

  1. Just look at the next function after CTFMinigun::GetProjectileDamage in the Listing Window

  2. Verify if you found the correct one by confirming that it makes an early call to CTFWeaponBase::GetWeaponSpread. And again, you can also check Decompile window to your right and
    you should see something that looks like this code snippet in it with values such as
    0.75,1.0 and so on (it's slightly different from CTFMinigun::GetProjectileDamage):

  fVar4 = fVar2 - 0.75;  
  if (fVar2 - 0.75 <= fVar3) {  
    fVar4 = fVar3;  
  }  
  if (fVar4 < 1.0) {  
    if (fVar4 <= 0.0) {  
      fVar4 = 0.0;  
    }  
    if (1.0 <= fVar4) {  
      fVar4 = 1.0;  
    }  
    fVar1 = (float10)((1.5 - fVar4 * 0.5) * (float)fVar1);  
  }
  1. If you successfully found it, Rename the FUN_ to CTFMinigun::GetWeaponSpread

CTFPlayer::ApplyPunchImpulseX

Signature (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x83\xEC\x08\x53\x56\x8B\xF1\xB3\x01"
"linux"   "@_ZN9CTFPlayer18ApplyPunchImpulseXEf"

Finding It Without a Signature

  1. Search for the string:

    aiming_no_flinch
    
  2. Click on the result once.

  3. Look at its cross-references (XREFs) in the Listing Window.
    You should see a single FUN_ there. Double-Click it.

  4. If you are really unsure, look now at the decompiled code in the Decompile Window. You should see this line in there:

    uVar5 = FUN_101dcbf0(0,"aiming_no_flinch",(int)this,0,'\x01');
    
  5. Rename the FUN_ to CTFPlayer::ApplyPunchImpulseX

CTFProjectile_BallOfFire::Burn

Signature (last updated 13th May 2025)

"windows" "\x53\x8B\xDC\x83\xEC\x08\x83\xE4\xF0\x83\xC4\x04\x55\x8B\x6B\x2A\x89\x6C\x24\x2A\x8B\xEC\x81\xEC\x48\x02\x00\x00\x56\x57\x8B\xF9\x8B\x8F"
"linux"   "@_ZN24CTFProjectile_BallOfFire4BurnEP11CBaseEntity"

Finding It Without a Signature

  1. Search for the string:

    Weapon_DragonsFury.BonusDamage
    
  2. Click on the result once.

  3. Look at its cross-references (XREFs) in the Listing Window.
    You should see a single FUN_ there along with one without FUN_ in it. Double-Click it (do not click on the one without a FUN_).

  4. You should now be in the correct function. You can double-check by seeing if code similar to this appears:

        local_d4 = "Weapon_DragonsFury.BonusDamage";  
     if (param_1[6] == 0) {  
       iVar6 = 0;  
     }  
     else {  
       iVar6 = (int)*(short *)(param_1[6] + 6);  
     }  
     FUN_1032bab0(local_60,iVar6,&local_d8);  
     FUN_1012eab0(local_a8);  
     if (piVar4 != (int *)0x0) {  
       FUN_10211f60(&local_d8);  
       local_b8 = 0;  
       local_b4 = 0.0;  
       local_d4 = "Weapon_DragonsFury.BonusDamagePain";  
       FUN_104496a0(local_114,(int)piVar4);  
       if (piVar4[6] == 0) {  
         iVar6 = 0;  
       }  
    
  5. A extra way to doublecheck: These 3 strings should appear in the same function: Weapon_DragonsFury.BonusDamage, Weapon_DragonsFury.BonusDamagePain and
    Weapon_DragonsFury.BonusDamageHit

  6. Rename the FUN_ to CTFProjectile_BallOfFire::Burn

CTFWeaponBaseMelee::OnSwingHit

Signature (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x81\xEC\x50\x01\x00\x00\x53\x56\x57"  
"linux"   "@_ZN18CTFWeaponBaseMelee10OnSwingHitER10CGameTrace"

Finding It Without a Signature

  1. Search for the string:

    speed_buff_ally
    
  2. Click on the result once.

  3. Look at its cross-references (XREFs) in the Listing Window.
    You should see a single FUN_, Double-Click it.

  4. You should now be in the function, to doublecheck, you can look in the Decompiled Window and look for this code snippet:

       iVar5 = CALL_ATTRIB_HOOK_INT(0,"speed_buff_ally",(int)this,0,'\x01');  
    if  ((0 < iVar5) && (*(int *)(param_1 + 0x4c) != 0)) {  
      CTFPlayerShared::AddCond(this_00 + 0x6b8,4.48416e-44,2.0,(int *)0x0);  
      CTFPlayerShared::AddCond(piVar4 + 0x6b8,4.48416e-44,3.6,(int *)0x0);  
      FUN_10487ba0((int)this,(int)piVar4,this_00,0x42,1);  
    }
    

See how the first FUN_ call inside the if statement has 2.0 and the second has 3.6? Yes that's for The Disciplinary Action.

  1. After you have renamed the FUN_ to CTFWeaponBaseMelee::OnSwingHit, you might as well grab CTFPlayerShared::AddCond at the same time.

    • Go back to the if statement that had that 2.0 and 3.6 in the FUN_'s`parameters.
    • Double-click either of them (not the third one!).
    • name the FUN_ to CTFPlayerShared::AddCond.

CTFGameRules::PlayerMayCapturePoint

Signature (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x53\x56\x57\x8B\x7D\x2A\x8B\xD9\x85\xFF\x74\x2A\x8B\x07\x8B\xCF\x8B\x80"  
"linux" "@_ZN12CTFGameRules21PlayerMayCapturePointEP11CBasePlayeriPci"

Finding It Without a Signature

Search for the string "#Cant_cap_disguised" Click on it then check out the XREF. Click on the FUN_

Done.

  1. Search for the string:

    #Cant_cap_disguised
    

    (And yes, the # is part of the string do not omit it!)

  2. Click on the result once.

  3. Look at its cross-references (XREFs) in the Listing Window.
    You should see a single FUN_, Double-Click it.

  4. Rename the FUN_ to CTFGameRules::PlayerMayCapturePoint

CObjectSentrygun::OnWrenchHit

Signature (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x83\xEC\x08\x53\x56\x8B\xF1\x57\x80\xBE\x2A\x2A\x2A\x2A\x00\x74"  
"linux"   "@_ZN16CObjectSentrygun11OnWrenchHitEP9CTFPlayerP9CTFWrench6Vector"

Finding It Without a Signature

  1. First, we need to find CTFWrench::GetRepairAmount

    • Start by searching for the string:
    mult_repair_value
    
    • Click the result once.
    • Look at its cross-references (XREFs) in the Listing Window. you should see two FUN_'s, both of them are CTFWrench::GetRepairAmount
    • Double-click either of the two it does not matter.
    • Rename the FUN_ to CTFWrench::GetRepairAmount
  2. Now while still in the function CTFWrench::GetRepairAmount, look at the Listing Window. IMAGE_HERE

  3. Double-Click on one of the FUN_'s, if you arrive at a fairly short function, it's the wrong one. go back and try the other one.

  4. Now in the Decompile window, click once anywhere inside of it. then press CTRL+F to open the Decompiler find text dialog.

    • For Find: type
    0.33
    
    • Ensure that String is selected as format.
    • Press Next
    • Keep pressing Next until the dialog says Reached the bottom, continued from top
    • What you want to check: If 0.33 appears 3 times in the decompiled code, and that it's attached to code similar to this:
        if (*(int *)((int)this + 0xb34) == 1) {
       fVar8 = (float10)((float)fVar8 * 0.33);
     }
    
    • If it does, then you are in the correct function.
  5. Rename the FUN_ to CObjectSentrygun::OnWrenchHit

CTFLunchBox::ApplyBiteEffects

Signature (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x51\x53\x8B\xD9\x56\x57\x6A\x01"  
"linux" "@_ZN11CTFLunchBox16ApplyBiteEffectsEP9CTFPlayer"

Finding It Without a Signature

  1. Search for the string:

    lunchbox_healing_scale
    
  2. Click on the result once.

  3. Look at its cross-references (XREFs) in the Listing Window.
    You should see a single FUN_ there. Double-Click it.

  4. Rename the FUN_ to CTFLunchBox::ApplyBiteEffects

CTFProjectile_Arrow::BuildingHealingArrow

Signature (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x83\xEC\x24\x53\x56\x57\x8B\x7D\x2A\x8B\xD9\x57"  
"linux"   "@_ZN19CTFProjectile_Arrow20BuildingHealingArrowEP11CBaseEntity"

Finding It Without a Signature

  1. Search for the string:

    arrow_heals_buildings
    
  2. Click on the result once.

  3. Look at its cross-references (XREFs) in the Listing Window.
    You should see a single FUN_ there. Double-Click it.

  4. Rename the FUN_ to CTFProjectile_Arrow::BuildingHealingArrow

CBaseMultiplayerPlayer::AwardAchievement

Signature (last updated 13th May 2025)

"windows" "\x55\x8B\xEC\x83\xEC\x20\x56\x8B\xF1\x8D\x4D\x2A\xE8\x2A\x2A\x2A\x2A\x56\x8D\x4D\x2A\xC7\x45\x2A\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8D\x45\x2A\x68\x2A\x2A\x2A\x2A\x50\xE8\x2A\x2A\x2A\x2A\xFF\x75"  
"linux"   "@_ZN22CBaseMultiplayerPlayer16AwardAchievementEii"

Finding It Without a Signature

It's a good idea to first find two additional functions to make
it easier to identify the AwardAchivement function.
WRITE_SHORT
and
UserMessageBegin

  1. WRITE_SHORT

    • Search for the string:
    WRITE_SHORT called with no active message\n
    
    • Click on the result once.
    • Look at its cross-references (XREFs) in the Listing Window.
      You should see a single FUN_ there. Double-Click it.
    • Rename the FUN_ to WRITE_SHORT
  2. UserMessageBegin

    • Search for the string:
    UserMessageBegin:  Unregistered message
    
    • Click on the result once.
    • Look at its cross-references (XREFs) in the Listing Window.
      You should see a single FUN_ there. Double-Click it.
    • Rename the FUN_ to UserMessageBegin
  3. Now with these two functions discovered, search for the string:

AchievementEvent
  1. Now you will see two FUN_'s, double-click on one of them. look in the Decompile Window.

    • If you see a bunch of FUN_'s like this:
    FUN_1043f740(DAT_10a92324,"Geiger",1);  
    FUN_1043f740(DAT_10a92324,"Train",1);  
    FUN_1043f740(DAT_10a92324,"HudText",0xffffffff);  
    FUN_1043f740(DAT_10a92324,"SayText",0xffffffff);  
    FUN_1043f740(DAT_10a92324,"SayText2",0xffffffff);  
    ...
    

    that just keep going and going, you got the wrong FUN_, go back and double-click the other one.

  2. Now looking in the Decompile Window, you should see something like this:

    FUN_1030c540(local_24);
    local_24[0] = &PTR_`scalar_deleting_destructor'_1078e4f0;
    FUN_1030c960(local_24,(int)this);
    UserMessageBegin(local_24,0x1079725c);
    WRITE_SHORT(param_1);
    WRITE_SHORT(param_2);
    FUN_1026fce0();
    FUN_1030c6e0(local_24);
    return;
    

    If you do, then you are in the correct FUN_.

  3. Rename the FUN_ to CBaseMultiplayerPlayer::AwardAchievement

Preparing to make it easier to decode the mess in Decompile Window

Functions that are good to have to make it easier to read the Decompile Window

CTFPlayerShared::InCond

Found in CTFWeaponBaseGun::GetProjectileDamage. Use the function filter and search for it (you did name the function when you found it in the steps
for CTFMinigun::GetProjectileDamage, right?).

When the function has been opened in the Decompile Window,
click somewhere inside of it. Then press CTRL+´F to open
the search window.

For Find:, enter mult_dmg_disguised. Make sure
String is selected. Then press Next.

You should now have arrived at
something that looks something like this:

bVar2 = FUN_1051ff20(piVar3 + 0x6b8,3); if (!bVar2) goto LAB_106385b3; fVar8 = FUN_1044b7d0((float)fVar8,"mult_dmg_disguised",(int)param_1,0,'\x01'); local_8 = (float)fVar8;

Look at the first line, what's interesting is the last parameter, which is 3.
Keep this in mind.
Now go to the original SourceCode (source sdk 2013).

Search for mult_dmg_disguised in the file
src/game/shared/tf/tf_weaponbase_gun.cpp.

You ought to arrive at something like this:

// Some weapons mod dmg when not disguised bool bDisguised = pPlayer && pPlayer->m_Shared.InCond( TF_COND_DISGUISED ); if ( bDisguised ) { CALL_ATTRIB_HOOK_FLOAT( flDamage, mult_dmg_disguised ); }

If you also check the file src/game/shared/tf/tf_shareddefs.h.
The Value of `TF_COND_DISGUISED``is 3.

Besides as the final verify: We know that mult_dmg_disguised
only has a single FUN_ in the XREF.
bVar2 is assigned whatever we got from FUN_1051ff20
which can be nothing else but InCond function.

Rightclick on FUN_1051ff20 in the Decompiled Window in Ghidra.
Name it CTFPlayerShared::InCond.

CALL_ATTRIB_HOOK_FLOAT

Just follow the steps for CTFPlayerShared::InCond as the FUN_
directly after the if statement is that one.

Vars that are good to have to make it easier to read the Decompile Window

Something one can do to make it easier to read the decompiled code
and compare to the .so binary (and the original source code)
is to find and name the vars.

gameeventmanager

Search for the string halloween_pumpkin_grab and click it, in the XREF you should see PackTouch (PackTouch is always avaible
despite Windows TF2 server binary not containing debug symbols).

Double Click on PackTouch. Now go to Decompile Window. You should see something like this:

piVar8 = (int *)(**(code **)(*DAT_10a2b7d4 + 0x18))("halloween_pumpkin_grab");

That DAT_ is the gameeventmanager.
Rightclick on it in the Decompiled Window,
then pick Rename Global.

In the dialog option, look at Enter Label:
Name it gameeventmanager, change nothing else and just press OK.

Don't forget to press the tiny Save Disk Icon in the top left!

engine

Located just below the gameeventmanager in PackTouch.
Since you have already done the steps for it, you can just rightclick
on the DAT_ and repeat with renaming

The code should look something like this:
uVar7 = (**(code **)(*DAT_10a2b7b4 + 0x3c))();
but use engine instead as the label.

gpGlobals

Probably one of the most important global vars to name to make it easier for you.

It's found in CTFWeaponBaseGun::GetProjectileDamage.
Open the function so it appears in the Decompiled Window.

Click somewhere in that window, and press CTRL+F.
In Find:, write accuracy_scales_damage, make sure
String is selected and press Next.

Directly below the search result is a line that looks kinda like this:
ìVar6 = DAT_10a2b7e8;.

Or for more context:

fVar8 = CALL_ATTRIB_HOOK_FLOAT(1.0,"accuracy_scales_damage",(int)param_1,0,'\x01'); iVar6 = DAT_10a2b7e8;

It's the line directly below the call to that float function. That DAT_ is the gpGlobals.
Rightclick on it in the Decompiled Window,
then pick Rename Global.

In the dialog option, look at Enter Label:
Name it gpGlobals, change nothing else and just press OK.

Don't forget to press the tiny Save Disk Icon in the top left!

makesig.py - the wonder tool that builds signatures for you.

makesig.py is a script that helps you build the shortest unique signatures for the Windows Binary. It can also be used for Linux if for some weird reason the mangled name does not work,
but 99.99% of the time you will not need to use a byte signature for the Linux binary.

The ultimate chad: nosoop, made this tool. You can go here if you want to see the original.
https://github.com/nosoop/ghidra_scripts Big thanks to our lord and savior (he also made SourceScramble. Kneel apes!)

You can find the script in the makesig.py section (It's quite large which is why it has it's own
wikipage): WIKIPAGE HERE

After you have copied the script, Look at the top of your CodeBrowser window. Find Window, click it. Then click at Script Manager. Alternatively click on the Green Play Button in the toolbar.

With the Script Manager open, it ought to ask you the first time around where you want your scripts.
If it did not, click this button.

scriptmanager_toolbar

Then, in the Bundle Manager Window, click the red + sign.
A dialog option should open asking you to choose a folder,
jar or bnd files.

You want to create a new folder in whatever location is appropriate for you.

If Linux: /home/YOUR_USER_NAME/ghidra_scripts

If Windows: C:\Users\YOUR_USER_NAME\Mina dokument\ghidra_scripts

The folder MUST be named ghidra_scripts or Ghidra
will not accept it.
Once you are done, make sure it's ticked in the square checkbox
in the Bundle Manager, Ghidra should have done this automatically but best to check.

Now close down Bundle Manager and press the button next to the Refresh Button.

scriptmanager_toolbar_createnew

Ghidra will ask you what type of script you are planning to make.
Choose Jython if it's not already selected, and press OK.

It will then ask you to select a directory, you should now see the earlier ghidra_scripts folder that you created.
Select it, and for Enter script file name:
write in makesig.py and press OK.

If you see this dialog:

dialog directory activate automatically scriptmanager

Then just press OK.

It should now open a editor, it should look kinda like this:

script editor scriptmanager

Just remove everything inside of makesig.py, then paste in the makesig.py code you either got from this wiki or nosoops original.

finished makesig scriptmanager

Press the tiny Save Disk, and you are done.

Speeding up makesig.py usage

Instead of having to constantly open the script manager, you can assign a hotkey to
the makesig.py script.

hotkeying makesig - scriptmanager

If you have issues finding the makesig.py script, just type makesig into the Filter: field at the bottom of Script Manager.

Then, rightclick the makesig script and select Assign Key Binding. Now, just press your Hotkey, then click OK. (I use CTRL+NUMPAD0 if you are wondering).

Finally using makesig.py

Now we are setup to start generating signatures. We will use CTFWeaponBaseGun::GetProjectileDamage for this exercise.

Begin by opening the function in the CodeBrowser. Once you have it open, look in the Listing Window. Click on either the function name in the Decompiled Window OR the start address of the function (you do not need to select it as if selecting text, just click once).

click here or here for makesig - signature_generation

After you have clicked one of the two (which one does not matter).
Press your hotkey or open Script Manager and double-click on makesig.py

You will see a dragon logo that looks like it's chewing on bits of data (lmfao).
after it's done loading, you should see this:

running makesig - generating signature

You want to have start of function
selected, then press OK.

After just a few seconds, you should see output at the bottom of CodeBrowser Window.

If you are using my modified one from the wiki, you will see this:

Signature for CTFWeaponBaseGun::GetProjectileDamage Shortest Unique: Ghidra: 55 8B EC 83 EC 1C 53 56 8B D9 57 89 5D Gamedata: \x55\x8B\xEC\x83\xEC\x1C\x53\x56\x8B\xD9\x57\x89\x5D Optional 24-Byte Signature: Ghidra: 55 8B EC 83 EC 1C 53 56 8B D9 57 89 5D ? E8 ? ? ? ? 8B F8 85 FF 74 Gamedata: \x55\x8B\xEC\x83\xEC\x1C\x53\x56\x8B\xD9\x57\x89\x5D\x2A\xE8\x2A\x2A\x2A\x2A\x8B\xF8\x85\xFF\x74 Optional 32-Byte Signature: Ghidra: 55 8B EC 83 EC 1C 53 56 8B D9 57 89 5D ? E8 ? ? ? ? 8B F8 85 FF 74 ? 8B 17 8B CF 8B 92 ? Gamedata: \x55\x8B\xEC\x83\xEC\x1C\x53\x56\x8B\xD9\x57\x89\x5D\x2A\xE8\x2A\x2A\x2A\x2A\x8B\xF8\x85\xFF\x74\x2A\x8B\x17\x8B\xCF\x8B\x92\x2A

If you are using the original one nosoop made, you will see this:

Signature for CTFWeaponBaseGun::GetProjectileDamage 55 8B EC 83 EC 1C 53 56 8B D9 57 89 5D \x55\x8B\xEC\x83\xEC\x1C\x53\x56\x8B\xD9\x57\x89\x5D

The one without \x is used to search in the binary for that sequence of bytes which can be handy (Search>Memory.... While the \x one is for the gamedata folder.

There's not much more to it really. The next section will take all we have learned so far, and show how to update signatures and offsets.

How to update signatures and offsets

UNDER CONSTRUCTION