Closed malloc2k closed 2 months ago
Hey there, the first signature you mentioned uses 0x2A for wildcards, I assume.
Generally speaking:
It comes down to the use case and personal preference. I personally prefer shorter signatures, as they can also be matched slightly quicker than long signatures. It ultimately depends on what you are working with.
My plugin generates "40 56 57 48 81 EC 88 00 00 00" by default for the shortest direct signature. It includes the part where it reserves memory for the stack variables, and the value 0x88 can change once there is a change in variable count or size inside of the function. It is "good enough" for that version of server dll, but I'd also deem this a rather weak signature.
In that case, you can click on the "Operand types" Button of my plugin, and check "Immediate Value" as wildcardable operands, so the 0x88 part is wildcarded. Then, the signature becomes longer and changes to "40 56 57 48 81 EC ? ? ? ? 48 8B F9 8B F2", which is two bytes shorter than the one you originally posted. I'd say this is probably good enough, but it's better to check multiple versions of server.dll to check for uniqueness.
If that's not "accurate" enough for you, and you want to manually define how many instructions should be included in the signature, select parts of the code like this: and select the "Copy selected code" option. It can be as long as you like: "40 56 57 48 81 EC ? ? ? ? 48 8B F9 8B F2 8B CA E8 ? ? ? ? 48 85 C0 0F 84 ? ? ? ? 8D 46 ? 83 F8".
If generating signatures for the function itself doesnt work out, you can still search for references of your function and create signatures for those ("Find shortest XREF signature..." option from the plugin), if that gives you better results:
Top 5 Signatures out of 6 xrefs for 18060C5B0:
XREF Signature #1 @ 1804F4030: E8 ? ? ? ? EB ? 49 8D 9F
XREF Signature #2 @ 180511FC8: E8 ? ? ? ? 40 84 FF 40 0F 94 C7
XREF Signature #3 @ 1805EF87A: E8 ? ? ? ? B3 ? E9 ? ? ? ? BA ? ? ? ? 48 8B CF
XREF Signature #4 @ 1805EF88E: E8 ? ? ? ? B3 ? E9 ? ? ? ? BA ? ? ? ? 48 8D 0D
XREF Signature #5 @ 1805123D9: E8 ? ? ? ? 48 83 C3 ? 48 83 EF ? 75 ? 4C 8B 7C 24 ? 45 85 E4
Each one of these signatures points to code that calls your desired function, like "call sub_18060C5B0".
All of the above methods should individually fullfill the job. At the end, a good signature should be long enough to uniquely match your selected part of the code, yet be as short as possible to still match over multiple binary revisions.
Only time (and updated/future or historical versions of server.dll) will tell which one of those signatures are actually good and stable, and which ones are not. I'd personally probably stick with "40 56 57 48 81 EC ? ? ? ? 48 8B F9 8B F2".
The signature you mentioned (\x8B\xCA\xE8\x00\x00\x00\x00\x48\x85\xC0\x0F\x84\x00\x00\x00\x00\x8D\x46) can't be found in server.dll. How did you get that?
Hey there, the first signature you mentioned uses 0x2A for wildcards, I assume.
Generally speaking:
- Longer signatures might be more "accurate" and you can be more certain that you find the exact same function again, because more parts of the code have to match.
- At the same time, once a small part of the signatured code changes, the signature will "break" and you won't be able find the function anymore. By having a longer signature, you have a slightly higher probability that your signature can break over time, and thus, shorter signatures can be deemed "more stable".
- However, there is also a small chance for shorter signatures to be matched in other parts of the code (when the server.dll gets updated and new functions are introduced), thus losing its uniqueness.
It comes down to the use case and personal preference. I personally prefer shorter signatures, as they can also be matched slightly quicker than long signatures. It ultimately depends on what you are working with.
My plugin generates "40 56 57 48 81 EC 88 00 00 00" by default for the shortest direct signature. It includes the part where it reserves memory for the stack variables, and the value 0x88 can change once there is a change in variable count or size inside of the function. It is "good enough" for that version of server dll, but I'd also deem this a rather weak signature.
In that case, you can click on the "Operand types" Button of my plugin, and check "Immediate Value" as wildcardable operands, so the 0x88 part is wildcarded. Then, the signature becomes longer and changes to "40 56 57 48 81 EC ? ? ? ? 48 8B F9 8B F2", which is two bytes shorter than the one you originally posted. I'd say this is probably good enough, but it's better to check multiple versions of server.dll to check for uniqueness.
If that's not "accurate" enough for you, and you want to manually define how many instructions should be included in the signature, select parts of the code like this: and select the "Copy selected code" option. It can be as long as you like: "40 56 57 48 81 EC ? ? ? ? 48 8B F9 8B F2 8B CA E8 ? ? ? ? 48 85 C0 0F 84 ? ? ? ? 8D 46 ? 83 F8".
If generating signatures for the function itself doesnt work out, you can still search for references of your function and create signatures for those ("Find shortest XREF signature..." option from the plugin), if that gives you better results:
Top 5 Signatures out of 6 xrefs for 18060C5B0: XREF Signature #1 @ 1804F4030: E8 ? ? ? ? EB ? 49 8D 9F XREF Signature #2 @ 180511FC8: E8 ? ? ? ? 40 84 FF 40 0F 94 C7 XREF Signature #3 @ 1805EF87A: E8 ? ? ? ? B3 ? E9 ? ? ? ? BA ? ? ? ? 48 8B CF XREF Signature #4 @ 1805EF88E: E8 ? ? ? ? B3 ? E9 ? ? ? ? BA ? ? ? ? 48 8D 0D XREF Signature #5 @ 1805123D9: E8 ? ? ? ? 48 83 C3 ? 48 83 EF ? 75 ? 4C 8B 7C 24 ? 45 85 E4
Each one of these signatures points to code that calls your desired function, like "call sub_18060C5B0".
All of the above methods should individually fullfill the job. At the end, a good signature should be long enough to uniquely match your selected part of the code, yet be as short as possible to still match over multiple binary revisions.
Only time (and updated/future or historical versions of server.dll) will tell which one of those signatures are actually good and stable, and which ones are not. I'd personally probably stick with "40 56 57 48 81 EC ? ? ? ? 48 8B F9 8B F2".
The signature you mentioned (\x8B\xCA\xE8\x00\x00\x00\x00\x48\x85\xC0\x0F\x84\x00\x00\x00\x00\x8D\x46) can't be found in server.dll. How did you get that?
Hey,
First of all thanks for the dedication writing all that, it really helped me out understand a bit more about all this.
The signature i sent you is from a popular metamod:source plugin (the lowest level of plugin making for CS2 and other games) called CS2Fixes. They have a file called "cs2fixes.games.txt" -> here they store their signatures in order to post hooks to their respective functions. The people that put the sigs there are highly experience hence why I decided to follow their steps on trying to find signatures in order to learn.
The signature I sent that "should be" (and it is) is the first one from these guys.
The second one is from using your plugin. Signature for 18060C5BF: \x8B\xCA\xE8\x00\x00\x00\x00\x48\x85\xC0\x0F\x84\x00\x00\x00\x00\x8D\x46 xxx????xxxxx????xx
idk if the little xxx etc did anything so i just removed it off :/
that is the actions and outputs im using in order to get it
Yeah @A200K i just check the little xxx????xxxxx????xx and so on so on really mattered. I didnt know that, I was able to find it.
1 more question. What differs this plugin from "Fusion"? Thanks
Yes the wildcars are 0x2A
@malloc2k The little "xxx????xxxxx????xx" is actually the mask of the signature. You see, the signature represents the individual bytes of the executable code. Because the code(-bytes) can change over multiple revisions and updates of a program (or game), wildcards are introduced on parts that are very likely to change.
The bytes are: \x8B\xCA\xE8\x00\x00\x00\x00\x48\x85\xC0\x0F\x84\x00\x00\x00\x00\x8D\x46
The mask is: xxx????xxxxx????xx
An 'x' in the mask flags parts of the signature that should be matched as they are, while the '?' marks a wildcard, i.e. the byte value can be anything.
\x8B -> x \xCA -> x \xE8 -> x \x00 -> ? \x00 -> ? \x00 -> ? \x00 -> ? \x48 -> x etc.
That means, in memory, we look for a sequence of the bytes: 8B, CA, E8, anything, anything, anything, anything, 48 etc. By leaving away the mask, you won't be able to figure out what part of the signature should be matched exactly and what part is a wildcard. You could introduce a byte like 0x2A to represent questionmarks instead of having a separate mask, that's appearantly what the author of the CS2Fixes project did. It's not optimal though, as you won't be able to exactly match that specific 0x2A byte anymore.
The separated bytes + mask signature is actually pretty old. A modern approach is the IDA style signature, that combines bytes and wildcard questionmarks (mask) into one string.
I see. You created a signature for the address 18060C5BF
. If you want to achieve the same signature as in the other source code, you need to go to address 18060C5B0
(B0, not BF) and select that specific line in IDA before pressing CTRL+ALT+S.
This project was my very basic crude approach of a signature scanner plugin that I wrote to my liking (mostly for fun). Over time, people actually started using it and requested features for some reason, so I kept working on it. I was quite surprised how many stars (and active users) my project got :)
I never used fusion, I can't tell from experience. Compared to fusion (https://github.com/senator715/IDA-Fusion), my scanner plugin
Most of the time, the features were suggested by active users, and I just listened.
On the other hand, fusion might have some other extra features and options that I don't have, or it might be nicer to use. Whether you need some specific features is up to you. Fusion also spent a bit more time beautifying and explaining its features and functionality in the README, where I am currently lacking a bit. In the end, they are all the same, they create signatures :)
@malloc2k The little "xxx????xxxxx????xx" is actually the mask of the signature. You see, the signature represents the individual bytes of the executable code. Because the code(-bytes) can change over multiple revisions and updates of a program (or game), wildcards are introduced on parts that are very likely to change.
The bytes are:
\x8B\xCA\xE8\x00\x00\x00\x00\x48\x85\xC0\x0F\x84\x00\x00\x00\x00\x8D\x46
The mask is:xxx????xxxxx????xx
An 'x' in the mask flags parts of the signature that should be matched as they are, while the '?' marks a wildcard, i.e. the byte value can be anything.
\x8B -> x \xCA -> x \xE8 -> x \x00 -> ? \x00 -> ? \x00 -> ? \x00 -> ? \x48 -> x etc.
That means, in memory, we look for a sequence of the bytes: 8B, CA, E8, anything, anything, anything, anything, 48 etc. By leaving away the mask, you won't be able to figure out what part of the signature should be matched exactly and what part is a wildcard. You could introduce a byte like 0x2A to represent questionmarks instead of having a separate mask, that's appearantly what the author of the CS2Fixes project did. It's not optimal though, as you won't be able to exactly match that specific 0x2A byte anymore.
The separated bytes + mask signature is actually pretty old. A modern approach is the IDA style signature, that combines bytes and wildcard questionmarks (mask) into one string.
I see. You created a signature for the address
18060C5BF
. If you want to achieve the same signature as in the other source code, you need to go to address18060C5B0
(B0, not BF) and select that specific line in IDA before pressing CTRL+ALT+S.This project was my very basic crude approach of a signature scanner plugin that I wrote to my liking (mostly for fun). Over time, people actually started using it and requested features for some reason, so I kept working on it. I was quite surprised how many stars (and active users) my project got :)
I never used fusion, I can't tell from experience. Compared to fusion (https://github.com/senator715/IDA-Fusion), my scanner plugin
- is tremendously faster than fusion due to AVX signature scanning, noticeable on larger files
- has an XREF signature creation feature that the other plugin does not have
- allows you to select operands that should be wildcarded
- allows selection of instructions that should make up the signature (Copy selected bytes)
- has a more user friendly signature searching feature that extracts relevant parts and allows searching for any signature type
- has an extra signature output format
- also works on ARM binaries
- ...
Most of the time, the features were suggested by active users, and I just listened.
On the other hand, fusion might have some other extra features and options that I don't have, or it might be nicer to use. Whether you need some specific features is up to you. Fusion also spent a bit more time beautifying and explaining its features and functionality in the README, where I am currently lacking a bit. In the end, they are all the same, they create signatures :)
Hey once again,
thanks for all the clarification. I was actually aware ( in really really vast terms ) that the signatures had a mask, but I’ve never seen that style mask before, that’s why when I saw the signatures presented on CS2 Fixes I assumed this just wasn’t a thing anymore and just ignored it 😂.
Anyways, thanks for the clarification on fusion too, I’ve used it in the past and now I can to yours and I see it’s quite fast compared to it :)
You just earned a star ⭐️ :))
I also have like 1.2€ on PayPal I would like to send you, just to contribute ( for as little as 1.20€) is I think you deserve it, if you don’t mind drop your PayPal or PayPal.me link and I’ll gladly give you what I have for all this work and help.
Thanks so much,
malloc2k
@malloc2k No worries, you don't have to pay me :) Thanks for your kindness :)
Im kinda new to all this of reverse engineering and im currently working on CS2 (server.dll), to learn a bit I use the sigs that are correct from some guys and their sigs are long (better I assume?). When i gen myself the same sig, it comes shorter and seems like "imcomplete", is that normal or am I just dumb?
The Sig should is
\x40\x56\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\xF9\x8B\xF2\x8B\xCA
But the one i get from using this plugin is
\x8B\xCA\xE8\x00\x00\x00\x00\x48\x85\xC0\x0F\x84\x00\x00\x00\x00\x8D\x46
Thanks in advance!