Linux shows the symbols (used for linux sigs, the "@_zSomeFuncName123x") and names of functions [SomeFuncName(CBasePlayer)] but Windows is missing these and functions appear as sub_####. So we have to find something unique in the linux binary to reference and find in the windows binary.
The simplest thing to match are strings. Find a unique string in the linux file and find that in the windows one. Hopefully from the same function you're intending to use. Otherwise you start to jump around with xrefs.
For example: Function1 calls Function2. We want Function2 but it has no unique strings, Function1 has a unique string. So we find Function1 in windows, and find the call to Function2.
Or vice versa you want Function1 but only have a unique string to Function2. Goto the top of the Function2 (where it says something like "_zSomeFuncName123x" (just below the function "MyFunction2(*CBasePlayer this))" function name and press X, this will show a list of XRefs, other functions which are calling this one. Hopefully only Function1 is calling and we have our target.
Now the more complex stuff, if the above fails, we have no unique strings in any of the calls our target function uses or any from the functions calling our function (xrefs). Or there are too many calls to figure out our function.
We can (in most cases) use the VTable. When viewing the XRef list, look at Address line, you'll hopefully see ".rodata". Double click this and now you're viewing the vtable. Hopefully by viewing the nearby functions you can find a unique string to search for on windows. Then find that vtable on windows and count up or down in the vtable till you get to your function. The VTable usually doesn't change between OS so if your functions 5th down on Linux vtable from some unique reference you can find on windows, it's most likely the 5th down on windows too, but not 100% of the time.
I'm not good at explaining things so I hope this helps somewhat.
Edit: I've identified functions without strings or vtables by jumping around calls near the intended target function and with the use of HexRays for IDA visually comparing the code (especially useful if you have 5 different potential functions with your unique string, most of the time you'll be able to easily see your target one and the others are very different) . Visually comparing can be useful but it's rare to actually resort to this. I've only done that once. Another thing I did only once was search for a specific value or set of bytes and by chance they were identical in windows.
Edit2: Here is something I wrote up as an example some years ago to help a few others. Not sure how valid it is now, at least it might help.
PHP Code:
/*
* CTerrorPlayer::SetBecomeGhostAt(float)
* Finding:
1. Open server.so binary.
2. In the functions subview window search for "SetBecomeGhostAt"
3. Because there are no strings we need to view xrefs for the function (press X).
4. It's only called from "CanBecomeGhost" and several times.
5. Jump to "CanBecomeGhost" (press OK or double click a one of the xref addresses).
6. Thankfully this function has some strings. We will use "ghost_spawn_time".
7. Open server.dll and search (Alt T) in the strings subview window for "ghost_spawn_time".
8. Now we need to find the "SetBecomeGhostAt" function from here.
9. We are looking for a "call" and maybe with "movss" before it just like in the .so binary.
.text:1030AF0C F3 0F 11 04 24 movss [esp+14h+var_14], xmm0
.text:1030AF11 E8 3A D2 FD FF call sub_102E8150
10. Jump to the call sub_ (double click) and check if it's the same function (visually similar code, or using hex-rays F5).
11. In our function we can see both .dll and .so have: call ___RTDynamicCast
12. Check xrefs and it's only called from our previous function.
13. This is all good enough for me to assume it's the same and correct function.
14. Now we need to make a unique signature. We wildcard bytes which may change in future updates due to code shifting around. So all offsets: jmps, calls
In brackets are bytes I would wildcard, the F3 0F one because I'm not entirely sure but I think function arguments can change
if I wanted to properly know I'd google the asm and try to determine if I needed to wildcard everything.
.text:102E8150 55 push ebp
.text:102E8151 8B EC mov ebp, esp
.text:102E8153 F3 0F 10 [45 08] movss xmm0, [ebp+arg_0]
.text:102E8158 56 push esi
.text:102E8159 6A 00 push 0
.text:102E815B 68 [A4 83 78 10] push offset off_107883A4
*/
"CTerrorPlayer::SetBecomeGhostAt"
{
"library" "server"
"linux" "@_ZN13CTerrorPlayer16SetBecomeGhostAtEf"
"windows" "\x55\x8B\xEC\xF3\x0F\x2A\x2A\x2A\x56\x6A\x00\x68"
/* 55 8B EC F3 0F ? ? ? 56 6A 00 68 */
}
Edit3: Once you found the function in windows, you can copy the bytes from the start of the function and start wildcarding and testing by pressing Alt+B in IDA to search for a binary string of bytes.
Sometimes even though you have a unique sig it won't be found because the bytes have changed in memory. You need to wildcard more. You can easily test various signatures by using the
[ANY] Gamedata Sig Tester plugin. You can view more details about this stage on the wiki
Signature Scanning.
__________________