-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Speed up PE thunk and float search #70
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a nice improvement overall! I'd prefer to see a test and fix for the potential overlap issue before merging.
|
||
# TODO: Should check any section that has code, not just .text |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this TODO still relevant? Do you maybe want to add a follow-up ticket? I realised that there are more instances of this TODO around
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -22,6 +23,14 @@ | |||
|
|||
# pylint: disable=too-many-lines | |||
|
|||
# Match 6 byte absolute jump instructions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a suggestion (since this would also have applied to the old code): Since the reader (like me) might not be too familiar with the machine code instructions, maybe it would make sense to add some more information here? Like only those types of jumps are affected by the reloc table.
|
||
# Match floating point instructions. | ||
float_re = re.compile( | ||
rb"([\xd8\xd9\xdc\xdd])([\x05\x0d\x15\x1d\x25\x2d\x35\x3d])(.{4})", flags=re.S |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here - I couldn't tell from looking at it why this list is correct or complete.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, this needs more information. I forget how I arrived at this list. Maybe just from reading the opcodes and cutting it down to the instructions that reference a pointer
# We will check against possible float opcodes | ||
raw = text.read_virtual(addr - 2, 6) | ||
(opcode, opcode_ext, const_addr) = struct.unpack("<BBL", raw) | ||
for opcode, _, const_addr_bytes in float_re.findall(text_raw): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the second part need a match group if we are not interested in it?
if const_addr in seen_addrs: | ||
continue | ||
|
||
if opcode in (b"\xD8", b"\xD9"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Casing inconsistent with regex above; I'd go with all upper or all lower case for hex codes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was a black
adjustment in my stashed file, but now it doesn't seem to care if they're lower case.
text_raw = bytes(text_sect.view) | ||
|
||
# Find all 6 byte absolute jumps: FF 25 (addr) | ||
for match in abs_jump_re.finditer(text_raw): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
findall
above, finditer
here - we can probably use finditer
above as well
text_raw = bytes(text_sect.view) | ||
|
||
# Find all 6 byte absolute jumps: FF 25 (addr) | ||
for match in abs_jump_re.finditer(text_raw): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One potential issue (that doesn't happen for isle, but it could happen): finditer
and findall
look for non-overlapping matches. So there could be an instruction right before the jump that happens to have a FF 25
in its arguments, which then causes the subsequent jump to not be recognized. While taking a brief look I found this StackOverflow thread: https://stackoverflow.com/q/5616822/10666668
If you find a fix for that, it'd also be great to add a unit test. I am also not sure if the old version would handle that correctly or not.
Looking at the big picture, would it be better to move these two functions outside of |
Good point! We should separate the container formats (PE/ELF/MACHO/...) from the architectures (x86/x86_64/..) |
Haven't forgotten this. I'm going to move each of these functions to these to their own module which (I think) is a much better design. Since both of the interactions with the "compare core" and the database are just calling each of these functions, we could (eventually) move that code there too. The situation with the FPU instructions is more complicated than I had thought when I did the first version of this code. I think I landed on an okay subset of instructions but there are a few more we should get. |
When searching for thunks and floating point constants, we are looking for a specific kind of instruction. A binary regex makes sense and is much faster than the hacky approach we had before.
The float method would return duplicates where the same constant was used in multiple locations. That's now fixed.
I removed
populate_thunks
and there is now justthunks
, a@cached_property
.