Executable files analysis and capabilities detection using capa (Mandiant)
Intro
Reference: https://github.com/mandiant/capa
Capa detects capabilities in executable files.
It can be run against a PE, ELF, .NET module, or shellcode files and it tells you what it thinks the program can do. For example, it might suggest that the file is a backdoor, is capable of installing services, or relies on HTTP to communicate.
Capa consists of two main components that algorithmically triage unknown programs.
- First, a code analysis engine extracts features from files, such as strings, disassembly, and control flow.
- Second, a logic engine finds combinations of features that are expressed in a common rule format. When the logic engine finds a match, capa reports on the capability described by the rule.
Feature Extraction
The code analysis engine extracts low-level features from programs. All the features are consistent with what a human might recognize, such as strings or numbers, and enable capa to explain its work. These features typically fall into two large categories: file features and disassembly features.
- File features are extracted from the raw file data and its structure, e.g. the PE file header. This is information that you might notice by scrolling across the entire file. Besides the above discussed strings and imported APIs, these include exported function and section names.
- Disassembly features are extracted from an advanced static analysis of a file — this means disassembling and reconstructing control flow.
Capa Rules
A capa rule uses a structured combination of features to describe a capability that may be implemented in a program. If all required features are present, capa concludes that the program contains the capability.
Capa rules are YAML documents that contain metadata and a tree of statements to express their logic. Among other things, the rule language supports logical operators and counting.
Basic blocks group assembly code at a very low level making them an ideal place to match tightly related code segments. Besides within basic blocks, capa supports matching at the function and the file level. The function scope ties together all features in a disassembled function, while the file scope contains all features across the entire file.
Capa v4.0 is the first version to support analyzing .NET executables. With this new feature, we updated 49 existing rules and added 22 new rules to capture capabilities in .NET files. Read on to understand how we extended capa with .NET support.
File analysis
Python script to spin up a web server and upload file for analysis:
import os
import subprocess
from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['ALLOWED_EXTENSIONS'] = {'exe'}
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 # 10MB
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']
@app.route('/')
def index():
return render_template('upload_form.html')
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
file.save(filename)
result = execute_script(filename)
return render_template('result.html', result=result)
else:
flash('Invalid file type. Allowed file type is .exe')
return redirect(request.url)
def execute_script(filename):
try:
result = subprocess.check_output(['python', 'scripts/process_file.py', filename], stderr=subprocess.STDOUT, universal_newlines=True)
return result
except subprocess.CalledProcessError as e:
return e.output
if __name__ == '__main__':
app.secret_key = 'supersecretkey'
app.run(debug=True)
Python script “process_file.py”:
import sys
import subprocess
# Define the system script/command you want to execute
capa_script = "/path/to/capa/bin/capa"
if len(sys.argv) != 2:
print("Usage: process_file.py <filename>")
sys.exit(1)
filename = sys.argv[1]
print(f"Processing file: {filename}")
capa_command = [capa_script, "-r", "/path/to/capa/capa-rules-4.0.0/", "-s", "/path/to/capa/sigs/", filename]
try:
# Use subprocess.run to execute the system script/command
result = subprocess.run(capa_command, shell=False, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
print(result.stdout)
# Print the standard error (stderr) of the system script/command
print("Standard Error:")
print(result.stderr)
# Print the return code (exit code) of the system script/command
print("Return Code:", result.returncode)
except subprocess.CalledProcessError as e:
# If the system script/command returns a non-zero exit code, it raises an exception
print(f"Error: {e}")
print("Processing complete.")
Exe #1
Exe #2
Exe #3
Need Help?
The functionality discussed in this post, and so much more, are available via the SOCFortress platform. Let SOCFortress help you and your team keep your infrastructure secure.
Website: https://www.socfortress.co/
Contact Us: https://www.socfortress.co/contact_form.html