Skip to content

Commit 7790038

Browse files
author
Your Name
committed
Changes to add metadata to corpse
1 parent cbccd56 commit 7790038

File tree

7 files changed

+181
-4
lines changed

7 files changed

+181
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ node_modules
22
frida-cshell.js
33
frida-cshell
44
src/version.ts
5+
core

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.7.8",
3+
"version": "1.7.9",
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: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import { Dumpable } from './dumpable.js';
1111
import { Proc } from './proc.js';
1212
import { Rlimit } from './rlimit.js';
1313
import { SeLinux } from './selinux.js';
14+
import { Mem, MemProtection } from './mem.js';
15+
import { APP_VERSION, GIT_COMMIT_HASH } from '../../../version.js';
16+
import { Overlay } from '../../../memory/overlay.js';
17+
import { Regs } from '../../../breakpoints/regs.js';
18+
import { Vars } from '../../../vars/vars.js';
1419

1520
export class CorpseCmdLet extends CmdLetBase {
1621
name = 'corpse';
@@ -28,6 +33,7 @@ corpse - create a corpse file`;
2833
private dumpable: Dumpable | null = null;
2934
private clone: Fork | null = null;
3035
private proc: Proc | null = null;
36+
private mem: Mem | null = null;
3137

3238
public runSync(tokens: Token[]): Var {
3339
if (tokens.length != 0) return this.usage();
@@ -126,6 +132,13 @@ corpse - create a corpse file`;
126132
debug(`Restoring default signal action using rt_sigaction`);
127133
proc.rt_sigaction(Proc.SIGABRT, Proc.SIG_DFL);
128134

135+
for (const overlay of Overlay.all()) {
136+
debug(`Reverting overlay: ${overlay.toString()}`);
137+
overlay.revert();
138+
}
139+
140+
this.writeMetadata(debug);
141+
129142
debug(`Suicide`);
130143
proc.kill(pid, Proc.SIGABRT);
131144
} catch (error) {
@@ -141,6 +154,78 @@ corpse - create a corpse file`;
141154
}
142155
}
143156

157+
private writeMetadata(debug: (msg: string) => void) {
158+
const magicLen = 8;
159+
/* 43 4f 52 50 53 45 20 33 |CORPSE 3| */
160+
const magics: [Uint8Array, Uint8Array] = [
161+
new Uint8Array([0xde, 0xad, 0xfa, 0xce, 0xde, 0xad, 0xfa, 0xce]),
162+
new Uint8Array([0x9d, 0xe2, 0xa8, 0x9e, 0x8d, 0xe8, 0xda, 0xfd]),
163+
];
164+
const ranges = Process.enumerateRanges('---').map(r => {
165+
return {
166+
base: `0x${r.base.toString(16)}`,
167+
size: r.size,
168+
protection: r.protection,
169+
file_path: r.file?.path ?? null,
170+
file_offset: r.file?.offset ?? null,
171+
file_size: r.file?.size ?? null,
172+
};
173+
});
174+
const modules = Process.enumerateModules().map(m => {
175+
return {
176+
name: m.name,
177+
base: `0x${m.base.toString(16)}`,
178+
size: m.size,
179+
path: m.path,
180+
};
181+
});
182+
const regs = Regs.all().map(([name, value]) => {
183+
return {
184+
name: name,
185+
addr: value.toPointer(),
186+
value: value.getLiteral(),
187+
};
188+
});
189+
const vars = Vars.all().map(([name, value]) => {
190+
return {
191+
name: name,
192+
addr: value.toPointer(),
193+
value: value.getLiteral(),
194+
};
195+
});
196+
const metatdata = {
197+
version: APP_VERSION,
198+
hash: GIT_COMMIT_HASH,
199+
ranges,
200+
modules,
201+
regs,
202+
vars,
203+
};
204+
205+
const data = JSON.stringify(metatdata, null, 2);
206+
debug(`data: ${data}`);
207+
debug(`metadata size: ${Format.toSize(data.length)}`);
208+
209+
const alignedSize = Mem.pageAlign(magicLen + data.length);
210+
const totalSize = Process.pageSize * 2 + alignedSize;
211+
const mem = this.mem as Mem;
212+
const buffer = mem.map_anonymous(totalSize);
213+
mem.protect(buffer, Process.pageSize, MemProtection.PROT_NONE);
214+
mem.protect(
215+
buffer.add(Process.pageSize + alignedSize),
216+
Process.pageSize,
217+
MemProtection.PROT_NONE,
218+
);
219+
let cursor = buffer.add(Process.pageSize);
220+
for (let i = 0; i < magicLen; i++) {
221+
const x = magics[0][i] as number;
222+
const y = magics[1][i] as number;
223+
cursor.writeU8(x ^ y);
224+
cursor = cursor.add(1);
225+
}
226+
cursor.writeUtf8String(data);
227+
}
228+
144229
private checkCorpse(corePattern: string, pid: number) {
145230
const corePath = CorePattern.appendPid()
146231
? `${corePattern}.${pid}`
@@ -208,6 +293,7 @@ corpse - create a corpse file`;
208293
this.dumpable = new Dumpable();
209294
this.clone = new Fork();
210295
this.proc = new Proc();
296+
this.mem = new Mem();
211297
} catch {
212298
return false;
213299
}

