@efffrida/frida-tools 0.0.27 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/FridaDevice.d.ts +9 -8
  2. package/dist/FridaDevice.d.ts.map +1 -1
  3. package/dist/FridaDevice.js.map +1 -1
  4. package/dist/FridaDeviceAcquisitionError.d.ts +3 -18
  5. package/dist/FridaDeviceAcquisitionError.d.ts.map +1 -1
  6. package/dist/FridaDeviceAcquisitionError.js +2 -13
  7. package/dist/FridaDeviceAcquisitionError.js.map +1 -1
  8. package/dist/FridaScript.d.ts +12 -13
  9. package/dist/FridaScript.d.ts.map +1 -1
  10. package/dist/FridaScript.js +10 -9
  11. package/dist/FridaScript.js.map +1 -1
  12. package/dist/FridaSession.d.ts +21 -7
  13. package/dist/FridaSession.d.ts.map +1 -1
  14. package/dist/FridaSession.js.map +1 -1
  15. package/dist/FridaSessionError.d.ts +1 -16
  16. package/dist/FridaSessionError.d.ts.map +1 -1
  17. package/dist/FridaSessionError.js +2 -13
  18. package/dist/FridaSessionError.js.map +1 -1
  19. package/dist/internal/compiler.d.ts +2 -0
  20. package/dist/internal/compiler.d.ts.map +1 -0
  21. package/dist/internal/compiler.js +82 -0
  22. package/dist/internal/compiler.js.map +1 -0
  23. package/dist/internal/device.js +33 -32
  24. package/dist/internal/device.js.map +1 -1
  25. package/dist/internal/script.js +56 -105
  26. package/dist/internal/script.js.map +1 -1
  27. package/dist/internal/session.js +90 -48
  28. package/dist/internal/session.js.map +1 -1
  29. package/package.json +9 -16
  30. package/src/FridaDevice.ts +11 -10
  31. package/src/FridaDeviceAcquisitionError.ts +4 -29
  32. package/src/FridaScript.ts +22 -23
  33. package/src/FridaSession.ts +25 -7
  34. package/src/FridaSessionError.ts +2 -24
  35. package/src/internal/compiler.ts +122 -0
  36. package/src/internal/device.ts +85 -67
  37. package/src/internal/script.ts +209 -292
  38. package/src/internal/session.ts +116 -52
@@ -1,14 +1,17 @@
1
1
  import type * as Scope from "effect/Scope";
2
2
 
3
3
  import * as Context from "effect/Context";
4
+ import * as Deferred from "effect/Deferred";
4
5
  import * as Effect from "effect/Effect";
5
6
  import * as Layer from "effect/Layer";
6
7
  import * as Match from "effect/Match";
8
+ import * as Option from "effect/Option";
7
9
  import * as Predicate from "effect/Predicate";
8
- import * as Frida from "frida";
9
10
 
10
11
  import type * as FridaSession from "../FridaSession.ts";
11
12
 
13
+ import * as Frida from "frida";
14
+
12
15
  import * as FridaDevice from "../FridaDevice.ts";
13
16
  import * as FridaSessionError from "../FridaSessionError.ts";
14
17
 
@@ -18,12 +21,42 @@ export const FridaSessionTypeId: FridaSession.FridaSessionTypeId = Symbol.for(
18
21
  ) as FridaSession.FridaSessionTypeId;
19
22
 
20
23
  /** @internal */
21
- export const Tag = Context.GenericTag<FridaSession.FridaSession>("@efffrida/frida-tools/FridaSession");
24
+ export const Tag = Context.Service<FridaSession.FridaSession>("@efffrida/frida-tools/FridaSession");
22
25
 
23
26
  /** @internal */
24
27
  export const isFridaSession = (u: unknown): u is FridaSession.FridaSession =>
25
28
  Predicate.hasProperty(u, FridaSessionTypeId);
26
29
 
30
+ /** @internal */
31
+ export const resume = (session: Frida.Session): Effect.Effect<void, FridaSessionError.FridaSessionError, never> =>
32
+ Effect.tryPromise({
33
+ try: (signal) => {
34
+ const cancellable = new Frida.Cancellable();
35
+ signal.onabort = () => cancellable.cancel();
36
+ return session.resume(cancellable);
37
+ },
38
+ catch: (cause) =>
39
+ new FridaSessionError.FridaSessionError({
40
+ when: "resume",
41
+ cause,
42
+ }),
43
+ });
44
+
45
+ /** @internal */
46
+ export const detach = (session: Frida.Session): Effect.Effect<void, FridaSessionError.FridaSessionError, never> =>
47
+ Effect.tryPromise({
48
+ try: (signal) => {
49
+ const cancellable = new Frida.Cancellable();
50
+ signal.onabort = () => cancellable.cancel();
51
+ return session.detach(cancellable);
52
+ },
53
+ catch: (cause) =>
54
+ new FridaSessionError.FridaSessionError({
55
+ when: "detach",
56
+ cause,
57
+ }),
58
+ });
59
+
27
60
  /** @internal */
