I checked your sequence of bytes with IDA and it doesn't match to any function so it's likely wrong. To check yourself, in IDA, go to search, sequence of bytes, add your sequence and select find all occurrences and see if you get a result. Always check the sequences you make.
How to find the function you need:
Since TeamFull is really small and doesn't contain strings you can't find it directly. Look for a function that calls it and that preferable has strings or is called from a function that has strings. Checking regamedll we find HandleMenu_ChooseTeam that calls TeamFull and we are lucky, HandleMenu_ChooseTeam has a bunch of strings.
Just pick one, like "#Too_Many_Terrorists"(without quotes) and go to Strings window and search(alt+t) with this string. You should see something like this:
Code:
.data:101155E4 23 54 6F 6F 5F 4D 61 6E 79 5F+aTooManyTerrori db '#Too_Many_Terrorists',0
.data:101155E4 54 65 72 72 6F 72 69 73 74 73+ ; DATA XREF: sub_10066D10+243↑o
DATA XREF is what you are looking for. It tells you that the string is used inside sub_10066D10 => sub_10066D10 is HandleMenu_ChooseTeam. Now rename it so you can easily find it in the future.
Now, ideally, you would want to decompile HandleMenu_ChooseTeam(press F5) and look in the decompiled C-like code. If you don't have IDA with a decompiler then there is an alternative, but you need to be able to read assembly code.
Let's assume you don't have the decompiler. Go to IDA View A.
We see this in regamedll:
PHP Code:
if (CSGameRules()->TeamFull(team))
{
// The specified team is full
// attempt to kick a bot to make room for this player
bool madeRoom = false;
if (cv_bot_auto_vacate.value > 0 && !pPlayer->IsBot())
{
if (UTIL_KickBotFromTeam(team))
madeRoom = true;
}
if (!madeRoom)
{
ClientPrint(pPlayer->pev, HUD_PRINTCENTER, (team == TERRORIST) ? "#Terrorists_Full" : "#CTs_Full");
return FALSE;
}
}
TeamFull is near "#Terrorists_Full" string. So scroll on IDA View A until you find that string. Remember, what we are doing now is trying to find TeamFull call inside HandleMenu_ChooseTeam. We will look for an assembly instruction named "call", which is used to call functions.
Just a bit above this strings(4 lines) we see this:
Looks promising, it's a function call before our strings. But is it the right function? Let's look under it.
Code:
test eax, eax
jz short loc_10066F7C
In assembly, functions usually put their return values in eax register. Testing eax right after a call instruction usually means the code is checking for the return value.
test does bitwise and, so test eax, eax will set a flag called zero flag only if the return value stored in eax is 0.
The next instruction after this jz loc_10066F7C. jz checks if the zero flag is set(jump if 0) and if it is it will jump to loc_10066F7C address in the code(like a goto in pawn/C). Now look where loc_10066F7C is actually placed. It's way lower than the block of code we are interested in(the one with the strings).
If we put all this pieces together: the code calls a function, checks if it returned 0 and if it does return 0 it jumps away from the code we are interested in, exactly like when a if statement is false and the block of code from the if doesn't execute.
At this point you can be pretty sure that sub_1008ECA0 is the function we need. The assembly code matches the code we saw in regamedll.
You can also check the content of sub_1008ECA0 itself to make sure it matches the code from regamedll(and if do that you see it check for 1 or 2 which are the teams and returns something, so looks fine).
Let's build the signature:
Rename the function from sub_1008ECA0 to CHalfLifeMultiplay_TeamFull to make it easier in the future.
The bytes look like this:
Code:
8B 54 24 04
56
8B 74 24 0C
3B D6
75 06
....
From each line, you will keep only the first byte and replace the other bytes with ?, resulting in:
Code:
8B ? ? ? 56 8B ? ? ? 3B ? 75
We don't know if this is an unique identifier for our function, so search the sequence and notice that we get only one result. This means that the signature is good.
Now convert into orpheu format: [0x8B,"*","*","*",0x56,0x8B,"*","*","*",0x3B," *",0x75]
The signature file is almost correct, but you are missing the return value. In regamedll it is BOOL, but that's not a default type. BOOL is just a define for int(you can check by yourself).
The final result:
Code:
{
"name" : "TeamFull",
"class" : "CHalfLifeMultiplay",
"library" : "mod",
"arguments" :
[
{
"type" : "int"
}
],
"return" :
{
"type" : "int"
},
"identifiers" :
[
{
"os" : "windows",
"mod" : "cstrike",
"value" : [0x8B,"*","*","*",0x56,0x8B,"*","*","*",0x3B,"*",0x75]
},
{
"os" : "linux",
"mod" : "cstrike",
"value" : "_ZN18CHalfLifeMultiplay8TeamFullEi"
}
]
}
With orpheu loaded write "orpheu config" in the server console and look for the output:
Code:
Parsing file "TeamFull" started
Argument type "int" validated
Return type "int" validated
Searching for signature "[0x8b][*][*][*][0x56](...)" ... FOUND
Parsing file "TeamFull" ended
__________________