src/cmdlets/misc/corpse/mem.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
export enum MemProtection {
2+
PROT_NONE = 0,
3+
PROT_READ = 0x1,
4+
PROT_WRITE = 0x2,
5+
PROT_READ_WRITE = PROT_READ | PROT_WRITE,
6+
}
7+
8+
export class Mem {
9+
private static readonly MAP_PRIVATE: number = 0x2;
10+
private static readonly MAP_ANONYMOUS: number = 0x20;
11+
12+
private static readonly MAP_FAILED: NativePointer = ptr(-1);
13+
14+
/* void *mmap(void addr[.length], size_t length, int prot, int flags,
15+
int fd, off_t offset); */
16+
private fnMmap: SystemFunction<
17+
NativePointer,
18+
[NativePointer, number | UInt64, number, number, number, number | UInt64]
19+
>;
20+
21+
/* int mprotect(void addr[.len], size_t len, int prot); */
22+
private fnMprotect: SystemFunction<
23+
number,
24+
[NativePointer, number | UInt64, number]
25+
>;
26+
27+
public constructor() {
28+
const pMmap = Module.findExportByName(null, 'mmap');
29+
if (pMmap === null) throw new Error('failed to find mmap');
30+
31+
this.fnMmap = new SystemFunction(pMmap, 'pointer', [
32+
'pointer',
33+
'size_t',
34+
'int',
35+
'int',
36+
'int',
37+
'size_t',
38+
]);
39+
40+
const pMprotect = Module.findExportByName(null, 'mprotect');
41+
if (pMprotect === null) throw new Error('failed to find mprotect');
42+
43+
this.fnMprotect = new SystemFunction(pMprotect, 'int', [
44+
'pointer',
45+
'size_t',
46+
'int',
47+
]);
48+
}
49+
50+
public map_anonymous(size: number): NativePointer {
51+
const ret = this.fnMmap(
52+
ptr(0),
53+
size,
54+
MemProtection.PROT_READ | MemProtection.PROT_WRITE,
55+
Mem.MAP_ANONYMOUS | Mem.MAP_PRIVATE,
56+
-1,
57+
0,
58+
) as UnixSystemFunctionResult<NativePointer>;
59+
if (ret.value.equals(Mem.MAP_FAILED))
60+
throw new Error(`failed to mmap, errno: ${ret.errno}`);
61+
return ret.value;
62+
}
63+
64+
public protect(addr: NativePointer, size: number, prot: MemProtection) {
65+
const ret = this.fnMprotect(
66+
addr,
67+
size,
68+
prot,
69+
) as UnixSystemFunctionResult<number>;
70+
if (ret.value === -1)
71+
throw new Error(`failed to mprotect, errno: ${ret.errno}`);
72+
}
73+
74+
public static pageAlign(size: number): number {
75+
const mask = Process.pageSize - 1;
76+
return (size + mask) & ~mask;
77+
}
78+
}

src/memory/mem.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export class Mem {
3333
}
3434
}
3535

36-
private static modifyMemory(address: NativePointer, data: Uint8Array) {
36+
public static modifyMemory(address: NativePointer, data: Uint8Array) {
3737
const alignStart = this.pageAlignDown(address);
3838
const alignEnd = this.pageAlignUp(address.add(data.length));
3939
const pageShift = Math.log2(Process.pageSize);

src/memory/overlay.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,16 @@ export class Overlay {
8181
if (this.address.compare(addr.add(length)) >= 0) return false;
8282
return true;
8383
}
84+
85+
public static all(): Overlay[] {
86+
return Overlay.overlays.map(([_, overlay]) => overlay);
87+
}
88+
89+
public revert() {
90+
Mem.modifyMemory(this.address, this.data);
91+
}
92+
93+
public toString(): string {
94+
return `addr: ${this.address}, length: ${this.data.length}`;
95+
}
8496
}

0 commit comments

Comments
 (0)