By Jeff White (karttoon)
In this blog post I want to share a Python script that I wrote a few years back which generates YARA rules by using a byte->opcode abstraction method to match similar parts of code across files. At a high level, it's pretty straight-forward. It takes a cluster of files (ideally PE files) and attempts to find the longest common sequence (LCS) of x86/x64 opcodes with the idea that once you abstract back to just opcodes, you can find similar functions in other files and possibly unknown malware. There are a few other matching techniques employed that I'll dive into later but that is the gist. Hopefully the script can compliment hunters and analysts in searching for similar malware samples through automation. There are a lot of other similar tools already out there doing this, but it never hurts to have another option in the proverbial toolbox.
This script was written in Python and heavily utilizes Capstone and YARA Python modules. What initially started as a small script for CTF challenges, and an excuse to play with Capstone <3, has matured over time into more of an operational tool to leverage VirusTotal's Retrohunt capability. I've had a few wins with it but I can't say it's ever been terribly useful in my current capacity and thus it was more of an exercise in programming logic and interacting with files at a low-level.
The reality of this approach is that due to different versions of compilers, different compile time flags, architectures, variable values, etc, all can cause similar code in logic and structures that, at a byte level, is quite different. This is the gap that BinSequencer is trying to bridge.
Overview
The core matching technique in BinSequencer attempts to first determine where executable code may reside within a PE by looking at whether the "code" or "executable" bit is set within each section of the Windows PE file. Once it's identified the potential locations for code, it will disassemble the bytes into assembly instructions and strip out the opcode mnemonics. These opcode mnemonics will be strung together as a sequence in which the script attempts to find the longest match that exists across the sample set and then reverses the process of disassembling it back into bytes for YARA rules.
Below is an image I cobbled together to try and illustrate this particular process.
- Start with a PE file
- Identify potential locations for code
- Assembles bytes into instructions
- Strip out the opcode mnemonics into a sequence
- Find longest match across sample set
- Generate matching YARA rule by converting mnemonics back into bytes
One of the pro's of this method is that it makes logic matching easier. The mnemonic strings are essentially byte-agnostic, meaning that going from byte to opcode is easy. Looking at a sequence of just mnemonic opcodes is also much faster than byte-by-byte comparison so it helps when it comes to scaling this across large sample sets as well. Unfortunately, we can't have a pro without an equal con. Converting from mnemonic opcode back into a byte can be extremely problematic and this additional processing can slow things down significantly. You end up having to test various byte-variations and variable lengths of the operands used by the instructions to properly generate an accurate YARA rule, not to mention the problems with following wrong branches when building up the YARA rules, but I'll touch on this more later.
Assembly Primer
Before getting into the actual script, it behooves me to attempt and give a mini-x86 assembly overview in order to help illustrate some of the aforementioned pros and cons. The x86 instruction layout is below.
[prefix][opcode][mod-r/m][simb][operands]
When we go from low (bytes) to high (opcode) we will convert a byte like 0x75 to the opcode "JNZ" (jump if not zero). The bytes 0xF85 also use this same "JNZ" opcode so, regardless of the underlying bytes (0x75 vs 0xF85), we end up with the same opcode "JNZ" and the logic of the code remains intact. This is the major benefit of this abstraction technique.
Most instructions are fairly straight forward, "PUSHAD" will always be 0x60 and "CALL" will always be 0xE8 or 0xFF; however, the variations in the underlying bytes dictate things like operand length and change the overall size of the bytes in use.
; e80ef2ffff call 0xfffff213
; ff1548304000 call dword ptr [0x403048]
One of the above "CALL" instructions is 5 bytes in total while the other is 6 bytes. This is one area of variation in which it begins to complicate things when we end up disassembling "CALL" back into bytes for matching in a YARA rule. There are also built-in optimizations that x86 uses, such as 0x5, which is "ADD EAX, ???" where a value is added to the EAX register. These optimizations create additional variations in potential bytes because the initial bytes change a lot. The "XOR" opcode is a good example of one with baked in optimizations creating a lot of variation which must be accounted for within our YARA rule.
0x30 XOR r/m8 r8
0x31 XOR r/m16/32 r16/32
0x32 XOR r8 r/m8
0x33 XOR r16/32 r/m16/32
0x34 XOR AL imm8
0x35 XOR EAX imm16/32
0x80 XOR r/m8 imm8
0x81 XOR r/m16/32 imm16/32
0x82 XOR r/m8 imm8
0x83 XOR r/m16/32 imm8
This is 10 different byte-representations of the same opcode, so going from byte to opcode is easy, but reversing it can start to get tricky. As if that wasn't bad enough, it gets complicated further by things like the mod-r/m byte which changes the actual opcode meaning. The general 8-bit breakdown for the mod-r/m byte follows:
MOD (7,6) | Reg/Opcode (5,4,3) | R/M (2,1,0)
Using the 0x80 byte from the previous "XOR" example, take a look at the following two instructions.
xor byte ptr [0x418e58] = 8035 588e410037
sub byte ptr [0x418e58] = 802D 588e410037
The mod-r/m byte for the first instruction is 0x35 and 0x2D for the second. The 3 bits that dictate the opcode are 5,4, and 3. These correspond to a table of potential opcodess for that particular byte, so we can't just assume 0x80 is "XOR" when we do our conversion. For the 0x35 mod-r/m byte, the bits in question are 110, which equals 0x6 - the bits for 0x2D are 101, which equals 0x5. The table for that specific 0x80 byte is below.
0x0 = ADD
0x1 = OR
0x2 = ADC
0x3 = SBB
0x4 = AND
0x5 = SUB
0x6 = XOR
0x7 = CMP
I've probably re-written this script 3 times over the past 2-3 years tackling problems as they've developed from these types of variations that would pop-up. The "MOV" opcode has over 20 different variations by itself so sometimes things got quite messy!
BinSequencer
Alright, so back to the script. The Python "pefile" module is used for the extraction of code from the files, assuming it is a PE, and then the Capstone module is used for the actual disassembly engine. For each file, it will convert the extracted area of data and pull each instruction out, followed by each opcode mnemonic, which get strung into a "blob" which is used as the base for matching.
There are various ways to tune the functionality of this script from the command line which can be seen below.
usage: binsequencer.py [-h] [-c <integer_percent>] [-m <integer>]
[-l <integer>] [-v] [-a {x86,x64}] [-g <file>] [-d]
[-Q] [-n] [-o] [-s]
...
Sequence a set of binaries to identify commonalities in code structure.
positional arguments:
file
optional arguments:
-h, --help show this help message and exit
-c <integer_percent>, --commonality <integer_percent>
Commonality percentage the sets criteria for matches,
default 100
-m <integer>, --matches <integer>
Set the minimum number of matches to find, default 1
-l <integer>, --length <integer>
Set the minimum length of the instruction set, default
25
-v, --verbose Prints data while processing, use only for debugging
-a {x86,x64}, --arch {x86,x64}
Select code architecture of samples, default x86
-g <file>, --gold <file>
Override gold selection
-d, --default Accept default prompt values
-Q, --quiet Disable output except for YARA rule
-n, --nonpe Process non-PE files (eg PCAP/JAR/PDF/DOC)
-o, --opcode Use only the opcode matching technique
-s, --strings Include strings in YARA for matched hashes
The `-c` flag lets you specify the percentage of samples the sequence needs to exist in and the `-l` flag sets the minimum length of linear opcodes required. I've found 25 to be around the sweet spot for bare minimum accuracy as it usually covers a couple of functional blocks but, in general, the higher the better. When you go too low, it leads to non-unique common sequences of instructions, such as with prologue and epilogues or basic code re-use. The "blobs" will look like "jnz|jmp|add|mov|xor|call" with hundreds to a few hundred thousand opcodes.
Since we're doing comparisons, the script tries to identify the best initial file to use for analysis as the "gold" file. If it's doing a 100% match, it will search for the file with the lowest volume of instructions since it has to exist in every other file; it does the reverse if it dips below 100%. As an aside, it's also worth noting a limitation of YARA at this point. YARA has a hard-coded limit of 10,000 hex bytes that can used for a rule so I artificially limit the amount of opcodes that can be used to 4,000 as a safeguard.
To do the actual comparison, it uses a simple sliding window technique between the low match limit (25) and 4,000 opcodes, starting at the highest size and subtracting one opcode after each iteration until it empties and moves the window up by one offset. From there, it utilizes a number of tricks to speed things up, like black listing known bad sequences, so that it can zero in on the optimal matching length and reduce the number of iterations required.
Once it has a match of sequenced opcodes, it moves into the actual YARA generation which is where things get fun. One nice feature of YARA is the ability to do a boolean OR in the hex match. A "JMP" opcode, which can be the 0xE8 or 0xFF byte, would be "(E8|FF)". You can also do wildcards in YARA so "PUSH", which is 0x50 through 0x57 and 0x6A, can be represented as "(5?|6A)". Finally, you can account for overall instruction length with a byte jump in YARA like "[4-5]", which skips between 4 to 5 bytes before the next match.
As I intended to use this on primarily on VirusTotal, I began running into a few undocumented limitations VirusTotal imposed on the rules that can be used for retrohunting. If you have too many jumps, boolean OR's, and even in some scenarios just the length of the jump could cause your rule to fail. I suspect these limitations are primarily for efficiency/performance management but it's something that I had to account for throughout the script - your mileage may vary and I have not kept up with any changes.
Output
It's probably easier to just show some examples of the expected output to highlight what the script does. I've truncated parts of it and will interject commentary between the sections to explain each one. For this first example, I'll take a look at my favorite lame Malware - Hancitor!
python binsequencer.py Hancitor_Malware/
[+] Extracting instructions and generating sets
[-]Hancitor_Malware/e7b3ef04c211fafa36772da62ab1d250970d27745182d0f3736896cf7673dc3a_S1.exe
.text - 3740 instructions extracted
.edata - 477 instructions extracted
[-]Hancitor_Malware/6e73879ca49b40974cce575626e31541b49c07daa12ec2e9765c432bfac07a20_S1.exe
.text - 3740 instructions extracted
.edata - 477 instructions extracted
[-]Hancitor_Malware/2b3c920dca2fd71ecadd0ae500b2be354d138841de649c89bacb9dee81e89fd4_S1.exe
.text - 3740 instructions extracted
.edata - 477 instructions extracted
...
[-]Hancitor_Malware/ab90ed6cb461f17ce1f901097a045aba7c984898a0425767f01454689698f2e9_S1.exe
.text - 3740 instructions extracted
.edata - 477 instructions extracted
[-]Hancitor_Malware/594ab467454aafa64fc6bbf2b4aa92f7628d5861560eee1155805bd0987dbac3_S1.exe
.text - 3740 instructions extracted
.edata - 477 instructions extracted
[-]Hancitor_Malware/643951eee2dac8c3677f5ef7e9cb07444f12d165f6e401c1cd7afa27d7552367_S1.exe
.text - 3740 instructions extracted
.edata - 477 instructions extracted
The script takes a path to where the files reside and will iterate over each one to extract instructions. If you specify the `-n` flag, it will treat the files as non-PE, this was done for analyzing files of raw shellcode but the opcode technique holds up over other files as well (PCAP/JAR/whatever), but I wouldn't recommend it and you may run into bugs.
[+] Golden hash (3736 instructions) - Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe
Since I ran the script with it's default settings, it attempts a 100% match across all samples and thus finds the sample with the lowest instruction count since any match *must* exist in this file.
[+] Zeroing in longest mnemonic instruction set in .text
[-] Matches - 0 Block Size - 3259 Time - 0.00 seconds
[-] Matches - 0 Block Size - 1630 Time - 0.13 seconds
[-] Matches - 0 Block Size - 816 Time - 0.13 seconds
[-] Matches - 0 Block Size - 409 Time - 0.14 seconds
[-] Matches - 0 Block Size - 206 Time - 0.12 seconds
[-] Matches - 0 Block Size - 105 Time - 0.10 seconds
[-] Matches - 0 Block Size - 55 Time - 0.08 seconds
[-] Matches - 0 Block Size - 30 Time - 0.07 seconds
[+] Zeroing in longest mnemonic instruction set in .edata
[-] Moving 1 instruction sets to review with a length of 477
The script should iterate over each section in the golden hash that it identified as potentially having code and check these against the other samples. In this case, it does 8 iterations of the sliding window for sizes above the minimum of 25 and finds no matches in ".text". Then it moves on to the ".edata" section, which has 477 instructions, and finds that this match exists in all of the samples.
[*] Do you want to display matched instruction set? [Y/N] y
push|mov|sub|push|push|push|call|mov|add|test|je|push|mov|lea|add|push|push|push|call|cmp|jne|test|je|mov|xor|test|je|xor|inc|cmp|jb|pop|mov|pop|mov|pop|ret|pop|xor|pop|mov|pop|ret|mov|pop|mov|pop|ret|int3|int3|int3|int3|int3|int3|int3|push|mov|push|push|call|dec|add|neg|sbb|inc|pop|ret|int3|int3|int3|int3|int3|push|mov|sub|mov|push|push|push|mov|xor|add|movzx|lea|movzx|add|mov|mov|test|je|mov|mov|mov|mov|movzx|or|sub|mov|mov|mov|mov|movzx|or|sub|jne|mov|test|je|mov|inc|movzx|or|movzx|or|sub|je|mov|mov|test|js|jg|je|inc|add|add|mov|cmp|jae|mov|jmp|mov|lea|pop|pop|pop|lea|mov|pop|ret|pop|pop|xor|pop|mov|pop|ret|int3|int3|int3|int3|int3|int3|int3|int3|int3|push|mov|mov|mov|and|sub|xor|sub|cmp|jne|cmp|je|inc|cmp|jl|xor|pop|ret|int3|int3|int3|int3|push|mov|sub|push|mov|xor|push|push|xor|mov|mov|add|mov|mov|add|mov|add|mov|add|mov|mov|mov|mov|mov|mov|test|je|movsx|mov|cmp|jae|cmp|jae|mov|mov|mov|mov|movzx|add|mov|or|movzx|or|sub|jne|sub|test|je|mov|inc|movzx|or|movzx|or|sub|je|test|js|jg|je|mov|inc|cmp|jae|mov|mov|jmp|mov|mov|mov|add|pop|pop|mov|pop|mov|pop|ret|pop|xor|pop|mov|pop|mov|pop|ret|pop|pop|xor|pop|mov|pop|ret|int3|int3|int3|push|xor|mov|js|mov|mov|lodsd|mov|jmp|mov|lea|mov|pop|ret|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|push|mov|sub|mov|push|push|push|mov|add|call|mov|push|push|call|mov|push|push|mov|call|push|push|mov|call|mov|add|mov|test|jne|test|je|test|je|mov|mov|add|mov|cmp|je|mov|mov|add|add|cmp|je|mov|mov|add|add|mov|test|je|push|call|jmp|test|je|push|push|push|call|mov|test|je|mov|test|movzx|js|lea|push|push|call|cmp|je|mov|mov|add|mov|add|mov|cmp|jne|mov|add|mov|cmp|jne|pop|pop|pop|mov|pop|ret|int3|int3|int3|int3|int3|int3|int3|int3|int3|push|push|call|mov|push|call|push|call|add|pop|test|jne|ret|call|int3|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add
Again, designing this with the intent of being used during analysis, it prompts the user multiple times to display the results in various ways. The above lets you see the opcode sequence and gives a quick impression of whether or not the code construct seems to make logical sense. For example, you can see near the beginning 3 "PUSH" and then a "CALL", which is common behavior for pushing values to the stack before calling a function. This tells me what we're looking at is most likely code as opposed to data that just happened to be intermingled within a code section and disassembled.
As was stated before, it doesn't have to be code to work but the abstraction method will be less useful if it's not.
[*] Do you want to disassemble the underlying bytes? [Y/N] y
0x10003000: push ebp | 55
0x10003001: mov ebp, esp | 8BEC
0x10003003: sub esp, 0x1c | 83EC1C
0x10003006: push edi | 57
0x10003007: push dword ptr [ebp + 0xc] | FF750C
0x1000300a: push dword ptr [ebp + 8] | FF7508
0x1000300d: call 0x10003090 | E87E000000
0x10003012: mov edi, eax | 8BF8
0x10003014: add esp, 8 | 83C408
0x10003017: test edi, edi | 85FF
...
0x10003360: push esi | 56
0x10003361: push 0x403360 | 6860334000
0x10003366: call 0x10003140 | E8D5FDFFFF
0x1000336b: mov esi, eax | 8BF0
0x1000336d: push esi | 56
0x1000336e: call 0x10003270 | E8FDFEFFFF
0x10003373: push esi | 56
0x10003374: call 0x10003070 | E8F7FCFFFF
0x10003379: add esp, 0xc | 83C40C
0x1000337c: pop esi | 5E
0x1000337d: test eax, eax | 85C0
0x1000337f: jne 0x10003382 | 7501
0x10003381: ret | C3
0x10003382: call 0x10002010 | E889ECFFFF
0x10003387: int3 | CC
...
Similar to the previous display but with more details so you can see exactly what the assembly looks like.
[*] Do you want to display the raw byte blob? [Y/N] y
558BEC83EC1C57FF750CFF7508E87E0000008BF883C40885FF744456 ...
[*] Do you want to keep this set? [Y/N] y
[+] Keeping 1 mnemonic set using 100 % commonality out of 29 hashes
[-] Length - 477 Section - .edata
If you did not want to keep the match, possibly due to the code being part of a known library, not being unique, the match being just data and not an actual code construct you're after, then it's possible to decline it and restart the matching process.
[+] Printing offsets of type: longest
[-] Gold matches
----------v SET rule0 v----------
push|mov|sub|push|push|push|call|mov|add|test|je|push|mov|lea|add|push|push|push|call|cmp|jne|test|je|mov|xor|test|je|xor|inc|cmp|jb|pop|mov|pop|mov|pop|ret|pop|xor|pop|mov|pop|ret|mov|pop|mov|pop|ret|int3|int3|int3|int3|int3|int3|int3|push|mov|push|push|call|dec|add|neg|sbb|inc|pop|ret|int3|int3|int3|int3|int3|push|mov|sub|mov|push|push|push|mov|xor|add|movzx|lea|movzx|add|mov|mov|test|je|mov|mov|mov|mov|movzx|or|sub|mov|mov|mov|mov|movzx|or|sub|jne|mov|test|je|mov|inc|movzx|or|movzx|or|sub|je|mov|mov|test|js|jg|je|inc|add|add|mov|cmp|jae|mov|jmp|mov|lea|pop|pop|pop|lea|mov|pop|ret|pop|pop|xor|pop|mov|pop|ret|int3|int3|int3|int3|int3|int3|int3|int3|int3|push|mov|mov|mov|and|sub|xor|sub|cmp|jne|cmp|je|inc|cmp|jl|xor|pop|ret|int3|int3|int3|int3|push|mov|sub|push|mov|xor|push|push|xor|mov|mov|add|mov|mov|add|mov|add|mov|add|mov|mov|mov|mov|mov|mov|test|je|movsx|mov|cmp|jae|cmp|jae|mov|mov|mov|mov|movzx|add|mov|or|movzx|or|sub|jne|sub|test|je|mov|inc|movzx|or|movzx|or|sub|je|test|js|jg|je|mov|inc|cmp|jae|mov|mov|jmp|mov|mov|mov|add|pop|pop|mov|pop|mov|pop|ret|pop|xor|pop|mov|pop|mov|pop|ret|pop|pop|xor|pop|mov|pop|ret|int3|int3|int3|push|xor|mov|js|mov|mov|lodsd|mov|jmp|mov|lea|mov|pop|ret|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|int3|push|mov|sub|mov|push|push|push|mov|add|call|mov|push|push|call|mov|push|push|mov|call|push|push|mov|call|mov|add|mov|test|jne|test|je|test|je|mov|mov|add|mov|cmp|je|mov|mov|add|add|cmp|je|mov|mov|add|add|mov|test|je|push|call|jmp|test|je|push|push|push|call|mov|test|je|mov|test|movzx|js|lea|push|push|call|cmp|je|mov|mov|add|mov|add|mov|cmp|jne|mov|add|mov|cmp|jne|pop|pop|pop|mov|pop|ret|int3|int3|int3|int3|int3|int3|int3|int3|int3|push|push|call|mov|push|call|push|call|add|pop|test|jne|ret|call|int3|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add|add
----------^ SET rule0 ^-----------
Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe 0x10003000 - 0x100033fe in .edata
[-] Remaining matches
----------v SET rule0 v----------
Hancitor_Malware/e7b3ef04c211fafa36772da62ab1d250970d27745182d0f3736896cf7673dc3a_S1.exe 0x10003000 - 0x100033fe in .edata
Hancitor_Malware/6e73879ca49b40974cce575626e31541b49c07daa12ec2e9765c432bfac07a20_S1.exe 0x10003000 - 0x100033fe in .edata
Hancitor_Malware/2b3c920dca2fd71ecadd0ae500b2be354d138841de649c89bacb9dee81e89fd4_S1.exe 0x10003000 - 0x100033fe in .edata
...
Hancitor_Malware/ab90ed6cb461f17ce1f901097a045aba7c984898a0425767f01454689698f2e9_S1.exe 0x10003000 - 0x100033fe in .edata
Hancitor_Malware/594ab467454aafa64fc6bbf2b4aa92f7628d5861560eee1155805bd0987dbac3_S1.exe 0x10003000 - 0x100033fe in .edata
Hancitor_Malware/643951eee2dac8c3677f5ef7e9cb07444f12d165f6e401c1cd7afa27d7552367_S1.exe 0x10003000 - 0x100033fe in .edata
----------^ SET rule0 ^-----------
Once it has the match, it will show the offset within each file so that you can look at it further if needed. In this instance, you can see all of the matches happened in the ".edata" section at offset 0x10003000 through 0x100033FE. A quick look in IDA looks promising.
You can see the matched sequence extends across a number of function blocks and the code looks interesting with multiple instances of Win32 API calls commonly found in malware.
[+] Generating YARA rule for matches off of bytes from gold - Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe
[*] Do you want to try and morph rule0 for accuracy and attempt to make it VT Retro friendly [Y/N] y
[+] Check 01 - Checking for exact byte match
Before it actually does the YARA generation, the script can perform up to 3 various matching techniques in order to improve performance and accuracy. Each one builds upon the last and I'm going to spend a second detailing the three methods as they aren't all on display here.
- Check 01 - Exact byte-by-byte match for the entire instruction, not just opcode. More accurate per se but you run the risk of not catching the same logic with different values.
- Check 02 - Must be the same byte-length. Iterates over each byte and if it finds a boolean OR it will flip through them for that byte position. Wildcards non-matching values.
- Check 03 - Dynamically morphs rule by also adjusting variable lengths of wildcards or byte jumps between opcodes.
You can skip the first two checks with the `-o` flag (although the third check will still utilize their techniques during morphing to some degree).
[+] Check 02 - Checking for optimal opcode match
[*] Found optimal opcode match across all samples
[*] Do you want to include matched sample names in rule meta? [Y/N] y
[*] Do you want to include matched byte sequence in rule comments? [Y/N] y
Once the generation is complete and it validates the YARA rule, it will dump the rule to your console.
[+] Completed YARA rules
/*
SAMPLES:
Hancitor_Malware/18046a720cd23c57981fdfed59e3df775476b0f189b7f52e2fe5f50e1e6003e7_S1.exe
Hancitor_Malware/f4f026fbe3df5ee8ed848bd844fffb72b63006cfa8d1f053a9f3ee4c271e9188_S1.exe
...
Hancitor_Malware/40a8bb6e3eed57ed7bc802cc29b4e57360aa10c2de01d755f9577f07e10b848b_S1.exe
Hancitor_Malware/fed9cc2c7cfb97741470cb79c189a203545af88bdd67bc99e2d7499d343de653_S1.exe
BYTES:
558BEC83EC1C57FF750 ...
INFO:
binsequencer.py Hancitor_Malware/
Match SUCCESS for morphing
*/
rule rule0
{
meta:
description = "Autogenerated by Binsequencer v.1.0.4 from Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe"
author = ""
date = "2018-06-05"
strings:
$rule0_bytes = { 558B??83????57FF????FF????E8????????8B??83????85??74??568B????8D????03????6A??5056FF??????????83????75??F6??????74??8B????33??85??74??80??????403B??72??5EB8????????5F8B??5DC35E33??5F8B??5DC3B8????????5F8B??5DC3CCCCCCCCCCCCCC558B??68????????FF????E8????????4883????F7??1B??405DC3CCCCCCCCCC558B??83????8B????5356578B????33??03??0FB7????8D????0FB7????03??89????89????85??74??8B????8B??8A??88????0FB6??83????2B??89????8B??89????8B??0FB6??83????2B????75??8A????84??74??8A????420FB6??83????0FB6????83????2B??74??8B????8B????85??78??7F??74??4783????83????89????3B??73??8B????EB??8B????8D????5F5E5B8D????8B??5DC35F5E33??5B8B??5DC3CCCCCCCCCCCCCCCCCC558B??8B????8B??81??????????2B??33??2D????????80????75??80??????74??4183????7C??33??5DC3CCCCCCCC558B??83????538B????33??565733??8B????8B??????03??8B????8B????03??89????03??8B????03??89????89????8B????8B????89????89????85??74??0FBF????89????3B??73??3B????73??8B????8B????8B??8B????0FB6????03??8A??83????0FB6??83????2B??75??2B??84??74??8A????420FB6??83????0FB6????83????2B??74??85??78??7F??74??8B????463B??73??8B????8B????EB??8B????8B????8B????03????5F5E8B??5B8B??5DC35F33??5E8B??5B8B??5DC35F5E33??5B8B??5DC3CCCCCC5633??64??????????78??8B????8B????AD8B????EB??8B????8D????8B????5EC3CCCCCCCCCCCCCCCCCCCCCCCCCCCC558B??83????8B????5356578B????03??E8????????8B??68????????56E8????????8B??68????????5689????E8????????68????????5689????E8????????8B????83????89????85??75??85??0F84????????85??0F84????????8B??????????8B????03??89????83??????74??8B????8B??03??03??83????74??8B??8B????03??03??8B????85??74??50FF??EB??85??74??6A??6A??50FF??8B??85??74??8B??85??0FB7??78??8D????5051FF????39??74??89??8B????83????8B????83????8B????83????75??8B????83????89????83??????75??5F5E5B8B??5DC3CCCCCCCCCCCCCCCCCC5668????????E8????????8B??56E8????????56E8????????83????5E85??75??C3E8????????CC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 }
condition:
all of them
}
You can manually validate the rule matches with YARA as expected before retrohunting.
rule0 [description="Autogenerated by Binsequencer v.1.0.4 from Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe",author="",date="2018-06-05"] Hancitor_Malware//e7b3ef04c211fafa36772da62ab1d250970d27745182d0f3736896cf7673dc3a_S1.exe
0x2200:$rule0_bytes: 55 8B EC 83 EC 1C 57 FF 75 0C FF 75 08 E8 7E 00 00 00 8B F8 83 C4 08 85 FF 74 44 56 8B 77 0C 8D ...
rule0 [description="Autogenerated by Binsequencer v.1.0.4 from Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe",author="",date="2018-06-05"] Hancitor_Malware//6e73879ca49b40974cce575626e31541b49c07daa12ec2e9765c432bfac07a20_S1.exe
0x2200:$rule0_bytes: 55 8B EC 83 EC 1C 57 FF 75 0C FF 75 08 E8 7E 00 00 00 8B F8 83 C4 08 85 FF 74 44 56 8B 77 0C 8D ...
rule0 [description="Autogenerated by Binsequencer v.1.0.4 from Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe",author="",date="2018-06-05"] Hancitor_Malware//87a10cc169f9ffd0c75bb9846a99fb477fc4329840964b02349ae44a672729c2_S1.exe
0x2200:$rule0_bytes: 55 8B EC 83 EC 1C 57 FF 75 0C FF 75 08 E8 7E 00 00 00 8B F8 83 C4 08 85 FF 74 44 56 8B 77 0C 8D ...
...
rule0 [description="Autogenerated by Binsequencer v.1.0.4 from Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe",author="",date="2018-06-05"] Hancitor_Malware//643951eee2dac8c3677f5ef7e9cb07444f12d165f6e401c1cd7afa27d7552367_S1.exe
0x2200:$rule0_bytes: 55 8B EC 83 EC 1C 57 FF 75 0C FF 75 08 E8 7E 00 00 00 8B F8 83 C4 08 85 FF 74 44 56 8B 77 0C 8D ...
rule0 [description="Autogenerated by Binsequencer v.1.0.4 from Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe",author="",date="2018-06-05"] Hancitor_Malware//1c72f575d0c9574afcfcaab7e0b89fe0083dbe8ac20c0132a978eb1f6be59641_S1.exe
0x2200:$rule0_bytes: 55 8B EC 83 EC 1C 57 FF 75 0C FF 75 08 E8 7E 00 00 00 8B F8 83 C4 08 85 FF 74 44 56 8B 77 0C 8D ...
rule0 [description="Autogenerated by Binsequencer v.1.0.4 from Hancitor_Malware/fff786ec23e6385e1d4f06dcf6859cc2ce0a32cee46d8f2a0c8fd780b3ecf89a_S1.exe",author="",date="2018-06-05"] Hancitor_Malware//ab90ed6cb461f17ce1f901097a045aba7c984898a0425767f01454689698f2e9_S1.exe
0x2200:$rule0_bytes: 55 8B EC 83 EC 1C 57 FF 75 0C FF 75 08 E8 7E 00 00 00 8B F8 83 C4 08 85 FF 74 44 56 8B 77 0C 8D ...
Below is another examples where I utilize some of the tuning features of the script. Specifically, the match must exist in at least 75% of the samples, it will include strings that exist across all 75% of them, it will skip the first two matching techniques, and it will set Capstone to x64 architecture.
$ python binsequencer.py -c 75 -s -o -a x64 DarkComet_x64/
[+] Extracting instructions and generating sets
[-]DarkComet_x64/d4e28eebd4f485496590e55e245a22b17d58414ae22f5186da90b0cc8d4d2006
.text - 16007 instructions extracted
[-]DarkComet_x64/8841880e35b0936d7768e489f386e259970c98489a7ddd00e693797a394b4e39
.text - 16340 instructions extracted
[-]DarkComet_x64/c8dcafd948f8ae3b60c5d89365ad2fe328ceb74820fc1334e9d4853a3ad4c3e8
.text - 16340 instructions extracted
...
[-]DarkComet_x64/24a09b9dadb7471f29e1d2af22219c8fb94a2643bf481228ac60f48f55fa4e5f
.text - 16340 instructions extracted
[-]DarkComet_x64/1593b9482d71a52917eb1d3104eba822b93798eb812010afbbb50ab857fcbfab
.text - 16340 instructions extracted
[-]DarkComet_x64/2022ec23240d89da591ec57db5507c41fb3335253f6e1eb9306598d4a8255ef9
.text - 16340 instructions extracted
[+] Golden hash (16340 instructions) - DarkComet_x64/8841880e35b0936d7768e489f386e259970c98489a7ddd00e693797a394b4e39
[+] Zeroing in longest mnemonic instruction set in .text
[-] Matches - 0 Block Size - 4000 Time - 2.94 seconds
[-] Matches - 0 Block Size - 2000 Time - 2.44 seconds
[-] Matches - 0 Block Size - 1000 Time - 1.85 seconds
[-] Matches - 333 Block Size - 500 Time - 2.50 seconds
[-] Matches - 39 Block Size - 750 Time - 1.86 seconds
[-] Matches - 0 Block Size - 875 Time - 1.79 seconds
[-] Matches - 0 Block Size - 813 Time - 1.76 seconds
[-] Matches - 7 Block Size - 782 Time - 1.78 seconds
[-] Matches - 0 Block Size - 797 Time - 1.75 seconds
[-] Matches - 0 Block Size - 790 Time - 1.76 seconds
[-] Matches - 2 Block Size - 787 Time - 1.75 seconds
[-] Matches - 2 Block Size - 787 Time - 1.75 seconds
[-] Matches - 1 Block Size - 788 Time - 1.75 seconds
[-] Matches - 0 Block Size - 789 Time - 1.74 seconds
[-] Moving 1 instruction sets to review with a length of 788
[*] Do you want to display matched instruction set? [Y/N] y
add|add|add|add|add|add|add|add|outsb|push|jb|.byte|jae|push|outsd|imul|add|je|outsd|imul|outsb|outsw|jb|.byte|je|outsd|outsb|add|push|push|je|.byte|insb|jne|js|add|.byte|add|jne|insb|push|imul|push|jne|jb|push|.byte|insb|jne|js|add|xchg|add|imul|jb|jbe|insb|push|.byte|insb|jne|add|add|jb|.byte|je|jns|js|add|push|jo|outsb|jns|js|add|push|push|jne|jb|outsb|outsw|jns|add|add|insb|je|push|.byte|insb|jne|add|add|insb|outsd|.byte|.byte|je|outsb|outsb|imul|push|imul|push|imul|jne|je|outsd|imul|jb|jbe|insb|jae|xor|push|insb|outsd|jae|jns|push|push|xor|insb|insb|add|push|add|.byte|insd|jo|add|.byte|add|insb|outsb|add|add|imul|add|imul|mov|je|jne|jb|outsb|je|jb|.byte|jae|add|add|outsd|.byte|.byte|insb|outsd|.byte|imul|add|outsd|jae|add|add|jo|outsb|outsb|jbe|jb|outsb|insd|outsb|je|je|imul|add|je|imul|imul|jns|add|mov|.byte|.byte|insb|insb|insb|outsd|.byte|add|je|jb|jbe|je|push|jb|imul|add|add|je|imul|.byte|jne|jae|add|add|jae|push|.byte|.byte|.byte|jns|add|jbe|je|jns|je|insd|imul|jns|add|add|outsd|.byte|.byte|insb|push|outsb|insb|outsd|.byte|imul|add|je|push|.byte|je|.byte|.byte|insd|add|jb|.byte|je|imul|jns|add|cmp|imul|je|imul|je|.byte|jae|jb|outsd|jb|add|je|jb|.byte|jb|jae|add|add|insd|outsd|jbe|imul|jns|add|insb|add|je|imul|.byte|jne|jae|add|ret|insb|outsd|.byte|.byte|insb|jb|add|xor|imul|add|je|jb|jbe|je|push|jb|imul|imul|add|imul|add|add|.byte|insb|insb|insb|outsd|.byte|add|cmp|push|jb|jbe|je|push|jb|imul|imul|add|je|outsd|jne|imul|add|add|outsb|js|imul|outsd|insd|jo|jb|push|je|imul|add|outsb|add|push|add|outsd|jae|.byte|.byte|outsb|insb|add|outsd|.byte|.byte|insb|jb|add|add|je|imul|js|je|jb|.byte|jae|add|add|.byte|.byte|je|push|imul|insb|push|imul|jb|.byte|je|imul|imul|jne|.byte|add|je|imul|jb|add|jb|push|jae|jne|.byte|add|add|push|jae|jne|.byte|add|or|outsd|jb|imul|push|.byte|je|add|je|jbe|outsb|je|add|add|je|outsd|jne|.byte|.byte|.byte|outsb|insb|push|add|.byte|add|jb|.byte|je|jae|.byte|add|js|push|je|imul|xor|push|jb|je|imul|je|jb|jbe|push|jns|add|push|outsd|insb|jne|outsb|outsw|jb|.byte|je|outsd|outsb|add|add|jb|imul|jb|.byte|add|outsd|push|jae|jne|.byte|add|.byte|add|.byte|.byte|je|jbe|outsb|je|add|out|je|js|je|outsd|push|jb|.byte|jae|add|movsb|add|.byte|.byte|je|push|jb|.byte|jae|add|ret|add|.byte|imul|je|jne|jb|outsb|je|imul|jns|add|mov|je|insd|jo|imul|add|adc|jae|je|jbe|outsb|je|add|outsd|.byte|imul|outsd|jne|.byte|add|jp|je|jns|je|insd|outsb|outsw|add|add|imul|js|add|wait|add|.byte|.byte|je|jne|js|add|.byte|add|je|jne|jb|outsb|je|imul|jns|add|stosd|add|je|jb|imul|stosb|add|je|jb|imul|je|insd|jo|.byte|je|add|mov|jb|.byte|je|push|push|add|add|.byte|insb|imul|outsd|imul|rol|jo|push|xor|insb|insb|add|retf|add|je|jbe|.byte|.byte|.byte|.byte|jo|add|xor|insb|insb|add|insb|je|insd|push|js|add|jae|je|jo|imul|fiadd|outsb|imul|add|.byte|jb|jb|jbe|add|add|imul|jae|js|.byte|add|.byte|jb|js|add|add|.byte|jb|jo|jb|add|adc|jae|.byte|jo|std|add|push|je|imul|je|insb|je|insd|push|js|add|insb|outsd|outsd|js|outsb|imul|jb|insd|add|insb|push|imul|outsd|.byte|add|add|.byte|.byte|insb|push|imul|rol|push|je|imul|js|add|scasb|add|jo|je|push|.byte|add|retf|je|imul|outsb|push|je|add|add|outsd|ja|imul|.byte|add|je|imul|jae|add|add|je|insb|je|insd|add|imul|.byte|jae|add|add|imul|jae|add|adc|jae|.byte|outsd|js|add|add|je|add|push|outsb|jae|.byte|add|cdq|add|je|outsd|jb|jb|jne|push|imul|add|push|.byte|imul|je|jo|.byte|.byte|.byte|push|.byte|je|add|push|outsb|insb|je|insd|jae|.byte|add|push|imul|outsb|push|je|add|push|imul|.byte|je|push|push|push|xor|insb|insb|add|push|add|jae|jo|imul|add
[*] Do you want to disassemble the underlying bytes? [Y/N] y
0x1000dbbb: add byte ptr [rax], al | 0000
0x1000dbbd: add byte ptr [rax], al | 0000
0x1000dbbf: add byte ptr [rax], al | 0000
0x1000dbc1: add byte ptr [rax], al | 0000
0x1000dbc3: add byte ptr [rax], al | 0000
0x1000dbc5: add byte ptr [rax], al | 0000
0x1000dbc7: add bh, dh | 00F7
0x1000dbc9: add dword ptr [rdi + 0x70], ecx | 014F70
0x1000dbcc: outsb dx, byte ptr gs:[rsi] | 656E
...
0x1000e3b4: insb byte ptr [rdi], dx | 2E646C
0x1000e3b7: insb byte ptr [rdi], dx | 6C
0x1000e3b8: add byte ptr [rax], al | 0000
0x1000e3ba: push rdx | 52
0x1000e3bb: add ebx, dword ptr [rdi + 0x76] | 035F76
0x1000e3be: jae 0x1000e42e | 736E
0x1000e3c0: jo 0x1000e434 | 7072
0x1000e3c2: imul ebp, dword ptr [rsi + 0x74], 0x71000066 | 696E7466000071
0x1000e3c9: add byte ptr [rdi + 0x5f], bl | 005F5F
[*] Do you want to display the raw byte blob? [Y/N] y
00000000000000000000000000F7014F70656E50726F63 ...
[*] Do you want to keep this set? [Y/N] y
[+] Keeping 1 mnemonic set using 75 % commonality out of 50 hashes
[-] Length - 788 Section - .text
[+] Printing offsets of type: longest
[-] Gold matches
----------v SET rule0 v----------
add|add|add|add|add|add|add|add|outsb|push|jb|.byte|jae|push|outsd|imul|add|je|outsd|imul|outsb|outsw|jb|.byte|je|outsd|outsb|add|push|push|je|.byte|insb|jne|js|add|.byte|add|jne|insb|push|imul|push|jne|jb|push|.byte|insb|jne|js|add|xchg|add|imul|jb|jbe|insb|push|.byte|insb|jne|add|add|jb|.byte|je|jns|js|add|push|jo|outsb|jns|js|add|push|push|jne|jb|outsb|outsw|jns|add|add|insb|je|push|.byte|insb|jne|add|add|insb|outsd|.byte|.byte|je|outsb|outsb|imul|push|imul|push|imul|jne|je|outsd|imul|jb|jbe|insb|jae|xor|push|insb|outsd|jae|jns|push|push|xor|insb|insb|add|push|add|.byte|insd|jo|add|.byte|add|insb|outsb|add|add|imul|add|imul|mov|je|jne|jb|outsb|je|jb|.byte|jae|add|add|outsd|.byte|.byte|insb|outsd|.byte|imul|add|outsd|jae|add|add|jo|outsb|outsb|jbe|jb|outsb|insd|outsb|je|je|imul|add|je|imul|imul|jns|add|mov|.byte|.byte|insb|insb|insb|outsd|.byte|add|je|jb|jbe|je|push|jb|imul|add|add|je|imul|.byte|jne|jae|add|add|jae|push|.byte|.byte|.byte|jns|add|jbe|je|jns|je|insd|imul|jns|add|add|outsd|.byte|.byte|insb|push|outsb|insb|outsd|.byte|imul|add|je|push|.byte|je|.byte|.byte|insd|add|jb|.byte|je|imul|jns|add|cmp|imul|je|imul|je|.byte|jae|jb|outsd|jb|add|je|jb|.byte|jb|jae|add|add|insd|outsd|jbe|imul|jns|add|insb|add|je|imul|.byte|jne|jae|add|ret|insb|outsd|.byte|.byte|insb|jb|add|xor|imul|add|je|jb|jbe|je|push|jb|imul|imul|add|imul|add|add|.byte|insb|insb|insb|outsd|.byte|add|cmp|push|jb|jbe|je|push|jb|imul|imul|add|je|outsd|jne|imul|add|add|outsb|js|imul|outsd|insd|jo|jb|push|je|imul|add|outsb|add|push|add|outsd|jae|.byte|.byte|outsb|insb|add|outsd|.byte|.byte|insb|jb|add|add|je|imul|js|je|jb|.byte|jae|add|add|.byte|.byte|je|push|imul|insb|push|imul|jb|.byte|je|imul|imul|jne|.byte|add|je|imul|jb|add|jb|push|jae|jne|.byte|add|add|push|jae|jne|.byte|add|or|outsd|jb|imul|push|.byte|je|add|je|jbe|outsb|je|add|add|je|outsd|jne|.byte|.byte|.byte|outsb|insb|push|add|.byte|add|jb|.byte|je|jae|.byte|add|js|push|je|imul|xor|push|jb|je|imul|je|jb|jbe|push|jns|add|push|outsd|insb|jne|outsb|outsw|jb|.byte|je|outsd|outsb|add|add|jb|imul|jb|.byte|add|outsd|push|jae|jne|.byte|add|.byte|add|.byte|.byte|je|jbe|outsb|je|add|out|je|js|je|outsd|push|jb|.byte|jae|add|movsb|add|.byte|.byte|je|push|jb|.byte|jae|add|ret|add|.byte|imul|je|jne|jb|outsb|je|imul|jns|add|mov|je|insd|jo|imul|add|adc|jae|je|jbe|outsb|je|add|outsd|.byte|imul|outsd|jne|.byte|add|jp|je|jns|je|insd|outsb|outsw|add|add|imul|js|add|wait|add|.byte|.byte|je|jne|js|add|.byte|add|je|jne|jb|outsb|je|imul|jns|add|stosd|add|je|jb|imul|stosb|add|je|jb|imul|je|insd|jo|.byte|je|add|mov|jb|.byte|je|push|push|add|add|.byte|insb|imul|outsd|imul|rol|jo|push|xor|insb|insb|add|retf|add|je|jbe|.byte|.byte|.byte|.byte|jo|add|xor|insb|insb|add|insb|je|insd|push|js|add|jae|je|jo|imul|fiadd|outsb|imul|add|.byte|jb|jb|jbe|add|add|imul|jae|js|.byte|add|.byte|jb|js|add|add|.byte|jb|jo|jb|add|adc|jae|.byte|jo|std|add|push|je|imul|je|insb|je|insd|push|js|add|insb|outsd|outsd|js|outsb|imul|jb|insd|add|insb|push|imul|outsd|.byte|add|add|.byte|.byte|insb|push|imul|rol|push|je|imul|js|add|scasb|add|jo|je|push|.byte|add|retf|je|imul|outsb|push|je|add|add|outsd|ja|imul|.byte|add|je|imul|jae|add|add|je|insb|je|insd|add|imul|.byte|jae|add|add|imul|jae|add|adc|jae|.byte|outsd|js|add|add|je|add|push|outsb|jae|.byte|add|cdq|add|je|outsd|jb|jb|jne|push|imul|add|push|.byte|imul|je|jo|.byte|.byte|.byte|push|.byte|je|add|push|outsb|insb|je|insd|jae|.byte|add|push|imul|outsb|push|je|add|push|imul|.byte|je|push|push|push|xor|insb|insb|add|push|add|jae|jo|imul|add
----------^ SET rule0 ^-----------
DarkComet_x64/8841880e35b0936d7768e489f386e259970c98489a7ddd00e693797a394b4e39 0x1000dbbb - 0x1000e3c9 in .text
[-] Remaining matches
----------v SET rule0 v----------
DarkComet_x64/d4e28eebd4f485496590e55e245a22b17d58414ae22f5186da90b0cc8d4d2006 0x1000d707 - 0x1000df19 in .text
DarkComet_x64/c8dcafd948f8ae3b60c5d89365ad2fe328ceb74820fc1334e9d4853a3ad4c3e8 0x1000dbbb - 0x1000e3c9 in .text
DarkComet_x64/3faaac0cc5a64fa2a14e2d733cd10faf93fcaa05f7a5bf60bbf4540b95c37bf9 0x1000dbbb - 0x1000e3c9 in .text
DarkComet_x64/d5134afb4b67af145384a5ca68dac7345e375c4c97a5d1bdd9d0419a20c72c15 0x1000d707 - 0x1000df19 in .text
...
DarkComet_x64/4c70caa63cce7fcc4e66d2696ffb1844536b353775b874458549957b19cedbdf 0x1000d707 - 0x1000df19 in .text
DarkComet_x64/95216ff79bd77eada3004203ccf8ba3eee2cfbe3800b3227c3fe0b2f12f32362 0x1000dbbb - 0x1000e3c9 in .text
DarkComet_x64/24a09b9dadb7471f29e1d2af22219c8fb94a2643bf481228ac60f48f55fa4e5f 0x1000dbbb - 0x1000e3c9 in .text
DarkComet_x64/1593b9482d71a52917eb1d3104eba822b93798eb812010afbbb50ab857fcbfab 0x1000dbbb - 0x1000e3c9 in .text
DarkComet_x64/2022ec23240d89da591ec57db5507c41fb3335253f6e1eb9306598d4a8255ef9 0x1000dbbb - 0x1000e3c9 in .text
----------^ SET rule0 ^-----------
[+] Generating YARA rule for matches off of bytes from gold - DarkComet_x64/8841880e35b0936d7768e489f386e259970c98489a7ddd00e693797a394b4e39
[*] Do you want to try and morph rule0 for accuracy and attempt to make it VT Retro friendly [Y/N] y
[+] Check 03 - Dynamically morphing YARA rule0
[*] Dynamic morphing succeeded
[*] Do you want to include matched sample names in rule meta? [Y/N] y
[*] Do you want to include matched byte sequence in rule comments? [Y/N] y
[+] Completed YARA rules
/*
SAMPLES:
DarkComet_x64/84bc7ecfe0a9170892b9a2ebd0fc88a41b33951db3b57b7c51faed55930b3a26
DarkComet_x64/dacf28a75841b59284a14e8ad87b3a9dd93edca75adf2bd651d8de684ab1b53a
DarkComet_x64/e1000ad839f519cc74b40013bea2c294b85a02460f860f58665e48ab4919ed90
DarkComet_x64/cb8e7cd1401d263c935add9d31738df96832df039bec31a9209b09fcf90c3c5a
...
DarkComet_x64/422fc02a254a3e60336932cfe67121766fcefd7da4c734e8d0660d692b8a439b
DarkComet_x64/c69a7d7f88c16345afa4ed7b6b456a286ab64df4bdbeef00e39b212f2884d6ca
DarkComet_x64/2a19a370ae166a6e3f184031f9dc9a94d158317fbae50ca682c6e07e0acb537a
DarkComet_x64/d003ec22e4d9c86f106c8d5d6e2c8788fdc158c78c1f98b452c872370cb4176e
BYTES:
00000000000000000000000000F7014F70656E50726F63 ...
INFO:
binsequencer.py -c 75 -s -o -a x64 DarkComet_x64/
Match SUCCESS for morphing
*/
rule rule0
{
meta:
description = "Autogenerated by Binsequencer v.1.0.4 from DarkComet_x64/8841880e35b0936d7768e489f386e259970c98489a7ddd00e693797a394b4e39"
author = ""
date = "2018-06-05"
strings:
$rule0_bytes = { 000000000000000000000000????01????656E5072????6573??546F6B????????????4765????6F6B??????6E666F72????74??6F6E??????5265????6574????6C75??45????0000??01????75??6C5369??????????????67??75??72??56??6C75??45????00009601??????6B??????72??76??6C65????????6C75????????02????6743??????74??4B65????78????????5265674F????6E4B65????78????????5265????75??72??49??666F4B65????000047??????674465??6574??56??6C75??????????????6C6F????74??41??6449??69??????????????5369??????????????65????69??????????????75??74??6F6B??????72??76??6C656765????30??52656743??6F73??4B65????41????41??49????2E64??6C00005405??????????6D70??0000??05????????6C656E??????4B??????????6565??????01????6565????????????????C6????6574??75??72??6E74??72????6573??????02????6F????6C4C????6B????49??????????6F73??????01????70??6E6445??76??72??6E6D656E74??74??69????????????02????74??69????????????69????????????79??0000BB????????????6C41??6C6F????????4765????72??76??74??5072??6669????????????????01????74??69????????????????75??6573??0000????49????42??????????6442????65????76??4765????79??74??6D44??????????????79??????02????6F????6C556E6C6F??6B????6702????74??68??????????74??????6D65??????????72????74??44??????????????79??000038??46??????????????74??69??????????????4765??????73??45????6F72??????????6574??72????4164??????73??000003????656D6F76??44??????????????79??00006C04??6574??69????????????????75??6573??0000C2????6C6F????6C46????65????34??46??????????????65??????4765????72??76??74??5072??6669??????????69????????????03??????644C??????????????000046??????????6C41??6C6F??000039??????????65??72??76??74??5072??6669??????????69????????????02????74??6F6475??6546????????????????000049??????6E644E??????46????????????????6F6D70??72??5374??69????????????05????????656E000052??????6F73??????6E646C65??????4C??????6C46????65????????????6574??46????????????????78??74??72????6573??????????????????74??5469????????????6C65??69????????????72????74??46????????????????69????????????75????65??????????6574??69??????????????6572????????46????65??6573??75????65????43????????64??6573??75????65????08??????????46??72??69????????????6A????74??6704??6574??76??6E74??????02????74??6F6475????????6E646C65??0000??01????72????74??6573????6765??????78??536574??69??????????????34??5772??74??46????????????????74??72??76??5479??65??????????????566F6C75??6549??666F72????74??6F6E??????04??6572??69????????????72????64????????????656F66??6573??75????65????????????????74??45????6E74??0000E6??4765????78??74??6F64????72????6573??0000A4??????????74??5072????6573????????C303??????6446????????????????6574??75??72??6E74??69????????????79??000089??4765????656D70??69??????????????000012????6573??74??76??6E74????????4C????6B??????6F75????65????7A??4765????79??74??6D49??666F????03??????644C??????????????78??00009B??????????74??4D????6578??0000??01????74??75??72??6E74??69????????????79??0000AB02????74??6572??69????????????AA02????74??6572??69????????????4765????656D70????74????????B4??43??????74??5468????????000048??????????6C46????????????????6F46????????????????C0??????6565????4B????4E????????2E64??6C0000CB01????74??6576??????????70????????49????2E64??6C????????????44??6749????6D546578????????????????4465????74??70??69????????????DA??45??6444??????????????????????72??72??76????????????69??????????????73??78????????????72??6578????????????????72??70??6572??000011??4D65??????676542????????FD01??????64??74??69????????????4765????6C6749????6D546578????????????????6C6F6742??78??6E6469????????????72??6D??????????????6C5769????????????6F??????????????????6C65??69????????????D2??536574??69????????????78????????AE????????70??74??68??????????6765??????CA????6574??69????????????6E67??74????????02????6F77??69??????????????02????74??69????????????73??????01????74??6C6749????6D000069????????????73??????????02????656B??????73??6765??????12??4D65??????676542??78??????01????74??????????53656E644D????????6765??????9902????74??6F72??6772??75??64??69????????????02????67????69??????????????74??70????????6A????74????????53656E6444??6749????6D4D65??????6765??????????????5769????????????6E67??74????????????????5769??????????????74??555345??33??2E64??6C00005203????73??70??69?????????????????? }
$string_0 = { 21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E } // !This program cannot be run in DOS mode.
$string_1 = { 52696368 } // Rich
$string_2 = { 2E74657874 } // .text
$string_3 = { 602E64617461 } // `.data
$string_4 = { 2E7064617461 } // .pdata
$string_5 = { 402E72737263 } // @.rsrc
$string_6 = { 402E72656C6F63 } // @.reloc
$string_7 = { 41445641504933322E646C6C } // ADVAPI32.dll
...
$string_1429 = { 5704505805405204104305402E04505804502002002002002002002002002002002002002E04D0550490 } // WEXTRACT.EXE .MUI
$string_1430 = { 5007206F06407506307404E06106D0650 } // ProductName
$string_1431 = { 5706906E06406F0770730 } // Windows
$string_1432 = { 2004906E07406507206E06507402004507807006C06F0720650720 } // Internet Explorer
$string_1433 = { 5007206F06407506307405606507207306906F06E0 } // ProductVersion
$string_1434 = { 5606107204606906C06504906E06606F0 } // VarFileInfo
$string_1435 = { 5407206106E07306C06107406906F06E0 } // Translation
condition:
all of them
}
That about sums it up. Hopefully someone finds it useful but if not, c'est la vie.
The GIT for this script is up. Enjoy.
Older posts...