-
-
Save alexander-hanel/76c6c06d7a2a75ccb5ace0805b38554a to your computer and use it in GitHub Desktop.
| import yara | |
| import operator | |
| import idautils | |
| SEARCH_CASE = 4 | |
| SEARCH_REGEX = 8 | |
| SEARCH_NOBRK = 16 | |
| SEARCH_NOSHOW = 32 | |
| SEARCH_UNICODE = 64 | |
| SEARCH_IDENT = 128 | |
| SEARCH_BRK = 256 | |
| class YaraIDASearch: | |
| def __init__(self): | |
| self.mem_results = "" | |
| self.mem_offsets = [] | |
| if not self.mem_results: | |
| self._get_memory() | |
| def _get_memory(self): | |
| print("Status: Loading memory for Yara.") | |
| result = b"" | |
| segments_starts = [ea for ea in idautils.Segments()] | |
| offsets = [] | |
| start_len = 0 | |
| for start in segments_starts: | |
| end = idc.get_segm_end(start) | |
| result += idc.get_bytes(start, end - start) | |
| offsets.append((start, start_len, len(result))) | |
| start_len = len(result) | |
| print("Status: Memory has been loaded.") | |
| self.mem_results = result | |
| self.mem_offsets = offsets | |
| def _to_virtual_address(self, offset, segments): | |
| va_offset = 0 | |
| for seg in segments: | |
| if seg[1] <= offset < seg[2]: | |
| va_offset = seg[0] + (offset - seg[1]) | |
| return va_offset | |
| def _init_sig(self, sig_type, pattern, sflag): | |
| if SEARCH_REGEX & sflag: | |
| signature = "/%s/" % pattern | |
| if SEARCH_CASE & sflag: | |
| # ida is not case sensitive by default but yara is | |
| pass | |
| else: | |
| signature += " nocase" | |
| if SEARCH_UNICODE & sflag: | |
| signature += " wide" | |
| elif sig_type == "binary": | |
| signature = "{ %s }" % pattern | |
| elif sig_type == "text" and (SEARCH_REGEX & sflag) == False: | |
| signature = '"%s"' % pattern | |
| if SEARCH_CASE & sflag: | |
| pass | |
| else: | |
| signature += " nocase" | |
| signature += " wide ascii" | |
| yara_rule = "rule foo : bar { strings: $a = %s condition: $a }" % signature | |
| return yara_rule | |
| def _compile_rule(self, signature): | |
| try: | |
| rules = yara.compile(source=signature) | |
| except Exception as e: | |
| print("ERROR: Cannot compile Yara rule %s" % e) | |
| return False, None | |
| return True, rules | |
| def _search(self, signature): | |
| status, rules = self._compile_rule(signature) | |
| if not status: | |
| return False, None | |
| values = [] | |
| matches = rules.match(data=self.mem_results) | |
| if not matches: | |
| return False, None | |
| for rule_match in matches: | |
| for match in rule_match.strings: | |
| match_offset = match[0] | |
| values.append(self._to_virtual_address(match_offset, self.mem_offsets)) | |
| return values | |
| def find_binary(self, bin_str, sflag=0): | |
| yara_sig = self._init_sig("binary", bin_str, sflag) | |
| offset_matches = self._search(yara_sig) | |
| return offset_matches | |
| def find_text(self, q_str, sflag=0): | |
| yara_sig = self._init_sig("text", q_str, sflag) | |
| offset_matches = self._search(yara_sig) | |
| return offset_matches | |
| def find_sig(self, yara_rule): | |
| # recommendation/fork by R3MRUM https://github.com/R3MRUM | |
| offset_matches = self._search(yara_rule) | |
| return offset_matches | |
| def reload_scan_memory(self): | |
| self._get_memory() | |
alexander-hanel
commented
Aug 26, 2019
Hey Alex, I've added a simple find_sig function that accepts an existing yara signature as opposed to using the present find_text and find_binary functions that build the rule for you. If you think it is worth it, please incorporate the changes into your version:
https://gist.github.com/R3MRUM/f7b1b5ede9876c7e81385c138c871b13
Thanks @R3MRUM for the find_sig function. I updated the byte extraction to be faster and added your code. Cheers.
Hi Alex! Binary search in order to work is missing the brackets.
It should be signature = "{ %s }" % pattern
Thanks for this script is very useful for doing binary searches with wildcards in IDA!
@sisoma2 I typically add the brackets when doing the binary search but I included the update you mentioned. Now it does not require the brackets. Here is a git of this script https://github.com/alexander-hanel/YaraIDASearch/blob/master/yara_ida_search.py