bla-agents 1.1.0 → 1.5.3
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.
- package/.agents/skills/blind-llm-agents/SKILL.md +20 -14
- package/DISCLAIMER.md +15 -7
- package/README.md +153 -198
- package/dist/bundler/index.d.ts +19 -2
- package/dist/bundler/index.d.ts.map +1 -1
- package/dist/bundler/index.js +47 -4
- package/dist/bundler/index.js.map +1 -1
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +123 -18
- package/dist/cli.js.map +1 -1
- package/dist/core/config.d.ts +54 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +160 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/coverage-contract.d.ts +97 -0
- package/dist/core/coverage-contract.d.ts.map +1 -0
- package/dist/core/coverage-contract.js +164 -0
- package/dist/core/coverage-contract.js.map +1 -0
- package/dist/core/debug-posture.d.ts +40 -0
- package/dist/core/debug-posture.d.ts.map +1 -0
- package/dist/core/debug-posture.js +197 -0
- package/dist/core/debug-posture.js.map +1 -0
- package/dist/core/detector.d.ts.map +1 -1
- package/dist/core/detector.js +58 -6
- package/dist/core/detector.js.map +1 -1
- package/dist/core/identifiers.d.ts +32 -0
- package/dist/core/identifiers.d.ts.map +1 -0
- package/dist/core/identifiers.js +263 -0
- package/dist/core/identifiers.js.map +1 -0
- package/dist/core/llm-directives.d.ts +12 -0
- package/dist/core/llm-directives.d.ts.map +1 -0
- package/dist/core/llm-directives.js +23 -0
- package/dist/core/llm-directives.js.map +1 -0
- package/dist/core/prng.d.ts +10 -1
- package/dist/core/prng.d.ts.map +1 -1
- package/dist/core/prng.js +27 -2
- package/dist/core/prng.js.map +1 -1
- package/dist/core/release-plan.d.ts +68 -0
- package/dist/core/release-plan.d.ts.map +1 -0
- package/dist/core/release-plan.js +235 -0
- package/dist/core/release-plan.js.map +1 -0
- package/dist/core/sarif.d.ts +53 -0
- package/dist/core/sarif.d.ts.map +1 -0
- package/dist/core/sarif.js +91 -0
- package/dist/core/sarif.js.map +1 -0
- package/dist/core/sqlite-runtime.d.ts +13 -0
- package/dist/core/sqlite-runtime.d.ts.map +1 -1
- package/dist/core/sqlite-runtime.js +38 -8
- package/dist/core/sqlite-runtime.js.map +1 -1
- package/dist/core/types.d.ts +7 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/engine/auditor.d.ts.map +1 -1
- package/dist/engine/auditor.js +251 -8
- package/dist/engine/auditor.js.map +1 -1
- package/dist/engine/benchmark.d.ts +1 -1
- package/dist/engine/benchmark.d.ts.map +1 -1
- package/dist/engine/benchmark.js +121 -41
- package/dist/engine/benchmark.js.map +1 -1
- package/dist/engine/defender.d.ts +1 -0
- package/dist/engine/defender.d.ts.map +1 -1
- package/dist/engine/defender.js +7 -1
- package/dist/engine/defender.js.map +1 -1
- package/dist/engine/harden.d.ts +61 -0
- package/dist/engine/harden.d.ts.map +1 -0
- package/dist/engine/harden.js +292 -0
- package/dist/engine/harden.js.map +1 -0
- package/dist/engine/protector.d.ts.map +1 -1
- package/dist/engine/protector.js +162 -21
- package/dist/engine/protector.js.map +1 -1
- package/dist/identity.d.ts +112 -2
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +112 -2
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +26 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -9
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +59 -152
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +466 -50
- package/dist/mcp/server.js.map +1 -1
- package/dist/setup/clients.d.ts +49 -1
- package/dist/setup/clients.d.ts.map +1 -1
- package/dist/setup/clients.js +1193 -20
- package/dist/setup/clients.js.map +1 -1
- package/dist/setup/doctor.d.ts +58 -14
- package/dist/setup/doctor.d.ts.map +1 -1
- package/dist/setup/doctor.js +316 -22
- package/dist/setup/doctor.js.map +1 -1
- package/dist/setup/setup.d.ts +77 -7
- package/dist/setup/setup.d.ts.map +1 -1
- package/dist/setup/setup.js +591 -62
- package/dist/setup/setup.js.map +1 -1
- package/dist/shields/chaff/chaff-generator.d.ts.map +1 -1
- package/dist/shields/chaff/chaff-generator.js +12 -3
- package/dist/shields/chaff/chaff-generator.js.map +1 -1
- package/dist/shields/deception/architecture-mirage.js +1 -1
- package/dist/shields/deception/architecture-mirage.js.map +1 -1
- package/dist/shields/deception/canary-honeypot.d.ts +33 -0
- package/dist/shields/deception/canary-honeypot.d.ts.map +1 -0
- package/dist/shields/deception/canary-honeypot.js +95 -0
- package/dist/shields/deception/canary-honeypot.js.map +1 -0
- package/dist/shields/deception/cognitive-armor-trigger.d.ts +43 -0
- package/dist/shields/deception/cognitive-armor-trigger.d.ts.map +1 -0
- package/dist/shields/deception/cognitive-armor-trigger.js +204 -0
- package/dist/shields/deception/cognitive-armor-trigger.js.map +1 -0
- package/dist/shields/deception/crash-trace-decoy.js +1 -1
- package/dist/shields/deception/crash-trace-decoy.js.map +1 -1
- package/dist/shields/deception/decompiler-illusion.js +1 -1
- package/dist/shields/deception/decompiler-illusion.js.map +1 -1
- package/dist/shields/deception/diff-noise-injector.js +1 -1
- package/dist/shields/deception/diff-noise-injector.js.map +1 -1
- package/dist/shields/deception/evidence-contract-poison.js +1 -1
- package/dist/shields/deception/evidence-contract-poison.js.map +1 -1
- package/dist/shields/deception/format-payloads.d.ts +21 -0
- package/dist/shields/deception/format-payloads.d.ts.map +1 -0
- package/dist/shields/deception/format-payloads.js +24 -0
- package/dist/shields/deception/format-payloads.js.map +1 -0
- package/dist/shields/deception/index.d.ts +10 -2
- package/dist/shields/deception/index.d.ts.map +1 -1
- package/dist/shields/deception/index.js +20 -3
- package/dist/shields/deception/index.js.map +1 -1
- package/dist/shields/deception/prompt-completion-poison.d.ts +3 -2
- package/dist/shields/deception/prompt-completion-poison.d.ts.map +1 -1
- package/dist/shields/deception/prompt-completion-poison.js +6 -3
- package/dist/shields/deception/prompt-completion-poison.js.map +1 -1
- package/dist/shields/deception/shadow-business-logic.js +4 -4
- package/dist/shields/deception/shadow-business-logic.js.map +1 -1
- package/dist/shields/deception/system-diagnostic-decoy.d.ts +36 -0
- package/dist/shields/deception/system-diagnostic-decoy.d.ts.map +1 -0
- package/dist/shields/deception/system-diagnostic-decoy.js +101 -0
- package/dist/shields/deception/system-diagnostic-decoy.js.map +1 -0
- package/dist/shields/exhaustion/asar-header-amplifier.d.ts +12 -3
- package/dist/shields/exhaustion/asar-header-amplifier.d.ts.map +1 -1
- package/dist/shields/exhaustion/asar-header-amplifier.js +30 -8
- package/dist/shields/exhaustion/asar-header-amplifier.js.map +1 -1
- package/dist/shields/exhaustion/bpe-token-amplifier.js +2 -2
- package/dist/shields/exhaustion/bpe-token-amplifier.js.map +1 -1
- package/dist/shields/exhaustion/callgraph-labyrinth.js +2 -2
- package/dist/shields/exhaustion/callgraph-labyrinth.js.map +1 -1
- package/dist/shields/exhaustion/cdp-shape-budget-breaker.js +1 -1
- package/dist/shields/exhaustion/cdp-shape-budget-breaker.js.map +1 -1
- package/dist/shields/exhaustion/frida-capture-saturation.d.ts +10 -5
- package/dist/shields/exhaustion/frida-capture-saturation.d.ts.map +1 -1
- package/dist/shields/exhaustion/frida-capture-saturation.js +21 -8
- package/dist/shields/exhaustion/frida-capture-saturation.js.map +1 -1
- package/dist/shields/exhaustion/index.d.ts +2 -2
- package/dist/shields/exhaustion/index.d.ts.map +1 -1
- package/dist/shields/exhaustion/index.js +2 -2
- package/dist/shields/exhaustion/index.js.map +1 -1
- package/dist/shields/exhaustion/obligation-flooder.d.ts +17 -5
- package/dist/shields/exhaustion/obligation-flooder.d.ts.map +1 -1
- package/dist/shields/exhaustion/obligation-flooder.js +20 -8
- package/dist/shields/exhaustion/obligation-flooder.js.map +1 -1
- package/dist/shields/exhaustion/rea-budget-matrix.d.ts +8 -2
- package/dist/shields/exhaustion/rea-budget-matrix.d.ts.map +1 -1
- package/dist/shields/exhaustion/rea-budget-matrix.js +139 -16
- package/dist/shields/exhaustion/rea-budget-matrix.js.map +1 -1
- package/dist/shields/exhaustion/regex-worker-tarpit.d.ts.map +1 -1
- package/dist/shields/exhaustion/regex-worker-tarpit.js +2 -1
- package/dist/shields/exhaustion/regex-worker-tarpit.js.map +1 -1
- package/dist/shields/exhaustion/wasm-interface-exhaustion.d.ts +7 -4
- package/dist/shields/exhaustion/wasm-interface-exhaustion.d.ts.map +1 -1
- package/dist/shields/exhaustion/wasm-interface-exhaustion.js +16 -7
- package/dist/shields/exhaustion/wasm-interface-exhaustion.js.map +1 -1
- package/dist/shields/formats/android-dex-xref.d.ts +19 -0
- package/dist/shields/formats/android-dex-xref.d.ts.map +1 -0
- package/dist/shields/formats/android-dex-xref.js +427 -0
- package/dist/shields/formats/android-dex-xref.js.map +1 -0
- package/dist/shields/formats/android-manifest.d.ts +44 -0
- package/dist/shields/formats/android-manifest.d.ts.map +1 -0
- package/dist/shields/formats/android-manifest.js +240 -0
- package/dist/shields/formats/android-manifest.js.map +1 -0
- package/dist/shields/formats/android-r8.d.ts +44 -0
- package/dist/shields/formats/android-r8.d.ts.map +1 -0
- package/dist/shields/formats/android-r8.js +246 -0
- package/dist/shields/formats/android-r8.js.map +1 -0
- package/dist/shields/formats/apple-plist.d.ts +15 -0
- package/dist/shields/formats/apple-plist.d.ts.map +1 -1
- package/dist/shields/formats/apple-plist.js +59 -1
- package/dist/shields/formats/apple-plist.js.map +1 -1
- package/dist/shields/formats/archive.d.ts +27 -6
- package/dist/shields/formats/archive.d.ts.map +1 -1
- package/dist/shields/formats/archive.js +247 -45
- package/dist/shields/formats/archive.js.map +1 -1
- package/dist/shields/formats/asar.d.ts +50 -10
- package/dist/shields/formats/asar.d.ts.map +1 -1
- package/dist/shields/formats/asar.js +265 -39
- package/dist/shields/formats/asar.js.map +1 -1
- package/dist/shields/formats/bun-standalone.d.ts +78 -0
- package/dist/shields/formats/bun-standalone.d.ts.map +1 -0
- package/dist/shields/formats/bun-standalone.js +272 -0
- package/dist/shields/formats/bun-standalone.js.map +1 -0
- package/dist/shields/formats/dotnet-managed.d.ts +9 -0
- package/dist/shields/formats/dotnet-managed.d.ts.map +1 -1
- package/dist/shields/formats/dotnet-managed.js +26 -1
- package/dist/shields/formats/dotnet-managed.js.map +1 -1
- package/dist/shields/formats/electron-fuses.d.ts +63 -8
- package/dist/shields/formats/electron-fuses.d.ts.map +1 -1
- package/dist/shields/formats/electron-fuses.js +297 -65
- package/dist/shields/formats/electron-fuses.js.map +1 -1
- package/dist/shields/formats/erlang-beam.d.ts +34 -0
- package/dist/shields/formats/erlang-beam.d.ts.map +1 -0
- package/dist/shields/formats/erlang-beam.js +319 -0
- package/dist/shields/formats/erlang-beam.js.map +1 -0
- package/dist/shields/formats/evm-bytecode.d.ts +28 -0
- package/dist/shields/formats/evm-bytecode.d.ts.map +1 -0
- package/dist/shields/formats/evm-bytecode.js +124 -0
- package/dist/shields/formats/evm-bytecode.js.map +1 -0
- package/dist/shields/formats/go-flutter-exhaustion.d.ts +55 -0
- package/dist/shields/formats/go-flutter-exhaustion.d.ts.map +1 -0
- package/dist/shields/formats/go-flutter-exhaustion.js +346 -0
- package/dist/shields/formats/go-flutter-exhaustion.js.map +1 -0
- package/dist/shields/formats/gpu-ptx.d.ts +40 -0
- package/dist/shields/formats/gpu-ptx.d.ts.map +1 -0
- package/dist/shields/formats/gpu-ptx.js +62 -0
- package/dist/shields/formats/gpu-ptx.js.map +1 -0
- package/dist/shields/formats/headers.d.ts.map +1 -1
- package/dist/shields/formats/headers.js +54 -14
- package/dist/shields/formats/headers.js.map +1 -1
- package/dist/shields/formats/jvm-bytecode.d.ts +20 -0
- package/dist/shields/formats/jvm-bytecode.d.ts.map +1 -0
- package/dist/shields/formats/jvm-bytecode.js +134 -0
- package/dist/shields/formats/jvm-bytecode.js.map +1 -0
- package/dist/shields/formats/mobile-game.d.ts +4 -0
- package/dist/shields/formats/mobile-game.d.ts.map +1 -1
- package/dist/shields/formats/mobile-game.js +16 -0
- package/dist/shields/formats/mobile-game.js.map +1 -1
- package/dist/shields/formats/model.d.ts +22 -8
- package/dist/shields/formats/model.d.ts.map +1 -1
- package/dist/shields/formats/model.js +231 -59
- package/dist/shields/formats/model.js.map +1 -1
- package/dist/shields/formats/native.d.ts +65 -11
- package/dist/shields/formats/native.d.ts.map +1 -1
- package/dist/shields/formats/native.js +413 -108
- package/dist/shields/formats/native.js.map +1 -1
- package/dist/shields/formats/pcap-capture.d.ts +27 -0
- package/dist/shields/formats/pcap-capture.d.ts.map +1 -0
- package/dist/shields/formats/pcap-capture.js +201 -0
- package/dist/shields/formats/pcap-capture.js.map +1 -0
- package/dist/shields/formats/python.d.ts +22 -1
- package/dist/shields/formats/python.d.ts.map +1 -1
- package/dist/shields/formats/python.js +568 -27
- package/dist/shields/formats/python.js.map +1 -1
- package/dist/shields/formats/sourcemap.d.ts.map +1 -1
- package/dist/shields/formats/sourcemap.js +2 -0
- package/dist/shields/formats/sourcemap.js.map +1 -1
- package/dist/shields/formats/sqlite.d.ts +87 -15
- package/dist/shields/formats/sqlite.d.ts.map +1 -1
- package/dist/shields/formats/sqlite.js +377 -42
- package/dist/shields/formats/sqlite.js.map +1 -1
- package/dist/shields/formats/wasm.d.ts +6 -0
- package/dist/shields/formats/wasm.d.ts.map +1 -1
- package/dist/shields/formats/wasm.js +118 -3
- package/dist/shields/formats/wasm.js.map +1 -1
- package/dist/shields/javascript/ast-shield.d.ts +25 -5
- package/dist/shields/javascript/ast-shield.d.ts.map +1 -1
- package/dist/shields/javascript/ast-shield.js +428 -58
- package/dist/shields/javascript/ast-shield.js.map +1 -1
- package/dist/shields/runtime/memory-diff-shield.d.ts +56 -0
- package/dist/shields/runtime/memory-diff-shield.d.ts.map +1 -0
- package/dist/shields/runtime/memory-diff-shield.js +170 -0
- package/dist/shields/runtime/memory-diff-shield.js.map +1 -0
- package/dist/shields/runtime/runtime-shield.d.ts +12 -16
- package/dist/shields/runtime/runtime-shield.d.ts.map +1 -1
- package/dist/shields/runtime/runtime-shield.js +30 -24
- package/dist/shields/runtime/runtime-shield.js.map +1 -1
- package/dist/shields/tarpit/opaque-predicates.d.ts.map +1 -1
- package/dist/shields/tarpit/opaque-predicates.js +3 -3
- package/dist/shields/tarpit/opaque-predicates.js.map +1 -1
- package/dist/shields/tarpit/tarpit-generator.d.ts +9 -4
- package/dist/shields/tarpit/tarpit-generator.d.ts.map +1 -1
- package/dist/shields/tarpit/tarpit-generator.js +30 -23
- package/dist/shields/tarpit/tarpit-generator.js.map +1 -1
- package/package.json +13 -6
|
@@ -1,8 +1,196 @@
|
|
|
1
|
+
import { detectBunStandaloneGraph, } from "./bun-standalone.js";
|
|
1
2
|
import { deflateSync } from "node:zlib";
|
|
2
3
|
import { REA_INTERNAL_LIMITS } from "../../identity.js";
|
|
3
4
|
import { SeededPrng } from "../../core/prng.js";
|
|
4
5
|
import { generateChaffPayloads } from "../chaff/chaff-generator.js";
|
|
5
|
-
import {
|
|
6
|
+
import { generateCanaryHoneypot } from "../deception/canary-honeypot.js";
|
|
7
|
+
import { generateSystemDiagnosticDecoy } from "../deception/system-diagnostic-decoy.js";
|
|
8
|
+
import { generateCognitiveArmorTrigger } from "../deception/cognitive-armor-trigger.js";
|
|
9
|
+
import { buildDecoyElectronFuseSentinels, hardenElectronFusesWithContext, inspectElectronFusesInBuffer, } from "./electron-fuses.js";
|
|
10
|
+
import { buildGoBuildInfoExhaustionPayload, buildFlutterPoolExhaustionPayload, buildMappedGoBuildInfoPlant, buildMappedFlutterIsolatePoolPlant, } from "./go-flutter-exhaustion.js";
|
|
11
|
+
export class InvalidNativeBinaryError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "InvalidNativeBinaryError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
18
|
+
/**
|
|
19
|
+
* Validates ELF64 little-endian header, program headers (`PT_LOAD`, `p_filesz <= p_memsz`,
|
|
20
|
+
* non-overlapping virtual address ranges, in-bounds file ranges), and section headers
|
|
21
|
+
* (in-bounds file ranges, valid `e_shstrndx`, non-overlapping file-backed sections).
|
|
22
|
+
*/
|
|
23
|
+
export function validateElf64Layout(bytes) {
|
|
24
|
+
if (bytes.length < 64 ||
|
|
25
|
+
bytes[0] !== 0x7f ||
|
|
26
|
+
bytes[1] !== 0x45 ||
|
|
27
|
+
bytes[2] !== 0x4c ||
|
|
28
|
+
bytes[3] !== 0x46) {
|
|
29
|
+
throw new InvalidNativeBinaryError("Invalid or truncated ELF header (minimum 64 bytes required)");
|
|
30
|
+
}
|
|
31
|
+
if (bytes[4] !== 2 || bytes[5] !== 1) {
|
|
32
|
+
throw new InvalidNativeBinaryError("Unsupported ELF class or endianness (expected ELF64 little-endian)");
|
|
33
|
+
}
|
|
34
|
+
const phoffBig = bytes.readBigUInt64LE(32);
|
|
35
|
+
const shoffBig = bytes.readBigUInt64LE(40);
|
|
36
|
+
const ehsize = bytes.readUInt16LE(52);
|
|
37
|
+
const phentsize = bytes.readUInt16LE(54);
|
|
38
|
+
const phnum = bytes.readUInt16LE(56);
|
|
39
|
+
const shentsize = bytes.readUInt16LE(58);
|
|
40
|
+
const shnum = bytes.readUInt16LE(60);
|
|
41
|
+
const shstrndx = bytes.readUInt16LE(62);
|
|
42
|
+
if (ehsize !== 0 && (ehsize < 64 || ehsize > bytes.length)) {
|
|
43
|
+
throw new InvalidNativeBinaryError(`Invalid ELF64 e_ehsize: ${ehsize}`);
|
|
44
|
+
}
|
|
45
|
+
if (phoffBig > MAX_SAFE_BIGINT || shoffBig > MAX_SAFE_BIGINT) {
|
|
46
|
+
throw new InvalidNativeBinaryError("ELF64 header table offsets exceed safe integer range");
|
|
47
|
+
}
|
|
48
|
+
const phoff = Number(phoffBig);
|
|
49
|
+
const shoff = Number(shoffBig);
|
|
50
|
+
const programHeaders = [];
|
|
51
|
+
const phTableEnd = phnum > 0 ? phoff + phnum * phentsize : 0;
|
|
52
|
+
if (phnum > 0) {
|
|
53
|
+
if (phentsize < 56 ||
|
|
54
|
+
phoff < 64 ||
|
|
55
|
+
!Number.isSafeInteger(phTableEnd) ||
|
|
56
|
+
phTableEnd > bytes.length) {
|
|
57
|
+
throw new InvalidNativeBinaryError("ELF64 program header table out of bounds or malformed");
|
|
58
|
+
}
|
|
59
|
+
for (let i = 0; i < phnum; i++) {
|
|
60
|
+
const phdr = phoff + i * phentsize;
|
|
61
|
+
const pType = bytes.readUInt32LE(phdr);
|
|
62
|
+
const pFlags = bytes.readUInt32LE(phdr + 4);
|
|
63
|
+
const pOffsetBig = bytes.readBigUInt64LE(phdr + 8);
|
|
64
|
+
const pVaddrBig = bytes.readBigUInt64LE(phdr + 16);
|
|
65
|
+
const pPaddrBig = bytes.readBigUInt64LE(phdr + 24);
|
|
66
|
+
const pFileszBig = bytes.readBigUInt64LE(phdr + 32);
|
|
67
|
+
const pMemszBig = bytes.readBigUInt64LE(phdr + 40);
|
|
68
|
+
const pAlignBig = bytes.readBigUInt64LE(phdr + 48);
|
|
69
|
+
if (pOffsetBig > MAX_SAFE_BIGINT || pFileszBig > MAX_SAFE_BIGINT) {
|
|
70
|
+
throw new InvalidNativeBinaryError(`ELF64 program header ${i} file offset/size exceeds safe integer range`);
|
|
71
|
+
}
|
|
72
|
+
const pOffset = Number(pOffsetBig);
|
|
73
|
+
const pFilesz = Number(pFileszBig);
|
|
74
|
+
if (!Number.isSafeInteger(pOffset + pFilesz) ||
|
|
75
|
+
pOffset + pFilesz > bytes.length) {
|
|
76
|
+
throw new InvalidNativeBinaryError(`ELF64 program header ${i} file range [${pOffset}, ${pOffset + pFilesz}) out of bounds (${bytes.length})`);
|
|
77
|
+
}
|
|
78
|
+
if (pType === 1) {
|
|
79
|
+
// PT_LOAD
|
|
80
|
+
if (pMemszBig < pFileszBig) {
|
|
81
|
+
throw new InvalidNativeBinaryError(`ELF64 PT_LOAD segment ${i} has p_memsz (${pMemszBig}) < p_filesz (${pFileszBig})`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
programHeaders.push({
|
|
85
|
+
index: i,
|
|
86
|
+
type: pType,
|
|
87
|
+
flags: pFlags,
|
|
88
|
+
offset: pOffset,
|
|
89
|
+
vaddr: pVaddrBig,
|
|
90
|
+
paddr: pPaddrBig,
|
|
91
|
+
filesz: pFilesz,
|
|
92
|
+
memsz: pMemszBig,
|
|
93
|
+
align: pAlignBig,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// Verify no two PT_LOAD segments have overlapping virtual address ranges
|
|
97
|
+
const loadSegments = programHeaders.filter((ph) => ph.type === 1 && ph.memsz > 0n);
|
|
98
|
+
for (let i = 0; i < loadSegments.length; i++) {
|
|
99
|
+
const a = loadSegments[i];
|
|
100
|
+
const aEnd = a.vaddr + a.memsz;
|
|
101
|
+
for (let j = i + 1; j < loadSegments.length; j++) {
|
|
102
|
+
const b = loadSegments[j];
|
|
103
|
+
const bEnd = b.vaddr + b.memsz;
|
|
104
|
+
if (a.vaddr < bEnd && b.vaddr < aEnd) {
|
|
105
|
+
throw new InvalidNativeBinaryError(`ELF64 PT_LOAD segments ${a.index} and ${b.index} have overlapping virtual address ranges`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const sectionHeaders = [];
|
|
111
|
+
const shTableEnd = shnum > 0 ? shoff + shnum * shentsize : 0;
|
|
112
|
+
if (shnum > 0) {
|
|
113
|
+
if (shentsize < 64 ||
|
|
114
|
+
shoff < 64 ||
|
|
115
|
+
!Number.isSafeInteger(shTableEnd) ||
|
|
116
|
+
shTableEnd > bytes.length) {
|
|
117
|
+
throw new InvalidNativeBinaryError("ELF64 section header table out of bounds or malformed");
|
|
118
|
+
}
|
|
119
|
+
if (phnum > 0 && phoff < shTableEnd && shoff < phTableEnd) {
|
|
120
|
+
throw new InvalidNativeBinaryError("ELF64 section header table overlaps program header table");
|
|
121
|
+
}
|
|
122
|
+
if (shstrndx !== 0 && shstrndx >= shnum) {
|
|
123
|
+
throw new InvalidNativeBinaryError(`ELF64 e_shstrndx (${shstrndx}) out of bounds for e_shnum (${shnum})`);
|
|
124
|
+
}
|
|
125
|
+
for (let s = 0; s < shnum; s++) {
|
|
126
|
+
const shdr = shoff + s * shentsize;
|
|
127
|
+
const shName = bytes.readUInt32LE(shdr);
|
|
128
|
+
const shType = bytes.readUInt32LE(shdr + 4);
|
|
129
|
+
const shFlags = bytes.readBigUInt64LE(shdr + 8);
|
|
130
|
+
const shAddr = bytes.readBigUInt64LE(shdr + 16);
|
|
131
|
+
const shOffsetBig = bytes.readBigUInt64LE(shdr + 24);
|
|
132
|
+
const shSizeBig = bytes.readBigUInt64LE(shdr + 32);
|
|
133
|
+
if (shOffsetBig > MAX_SAFE_BIGINT || shSizeBig > MAX_SAFE_BIGINT) {
|
|
134
|
+
throw new InvalidNativeBinaryError(`ELF64 section ${s} offset/size exceeds safe integer range`);
|
|
135
|
+
}
|
|
136
|
+
const shOffset = Number(shOffsetBig);
|
|
137
|
+
const shSize = Number(shSizeBig);
|
|
138
|
+
// File-backed sections: not SHT_NULL (0) and not SHT_NOBITS (8)
|
|
139
|
+
if (s >= 1 && shType !== 0 && shType !== 8) {
|
|
140
|
+
if (!Number.isSafeInteger(shOffset + shSize) ||
|
|
141
|
+
shOffset + shSize > bytes.length) {
|
|
142
|
+
throw new InvalidNativeBinaryError(`ELF64 section ${s} file range [${shOffset}, ${shOffset + shSize}) out of bounds (${bytes.length})`);
|
|
143
|
+
}
|
|
144
|
+
if (shSize > 0) {
|
|
145
|
+
if (shOffset < 64) {
|
|
146
|
+
throw new InvalidNativeBinaryError(`ELF64 section ${s} overlaps ELF64 header`);
|
|
147
|
+
}
|
|
148
|
+
if (phnum > 0 &&
|
|
149
|
+
shOffset < phTableEnd &&
|
|
150
|
+
phoff < shOffset + shSize) {
|
|
151
|
+
throw new InvalidNativeBinaryError(`ELF64 section ${s} overlaps program header table`);
|
|
152
|
+
}
|
|
153
|
+
if (shOffset < shTableEnd && shoff < shOffset + shSize) {
|
|
154
|
+
throw new InvalidNativeBinaryError(`ELF64 section ${s} overlaps section header table`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
sectionHeaders.push({
|
|
159
|
+
index: s,
|
|
160
|
+
nameOffset: shName,
|
|
161
|
+
type: shType,
|
|
162
|
+
flags: shFlags,
|
|
163
|
+
addr: shAddr,
|
|
164
|
+
offset: shOffset,
|
|
165
|
+
size: shSize,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// Verify no two non-empty file-backed sections overlap in file range
|
|
169
|
+
const fileBackedSections = sectionHeaders.filter((sec) => sec.index >= 1 && sec.type !== 0 && sec.type !== 8 && sec.size > 0);
|
|
170
|
+
for (let i = 0; i < fileBackedSections.length; i++) {
|
|
171
|
+
const a = fileBackedSections[i];
|
|
172
|
+
const aEnd = a.offset + a.size;
|
|
173
|
+
for (let j = i + 1; j < fileBackedSections.length; j++) {
|
|
174
|
+
const b = fileBackedSections[j];
|
|
175
|
+
const bEnd = b.offset + b.size;
|
|
176
|
+
if (a.offset < bEnd && b.offset < aEnd) {
|
|
177
|
+
throw new InvalidNativeBinaryError(`ELF64 sections ${a.index} and ${b.index} have overlapping file ranges`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
phoff,
|
|
184
|
+
phentsize,
|
|
185
|
+
phnum,
|
|
186
|
+
shoff,
|
|
187
|
+
shentsize,
|
|
188
|
+
shnum,
|
|
189
|
+
shstrndx,
|
|
190
|
+
programHeaders,
|
|
191
|
+
sectionHeaders,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
6
194
|
export function inspectNativeBinary(bytes) {
|
|
7
195
|
let format = "unknown";
|
|
8
196
|
let bits = 64;
|
|
@@ -65,12 +253,29 @@ export function inspectNativeBinary(bytes) {
|
|
|
65
253
|
const hasRustDepV0 = textLatin1.includes(".dep-v0");
|
|
66
254
|
const hasGoBuildInfo = textLatin1.includes(".go.buildinfo") ||
|
|
67
255
|
textLatin1.includes("__go_buildinfo") ||
|
|
68
|
-
textLatin1.includes("\xff Go buildinf:")
|
|
256
|
+
textLatin1.includes("\xff Go buildinf:") ||
|
|
257
|
+
textLatin1.includes("[BLA-GO-BUILDINFO]");
|
|
258
|
+
const goBuildInfoFramed = textLatin1.includes("[BLA-GO-BUILDINFO]") ||
|
|
259
|
+
textLatin1.includes(".gopclntab") ||
|
|
260
|
+
textLatin1.includes("runtime.moduledata");
|
|
261
|
+
let dartPoolPackageUriCount = 0;
|
|
262
|
+
let dartPoolTokenCount = 0;
|
|
263
|
+
for (const run of textLatin1.split("\0")) {
|
|
264
|
+
if (run.startsWith("package:") || run.startsWith("dart:")) {
|
|
265
|
+
dartPoolPackageUriCount++;
|
|
266
|
+
}
|
|
267
|
+
else if (run.length >= 5 &&
|
|
268
|
+
run.length <= 128 &&
|
|
269
|
+
/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(run)) {
|
|
270
|
+
dartPoolTokenCount++;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
69
273
|
const printableMatches = textLatin1.match(/[A-Za-z0-9_/:.-]{6,}/g) ?? [];
|
|
70
274
|
const blaProtected = textLatin1.includes("BLA-NATIVE-SHIELD") ||
|
|
71
275
|
rustcMatches.size > REA_INTERNAL_LIMITS.RUST_MAX_COMMIT_HASHES ||
|
|
72
276
|
fuseInspection.exceedsReaSentinelLimit ||
|
|
73
|
-
dartSnapshotHashesCount >
|
|
277
|
+
dartSnapshotHashesCount >
|
|
278
|
+
REA_INTERNAL_LIMITS.DART_MAX_SNAPSHOT_HASH_CANDIDATES ||
|
|
74
279
|
textLatin1.includes("Architecture Notice: Core business logic");
|
|
75
280
|
return {
|
|
76
281
|
format,
|
|
@@ -79,8 +284,11 @@ export function inspectNativeBinary(bytes) {
|
|
|
79
284
|
rustcCommitHashesCount: rustcMatches.size,
|
|
80
285
|
electronFuseSentinelsCount: fuseInspection.sentinelCount,
|
|
81
286
|
dartSnapshotHashesCount,
|
|
287
|
+
dartPoolPackageUriCount,
|
|
288
|
+
dartPoolTokenCount,
|
|
82
289
|
hasRustDepV0,
|
|
83
290
|
hasGoBuildInfo,
|
|
291
|
+
goBuildInfoFramed,
|
|
84
292
|
extractedStringsCount: printableMatches.length,
|
|
85
293
|
blaProtected,
|
|
86
294
|
};
|
|
@@ -122,60 +330,164 @@ export function buildDecoyRustAuditablePayload(prng) {
|
|
|
122
330
|
];
|
|
123
331
|
return deflateSync(Buffer.from(JSON.stringify({ format: 1, packages }), "utf8"));
|
|
124
332
|
}
|
|
333
|
+
/** Resolve ELF64 section names from the section-header string table. */
|
|
334
|
+
export function resolveElf64SectionNames(bytes, layout) {
|
|
335
|
+
const map = new Map();
|
|
336
|
+
if (layout.shnum === 0 ||
|
|
337
|
+
layout.shstrndx === 0 ||
|
|
338
|
+
layout.shstrndx >= layout.shnum) {
|
|
339
|
+
return map;
|
|
340
|
+
}
|
|
341
|
+
const strSec = layout.sectionHeaders[layout.shstrndx];
|
|
342
|
+
if (!strSec || strSec.size === 0 || strSec.offset + strSec.size > bytes.length) {
|
|
343
|
+
return map;
|
|
344
|
+
}
|
|
345
|
+
const strtab = bytes.subarray(strSec.offset, strSec.offset + strSec.size);
|
|
346
|
+
for (const sh of layout.sectionHeaders) {
|
|
347
|
+
if (sh.index === 0)
|
|
348
|
+
continue;
|
|
349
|
+
if (sh.nameOffset >= strtab.length)
|
|
350
|
+
continue;
|
|
351
|
+
let end = sh.nameOffset;
|
|
352
|
+
while (end < strtab.length && strtab[end] !== 0)
|
|
353
|
+
end++;
|
|
354
|
+
const name = strtab.subarray(sh.nameOffset, end).toString("utf8");
|
|
355
|
+
if (name.length > 0)
|
|
356
|
+
map.set(name, sh);
|
|
357
|
+
}
|
|
358
|
+
return map;
|
|
359
|
+
}
|
|
125
360
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
361
|
+
* Plant framed Go buildinfo into `.go.buildinfo` (preferred) or the first
|
|
362
|
+
* writable non-executable PT_LOAD file range so REA's mapped parser trips.
|
|
363
|
+
* Never mutates program/section header fields — only file-backed bytes.
|
|
129
364
|
*/
|
|
130
|
-
function
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
rec[3] = 0xdc;
|
|
139
|
-
rec.writeBigUInt64LE(64n, 4); // headerLength
|
|
140
|
-
rec.writeBigUInt64LE(3n, 12); // kind = 3 (FullAOT)
|
|
141
|
-
const hash32 = i.toString(16).padStart(8, "0") + prng.hex(24);
|
|
142
|
-
rec.write(hash32, 20, "ascii");
|
|
143
|
-
records.push(rec);
|
|
365
|
+
function injectMappedGoBuildInfo(working, layout, intensity) {
|
|
366
|
+
// Only mutate a named `.go.buildinfo` PROGBITS section. Generic PT_LOAD
|
|
367
|
+
// fallback would rewrite arbitrary ELF fixtures and violate the
|
|
368
|
+
// trailer-only / section-integrity red line for non-Go binaries.
|
|
369
|
+
const names = resolveElf64SectionNames(working, layout);
|
|
370
|
+
const named = names.get(".go.buildinfo");
|
|
371
|
+
if (!named || named.type !== 1 || named.size < 48) {
|
|
372
|
+
return { planted: false, tripsMax: false, offset: -1, size: 0 };
|
|
144
373
|
}
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
374
|
+
const alignPad = Number((16n - (named.addr % 16n)) % 16n);
|
|
375
|
+
const writeAt = named.offset + alignPad;
|
|
376
|
+
const room = named.size - alignPad;
|
|
377
|
+
if (room < 48) {
|
|
378
|
+
return { planted: false, tripsMax: false, offset: -1, size: 0 };
|
|
379
|
+
}
|
|
380
|
+
const plant = buildMappedGoBuildInfoPlant(intensity, room);
|
|
381
|
+
if (plant.buffer.length === 0) {
|
|
382
|
+
return { planted: false, tripsMax: false, offset: -1, size: 0 };
|
|
383
|
+
}
|
|
384
|
+
// Clear the section then plant so prior padding cannot confuse parsers.
|
|
385
|
+
working.fill(0, named.offset, named.offset + named.size);
|
|
386
|
+
plant.buffer.copy(working, writeAt);
|
|
387
|
+
return {
|
|
388
|
+
planted: true,
|
|
389
|
+
tripsMax: plant.tripsMaxBuildInfoBytes,
|
|
390
|
+
offset: writeAt,
|
|
391
|
+
size: plant.buffer.length,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Plant Flutter pool strings inside `.isolate` / isolate snapshot data regions
|
|
396
|
+
* (or after an embedded Dart snapshot magic) so REA's string-pool projection
|
|
397
|
+
* from isolate data observes the decoys.
|
|
398
|
+
*/
|
|
399
|
+
function injectMappedFlutterIsolatePool(working, layout, prng) {
|
|
400
|
+
// Only plant into an explicitly named `.isolate` section so generic
|
|
401
|
+
// `.rodata` / ELF fixtures stay byte-identical under trailer-only protect.
|
|
402
|
+
const names = resolveElf64SectionNames(working, layout);
|
|
403
|
+
const named = names.get(".isolate");
|
|
404
|
+
if (!named || named.type !== 1 || named.size < 64) {
|
|
405
|
+
return { planted: false, uris: 0, tokens: 0, offset: -1 };
|
|
406
|
+
}
|
|
407
|
+
let plantAt = named.offset;
|
|
408
|
+
let includeHeader = true;
|
|
409
|
+
if (named.size >= 52 &&
|
|
410
|
+
working[named.offset] === 0xf5 &&
|
|
411
|
+
working[named.offset + 1] === 0xf5 &&
|
|
412
|
+
working[named.offset + 2] === 0xdc &&
|
|
413
|
+
working[named.offset + 3] === 0xdc) {
|
|
414
|
+
plantAt = named.offset + 52;
|
|
415
|
+
includeHeader = false;
|
|
416
|
+
}
|
|
417
|
+
const capacity = named.offset + named.size - plantAt;
|
|
418
|
+
if (capacity < 64) {
|
|
419
|
+
return { planted: false, uris: 0, tokens: 0, offset: -1 };
|
|
420
|
+
}
|
|
421
|
+
const plant = buildMappedFlutterIsolatePoolPlant(capacity, prng, {
|
|
422
|
+
includeSnapshotHeader: includeHeader,
|
|
423
|
+
});
|
|
424
|
+
if (plant.buffer.length === 0) {
|
|
425
|
+
return { planted: false, uris: 0, tokens: 0, offset: -1 };
|
|
426
|
+
}
|
|
427
|
+
plant.buffer.copy(working, plantAt);
|
|
428
|
+
return {
|
|
429
|
+
planted: true,
|
|
430
|
+
uris: plant.packageAndDartUris,
|
|
431
|
+
tokens: plant.classLikeTokens,
|
|
432
|
+
offset: plantAt,
|
|
433
|
+
};
|
|
158
434
|
}
|
|
159
435
|
/**
|
|
160
|
-
* Protects a Native Binary (ELF / Mach-O / PE) against
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* 3. **Go (`GoBuildInfoSearch.ts` / `GoModuleText.ts`)**: Embeds decoy Go module table entries (`mod\t`, `dep\t`).
|
|
165
|
-
* 4. **Electron Fuses (`ElectronFuseReader.ts`)**: Hardens any real Electron Fuse V1 wire in-place AND injects
|
|
166
|
-
* 34 decoy `dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX` sentinels (`> maximumSentinelsPerSlice = 32`)!
|
|
167
|
-
* 5. **Flutter / Dart AOT (`FlutterPayloadScan.ts`)**: Injects 66 Dart snapshot magic records (`> 64` cap) and
|
|
168
|
-
* 6 LLVM toolchain lines (`> 4` cap).
|
|
169
|
-
* 6. **ELF64 `.rodata` Extension**: Extends the read-only `.rodata` section and `PT_LOAD` segment so
|
|
170
|
-
* REA's `mergedReadOnlyFileRanges` and slice scanners read the entire defensive trailer.
|
|
436
|
+
* Protects a Native Binary (ELF / Mach-O / PE) against REA's native & desktop analyzers
|
|
437
|
+
* while strictly preserving ELF64 `PT_LOAD` (`p_offset`, `p_filesz`, `p_memsz` / BSS) and
|
|
438
|
+
* section header boundaries. Real Electron fuses are only mutated when an explicit
|
|
439
|
+
* verified `electronHardeningContext` is provided.
|
|
171
440
|
*/
|
|
172
441
|
export function protectNativeBinary(bytes, options = {}) {
|
|
442
|
+
const bunCarrier = detectBunStandaloneGraph(bytes);
|
|
443
|
+
if (bunCarrier.kind === "appended-trailer" ||
|
|
444
|
+
bunCarrier.kind === "appended-trailer-sized") {
|
|
445
|
+
return {
|
|
446
|
+
buffer: Buffer.from(bytes),
|
|
447
|
+
rustcHashesInjected: 0,
|
|
448
|
+
electronFuseSentinelsInjected: 0,
|
|
449
|
+
dartSnapshotHashesInjected: 0,
|
|
450
|
+
dartPoolUrisInjected: 0,
|
|
451
|
+
dartPoolTokensInjected: 0,
|
|
452
|
+
goBuildInfoExceedsLimit: false,
|
|
453
|
+
mappedGoBuildInfoPlanted: false,
|
|
454
|
+
mappedFlutterPoolPlanted: false,
|
|
455
|
+
chaffPayloadsEmbedded: 0,
|
|
456
|
+
binarySectionsPatched: 0,
|
|
457
|
+
bunStandaloneCarrier: bunCarrier.kind,
|
|
458
|
+
bunStandaloneGraphPreserved: true,
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
const isElfMagic = bytes.length >= 4 &&
|
|
462
|
+
bytes[0] === 0x7f &&
|
|
463
|
+
bytes[1] === 0x45 &&
|
|
464
|
+
bytes[2] === 0x4c &&
|
|
465
|
+
bytes[3] === 0x46;
|
|
466
|
+
const elfBefore = isElfMagic ? validateElf64Layout(bytes) : undefined;
|
|
173
467
|
const intensity = options.intensity ?? "balanced";
|
|
174
468
|
const prng = new SeededPrng(options.seed ?? "bla-native-shield-v1");
|
|
175
469
|
const chaffPayloads = generateChaffPayloads(prng, intensity);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
470
|
+
let workingInput = Buffer.from(bytes);
|
|
471
|
+
let electronHardeningReport;
|
|
472
|
+
let patchedInPlaceCount = 0;
|
|
473
|
+
if (options.electronHardeningContext) {
|
|
474
|
+
electronHardeningReport = hardenElectronFusesWithContext(workingInput, options.electronHardeningContext);
|
|
475
|
+
workingInput = Buffer.from(electronHardeningReport.buffer);
|
|
476
|
+
patchedInPlaceCount =
|
|
477
|
+
electronHardeningReport.mutatedFuses.length > 0 ? 1 : 0;
|
|
478
|
+
}
|
|
479
|
+
const decoySentinelsInjected = 34;
|
|
480
|
+
const decoySentinelsBuffer = buildDecoyElectronFuseSentinels(prng, decoySentinelsInjected);
|
|
481
|
+
let mappedGoBuildInfoPlanted = false;
|
|
482
|
+
let mappedFlutterPoolPlanted = false;
|
|
483
|
+
let mappedGoTripsMax = false;
|
|
484
|
+
if (elfBefore) {
|
|
485
|
+
const goPlant = injectMappedGoBuildInfo(workingInput, elfBefore, intensity);
|
|
486
|
+
mappedGoBuildInfoPlanted = goPlant.planted;
|
|
487
|
+
mappedGoTripsMax = goPlant.tripsMax;
|
|
488
|
+
const flutterPlant = injectMappedFlutterIsolatePool(workingInput, elfBefore, prng);
|
|
489
|
+
mappedFlutterPoolPlanted = flutterPlant.planted;
|
|
490
|
+
}
|
|
179
491
|
// 1. Generate 68 distinct `/rustc/<40-hex>/` strings (> REA's MAX_RUSTC_HASHES = 64!)
|
|
180
492
|
const rustcCount = 68;
|
|
181
493
|
const rustcLines = [];
|
|
@@ -183,86 +495,79 @@ export function protectNativeBinary(bytes, options = {}) {
|
|
|
183
495
|
const hash = i.toString(16).padStart(8, "0") + prng.hex(32);
|
|
184
496
|
rustcLines.push(`/rustc/${hash}/library/core/src/enclave_guard.rs\0`);
|
|
185
497
|
}
|
|
186
|
-
// 2.
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
498
|
+
// 2. Framed Go buildinfo + pclntab/moduledata bait
|
|
499
|
+
const goBuildInfo = buildGoBuildInfoExhaustionPayload(prng, intensity);
|
|
500
|
+
// 3. Generate architectural chaff strings + Canary Honeypot + System-Diagnostic Rabbit Holes for Ghidra/Hopper/IDA
|
|
501
|
+
const chaffBlock = chaffPayloads
|
|
502
|
+
.map((p) => `${p.symbolName}: ${p.rawText}\0`)
|
|
503
|
+
.join("");
|
|
504
|
+
const canaryHoneypot = generateCanaryHoneypot(prng, intensity);
|
|
505
|
+
const systemDiagnostics = generateSystemDiagnosticDecoy(prng, intensity);
|
|
506
|
+
const cognitiveArmor = generateCognitiveArmorTrigger(prng, intensity);
|
|
507
|
+
const canaryAndDiagnosticBlock = [
|
|
508
|
+
...canaryHoneypot.syntheticCanaryTokens.map((tok) => `PROTECTED_CANARY_CREDENTIAL=${tok}\0`),
|
|
509
|
+
...canaryHoneypot.ambiguousCredentialUrls.map((url) => `TRANSPORT_ENDPOINT=${url}\0`),
|
|
510
|
+
...systemDiagnostics.diagnosticsInjected.map((d) => `[${d.subsystem}] ${d.errorClass} (${d.systemCode}): ${d.diagnosticMessage} Remediation: ${d.remediationRabbitHole}\0`),
|
|
511
|
+
...cognitiveArmor.triggersInjected.map((t) => `[COGNITIVE_ARMOR_INTERLOCK:${t.classifierDomain}] ${t.coupledAnchorSymbol} => ${t.triggerPayload.replace(/\r?\n/g, " ")}\0`),
|
|
194
512
|
].join("");
|
|
195
|
-
// 3. Generate architectural chaff strings for Ghidra / Hopper / IDA string tables
|
|
196
|
-
const chaffBlock = chaffPayloads.map((p) => `${p.symbolName}: ${p.rawText}\0`).join("");
|
|
197
513
|
const depV0Payload = buildDecoyRustAuditablePayload(prng);
|
|
198
|
-
const
|
|
514
|
+
const flutterPool = buildFlutterPoolExhaustionPayload(prng);
|
|
515
|
+
const dartOverflowPayload = flutterPool.buffer;
|
|
199
516
|
const shieldTrailer = Buffer.concat([
|
|
200
517
|
Buffer.from("\0[BLA-NATIVE-SHIELD-V1]\0.dep-v0\0", "utf8"),
|
|
201
518
|
Buffer.from(rustcLines.join(""), "latin1"),
|
|
202
|
-
|
|
203
|
-
|
|
519
|
+
goBuildInfo.buffer,
|
|
520
|
+
decoySentinelsBuffer,
|
|
204
521
|
dartOverflowPayload,
|
|
205
522
|
Buffer.from(chaffBlock, "utf8"),
|
|
523
|
+
Buffer.from(canaryAndDiagnosticBlock, "utf8"),
|
|
206
524
|
depV0Payload,
|
|
207
525
|
]);
|
|
208
526
|
const outBytes = Buffer.concat([workingInput, shieldTrailer]);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const phnum = outBytes.readUInt16LE(56);
|
|
225
|
-
for (let p = 0; p < phnum; p++) {
|
|
226
|
-
const phdr = phoff + p * phentsize;
|
|
227
|
-
if (phdr + 56 <= outBytes.length) {
|
|
228
|
-
const pType = outBytes.readUInt32LE(phdr);
|
|
229
|
-
const pOffset = Number(outBytes.readBigUInt64LE(phdr + 8));
|
|
230
|
-
const pFilesz = Number(outBytes.readBigUInt64LE(phdr + 32));
|
|
231
|
-
if (pType === 1 && pOffset + pFilesz === workingInput.length) {
|
|
232
|
-
outBytes.writeBigUInt64LE(BigInt(outBytes.length - pOffset), phdr + 32);
|
|
233
|
-
outBytes.writeBigUInt64LE(BigInt(outBytes.length - pOffset), phdr + 40);
|
|
234
|
-
binarySectionsPatched++;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
for (let s = 1; s < shnum; s++) {
|
|
239
|
-
const shdr = shoff + s * shentsize;
|
|
240
|
-
if (shdr + 64 <= outBytes.length) {
|
|
241
|
-
const shType = outBytes.readUInt32LE(shdr + 4);
|
|
242
|
-
const shFlags = Number(outBytes.readBigUInt64LE(shdr + 8));
|
|
243
|
-
const shOffset = Number(outBytes.readBigUInt64LE(shdr + 24));
|
|
244
|
-
const shSize = Number(outBytes.readBigUInt64LE(shdr + 32));
|
|
245
|
-
const isReadOnlyProgbits = shType === 1 && (shFlags & 1) === 0 && (shFlags & 4) === 0;
|
|
246
|
-
if (isReadOnlyProgbits && shOffset + shSize <= workingInput.length) {
|
|
247
|
-
const newSize = outBytes.length - shOffset;
|
|
248
|
-
outBytes.writeBigUInt64LE(BigInt(newSize), shdr + 32);
|
|
249
|
-
binarySectionsPatched++;
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
527
|
+
const binarySectionsPatched = 1 + patchedInPlaceCount + (elfBefore ? 2 : 0);
|
|
528
|
+
if (elfBefore) {
|
|
529
|
+
const elfAfter = validateElf64Layout(outBytes);
|
|
530
|
+
for (let i = 0; i < elfBefore.programHeaders.length; i++) {
|
|
531
|
+
const beforePh = elfBefore.programHeaders[i];
|
|
532
|
+
const afterPh = elfAfter.programHeaders[i];
|
|
533
|
+
if (beforePh.type !== afterPh.type ||
|
|
534
|
+
beforePh.flags !== afterPh.flags ||
|
|
535
|
+
beforePh.offset !== afterPh.offset ||
|
|
536
|
+
beforePh.vaddr !== afterPh.vaddr ||
|
|
537
|
+
beforePh.paddr !== afterPh.paddr ||
|
|
538
|
+
beforePh.filesz !== afterPh.filesz ||
|
|
539
|
+
beforePh.memsz !== afterPh.memsz ||
|
|
540
|
+
beforePh.align !== afterPh.align) {
|
|
541
|
+
throw new InvalidNativeBinaryError(`ELF64 program header ${i} was mutated during protection`);
|
|
253
542
|
}
|
|
254
543
|
}
|
|
255
|
-
|
|
256
|
-
|
|
544
|
+
for (let s = 0; s < elfBefore.sectionHeaders.length; s++) {
|
|
545
|
+
const beforeSh = elfBefore.sectionHeaders[s];
|
|
546
|
+
const afterSh = elfAfter.sectionHeaders[s];
|
|
547
|
+
if (beforeSh.type !== afterSh.type ||
|
|
548
|
+
beforeSh.flags !== afterSh.flags ||
|
|
549
|
+
beforeSh.addr !== afterSh.addr ||
|
|
550
|
+
beforeSh.offset !== afterSh.offset ||
|
|
551
|
+
beforeSh.size !== afterSh.size) {
|
|
552
|
+
throw new InvalidNativeBinaryError(`ELF64 section header ${s} was mutated during protection`);
|
|
553
|
+
}
|
|
257
554
|
}
|
|
258
555
|
}
|
|
259
556
|
return {
|
|
260
557
|
buffer: outBytes,
|
|
261
558
|
rustcHashesInjected: rustcCount,
|
|
262
|
-
electronFuseSentinelsInjected:
|
|
263
|
-
dartSnapshotHashesInjected:
|
|
559
|
+
electronFuseSentinelsInjected: decoySentinelsInjected,
|
|
560
|
+
dartSnapshotHashesInjected: flutterPool.snapshotHashes,
|
|
561
|
+
dartPoolUrisInjected: flutterPool.packageAndDartUris,
|
|
562
|
+
dartPoolTokensInjected: flutterPool.classLikeTokens,
|
|
563
|
+
goBuildInfoExceedsLimit: goBuildInfo.exceedsMaxBuildInfoBytes || mappedGoTripsMax,
|
|
564
|
+
mappedGoBuildInfoPlanted,
|
|
565
|
+
mappedFlutterPoolPlanted,
|
|
264
566
|
chaffPayloadsEmbedded: chaffPayloads.length,
|
|
265
567
|
binarySectionsPatched,
|
|
568
|
+
...(electronHardeningReport ? { electronHardeningReport } : {}),
|
|
569
|
+
bunStandaloneCarrier: bunCarrier.kind,
|
|
570
|
+
bunStandaloneGraphPreserved: bunCarrier.kind !== "none",
|
|
266
571
|
};
|
|
267
572
|
}
|
|
268
573
|
export function detectNativeFormatName(format) {
|