Skip to content

Commit ba12d43

Browse files
author
Your Name
committed
Fixes to generation of corpse
1 parent 36e917f commit ba12d43

File tree

10 files changed

+129
-243
lines changed

10 files changed

+129
-243
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.7.6",
3+
"version": "1.7.7",
44
"description": "Frida's CShell",
55
"scripts": {
66
"prepare": "npm run build && npm run version && npm run package && npm run copy",

src/cmdlets/misc/corpse/clone.ts

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/cmdlets/misc/corpse/core_filter.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,12 @@ export class CoreFilter {
33
public static readonly NEEDED: UInt64 = uint64(0x1ff);
44
private constructor() {}
55

6-
public static get(): UInt64 {
7-
const text = File.readAllText(CoreFilter.CORE_FILTER).trimEnd();
8-
const value = uint64(`0x${text}`);
9-
return value;
10-
}
11-
12-
public static trySet(value: UInt64): boolean {
6+
public static set(value: UInt64) {
137
const text = `0x${value.toString(16)}`;
148
try {
159
File.writeAllText(CoreFilter.CORE_FILTER, text);
16-
return true;
17-
} catch {
18-
return false;
10+
} catch (error) {
11+
throw new Error(`failed to set core filter, ${error}`);
1912
}
2013
}
2114
}

src/cmdlets/misc/corpse/corpse.ts

Lines changed: 47 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { CmdLetBase } from '../../../commands/cmdlet.js';
22
import { Output } from '../../../io/output.js';
33
import { Token } from '../../../io/token.js';
4-
import { Exception } from '../../../misc/exception.js';
54
import { Files } from '../../../misc/files.js';
65
import { Format } from '../../../misc/format.js';
76
import { Var } from '../../../vars/var.js';
8-
import { Clone } from './clone.js';
7+
import { Fork } from './fork.js';
98
import { CoreFilter } from './core_filter.js';
109
import { CorePattern } from './core_pattern.js';
1110
import { Dumpable } from './dumpable.js';
@@ -21,22 +20,17 @@ export class CorpseCmdLet extends CmdLetBase {
2120
private static readonly USAGE: string = `Usage: corpse
2221
corpse - create a corpse file`;
2322

24-
private static readonly CHILD_SLEEP_DURATION: number = 0.1;
2523
private static readonly PARENT_SLEEP_DURATION: number = 0.5;
2624
private static readonly WAIT_DURATION: number = 20;
27-
private static readonly PARENT_DELAY_DURATION: number = 2;
2825
private static readonly ELF_MAGIC: number = 0x7f454c46;
2926

3027
private rlimit: Rlimit | null = null;
3128
private dumpable: Dumpable | null = null;
32-
private clone: Clone | null = null;
29+
private clone: Fork | null = null;
3330
private proc: Proc | null = null;
3431

3532
public runSync(tokens: Token[]): Var {
36-
if (tokens.length != 0) {
37-
Output.writeln(CorpseCmdLet.USAGE);
38-
return Var.ZERO;
39-
}
33+
if (tokens.length != 0) return this.usage();
4034

4135
const corePattern = CorePattern.get();
4236
this.status(`Got core pattern: '${corePattern}'`);
@@ -48,109 +42,33 @@ corpse - create a corpse file`;
4842
run 'setenforce 0' to disable`);
4943
}
5044

51-
/* set the rlimit */
52-
const rlimit = this.rlimit as Rlimit;
53-
const limit = rlimit.get();
54-
this.debug(
55-
`Read rlimit - soft: ${limit.sortLimit}, hard: ${limit.hardLimit}`,
56-
);
57-
if (rlimit.isUnlimited(limit)) {
58-
this.debug('Rlimit is unlimited');
59-
} else {
60-
this.debug('Setting rlimit to unlimited');
61-
rlimit.set(Rlimit.UNLIMITED);
62-
}
63-
this.status('Rlimit has been configured');
45+
/* run the clone */
46+
const debugFileName = Files.getRandomFileName('debug');
47+
this.status(`Creating debug file: '${debugFileName}'`);
48+
const debugFile = new File(debugFileName, 'w');
49+
const debug = (msg: string) => {
50+
debugFile.write(`${msg}\n`);
51+
debugFile.flush();
52+
};
6453

54+
this.status('Reconfiguring exception handling');
6555
try {
66-
/* Set the core filter*/
67-
const coreFilter = CoreFilter.get();
68-
this.status(`Read core filter: 0x${coreFilter.toString(16)}`);
69-
if (coreFilter.equals(CoreFilter.NEEDED)) {
70-
this.debug('Core filter is already set');
71-
} else {
72-
this.debug('Setting core filter');
73-
CoreFilter.trySet(CoreFilter.NEEDED);
74-
}
75-
this.status('Core filter has been configured');
76-
77-
try {
78-
/* set dumpable */
79-
const dumpable = this.dumpable as Dumpable;
80-
const isDumpable = dumpable.get();
81-
this.status(`Read dumpable: ${isDumpable}`);
82-
if (isDumpable === 0) {
83-
this.debug('Setting dumpable');
84-
dumpable.set(1);
85-
} else {
86-
this.debug('Dumpable is already set');
87-
}
88-
this.status('Dumpable has been configured');
89-
90-
/* run the clone */
91-
try {
92-
const debugFileName = Files.getRandomFileName('debug');
93-
this.status(`Creating debug file: '${debugFileName}'`);
94-
const debugFile = new File(debugFileName, 'w');
95-
const debug = (msg: string) => {
96-
debugFile.write(`${msg}\n`);
97-
debugFile.flush();
98-
};
99-
100-
this.status('Reconfiguring exception handling');
101-
Exception.propagate();
102-
try {
103-
const clone = this.clone as Clone;
104-
const childPid = clone.clone(
105-
(childPid: number) => {
106-
this.runParent(childPid);
107-
},
108-
() => {
109-
this.runChild(debug);
110-
},
111-
);
112-
this.debug(
113-
`Checking for corpse - core pattern: '${corePattern}', pid: ${childPid}`,
114-
);
115-
this.checkCorpse(corePattern, childPid);
116-
} finally {
117-
this.status('Restoring exception handling');
118-
Exception.suppress();
119-
this.debug(`Checking debug file: '${debugFileName}'`);
120-
this.checkDebugFile(debugFileName);
121-
}
122-
} finally {
123-
/* Restore dumpable */
124-
this.status('Restoring dumpable');
125-
if (isDumpable === 0) {
126-
this.debug('Resetting dumpable');
127-
dumpable.set(isDumpable);
128-
} else {
129-
this.debug('No need to reset dumpable');
130-
}
131-
this.debug('Restored dumpable');
132-
}
133-
} finally {
134-
/* Restore core filter */
135-
this.status('Restoring core filter');
136-
if (coreFilter.equals(CoreFilter.NEEDED)) {
137-
this.debug('No need to restore core filter');
138-
} else {
139-
this.debug('Restoring core filter');
140-
CoreFilter.trySet(coreFilter);
141-
}
142-
this.debug('Restored core filter');
143-
}
56+
const clone = this.clone as Fork;
57+
const childPid = clone.fork(
58+
(childPid: number) => {
59+
this.runParent(childPid);
60+
},
61+
() => {
62+
this.runChild(debug);
63+
},
64+
);
65+
this.debug(
66+
`Checking for corpse - core pattern: '${corePattern}', pid: ${childPid}`,
67+
);
68+
this.checkCorpse(corePattern, childPid);
14469
} finally {
145-
/* Restore rlimit */
146-
this.status('Restoring rlimit');
147-
if (rlimit.isUnlimited(limit)) {
148-
this.debug('No need to restore rlimit');
149-
} else {
150-
this.debug('Restoring rlimit');
151-
rlimit.set(limit);
152-
}
153-
this.debug('Restored rlimit');
70+
this.debug(`Checking debug file: '${debugFileName}'`);
71+
this.checkDebugFile(debugFileName);
15472
}
15573

15674
return Var.ZERO;
@@ -161,17 +79,14 @@ corpse - create a corpse file`;
16179

16280
const proc = this.proc as Proc;
16381

164-
this.debug(`Delaying: ${CorpseCmdLet.PARENT_DELAY_DURATION}s`);
165-
Thread.sleep(CorpseCmdLet.PARENT_DELAY_DURATION);
166-
16782
const limit =
16883
CorpseCmdLet.WAIT_DURATION / CorpseCmdLet.PARENT_SLEEP_DURATION;
16984

17085
this.debug(`Parent limit: ${limit}`);
171-
this.debug(`Delay between signals: ${CorpseCmdLet.PARENT_SLEEP_DURATION}s`);
86+
this.debug(
87+
`Delay between waitpids: ${CorpseCmdLet.PARENT_SLEEP_DURATION}s`,
88+
);
17289
for (let i = 0; i < limit; i++) {
173-
proc.kill(childPid, Proc.SIGABRT);
174-
17590
const status = proc.waitpid(childPid);
17691
this.debug(
17792
[
@@ -197,14 +112,22 @@ corpse - create a corpse file`;
197112
debug(`PID: ${pid}`);
198113

199114
try {
200-
const limit =
201-
CorpseCmdLet.WAIT_DURATION / CorpseCmdLet.CHILD_SLEEP_DURATION;
202-
debug(`Child limit: ${limit}`);
203-
debug(`Delay between sleeps: ${CorpseCmdLet.CHILD_SLEEP_DURATION}s`);
204-
for (let i = 0; i < limit; i++) {
205-
Thread.sleep(CorpseCmdLet.CHILD_SLEEP_DURATION);
206-
}
207-
debug(`Child limit exceeded`);
115+
const rlimit = this.rlimit as Rlimit;
116+
rlimit.set(Rlimit.UNLIMITED);
117+
debug(`set rlimit`);
118+
119+
CoreFilter.set(CoreFilter.NEEDED);
120+
debug(`set core filter`);
121+
122+
const dumpable = this.dumpable as Dumpable;
123+
dumpable.set(1);
124+
debug(`set dumpable`);
125+
126+
debug(`Restoring default signal action using rt_sigaction`);
127+
proc.rt_sigaction(Proc.SIGABRT, Proc.SIG_DFL);
128+
129+
debug(`Suicide`);
130+
proc.kill(pid, Proc.SIGABRT);
208131
} catch (error) {
209132
if (error instanceof Error) {
210133
debug(`ERROR: ${error.message}`);
@@ -283,7 +206,7 @@ corpse - create a corpse file`;
283206
try {
284207
this.rlimit = new Rlimit();
285208
this.dumpable = new Dumpable();
286-
this.clone = new Clone();
209+
this.clone = new Fork();
287210
this.proc = new Proc();
288211
} catch {
289212
return false;

src/cmdlets/misc/corpse/dumpable.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,14 @@
11
export class Dumpable {
2-
private static readonly PR_GET_DUMPABLE: number = 3;
32
private static readonly PR_SET_DUMPABLE: number = 4;
4-
private fnGetPrctl: SystemFunction<number, [number]>;
53
private fnSetPrctl: SystemFunction<number, [number, number | UInt64]>;
64

75
public constructor() {
86
const pPrctl = Module.findExportByName(null, 'prctl');
97
if (pPrctl === null) throw new Error('failed to find prctl');
108

11-
this.fnGetPrctl = new SystemFunction(pPrctl, 'int', ['int']);
12-
139
this.fnSetPrctl = new SystemFunction(pPrctl, 'int', ['int', 'size_t']);
1410
}
1511

16-
public get(): number {
17-
const ret = this.fnGetPrctl(
18-
Dumpable.PR_GET_DUMPABLE,
19-
) as UnixSystemFunctionResult<number>;
20-
return ret.value;
21-
}
22-
2312
public set(value: number) {
2413
const ret = this.fnSetPrctl(
2514
Dumpable.PR_SET_DUMPABLE,

src/cmdlets/misc/corpse/fork.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export class Fork {
2+
private fnFork: SystemFunction<number, []>;
3+
public constructor() {
4+
const pFork = Module.findExportByName(null, 'fork');
5+
if (pFork === null) throw new Error('failed to find fork');
6+
7+
this.fnFork = new SystemFunction(pFork, 'int', []);
8+
}
9+
10+
public fork(
11+
parentCallback: (childPid: number) => void,
12+
childCallback: () => void,
13+
): number {
14+
const ret = this.fnFork() as UnixSystemFunctionResult<number>;
15+
if (ret.value === -1) {
16+
throw new Error(`failed to clone, errno: ${ret.errno}`);
17+
} else if (ret.value === 0) {
18+
childCallback();
19+
} else {
20+
parentCallback(ret.value);
21+
}
22+
23+
return ret.value;
24+
}
25+
}

0 commit comments

Comments
 (0)