28
61
  export const frontmost = (
29
62
  options?: Frida.FrontmostQueryOptions | undefined
@@ -35,7 +68,7 @@ export const frontmost = (
35
68
  return device.getFrontmostApplication(options, cancellable);
36
69
  })
37
70
  ).pipe(
38
- Effect.flatMap(Effect.fromNullable),
71
+ Effect.flatMap(Effect.fromNullishOr),
39
72
  Effect.mapError(
40
73
  (cause) =>
41
74
  new FridaSessionError.FridaSessionError({
@@ -50,7 +83,7 @@ export const spawn = (
50
83
  program: string | ReadonlyArray<string>,
51
84
  options?: Frida.SpawnOptions | undefined
52
85
  ): Effect.Effect<number, FridaSessionError.FridaSessionError, FridaDevice.FridaDevice | Scope.Scope> => {
53
- const spawnEffect = Effect.flatMap(FridaDevice.FridaDevice, ({ device }) =>
86
+ const acquire = Effect.flatMap(FridaDevice.FridaDevice, ({ device }) =>
54
87
  Effect.tryPromise({
55
88
  try: (signal) => {
56
89
  const cancellable = new Frida.Cancellable();
@@ -65,22 +98,6 @@ export const spawn = (
65
98
  })
66
99
  );
67
100
 
68
- const resumeEffect = (pid: number) =>
69
- Effect.flatMap(FridaDevice.FridaDevice, ({ device }) =>
70
- Effect.tryPromise({
71
- try: (signal) => {
72
- const cancellable = new Frida.Cancellable();
73
- signal.onabort = () => cancellable.cancel();
74
- return device.resume(pid, cancellable);
75
- },
76
- catch: (cause) =>
77
- new FridaSessionError.FridaSessionError({
78
- when: "resume",
79
- cause,
80
- }),
81
- })
82
- );
83
-
84
101
  const release = (pid: number) =>
85
102
  Effect.flatMap(FridaDevice.FridaDevice, ({ device }) =>
86
103
  Effect.promise((signal) => {
@@ -90,7 +107,6 @@ export const spawn = (
90
107
  })
91
108
  );
92
109
 
93
- const acquire = Effect.tap(spawnEffect, resumeEffect);
94
110
  const resource = Effect.acquireRelease(acquire, release);
95
111
  return resource;
96
112
  };
@@ -104,6 +120,38 @@ export const attach = (
104
120
  FridaSessionError.FridaSessionError,
105
121
  FridaDevice.FridaDevice | Scope.Scope
106
122
  > => {
123
+ const detached = Deferred.makeUnsafe<
124
+ {
125
+ reason: Frida.SessionDetachReason;
126
+ crash: Option.Option<{
127
+ pid: number;
128
+ processName: string;
129
+ summary: string;
130
+ report: string;
131
+ parameters: unknown;
132
+ }>;
133
+ },
134
+ FridaSessionError.FridaSessionError
135
+ >();
136
+
137
+ const onDetached = (reason: Frida.SessionDetachReason, crash: Frida.Crash | null): void => {
138
+ Deferred.doneUnsafe(
139
+ detached,
140
+ Effect.succeed({
141
+ reason,
142
+ crash: Option.fromNullOr(crash).pipe(
143
+ Option.map((c) => ({
144
+ pid: c.pid,
145
+ processName: c.processName,
146
+ summary: c.summary,
147
+ report: c.report,
148
+ parameters: c.parameters,
149
+ }))
150
+ ),
151
+ })
152
+ );
153
+ };
154
+
107
155
  const acquire = Effect.flatMap(FridaDevice.FridaDevice, ({ device }) =>
108
156
  Effect.tryPromise({
109
157
  try: (signal) => {
@@ -123,45 +171,45 @@ export const attach = (
123
171
  Effect.promise((signal) => {
124
172
  const cancellable = new Frida.Cancellable();
125
173
  signal.onabort = () => cancellable.cancel();
174
+ session.detached.disconnect(onDetached);
126
175
  return session.detach(cancellable);
127
176
  });
128
177
 
129
178
  const resource = Effect.acquireRelease(acquire, release);
130
- return Effect.map(
131
- resource,
132
- (session) =>
133
- ({
134
- session,
135
- resume: Effect.tryPromise((signal) => {
136
- const cancellable = new Frida.Cancellable();
137
- signal.onabort = () => cancellable.cancel();
138
- return session.resume(cancellable);
139
- }),
140
- enableChildGating: Effect.tryPromise((signal) => {
179
+ return Effect.map(resource, (session) => {
180
+ session.detached.connect(onDetached);
181
+
182
+ return {
183
+ session,
184
+ pid: session.pid,
185
+ detached: detached,
186
+ resume: resume(session),
187
+ detach: detach(session),
188
+ enableChildGating: Effect.tryPromise((signal) => {
189
+ const cancellable = new Frida.Cancellable();
190
+ signal.onabort = () => cancellable.cancel();
191
+ return session.enableChildGating(cancellable);
192
+ }),
193
+ disableChildGating: Effect.tryPromise((signal) => {
194
+ const cancellable = new Frida.Cancellable();
195
+ signal.onabort = () => cancellable.cancel();
196
+ return session.disableChildGating(cancellable);
197
+ }),
198
+ setupPeerConnection: (opts?: Frida.PeerOptions | undefined) =>
199
+ Effect.tryPromise((signal) => {
141
200
  const cancellable = new Frida.Cancellable();
142
201
  signal.onabort = () => cancellable.cancel();
143
- return session.enableChildGating(cancellable);
202
+ return session.setupPeerConnection(opts, cancellable);
144
203
  }),
145
- disableChildGating: Effect.tryPromise((signal) => {
204
+ joinPortal: (address: string, opts?: Frida.PortalOptions | undefined) =>
205
+ Effect.tryPromise((signal) => {
146
206
  const cancellable = new Frida.Cancellable();
147
207
  signal.onabort = () => cancellable.cancel();
148
- return session.disableChildGating(cancellable);
208
+ return session.joinPortal(address, opts, cancellable);
149
209
  }),
150
- setupPeerConnection: (opts?: Frida.PeerOptions | undefined) =>
151
- Effect.tryPromise((signal) => {
152
- const cancellable = new Frida.Cancellable();
153
- signal.onabort = () => cancellable.cancel();
154
- return session.setupPeerConnection(opts, cancellable);
155
- }),
156
- joinPortal: (address: string, opts?: Frida.PortalOptions | undefined) =>
157
- Effect.tryPromise((signal) => {
158
- const cancellable = new Frida.Cancellable();
159
- signal.onabort = () => cancellable.cancel();
160
- return session.joinPortal(address, opts, cancellable);
161
- }),
162
- [FridaSessionTypeId]: FridaSessionTypeId,
163
- }) as const
164
- );
210
+ [FridaSessionTypeId]: FridaSessionTypeId,
211
+ } as const;
212
+ });
165
213
  };
166
214
 
167
215
  /** @internal */
@@ -169,9 +217,11 @@ export const layer = (
169
217
  target: number | string | ReadonlyArray<string>,
170
218
  options?: (Frida.SpawnOptions & Frida.SessionOptions) | undefined
171
219
  ): Layer.Layer<FridaSession.FridaSession, FridaSessionError.FridaSessionError, FridaDevice.FridaDevice> =>
172
- Layer.scoped(
220
+ Layer.effect(
173
221
  Tag,
174
222
  Effect.gen(function* () {
223
+ const { device } = yield* FridaDevice.FridaDevice;
224
+
175
225
  const pid = yield* Match.value(target).pipe(
176
226
  Match.when(Match.number, (proc) => Effect.succeed(proc)),
177
227
  Match.when(Match.string, (proc) => spawn(proc)),
@@ -179,6 +229,20 @@ export const layer = (
179
229
  );
180
230
 
181
231
  const session = yield* attach(pid, options);
232
+
233
+ yield* Effect.tryPromise({
234
+ try: (signal) => {
235
+ const cancellable = new Frida.Cancellable();
236
+ signal.onabort = () => cancellable.cancel();
237
+ return device.resume(session.pid, cancellable);
238
+ },
239
+ catch: (cause) =>
240
+ new FridaSessionError.FridaSessionError({
241
+ when: "resume",
242
+ cause,
243
+ }),
244
+ });
245
+
182
246
  return session;
183
247
  })
184
248
  );
@@ -187,4 +251,4 @@ export const layer = (
187
251
  export const layerFrontmost = (
188
252
  options?: Frida.FrontmostQueryOptions | undefined
189
253
  ): Layer.Layer<FridaSession.FridaSession, FridaSessionError.FridaSessionError, FridaDevice.FridaDevice> =>
190
- Layer.unwrapEffect(Effect.map(frontmost(options), (app) => layer(app.pid)));
254
+ Layer.unwrap(Effect.map(frontmost(options), (app) => layer(app.pid)));