| https://blogs.technet.microsoft.com/mmpc/2015/01/13/crowti-update-cryptowall-3-0/ |
Your antidote to the cyber-twaddle that is spread about security and malware. Many people research malware and security and the impact of both. Some insights are valuable; others are insanely stupid. MalBabble exists because insisting that conclusions be drawn from data is a coherent idea; that conjecture isn't evidence; and because appealing to conspiracy to validate ideas is intellectually lazy.
Thursday, December 31, 2015
Crowti
Malware References:
Monday, August 24, 2015
Pe Time Stamps and Yara
Lets leverage time stamps within malware with Yara! I mean, who cares if the time stamp is accurate -- its probably not -- its a know point, often switches between versions or campaigns and can be point of detection. Let's look at some logic:
1. PE Time Stamp doesn't exist
2. PE Time Stamp outside of a certain date (the future, the past, etc.)
3. PE Time Stamp and Resource Time Stamps (same, different, one older/younger than the other)
Now, with those ideas in mind, let's play. Oh, and before I forget, Yara uses Unix time for its date matching. Keep that in mind.
Starting simple. How about just seeing if a timestamp exists.
import "pe"
rule Atimestamp {
condition:
pe.timestamp != 0
}
That's not quite useful, so let's add a bit more into it. How about an exact date.
import "pe"
rule Exacttimestamp {
condition:
pe.timestamp == 1150700835
}
Or, something in a range...
import "pe"
rule timestamprange{
condition:
pe.timestamp > 1150700835 and pe.timestamp < 1373882334
}
yara doesn't really have a concept of "now" that I know of, but you can cheat a bit. If you leverage its ability to import external variables, you can write your "now" value and then assign it at run time with the "-d" option of the command line tool.
Anyway, here's an example of a resource time stamp younger than the pe time stamp.
import "pe"
rule rsrc_tp_younger{
condition:
pe.resource_timestamp != 0 and
pe.resource_timestamp < pe.timestamp
}
Even better, how about any of the resources...that match a particular hash value...
import "pe"
import "hash"
rule all_rsrc_files {
condition:
for any i in (0..pe.number_of_resources - 1):
(hash.md5(pe.resources[i].offset, pe.resources[i].length) == "49f68a5c8493ec2c0bf489821c21fc3b"
and pe.resource_timestamp < pe.timestamp)
}
While we are at it, how about we check for entropy of a resource and a time stamp...
import "pe"
import "math"
rule rsrc_entropy_timestamp {
condition:
for any i in (0..pe.number_of_resources - 1):
((math.entropy(pe.resources[i].offset, pe.resources[i].length) > 6) and (pe.resource_timestamp != 0 and pe.resource_timestamp < pe.timestamp))
}
Or, perhaps a particularly high entropy section...
import "pe"
import "math"
rule text_entropy {
condition:
math.in_range(math.entropy(pe.sections[pe.section_index(".text")].raw_data_offset, pe.sections[pe.section_index(".text")].raw_data_size), 4.0, 5.0)
}
1. PE Time Stamp doesn't exist
2. PE Time Stamp outside of a certain date (the future, the past, etc.)
3. PE Time Stamp and Resource Time Stamps (same, different, one older/younger than the other)
Now, with those ideas in mind, let's play. Oh, and before I forget, Yara uses Unix time for its date matching. Keep that in mind.
Starting simple. How about just seeing if a timestamp exists.
import "pe"
rule Atimestamp {
condition:
pe.timestamp != 0
}
That's not quite useful, so let's add a bit more into it. How about an exact date.
import "pe"
rule Exacttimestamp {
condition:
pe.timestamp == 1150700835
}
Or, something in a range...
import "pe"
rule timestamprange{
condition:
pe.timestamp > 1150700835 and pe.timestamp < 1373882334
}
yara doesn't really have a concept of "now" that I know of, but you can cheat a bit. If you leverage its ability to import external variables, you can write your "now" value and then assign it at run time with the "-d" option of the command line tool.
Anyway, here's an example of a resource time stamp younger than the pe time stamp.
import "pe"
rule rsrc_tp_younger{
condition:
pe.resource_timestamp != 0 and
pe.resource_timestamp < pe.timestamp
}
Even better, how about any of the resources...that match a particular hash value...
import "pe"
import "hash"
rule all_rsrc_files {
condition:
for any i in (0..pe.number_of_resources - 1):
(hash.md5(pe.resources[i].offset, pe.resources[i].length) == "49f68a5c8493ec2c0bf489821c21fc3b"
and pe.resource_timestamp < pe.timestamp)
}
While we are at it, how about we check for entropy of a resource and a time stamp...
import "pe"
import "math"
rule rsrc_entropy_timestamp {
condition:
for any i in (0..pe.number_of_resources - 1):
((math.entropy(pe.resources[i].offset, pe.resources[i].length) > 6) and (pe.resource_timestamp != 0 and pe.resource_timestamp < pe.timestamp))
}
Or, perhaps a particularly high entropy section...
import "pe"
import "math"
rule text_entropy {
condition:
math.in_range(math.entropy(pe.sections[pe.section_index(".text")].raw_data_offset, pe.sections[pe.section_index(".text")].raw_data_size), 4.0, 5.0)
}
Thursday, August 20, 2015
Okay, its been too long.
alright, I admit it. Its been way too long since I've posted. Telling myself I'm busy only goes so far.
Anyway, figured I might as well get back to talking about Yara. We dug into the PE header pretty pretty well but I did skip over what you can do with characteristics. This page on msdn can orient you to what I'm talking about. Or, if you use PeStudio from winitor (requires windows) you point it at your malware and get a good snapshot of the values. The point is you can grab characteristics of files, which is well and good if you are building a characteristics profile for family of malware. I'm not going to go through the complete list (you can find it here) but I am going to show you how to format a Yara rule to match on them. First, we'll just trap for some characteristics, say instances were debug information is stripped in the file and so are relocs as well. Don't forget to import "pe" or it will fail to run (obviously, we are using Yara 3.X...).
import "pe"
rule characteristics_simple {
condition
pe.characteristics & pe.RELOCS_STRIPPED and pe.characteristics & pe.EXECUTABLE_IMAGE
}
Trapping characteristics alone in a yara rule is best used for high level sorting. Still, it can be leveraged to be useful, say when you have small variances in the malware where the characteristics can play a role in more granular means of defining malware.
Let's grab some unique values and then add a few characteristics we are interested in as well.
rule characteristics_test {
strings:
$a1= "Ramdisk"
$a2= "Cache-Control:max-age"
$a3= "YYSSSSS"
$a4= "t4j SV3"
$a5= "Program started"
$a6= "Started already,"
$a7= "SoundMAX service agent" wide
condition:
(all of ($a*) and pe.characteristics & pe.DEBUG_STRIPPED and pe.characteristics & pe.RELOCS_STRIPPED)
}
Here we are looking for a few specific values and then our two characteristics of interest.
Now, the next example has nothing to do with the file header but it is something I've leveraged to be useful. That's employing the hash module to calculate hash values of or within the file. That's useful when you have a chunk of data in the file that's stable across a bunch of malware, even if the file hash differs. Say, when something gets appended to the end of a file. Or, in the middle. Whatever. Here's how to look at the last 512 bytes of a file
import "hash"
rule last512_test {
condition:
hash.md5(filesize - 512, 512)==“275876e34cf609db118f3d84b799a790”
}
Or, the front of the file.
import "hash"
rule first512_test {
condition:
hash.md5(0, 512)==“275876e34cf609db118f3d84b799a790”
}
If you don't like md5, switch it to sha1 or sha256; just use the same format and it works fine. I'll go into this more when I talk about the modules.
Anyway, figured I might as well get back to talking about Yara. We dug into the PE header pretty pretty well but I did skip over what you can do with characteristics. This page on msdn can orient you to what I'm talking about. Or, if you use PeStudio from winitor (requires windows) you point it at your malware and get a good snapshot of the values. The point is you can grab characteristics of files, which is well and good if you are building a characteristics profile for family of malware. I'm not going to go through the complete list (you can find it here) but I am going to show you how to format a Yara rule to match on them. First, we'll just trap for some characteristics, say instances were debug information is stripped in the file and so are relocs as well. Don't forget to import "pe" or it will fail to run (obviously, we are using Yara 3.X...).
import "pe"
rule characteristics_simple {
condition
pe.characteristics & pe.RELOCS_STRIPPED and pe.characteristics & pe.EXECUTABLE_IMAGE
}
Trapping characteristics alone in a yara rule is best used for high level sorting. Still, it can be leveraged to be useful, say when you have small variances in the malware where the characteristics can play a role in more granular means of defining malware.
Let's grab some unique values and then add a few characteristics we are interested in as well.
rule characteristics_test {
strings:
$a1= "Ramdisk"
$a2= "Cache-Control:max-age"
$a3= "YYSSSSS"
$a4= "t4j SV3"
$a5= "Program started"
$a6= "Started already,"
$a7= "SoundMAX service agent" wide
condition:
(all of ($a*) and pe.characteristics & pe.DEBUG_STRIPPED and pe.characteristics & pe.RELOCS_STRIPPED)
}
Here we are looking for a few specific values and then our two characteristics of interest.
Now, the next example has nothing to do with the file header but it is something I've leveraged to be useful. That's employing the hash module to calculate hash values of or within the file. That's useful when you have a chunk of data in the file that's stable across a bunch of malware, even if the file hash differs. Say, when something gets appended to the end of a file. Or, in the middle. Whatever. Here's how to look at the last 512 bytes of a file
import "hash"
rule last512_test {
condition:
hash.md5(filesize - 512, 512)==“275876e34cf609db118f3d84b799a790”
}
Or, the front of the file.
import "hash"
rule first512_test {
condition:
hash.md5(0, 512)==“275876e34cf609db118f3d84b799a790”
}
If you don't like md5, switch it to sha1 or sha256; just use the same format and it works fine. I'll go into this more when I talk about the modules.
Monday, July 6, 2015
Best quote that sums up my day
Like it says:
"More data does not equate to more visibility or coverage".
In fact, more data drives down retention while lengthening analysis time. The trick is to collect and retain the most relevant data, not just more of it. Since the definition of what's relevant fluctuates it can be a challenge, but some basics stand from incident to incident. The goal is maximum visibility with the smallest volume. The average mean time of detection was 229 days in 2014. Most data collection falls in a 30 to 90 day spectrum. That alone drives the high miss rate.
"More data does not equate to more visibility or coverage".
In fact, more data drives down retention while lengthening analysis time. The trick is to collect and retain the most relevant data, not just more of it. Since the definition of what's relevant fluctuates it can be a challenge, but some basics stand from incident to incident. The goal is maximum visibility with the smallest volume. The average mean time of detection was 229 days in 2014. Most data collection falls in a 30 to 90 day spectrum. That alone drives the high miss rate.
Thursday, April 9, 2015
Deeper into the PE Header
Its been a bit, longer than I would have liked, since I posted. Still, let's dive a bit deeper into the PE structure and get back to what we were doing. Before I dig into PE sections, let's talk about a couple of integral concepts. The first is about PE File Sections. A section in a PE file equates to a segment or resources in an NE file. Sections are either code or data. Text is considered data in this regard. So, effectively sections are just blocks of contiguous memory. Sections can contain code or data that the program declared and uses directly or the sections might be built by a linker or compiler. All that information about sections resides in a table, as directed by the COFF specification. The Section Table contains the name of the section, permissions and size.
A couple of things bear review here. The permission schema for sections is your standard read, write and execute. While some compilers and linkers are more efficient than others, both employ an efficiency algorithm to influence the "grouping" of data. They also try to keep section numbers low.
Again, that efficiency concept. That translates to executable things being grouped together with other executable things into a section and the same for others types of permission requirements. That doesn't mean you won't have 99 sections all marked executable, but it does mean that this kind of situation, just like its opposite of zero sections, is an outlier. So are these:
executable sections
common section names
section count
packers
zero byte section (null byte hash)
no sections named (rare)
Let's start with a few rules to tackle this (incomplete, not inclusive list of...) items. Oh, and before we start can we just agree that, yes, you'll need to match for the file type you want as part of the condition. Let's just skip that monotony at the moment. If you don't know what I mean, go to gary kessler's site of file magic for "magic" values.
Let's play around with finding executable sections. Its not uncommon for the data sections to have executable code. Usually the text section isn't, however, and that might be useful to look for. Since the "text" section is usually the first section, we would do it like this:
import "pe"
rule executable_code_in_text_section {
condition:
pe.sections[0].characteristics & SECTION_CNT_CODE
}
Of course, sections with executable code are different from sections that are executable:
import "pe"
rule executable_text_section {
condition:
pe.sections[0].characteristics & SECTION_MEM_EXECUTE
}
Of course, why all that's neat, it doesn't necessary solve any problems or help with detection. However about this: by default, ALL packers need to have at least one section that is readable, writeable and executable. That's something good worth detecting. It also requires the latest version of Yara (3.3 as of this writing) to function.
import "pe"
rule read_write_execute {
condition:
pe.sections[0].characteristics & SECTION_MEM_EXECUTE and
pe.sections[0].characteristics & SECTION_MEM_READ and
pe.sections[0].characteristics & SECTION_MEM_WRITE
}
This is more arbitrary but also can work with some tuning (the choice of 500 accommodates most section headers...):
import "pe"
rule read_write_execute {
strings:
$b = {80 00 00 20}
condition:
pe.number_of_sections > 0 and $b in (0..500)
}
You can do a lot with the section characteristics. Here's a good list from MSDN on characteristics but keep in mind when you contrast them with the yara documents on PE module, that they are similar but not identical. The differences should be pretty straightforward to decipher, just sub in "section" for "IMAGE_SCN" and so on.
I'll just skip writing out all the packers you can capture with yara. Here's a decent list to work from: Packers in Yara
import "pe"
rule no_sections
{
condition:
pe.number_of_sections == 0
}
Suggestions for reading to understand entropy uses for detection and pattern analysis for detection.
http://www.security-assessment.com/files/presentations/Ruxcon_2006_-_Unpacking_Virus,_Trojans_and_Worms.pdf
A couple of things bear review here. The permission schema for sections is your standard read, write and execute. While some compilers and linkers are more efficient than others, both employ an efficiency algorithm to influence the "grouping" of data. They also try to keep section numbers low.
Again, that efficiency concept. That translates to executable things being grouped together with other executable things into a section and the same for others types of permission requirements. That doesn't mean you won't have 99 sections all marked executable, but it does mean that this kind of situation, just like its opposite of zero sections, is an outlier. So are these:
executable sections
common section names
section count
packers
zero byte section (null byte hash)
no sections named (rare)
Let's start with a few rules to tackle this (incomplete, not inclusive list of...) items. Oh, and before we start can we just agree that, yes, you'll need to match for the file type you want as part of the condition. Let's just skip that monotony at the moment. If you don't know what I mean, go to gary kessler's site of file magic for "magic" values.
Let's play around with finding executable sections. Its not uncommon for the data sections to have executable code. Usually the text section isn't, however, and that might be useful to look for. Since the "text" section is usually the first section, we would do it like this:
import "pe"
rule executable_code_in_text_section {
condition:
pe.sections[0].characteristics & SECTION_CNT_CODE
}
Of course, sections with executable code are different from sections that are executable:
import "pe"
rule executable_text_section {
condition:
pe.sections[0].characteristics & SECTION_MEM_EXECUTE
}
Of course, why all that's neat, it doesn't necessary solve any problems or help with detection. However about this: by default, ALL packers need to have at least one section that is readable, writeable and executable. That's something good worth detecting. It also requires the latest version of Yara (3.3 as of this writing) to function.
import "pe"
rule read_write_execute {
condition:
pe.sections[0].characteristics & SECTION_MEM_EXECUTE and
pe.sections[0].characteristics & SECTION_MEM_READ and
pe.sections[0].characteristics & SECTION_MEM_WRITE
}
This is more arbitrary but also can work with some tuning (the choice of 500 accommodates most section headers...):
import "pe"
rule read_write_execute {
strings:
$b = {80 00 00 20}
condition:
pe.number_of_sections > 0 and $b in (0..500)
}
You can do a lot with the section characteristics. Here's a good list from MSDN on characteristics but keep in mind when you contrast them with the yara documents on PE module, that they are similar but not identical. The differences should be pretty straightforward to decipher, just sub in "section" for "IMAGE_SCN" and so on.
I'll just skip writing out all the packers you can capture with yara. Here's a decent list to work from: Packers in Yara
import "pe"
rule no_sections
{
condition:
pe.number_of_sections == 0
}
Suggestions for reading to understand entropy uses for detection and pattern analysis for detection.
http://www.security-assessment.com/files/presentations/Ruxcon_2006_-_Unpacking_Virus,_Trojans_and_Worms.pdf
Friday, January 23, 2015
The PE File Header: Digging the Rich Signature and other things
We touched on Rich data only briefly before and I'm not going to dwell on what it means any more than I did. Here's a link for a reminder of what is contained in it and why you only see it sometimes in PE files. This chunk of information not only reminds us that the file in question was built with a Microsoft compiler but can be leveraged for detection.
A couple of neat bits of information. PE Files are traditionally pretty hefty. The PE header alone can take up to 512 bytes because of file alignment. That's due to the specification though it be ignored in some instances to compress this into smaller sections. That's the entire goal of Tiny PE, for example. The information in the PE Header can be removed since really the only two things required in the header are e_magic (MZ) and e_lfanew (tells you the offset of the real PE Header). That's why we leveraged looking for the DOS stub and other items in the previous article. If they are missing and its an peexe then that's a useful indicator of obfuscation or compression via removal.
A couple of neat bits of information. PE Files are traditionally pretty hefty. The PE header alone can take up to 512 bytes because of file alignment. That's due to the specification though it be ignored in some instances to compress this into smaller sections. That's the entire goal of Tiny PE, for example. The information in the PE Header can be removed since really the only two things required in the header are e_magic (MZ) and e_lfanew (tells you the offset of the real PE Header). That's why we leveraged looking for the DOS stub and other items in the previous article. If they are missing and its an peexe then that's a useful indicator of obfuscation or compression via removal.
Previously we used information in the Rich Signature as static values. It can be helpful to determine obfuscation pursuing that method. It can also be useful in other ways. First off, a couple of points. The python library pefile reads this data in its latest release. The area has two constants and some helpers. Constants are awesome because they help you fight obfuscation. The values are (in hex) 52 69 63 68 for "Rich" and 44 61 6E 53 for "DanS". This last value is special. Following the "Rich" value at the end of the signature is a dword value that you XOR the beginning of the signature to derive DanS. Just past it should be a trio of identical checksum values. Here's what I'm talking about:
You can see the checksums are identical and one after another. The rest is an array of linker information values showing the build number, and product identifier. The link given previously provides the code necessary to find this information and derive the values if desired. You can also check out the powershell scripting from Exploit Monday to do it another way if desired.
I'm sure you've noted that I keep talking about obfuscation and XOR. That's obviously not the only means, easily ROT,ROL, and Shift techniques could be employed. People are lazy though and convenience can often drive a decision that security would have chosen otherwise.
Finding these kinds of things doesn't have to be done by hand or even by Yara. I like tools as much as the other guy but I believe in understanding the reason and technique behind them before employing them. In this case, Didier Steven's XORSearch is excellent tool to both find the key for XOR or any of the others mentioned and to unobfuscate the file afterward.
I'm sure you've noted that I keep talking about obfuscation and XOR. That's obviously not the only means, easily ROT,ROL, and Shift techniques could be employed. People are lazy though and convenience can often drive a decision that security would have chosen otherwise.
Finding these kinds of things doesn't have to be done by hand or even by Yara. I like tools as much as the other guy but I believe in understanding the reason and technique behind them before employing them. In this case, Didier Steven's XORSearch is excellent tool to both find the key for XOR or any of the others mentioned and to unobfuscate the file afterward.
Subscribe to:
Posts (Atom)