aboutsummaryrefslogtreecommitdiff
path: root/frida_mode/ts
diff options
context:
space:
mode:
Diffstat (limited to 'frida_mode/ts')
-rw-r--r--frida_mode/ts/lib/afl.ts373
-rw-r--r--frida_mode/ts/package-lock.json12
-rw-r--r--frida_mode/ts/package.json32
-rw-r--r--frida_mode/ts/tsconfig.json14
-rw-r--r--frida_mode/ts/tslint.json256
5 files changed, 687 insertions, 0 deletions
diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts
new file mode 100644
index 00000000..6da7fabc
--- /dev/null
+++ b/frida_mode/ts/lib/afl.ts
@@ -0,0 +1,373 @@
+class Afl {
+
+ /**
+ * Field containing the `Module` object for `afl-frida-trace.so` (the FRIDA mode
+ * implementation).
+ */
+ public static module: Module = Process.getModuleByName("afl-frida-trace.so");
+
+ /**
+ * This is equivalent to setting a value in `AFL_FRIDA_EXCLUDE_RANGES`,
+ * it takes as arguments a `NativePointer` and a `number`. It can be
+ * called multiple times to exclude several ranges.
+ */
+ public static addExcludedRange(addressess: NativePointer, size: number): void {
+ Afl.jsApiAddExcludeRange(addressess, size);
+ }
+
+ /**
+ * This is equivalent to setting a value in `AFL_FRIDA_INST_RANGES`,
+ * it takes as arguments a `NativePointer` and a `number`. It can be
+ * called multiple times to include several ranges.
+ */
+ public static addIncludedRange(addressess: NativePointer, size: number): void {
+ Afl.jsApiAddIncludeRange(addressess, size);
+ }
+
+ /**
+ * This must always be called at the end of your script. This lets
+ * FRIDA mode know that your configuration is finished and that
+ * execution has reached the end of your script. Failure to call
+ * this will result in a fatal error.
+ */
+ public static done(): void {
+ Afl.jsApiDone();
+ }
+
+ /**
+ * This function can be called within your script to cause FRIDA
+ * mode to trigger a fatal error. This is useful if for example you
+ * discover a problem you weren't expecting and want everything to
+ * stop. The user will need to enable `AFL_DEBUG_CHILD=1` to view
+ * this error message.
+ */
+ public static error(msg: string): void {
+ const buf = Memory.allocUtf8String(msg);
+ Afl.jsApiError(buf);
+ }
+
+ /**
+ * Function used to provide access to `__afl_fuzz_ptr`, which contains the length of
+ * fuzzing data when using in-memory test case fuzzing.
+ */
+ public static getAflFuzzLen(): NativePointer {
+
+ return Afl.jsApiGetSymbol("__afl_fuzz_len");
+ }
+
+ /**
+ * Function used to provide access to `__afl_fuzz_ptr`, which contains the fuzzing
+ * data when using in-memory test case fuzzing.
+ */
+ public static getAflFuzzPtr(): NativePointer {
+
+ return Afl.jsApiGetSymbol("__afl_fuzz_ptr");
+ }
+
+ /**
+ * Print a message to the STDOUT. This should be preferred to
+ * FRIDA's `console.log` since FRIDA will queue it's log messages.
+ * If `console.log` is used in a callback in particular, then there
+ * may no longer be a thread running to service this queue.
+ */
+ public static print(msg: string): void {
+ const STDOUT_FILENO = 2;
+ const log = `${msg}\n`;
+ const buf = Memory.allocUtf8String(log);
+ Afl.jsApiWrite(STDOUT_FILENO, buf, log.length);
+ }
+
+ /**
+ * See `AFL_FRIDA_DEBUG_MAPS`.
+ */
+ public static setDebugMaps(): void {
+ Afl.jsApiSetDebugMaps();
+ }
+
+ /**
+ * This has the same effect as setting `AFL_ENTRYPOINT`, but has the
+ * convenience of allowing you to use FRIDAs APIs to determine the
+ * address you would like to configure, rather than having to grep
+ * the output of `readelf` or something similarly ugly. This
+ * function should be called with a `NativePointer` as its
+ * argument.
+ */
+ public static setEntryPoint(address: NativePointer): void {
+ Afl.jsApiSetEntryPoint(address);
+ }
+
+ /**
+ * Function used to enable in-memory test cases for fuzzing.
+ */
+ public static setInMemoryFuzzing(): void {
+ Afl.jsApiAflSharedMemFuzzing.writeInt(1);
+ }
+
+ /**
+ * See `AFL_FRIDA_INST_DEBUG_FILE`. This function takes a single `string` as
+ * an argument.
+ */
+ public static setInstrumentDebugFile(file: string): void {
+ const buf = Memory.allocUtf8String(file);
+ Afl.jsApiSetInstrumentDebugFile(buf);
+ }
+
+ /**
+ * See `AFL_FRIDA_INST_TRACE`.
+ */
+ public static setInstrumentEnableTracing(): void {
+ Afl.jsApiSetInstrumentTrace();
+ }
+
+ /**
+ * See `AFL_INST_LIBS`.
+ */
+ public static setInstrumentLibraries(): void {
+ Afl.jsApiSetInstrumentLibraries();
+ }
+
+ /**
+ * See `AFL_FRIDA_INST_NO_OPTIMIZE`
+ */
+ public static setInstrumentNoOptimize(): void {
+ Afl.jsApiSetInstrumentNoOptimize();
+ }
+
+ /**
+ * See `AFL_FRIDA_INST_TRACE_UNIQUE`.
+ */
+ public static setInstrumentTracingUnique(): void {
+ Afl.jsApiSetInstrumentTraceUnique();
+ }
+
+ /**
+ * This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a
+ * `NativePointer` should be provided as it's argument.
+ */
+ public static setPersistentAddress(address: NativePointer): void {
+ Afl.jsApiSetPersistentAddress(address);
+ }
+
+ /**
+ * This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a
+ * `number` should be provided as it's argument.
+ */
+ public static setPersistentCount(count: number): void {
+ Afl.jsApiSetPersistentCount(count);
+ }
+
+ /**
+ * See `AFL_FRIDA_PERSISTENT_DEBUG`.
+ */
+ public static setPersistentDebug(): void {
+ Afl.jsApiSetPersistentDebug();
+ }
+
+ /**
+ * See `AFL_FRIDA_PERSISTENT_ADDR`. This function takes a NativePointer as an
+ * argument. See above for examples of use.
+ */
+ public static setPersistentHook(address: NativePointer): void {
+ Afl.jsApiSetPersistentHook(address);
+ }
+
+ /**
+ * This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a
+ * `NativePointer` should be provided as it's argument.
+ */
+ public static setPersistentReturn(address: NativePointer): void {
+ Afl.jsApiSetPersistentReturn(address);
+ }
+
+ /**
+ * See `AFL_FRIDA_INST_NO_PREFETCH`.
+ */
+ public static setPrefetchDisable(): void {
+ Afl.jsApiSetPrefetchDisable();
+ }
+
+ /*
+ * Set a function to be called for each instruction which is instrumented
+ * by AFL FRIDA mode.
+ */
+ public static setStalkerCallback(callback: NativePointer): void {
+ Afl.jsApiSetStalkerCallback(callback);
+ }
+
+ /**
+ * See `AFL_FRIDA_STATS_FILE`. This function takes a single `string` as
+ * an argument.
+ */
+ public static setStatsFile(file: string): void {
+ const buf = Memory.allocUtf8String(file);
+ Afl.jsApiSetStatsFile(buf);
+ }
+
+ /**
+ * See `AFL_FRIDA_STATS_INTERVAL`. This function takes a `number` as an
+ * argument
+ */
+ public static setStatsInterval(interval: number): void {
+ Afl.jsApiSetStatsInterval(interval);
+ }
+
+ /**
+ * See `AFL_FRIDA_STATS_TRANSITIONS`
+ */
+ public static setStatsTransitions(): void {
+ Afl.jsApiSetStatsTransitions();
+ }
+
+ /**
+ * See `AFL_FRIDA_OUTPUT_STDERR`. This function takes a single `string` as
+ * an argument.
+ */
+ public static setStdErr(file: string): void {
+ const buf = Memory.allocUtf8String(file);
+ Afl.jsApiSetStdErr(buf);
+ }
+
+ /**
+ * See `AFL_FRIDA_OUTPUT_STDOUT`. This function takes a single `string` as
+ * an argument.
+ */
+ public static setStdOut(file: string): void {
+ const buf = Memory.allocUtf8String(file);
+ Afl.jsApiSetStdOut(buf);
+ }
+
+ private static readonly jsApiAddExcludeRange = Afl.jsApiGetFunction(
+ "js_api_add_exclude_range",
+ "void",
+ ["pointer", "size_t"]);
+
+ private static readonly jsApiAddIncludeRange = Afl.jsApiGetFunction(
+ "js_api_add_include_range",
+ "void",
+ ["pointer", "size_t"]);
+
+ private static readonly jsApiAflSharedMemFuzzing = Afl.jsApiGetSymbol("__afl_sharedmem_fuzzing");
+
+ private static readonly jsApiDone = Afl.jsApiGetFunction(
+ "js_api_done",
+ "void",
+ []);
+
+ private static readonly jsApiError = Afl.jsApiGetFunction(
+ "js_api_error",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetDebugMaps = Afl.jsApiGetFunction(
+ "js_api_set_debug_maps",
+ "void",
+ []);
+
+ private static readonly jsApiSetEntryPoint = Afl.jsApiGetFunction(
+ "js_api_set_entrypoint",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction(
+ "js_api_set_instrument_debug_file",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetInstrumentLibraries = Afl.jsApiGetFunction(
+ "js_api_set_instrument_libraries",
+ "void",
+ []);
+
+ private static readonly jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction(
+ "js_api_set_instrument_no_optimize",
+ "void",
+ []);
+
+ private static readonly jsApiSetInstrumentTrace = Afl.jsApiGetFunction(
+ "js_api_set_instrument_trace",
+ "void",
+ []);
+
+ private static readonly jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction(
+ "js_api_set_instrument_trace_unique",
+ "void",
+ []);
+
+ private static readonly jsApiSetPersistentAddress = Afl.jsApiGetFunction(
+ "js_api_set_persistent_address",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetPersistentCount = Afl.jsApiGetFunction(
+ "js_api_set_persistent_count",
+ "void",
+ ["uint64"]);
+
+ private static readonly jsApiSetPersistentDebug = Afl.jsApiGetFunction(
+ "js_api_set_persistent_debug",
+ "void",
+ []);
+
+ private static readonly jsApiSetPersistentHook = Afl.jsApiGetFunction(
+ "js_api_set_persistent_hook",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetPersistentReturn = Afl.jsApiGetFunction(
+ "js_api_set_persistent_return",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetPrefetchDisable = Afl.jsApiGetFunction(
+ "js_api_set_prefetch_disable",
+ "void",
+ []);
+
+ private static readonly jsApiSetStalkerCallback = Afl.jsApiGetFunction(
+ "js_api_set_stalker_callback",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetStatsFile = Afl.jsApiGetFunction(
+ "js_api_set_stats_file",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetStatsInterval = Afl.jsApiGetFunction(
+ "js_api_set_stats_interval",
+ "void",
+ ["uint64"]);
+
+ private static readonly jsApiSetStatsTransitions = Afl.jsApiGetFunction(
+ "js_api_set_stats_transitions",
+ "void",
+ []);
+
+ private static readonly jsApiSetStdErr = Afl.jsApiGetFunction(
+ "js_api_set_stderr",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiSetStdOut = Afl.jsApiGetFunction(
+ "js_api_set_stdout",
+ "void",
+ ["pointer"]);
+
+ private static readonly jsApiWrite = new NativeFunction(
+ /* tslint:disable-next-line:no-null-keyword */
+ Module.getExportByName(null, "write"),
+ "int",
+ ["int", "pointer", "int"]);
+
+ private static jsApiGetFunction(name: string, retType: NativeType, argTypes: NativeType[]): NativeFunction {
+ const addr: NativePointer = Afl.module.getExportByName(name);
+
+ return new NativeFunction(addr, retType, argTypes);
+ }
+
+ private static jsApiGetSymbol(name: string): NativePointer {
+
+ return Afl.module.getExportByName(name);
+ }
+
+}
diff --git a/frida_mode/ts/package-lock.json b/frida_mode/ts/package-lock.json
new file mode 100644
index 00000000..e766c2c2
--- /dev/null
+++ b/frida_mode/ts/package-lock.json
@@ -0,0 +1,12 @@
+{
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "tsc": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/tsc/-/tsc-2.0.3.tgz",
+ "integrity": "sha512-SN+9zBUtrpUcOpaUO7GjkEHgWtf22c7FKbKCA4e858eEM7Qz86rRDpgOU2lBIDf0fLCsEg65ms899UMUIB2+Ow==",
+ "dev": true
+ }
+ }
+}
diff --git a/frida_mode/ts/package.json b/frida_mode/ts/package.json
new file mode 100644
index 00000000..47b693ed
--- /dev/null
+++ b/frida_mode/ts/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "@worksbutnottested/aflplusplus-frida",
+ "version": "1.0.0",
+ "description": "AFLplusplus Frida Mode",
+ "main": "./dist/frida.js",
+ "types": "./dist/frida.d.ts",
+ "files": [
+ "/dist/"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:worksbutnottested/AFLplusplus.git"
+ },
+ "publishConfig": {
+ "cache": "~/.npm",
+ "registry": "https://npm.pkg.github.com/@worksbutnottested"
+ },
+ "scripts": {
+ "prepare": "npm run build",
+ "build": "tsc",
+ "lint": "tslint -p tslint.json"
+ },
+ "devDependencies": {
+ "@types/node": "^14.14.2",
+ "typescript": "^4.0.3",
+ "typescript-tslint-plugin": "^0.5.5",
+ "tslint": "^6.1.3"
+ },
+ "dependencies": {
+ "@types/frida-gum": "^16.2.0"
+ }
+ }
diff --git a/frida_mode/ts/tsconfig.json b/frida_mode/ts/tsconfig.json
new file mode 100644
index 00000000..624e4496
--- /dev/null
+++ b/frida_mode/ts/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compilerOptions": {
+ "target": "es2020",
+ "lib": ["es2020"],
+ "strict": true,
+ "module": "commonjs",
+ "esModuleInterop": true,
+ "declaration": true,
+ "outDir": "./dist"
+ },
+ "include": [
+ "lib/**/*"
+ ]
+ }
diff --git a/frida_mode/ts/tslint.json b/frida_mode/ts/tslint.json
new file mode 100644
index 00000000..0e7a77ed
--- /dev/null
+++ b/frida_mode/ts/tslint.json
@@ -0,0 +1,256 @@
+{
+ "rules": {
+ "adjacent-overload-signatures": true,
+ "ban-types": {
+ "options": [
+ ["Object", "Avoid using the `Object` type. Did you mean `object`?"],
+ [
+ "Function",
+ "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."
+ ],
+ ["Boolean", "Avoid using the `Boolean` type. Did you mean `boolean`?"],
+ ["Number", "Avoid using the `Number` type. Did you mean `number`?"],
+ ["String", "Avoid using the `String` type. Did you mean `string`?"],
+ ["Symbol", "Avoid using the `Symbol` type. Did you mean `symbol`?"]
+ ]
+ },
+ "ban-ts-ignore": true,
+ "member-access": {
+ "options": ["check-accessor", "check-constructor", "check-parameter-property"]
+ },
+ "member-ordering": {
+ "options": {
+ "order": "statics-first",
+ "alphabetize": true
+ }
+ },
+ "no-any": true,
+ "no-empty-interface": true,
+ "no-for-in": true,
+ "no-import-side-effect": true,
+ "no-inferrable-types": { "options": ["ignore-params"] },
+ "no-internal-module": true,
+ "no-magic-numbers": true,
+ "no-namespace": true,
+ "no-non-null-assertion": true,
+ "no-reference": true,
+ "no-restricted-globals": true,
+ "no-this-assignment": true,
+ "no-var-requires": true,
+ "only-arrow-functions": true,
+ "prefer-for-of": true,
+ "prefer-readonly": true,
+ "promise-function-async": true,
+ "typedef": {
+ "options": [
+ "call-signature",
+ "parameter",
+ "property-declaration"
+ ]
+ },
+ "typedef-whitespace": {
+ "options": [
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ },
+ {
+ "call-signature": "onespace",
+ "index-signature": "onespace",
+ "parameter": "onespace",
+ "property-declaration": "onespace",
+ "variable-declaration": "onespace"
+ }
+ ]
+ },
+ "unified-signatures": true,
+ "await-promise": true,
+ "ban-comma-operator": true,
+ "curly": true,
+ "forin": true,
+ "function-constructor": true,
+ "label-position": true,
+ "no-arg": true,
+ "no-async-without-await": true,
+ "no-bitwise": true,
+ "no-conditional-assignment": true,
+ "no-console": true,
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-super": true,
+ "no-duplicate-switch-case": true,
+ "no-duplicate-variable": { "options": ["check-parameters"] },
+ "no-dynamic-delete": true,
+ "no-empty": true,
+ "no-eval": true,
+ "no-floating-promises": true,
+ "no-for-in-array": true,
+ "no-implicit-dependencies": true,
+ "no-inferred-empty-object-type": true,
+ "no-invalid-template-strings": true,
+ "no-misused-new": true,
+ "no-null-keyword": true,
+ "no-null-undefined-union": true,
+ "no-object-literal-type-assertion": true,
+ "no-promise-as-boolean": true,
+ "no-return-await": true,
+ "no-shadowed-variable": true,
+ "no-string-literal": true,
+ "no-string-throw": true,
+ "no-sparse-arrays": true,
+ "no-submodule-imports": true,
+ "no-tautology-expression": true,
+ "no-unbound-method": true,
+ "no-unnecessary-class": { "options": ["allow-empty-class", "allow-static-only"] },
+ "no-unsafe-any": false,
+ "no-unsafe-finally": true,
+ "no-unused-expression": true,
+ "no-var-keyword": true,
+ "no-void-expression": true,
+ "prefer-conditional-expression": true,
+ "radix": true,
+ "restrict-plus-operands": true,
+ "static-this": true,
+ "strict-boolean-expressions": true,
+ "strict-string-expressions": true,
+ "strict-comparisons": true,
+ "strict-type-predicates": true,
+ "switch-default": true,
+ "triple-equals": true,
+ "unnecessary-constructor": true,
+ "use-default-type-parameter": true,
+ "use-isnan": true,
+ "cyclomatic-complexity": true,
+ "eofline": true,
+ "indent": { "options": ["spaces"] },
+ "invalid-void": true,
+ "linebreak-style": { "options": "LF" },
+ "max-classes-per-file": { "options": 1 },
+ "max-file-line-count": { "options": 1000 },
+ "max-line-length": {
+ "options": { "limit": 120 }
+ },
+ "no-default-export": true,
+ "no-default-import": true,
+ "no-duplicate-imports": true,
+ "no-irregular-whitespace": true,
+ "no-mergeable-namespace": true,
+ "no-parameter-reassignment": true,
+ "no-require-imports": true,
+ "no-trailing-whitespace": true,
+ "object-literal-sort-keys": true,
+ "prefer-const": true,
+ "trailing-comma": {
+ "options": {
+ "esSpecCompliant": true,
+ "multiline": "always",
+ "singleline": "never"
+ }
+ },
+ "align": {
+ "options": ["parameters", "arguments", "statements", "elements", "members"]
+ },
+ "array-type": { "options": "array-simple" },
+ "arrow-parens": true,
+ "arrow-return-shorthand": { "options": "multiline" },
+ "binary-expression-operand-order": true,
+ "callable-types": true,
+ "class-name": true,
+ "comment-format": { "options": ["check-space", "check-uppercase"] },
+ "comment-type": { "options": ["singleline", "multiline", "doc", "directive"] },
+ "completed-docs": [
+ true,
+ {
+ "enums": true,
+ "methods": {"locations": "all", "privacies": ["public", "protected"]},
+ "properties": {"locations": "all", "privacies": ["public", "protected"]}
+ }
+ ],
+ "deprecation": true,
+ "encoding": true,
+ "file-name-casing": { "options": "camel-case" },
+ "import-spacing": true,
+ "increment-decrement": true,
+ "interface-name": true,
+ "interface-over-type-literal": true,
+ "jsdoc-format": { "options": "check-multiline-start" },
+ "match-default-export-name": true,
+ "new-parens": true,
+ "newline-before-return": true,
+ "newline-per-chained-call": true,
+ "no-angle-bracket-type-assertion": true,
+ "no-boolean-literal-compare": true,
+ "no-consecutive-blank-lines": true,
+ "no-parameter-properties": true,
+ "no-redundant-jsdoc": true,
+ "no-reference-import": true,
+ "no-unnecessary-callback-wrapper": true,
+ "no-unnecessary-initializer": true,
+ "no-unnecessary-qualifier": true,
+ "no-unnecessary-type-assertion": true,
+ "number-literal-format": true,
+ "object-literal-key-quotes": { "options": "consistent-as-needed" },
+ "object-literal-shorthand": true,
+ "one-line": {
+ "options": [
+ "check-catch",
+ "check-else",
+ "check-finally",
+ "check-open-brace",
+ "check-whitespace"
+ ]
+ },
+ "one-variable-per-declaration": true,
+ "ordered-imports": {
+ "options": {
+ "grouped-imports": true,
+ "import-sources-order": "case-insensitive",
+ "named-imports-order": "case-insensitive",
+ "module-source-path": "full"
+ }
+ },
+ "prefer-function-over-method": true,
+ "prefer-method-signature": true,
+ "prefer-object-spread": true,
+ "prefer-switch": true,
+ "prefer-template": true,
+ "prefer-while": true,
+ "quotemark": {
+ "options": ["double", "avoid-escape", "avoid-template"]
+ },
+ "return-undefined": true,
+ "semicolon": { "options": ["always"] },
+ "space-before-function-paren": {
+ "options": {
+ "anonymous": "never",
+ "asyncArrow": "always",
+ "constructor": "never",
+ "method": "never",
+ "named": "never"
+ }
+ },
+ "space-within-parens": { "options": 0 },
+ "switch-final-break": true,
+ "type-literal-delimiter": true,
+ "unnecessary-bind": true,
+ "unnecessary-else": true,
+ "variable-name": { "options": ["ban-keywords", "check-format", "require-const-for-all-caps"] },
+ "whitespace": {
+ "options": [
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-module",
+ "check-separator",
+ "check-type",
+ "check-typecast",
+ "check-preblock",
+ "check-type-operator",
+ "check-rest-spread"
+ ]
+ }
+ }
+}