Skip to content

Commit 3e33f94

Browse files
author
Your Name
committed
Use madvise to maximize memory dump
1 parent 5590fbc commit 3e33f94

File tree

4 files changed

+96
-3
lines changed

4 files changed

+96
-3
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "frida-cshell",
3-
"version": "1.8.4",
3+
"version": "1.8.5",
44
"description": "Frida's CShell",
55
"scripts": {
66
"prepare": "npm run version && npm run build && npm run package && npm run copy",

src/cmdlets/misc/corpse/corpse.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { APP_VERSION, GIT_COMMIT_HASH } from '../../../version.js';
1616
import { Overlay } from '../../../memory/overlay.js';
1717
import { Regs } from '../../../breakpoints/regs.js';
1818
import { Vars } from '../../../vars/vars.js';
19+
import { Madvise } from './madvise.js';
1920

2021
export class CorpseCmdLet extends CmdLetBase {
2122
name = 'corpse';
@@ -34,6 +35,7 @@ corpse - create a corpse file`;
3435
private clone: Fork | null = null;
3536
private proc: Proc | null = null;
3637
private mem: Mem | null = null;
38+
private madvise: Madvise | null = null;
3739

3840
public runSync(tokens: Token[]): Var {
3941
if (tokens.length != 0) return this.usage();
@@ -48,6 +50,9 @@ corpse - create a corpse file`;
4850
run 'setenforce 0' to disable`);
4951
}
5052

53+
const madvise = this.madvise as Madvise;
54+
madvise.tryForkAll(this.warning);
55+
5156
/* run the clone */
5257
const debugFileName = Files.getRandomFileName('debug');
5358
this.status(`Creating debug file: '${debugFileName}'`);
@@ -139,6 +144,9 @@ corpse - create a corpse file`;
139144

140145
this.writeMetadata(debug);
141146

147+
const madvise = this.madvise as Madvise;
148+
madvise.tryDumpAll(debug);
149+
142150
debug(`Suicide`);
143151
proc.kill(pid, Proc.SIGABRT);
144152
} catch (error) {
@@ -301,6 +309,7 @@ corpse - create a corpse file`;
301309
this.clone = new Fork();
302310
this.proc = new Proc();
303311
this.mem = new Mem();
312+
this.madvise = new Madvise();
304313
} catch {
305314
return false;
306315
}

src/cmdlets/misc/corpse/madvise.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { Mem } from '../../../memory/mem.js';
2+
3+
export class Madvise {
4+
private static readonly MADV_DOFORK: number = 11;
5+
private static readonly MADV_DODUMP: number = 17;
6+
// int madvise(void addr[.length], size_t length, int advice);
7+
private fnMadvise: SystemFunction<
8+
number,
9+
[NativePointer, UInt64 | number, number]
10+
>;
11+
12+
constructor() {
13+
const pMadvise = Module.findExportByName(null, 'madvise');
14+
if (pMadvise === null) throw new Error('failed to find madvise');
15+
16+
this.fnMadvise = new SystemFunction(pMadvise, 'int', [
17+
'pointer',
18+
'size_t',
19+
'int',
20+
]);
21+
}
22+
23+
private doFork(base: NativePointer, size: number) {
24+
const ret = this.fnMadvise(
25+
base,
26+
size,
27+
Madvise.MADV_DOFORK,
28+
) as UnixSystemFunctionResult<number>;
29+
if (ret.value !== 0)
30+
throw new Error(
31+
`failed to madvise, errno: ${ret.errno}, base: ${base}, size: ${size}`,
32+
);
33+
}
34+
35+
private doDump(base: NativePointer, size: number) {
36+
const ret = this.fnMadvise(
37+
base,
38+
size,
39+
Madvise.MADV_DODUMP,
40+
) as UnixSystemFunctionResult<number>;
41+
if (ret.value !== 0)
42+
throw new Error(
43+
`failed to madvise, errno: ${ret.errno}, base: ${base}, size: ${size}`,
44+
);
45+
}
46+
47+
private alignRange(
48+
base: NativePointer,
49+
size: number,
50+
): { base: NativePointer; size: number } {
51+
const limit = base.add(size);
52+
const alignedLimit = Mem.pageAlignUp(limit);
53+
const alignedBase = Mem.pageAlignDown(base);
54+
const alignedSize = alignedLimit.sub(alignedBase).toUInt32();
55+
return { base: alignedBase, size: alignedSize };
56+
}
57+
58+
private forAlignedRanges(fn: (base: NativePointer, size: number) => void) {
59+
Process.enumerateRanges('---').forEach(r => {
60+
const { base, size } = this.alignRange(r.base, r.size);
61+
fn(base, size);
62+
});
63+
}
64+
65+
public tryForkAll(debug: (msg: string) => void) {
66+
this.forAlignedRanges((base, size) => {
67+
try {
68+
this.doFork(base, size)
69+
} catch (e) {
70+
debug(`failed to madvise MADV_DOFORK range: ${e}, base: ${base}, size: ${size}`);
71+
}
72+
});
73+
}
74+
75+
public tryDumpAll(debug: (msg: string) => void) {
76+
this.forAlignedRanges((base, size) => {
77+
try {
78+
this.doDump(base, size)
79+
} catch (e) {
80+
debug(`failed to madvise MADV_DODUMP range: ${e}, base: ${base}, size: ${size}`);
81+
}
82+
});
83+
}
84+
}

0 commit comments

Comments
 (0)