mandiant / mandiant/capa

Add symbol name features for dynamically resolved function pointers

Open
#2,663 16 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
6.2k
Forks
726
Avg merge
11d 11h
Merged PRs (30d)
7

Description

### Summary

I want to be able to statically use the `api` feature for dynamically resolved function pointers, via `GetProcAddress` or `dlsym`.

### Motivation

While working on https://github.com/mandiant/capa-rules/pull/1046, I ran into a limitation where I couldn't precisly examine calls to `NtFsControlFile` because that function is commonly dynamically resolved at runtime via `GetProcAddress`

(examples from 7d333c9b11b06ef0982b61bfc062631bb6cf9d12d0d4f2cf1b807a25ddf62fbc)

![Image](https://github.com/user-attachments/assets/8ddca496-f165-43bd-9327-e83b5c2e5e8e)

![Image](https://github.com/user-attachments/assets/e8ead2d6-b01e-44d2-afe8-2e0ea4440a07)

IDA has special handling for auto-renaming pointers in .data when they are set via GetProcAddress. It would be very useful to be able to have a similar capability in capa so we can precisely inspect calls through static capa executions to dynamically resolved functions.

Additionally, it would be an added bonus to have a way to explicitly look for (or not for) dynamically resolved functions. Maybe something like:
```yml
# only match on NtFsControlFile calls going to .data
- api: NtFsControlFile
- runtime_resolved: true

# only match on calls to CreateProcessA going to .idata
- api: CreateProcessA
- runtime_resolved: false

# if not specified, do both
- api: CloseHandle
```

This feature could be supported on Linux as well by looking at `dlsym` calls

### Describe alternatives you've considered

The workaround I did in https://github.com/mandiant/capa-rules/pull/1046 was to just inspect how the arguments are set up for the NtFsControlFile calls we are interested in, and then look for a call. I'm not sure how accurate/precise this will be in practice though:

```yml
features:
- and:
- os: windows
- or:
- number: 0x11003c
- number: 0x110038
- number: 0x119ff8
- instruction:
- mnemonic: xor
- instruction:
- mnemonic: call
- not:
- characteristic: nzxor
```
## Additional context

n/a

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the GetProcAddress and dlsym examples linked in the issue, along with capa-rules pull request 1046 and commit 7d333c9b11b06ef0982b61bfc062631bb6cf9d12d0d4f2cf1b807a25ddf62fbc. Done should support static api matching for dynamically resolved function pointers and define whether runtime_resolved filtering works on Windows and Linux.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
reverse-engineering
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.