mandiant / mandiant/capa

Add an entropy file feature to detect packed code and encrypted sections

Open
#1,401 12 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

breaking-change enhancement
Dominant language
Python
Stars
6.2k
Forks
726
Avg merge
11d 11h
Merged PRs (30d)
7

Description

### Summary

This new feature would compute [Shannon's entropy](https://arxiv.org/pdf/1405.2061.pdf) for different sections of the executable, and then compare the computed (section name, entropy) pairs against the section names and the associated threshold values specified by the user in the rule file. If the section's entropy value surpasses the rule-defined threshold, then that feature evaluates to True, otherwise it evaluates to False.

This addition would afford capa the ability to perform entropy analysis for binary files, which in turn would make detecting packed, obfuscated, and encrypted binaries/data more feasible.

### Motivation

At its current state, capa relies primarily on api and file signatures as well as instruction mnemonics to detect different binary packing and encryption/obfuscation capabilities; however, this approach could be made more efficient by introducing per-section entropy analysis, since entropy provides a straightforward metric for detecting packed data. This is because high-value entropy is a characteristic of packed/encrypted software [[1]](#1), with values above 6.8 being generally associated with sections containing mostly encrypted data, and values below 5 being associated with sections that contain no encrypted data. This information could be paired with other features to ascertain whether an executable is packed or not.

For example, suppose we wish to write a rule that detects _xor_-obfuscation in which the _xor_ operation is implemented using _nand_ gates. Writing a corresponding rule for this capability using the traditional approach would be somewhat difficult, since the key capa features associated with this capability (the api signatures and the mnemonics: _and_, _not_) are quite common among non-malicious software; however, if we combine these features with a high entropy threshold value (.text section entropy value of 6.5 for example), then we can get a much clearer indication of whether the input file is packed or not.

### Syntax and implementation

I could think of 4 formats — listed below — for implementing this feature, but could not decide which one was best. For the first 3 formats, the section name and the associated entropy would be stored as the value member of the entropy feature, and for the final format they would be stored in two independent features that are children of a Statement resembling the entropy feature.

Here are the formats:

```yaml
# First approach: store the section name and associated entropy as a tuple; requires tuples to be added
# as possible values in the capa Feature class constructor.
- entropy: (".text", 5.7)

# Second approach: requires arrays to be added as possible values in the capa Feature class constructor,
# which can be useful in the future when adding explicit support for an arbitrary number of api arguments.
- entropy: [".text", 5.7]

# Third approach: with this approach, the to-be-stored Feature value would be a string. This string
# would then be split into the section name and the entropy value when the feature gets evaluated.
- entropy: .text 5.7

# Fourth approach: requires float values to be added to the parse_description() function in the capa.rules
# package, as well as a "section-entropy" Statement class.
- section-entropy:
- section: .text
- entropy: 5.7
```

For the first two approaches, I am not quite sure if the addition of tuples/lists values to capa can be done at the moment, and would need the developers say on that.

The third approach makes the most sense to me, since it is the best looking and the easiest to implement; however, storing two separate values in the same string feels somewhat like a hack.

As for the last approach, I don't see any difficulties adding floats to the parse_description() function, as it would require only some _value_type_ and _isinstance()_ checks to be added. However, I believe implementing the _section-entropy_ keyword as a Statement would be a huge hack.

### GSoC

I wish to be assigned this issue as part of my GSoC proposal. I have prepared some of the code required for the introduction of this feature, and can submit a PR shortly after the developers approve the request and provide their feedback (should they be in favor of adding it).

### References
[1] R. Lyda and J. Hamrock, "Using Entropy Analysis to Find Encrypted and Packed Malware," in IEEE Security & Privacy, vol. 5, no. 2, pp. 40-45, March-April 2007, doi: 10.1109/MSP.2007.48. [Open-Access Link](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.120.9861&rep=rep1&type=pdf)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the capa Feature class and the parse_description() function in the capa.rules package, then compare the four proposed YAML formats for representing section names and entropy thresholds. Done means selecting an implementation approach and defining the entropy comparison behavior needed to detect packed or encrypted sections.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
reverse-engineering, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.