Skip to content

Commit 88e5b4c

Browse files
author
Your Name
committed
Initial version
0 parents  commit 88e5b4c

12 files changed

+1394
-0
lines changed
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
2+
name: Build on tag
3+
4+
on:
5+
push:
6+
tags:
7+
- '*'
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-20.04
12+
permissions:
13+
contents: write
14+
packages: write
15+
16+
steps:
17+
- uses: actions/checkout@v2
18+
19+
- uses: actions/setup-node@v2
20+
with:
21+
node-version: '15'
22+
registry-url: 'https://npm.pkg.github.com'
23+
scope: '@worksbutnottested'
24+
always-auth: true
25+
26+
- name: Download dependencies
27+
run: |
28+
npm install --ignore-scripts
29+
env:
30+
NODE_AUTH_TOKEN: ${{secrets.NPM_PUBLISH}}
31+
32+
- name: Install dependencies
33+
run: |
34+
npm rebuild && npm run prepare --if-present
35+
36+
- name: Build & publish
37+
run: |
38+
npm run build
39+
npm publish
40+
env:
41+
NODE_AUTH_TOKEN: ${{secrets.NPM_PUBLISH}}
42+
43+
- name: Create Release
44+
id: create_release
45+
uses: actions/create-release@v1
46+
env:
47+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48+
with:
49+
tag_name: ${{ github.ref }}
50+
release_name: Release ${{ github.ref }}
51+
draft: false
52+
prerelease: false

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/node_modules/
2+
/dist/

README.md

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# stalker-coverage
2+
Stalker coverage is a small TypeScript module designed to be used with [FRIDA](https://frida.re/) to generate coverage information in [DynamoRio DRCOV](https://dynamorio.org/dynamorio_docs/page_drcov.html) format. This information can then be loaded into IDA using the [lighthouse](https://github.com/gaasedelen/lighthouse) plugin or Ghidra using the [Dragondance](https://github.com/0ffffffffh/dragondance) plugin.
3+
4+
# Example
5+
## Source Code
6+
The following C code will be used as our example:
7+
```c
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
11+
long square(long x)
12+
{
13+
return x * x;
14+
}
15+
16+
int main(int argc, char *argv[])
17+
{
18+
if (argc < 2) {
19+
printf("Give me an argument!\n");
20+
return 1;
21+
}
22+
23+
long x = strtol(argv[1], NULL, 0);
24+
long sq_x = square(x);
25+
printf("%ld squared is %ld\n", x, sq_x);
26+
return 0;
27+
}
28+
```
29+
We first compile the code as follows (note the use of the `-rdynamic` flag to allow FRIDA to more readily find the function):
30+
```bash
31+
$ gcc -rdynamic -o test test.c
32+
```
33+
## Project
34+
We can then start using the [frida-agent-example](https://github.com/oleavr/frida-agent-example) as a template project and install the `stalker-coverage` module:
35+
```bash
36+
$ npm install
37+
$ npm install --save stalker-coverage
38+
```
39+
## Using Stalker-Coverage
40+
We can then interact with this module using the following typescript code:
41+
```typescript
42+
import { Coverage } from "../node_modules/stalker-coverage/dist/coverage";
43+
/*
44+
* This sample replaces the 'main' function of the target application with one which starts
45+
* collecting coverage information, before calling the original 'main' function. Once the
46+
* original 'main' function returns, coverage collection is stopped. This coverage
47+
* information is written into a file which can then be directly loaded into IDA lighthouse
48+
* or Ghidra Dragondance.
49+
*/
50+
51+
/*
52+
* The address of the symbol 'main' which is to be used as the start and finish point to
53+
* collect coverage information.
54+
*/
55+
const mainAddress = DebugSymbol.fromName("main").address;
56+
57+
/**
58+
* The main module for the program for which we will collect coverage information (we will
59+
* not collect coverage information for any library dependencies).
60+
*/
61+
const mainModule = Process.enumerateModules()[0];
62+
63+
/*
64+
* A NativeFunction type for the 'main' function which will be used to call the original
65+
* function.
66+
*/
67+
const mainFunctionPointer = new NativeFunction(
68+
mainAddress,
69+
"int",
70+
["int", "pointer"],
71+
{ traps : "all"});
72+
73+
/*
74+
* A function to be used to replace the 'main' function. This function will start collecting
75+
* coverage information before calling the original 'main' function. Once this function
76+
* returns, the coverage collection will be stopped and flushed. Note that we cannot use
77+
* Interceptor.attach here, since this interferes with Stalker (which is used to provide the
78+
* coverage data).
79+
*/
80+
const mainReplacement = new NativeCallback(
81+
(argc, argv) => {
82+
const coverageFileName = `${mainModule.path}.dat`;
83+
const coverageFile = new File(coverageFileName, "wb+");
84+
85+
const coverage = Coverage.start({
86+
moduleFilter: (m) => Coverage.mainModule(m),
87+
onCoverage: (coverageData) => {
88+
coverageFile.write(coverageData);
89+
},
90+
threadFilter: (t) => Coverage.currentThread(t),
91+
});
92+
93+
const ret = mainFunctionPointer(argc, argv) as number;
94+
95+
coverage.stop();
96+
coverageFile.close();
97+
98+
return ret;
99+
},
100+
"int",
101+
["int", "pointer"]);
102+
103+
/*
104+
* Replace the 'main' function with our replacement function defined above.
105+
*/
106+
Interceptor.replace(mainAddress, mainReplacement);
107+
```
108+
We can build our project using the following command:
109+
```
110+
$ npm run build
111+
```
112+
## Running
113+
First we must download the FRIDA gadget from [here](https://github.com/frida/frida/releases) (be sure to rename it `frida-gadget.so`) and create a configuration file called `frida-gadget.config`
114+
```json
115+
{
116+
"interaction": {
117+
"type": "script",
118+
"path": "./_agent.js"
119+
}
120+
}
121+
```
122+
123+
Now we can run our application and collect the coverage information as follows:
124+
```
125+
$ LD_PRELOAD=./frida-gadget.so ./test 123
126+
123 squared is 15129
127+
```
128+
Coverage data should be stored along-side our test application in `test.dat`. This file can then de directly loaded into ghidra using the [Dragondance](https://github.com/0ffffffffh/dragondance) plugin.
129+
130+
## Screenshots
131+
We can then see the resulting coverage data inside of ghidra using the [Dragondance](https://github.com/0ffffffffh/dragondance) plugin.
132+
![Coverage1.png](https://github.com/WorksButNotTested/stalker-coverage/raw/master/img/Coverage1.png)
133+
![Coverage2.png](https://github.com/WorksButNotTested/stalker-coverage/raw/master/img/Coverage2.png)

img/Coverage1.png

596 KB
Loading

img/Coverage2.png

569 KB
Loading

0 commit comments

Comments
 (0)