Merge branch 'master' into master
This commit is contained in:
commit
9ea2740454
885
package-lock.json
generated
885
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -93,6 +93,7 @@
|
||||
"worker-loader": "^3.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alexaltea/capstone-js": "^3.0.5",
|
||||
"@astronautlabs/amf": "^0.0.6",
|
||||
"@blu3r4y/lzma": "^2.3.3",
|
||||
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
"From Base",
|
||||
"To BCD",
|
||||
"From BCD",
|
||||
"Text-Integer Conversion",
|
||||
"To HTML Entity",
|
||||
"From HTML Entity",
|
||||
"URL Encode",
|
||||
@ -558,6 +559,7 @@
|
||||
"Chi Square",
|
||||
"P-list Viewer",
|
||||
"Disassemble x86",
|
||||
"Disassemble ARM",
|
||||
"Pseudo-Random Number Generator",
|
||||
"Pseudo-Random Integer Generator",
|
||||
"Generate De Bruijn Sequence",
|
||||
|
||||
193
src/core/operations/DisassembleARM.mjs
Normal file
193
src/core/operations/DisassembleARM.mjs
Normal file
@ -0,0 +1,193 @@
|
||||
/**
|
||||
* @author MedjedThomasXM
|
||||
* @copyright Crown Copyright 2024
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import cs from "@alexaltea/capstone-js/dist/capstone.min.js";
|
||||
|
||||
/**
|
||||
* Disassemble ARM operation
|
||||
*/
|
||||
class DisassembleARM extends Operation {
|
||||
|
||||
/**
|
||||
* DisassembleARM constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Disassemble ARM";
|
||||
this.module = "Shellcode";
|
||||
this.description = "Disassembles ARM machine code into assembly language.<br><br>Supports ARM (32-bit), Thumb, and ARM64 (AArch64) architectures using the Capstone disassembly framework.<br><br>Input should be in hexadecimal.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/ARM_architecture_family";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Architecture",
|
||||
"type": "option",
|
||||
"value": ["ARM (32-bit)", "ARM64 (AArch64)"]
|
||||
},
|
||||
{
|
||||
"name": "Mode",
|
||||
"type": "option",
|
||||
"value": ["ARM", "Thumb", "Thumb + Cortex-M", "ARMv8"]
|
||||
},
|
||||
{
|
||||
"name": "Endianness",
|
||||
"type": "option",
|
||||
"value": ["Little Endian", "Big Endian"]
|
||||
},
|
||||
{
|
||||
"name": "Starting address (hex)",
|
||||
"type": "number",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Show instruction hex",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "Show instruction position",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
async run(input, args) {
|
||||
const [
|
||||
architecture,
|
||||
mode,
|
||||
endianness,
|
||||
startAddress,
|
||||
showHex,
|
||||
showPosition
|
||||
] = args;
|
||||
|
||||
// Remove whitespace from input
|
||||
const hexInput = input.replace(/\s/g, "");
|
||||
|
||||
// Validate hex input
|
||||
if (!/^[0-9a-fA-F]*$/.test(hexInput)) {
|
||||
throw new OperationError("Invalid hexadecimal input. Please provide valid hex characters only.");
|
||||
}
|
||||
|
||||
if (hexInput.length === 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (hexInput.length % 2 !== 0) {
|
||||
throw new OperationError("Invalid hexadecimal input. Length must be even.");
|
||||
}
|
||||
|
||||
// Convert hex string to byte array
|
||||
const bytes = [];
|
||||
for (let i = 0; i < hexInput.length; i += 2) {
|
||||
bytes.push(parseInt(hexInput.substr(i, 2), 16));
|
||||
}
|
||||
|
||||
// Determine architecture constant
|
||||
let arch;
|
||||
if (architecture === "ARM64 (AArch64)") {
|
||||
arch = cs.ARCH_ARM64;
|
||||
} else {
|
||||
arch = cs.ARCH_ARM;
|
||||
}
|
||||
|
||||
// Determine mode constant
|
||||
let modeValue = cs.MODE_LITTLE_ENDIAN;
|
||||
|
||||
if (architecture === "ARM (32-bit)") {
|
||||
switch (mode) {
|
||||
case "ARM":
|
||||
modeValue = cs.MODE_ARM;
|
||||
break;
|
||||
case "Thumb":
|
||||
modeValue = cs.MODE_THUMB;
|
||||
break;
|
||||
case "Thumb + Cortex-M":
|
||||
modeValue = cs.MODE_THUMB | cs.MODE_MCLASS;
|
||||
break;
|
||||
case "ARMv8":
|
||||
modeValue = cs.MODE_ARM | cs.MODE_V8;
|
||||
break;
|
||||
default:
|
||||
modeValue = cs.MODE_ARM;
|
||||
}
|
||||
} else {
|
||||
// ARM64 only has one mode (ARM mode is default for ARM64)
|
||||
modeValue = cs.MODE_ARM;
|
||||
}
|
||||
|
||||
// Add endianness
|
||||
if (endianness === "Big Endian") {
|
||||
modeValue |= cs.MODE_BIG_ENDIAN;
|
||||
}
|
||||
|
||||
if (isWorkerEnvironment()) {
|
||||
self.sendStatusMessage("Disassembling...");
|
||||
}
|
||||
|
||||
let disassembler;
|
||||
try {
|
||||
disassembler = new cs.Capstone(arch, modeValue);
|
||||
} catch (e) {
|
||||
throw new OperationError(`Failed to initialise Capstone disassembler: ${e}`);
|
||||
}
|
||||
|
||||
let instructions;
|
||||
try {
|
||||
instructions = disassembler.disasm(bytes, startAddress);
|
||||
} catch (e) {
|
||||
disassembler.close();
|
||||
// Check if it's a "no valid instructions" error (code 0 means OK but nothing decoded)
|
||||
if (e && e.includes && e.includes("code 0:")) {
|
||||
throw new OperationError(`No valid ${architecture} instructions found in input. The bytes may be for a different architecture or mode.`);
|
||||
}
|
||||
throw new OperationError(`Disassembly failed: ${e}`);
|
||||
}
|
||||
|
||||
// Format output
|
||||
const output = [];
|
||||
for (const insn of instructions) {
|
||||
let line = "";
|
||||
|
||||
if (showPosition) {
|
||||
// Format address as hex with 0x prefix
|
||||
const addrHex = "0x" + insn.address.toString(16).padStart(8, "0");
|
||||
line += addrHex + " ";
|
||||
}
|
||||
|
||||
if (showHex) {
|
||||
// Format instruction bytes as hex
|
||||
const bytesHex = insn.bytes.map(b => b.toString(16).padStart(2, "0")).join("");
|
||||
line += bytesHex.padEnd(16, " ") + " ";
|
||||
}
|
||||
|
||||
line += insn.mnemonic;
|
||||
if (insn.op_str) {
|
||||
line += " " + insn.op_str;
|
||||
}
|
||||
|
||||
output.push(line);
|
||||
}
|
||||
|
||||
disassembler.close();
|
||||
|
||||
return output.join("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default DisassembleARM;
|
||||
123
src/core/operations/TextIntegerConverter.mjs
Normal file
123
src/core/operations/TextIntegerConverter.mjs
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @author p-leriche [philip.leriche@cantab.net]
|
||||
* @copyright Crown Copyright 2025
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/* ---------- helper functions ---------- */
|
||||
|
||||
/**
|
||||
* Convert text to BigInt (big-endian byte interpretation)
|
||||
*/
|
||||
function textToBigInt(text) {
|
||||
if (text.length === 0) return 0n;
|
||||
|
||||
let result = 0n;
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const charCode = BigInt(text.charCodeAt(i));
|
||||
if (charCode > 255n) {
|
||||
throw new OperationError(
|
||||
`Character at position ${i} exceeds Latin-1 range (0-255).\n` +
|
||||
"Only ASCII and Latin-1 characters are supported.");
|
||||
}
|
||||
result = (result << 8n) | charCode;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert BigInt to text (big-endian byte interpretation)
|
||||
*/
|
||||
function bigIntToText(value) {
|
||||
if (value === 0n) return "";
|
||||
|
||||
const bytes = [];
|
||||
let num = value;
|
||||
|
||||
while (num > 0n) {
|
||||
bytes.unshift(Number(num & 0xFFn));
|
||||
num >>= 8n;
|
||||
}
|
||||
|
||||
return String.fromCharCode(...bytes);
|
||||
}
|
||||
|
||||
/* ---------- operation class ---------- */
|
||||
|
||||
/**
|
||||
* Text/Integer Converter operation
|
||||
*/
|
||||
class TextIntegerConverter extends Operation {
|
||||
/**
|
||||
* TextIntegerConverter constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.description =
|
||||
"Converts between text strings and large integers (decimal or hexadecimal).<br><br>" +
|
||||
"Text is interpreted as a big-endian sequence of character codes. For example:<br>" +
|
||||
"ABC is 0x414243 (hex) is 4276803 (decimal)<br>" +
|
||||
"<b>Input format detection:</b><br>" +
|
||||
"Decimal: digits 0-9 only<br>" +
|
||||
"Hexadecimal: 0x... prefix<br>" +
|
||||
"Quoted or unquoted text: treated as string<br><br>" +
|
||||
"<b>Character limitations:</b><br>" +
|
||||
"Text input may only contain ASCII and Latin-1 characters (code point < 256).<br>" +
|
||||
"Multi-byte Unicode characters will generate an error.<br><br>." ;
|
||||
this.infoURL = "https://wikipedia.org/wiki/Endianness";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Output format",
|
||||
type: "option",
|
||||
value: ["String", "Decimal", "Hexadecimal"]
|
||||
}
|
||||
];
|
||||
this.name = "Text-Integer Conversion";
|
||||
this.module = "Default";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const outputFormat = args[0];
|
||||
const trimmed = input.trim();
|
||||
|
||||
let bigIntValue;
|
||||
|
||||
if (!trimmed) {
|
||||
// Null input - treat as zero
|
||||
bigIntValue = 0;
|
||||
} else if (/^0x[0-9a-f]+$/i.test(trimmed) ||
|
||||
/^[+-]?[0-9]+$/.test(trimmed)) {
|
||||
// Hex or decimal integer
|
||||
bigIntValue = BigInt(trimmed);
|
||||
} else if (/^["'].*["']$/.test(trimmed)) {
|
||||
// Quoted string: Remove quotes and convert text to BigInt
|
||||
const text = trimmed.slice(1, -1);
|
||||
bigIntValue = textToBigInt(text);
|
||||
} else {
|
||||
// Assume it's unquoted text
|
||||
bigIntValue = textToBigInt(trimmed);
|
||||
}
|
||||
|
||||
// Convert to output format
|
||||
if (outputFormat === "String") {
|
||||
return bigIntToText(bigIntValue);
|
||||
} else if (outputFormat === "Decimal") {
|
||||
return bigIntValue.toString();
|
||||
} else { // Hexadecimal
|
||||
return "0x" + bigIntValue.toString(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default TextIntegerConverter;
|
||||
@ -61,6 +61,7 @@ import "./tests/Crypt.mjs";
|
||||
import "./tests/CSV.mjs";
|
||||
import "./tests/DateTime.mjs";
|
||||
import "./tests/DefangIP.mjs";
|
||||
import "./tests/DisassembleARM.mjs";
|
||||
import "./tests/DropNthBytes.mjs";
|
||||
import "./tests/ECDSA.mjs";
|
||||
import "./tests/ELFInfo.mjs";
|
||||
@ -165,6 +166,7 @@ import "./tests/SymmetricDifference.mjs";
|
||||
import "./tests/TakeNthBytes.mjs";
|
||||
import "./tests/Template.mjs";
|
||||
import "./tests/TextEncodingBruteForce.mjs";
|
||||
import "./tests/TextIntegerConverter.mjs";
|
||||
import "./tests/ToFromInsensitiveRegex.mjs";
|
||||
import "./tests/TranslateDateTimeFormat.mjs";
|
||||
import "./tests/Typex.mjs";
|
||||
|
||||
377
tests/operations/tests/DisassembleARM.mjs
Normal file
377
tests/operations/tests/DisassembleARM.mjs
Normal file
@ -0,0 +1,377 @@
|
||||
/**
|
||||
* Disassemble ARM tests.
|
||||
*
|
||||
* @author MedjedThomasXM
|
||||
*
|
||||
* @copyright Crown Copyright 2024
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
// ==================== ARM32 TESTS ====================
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 NOP (mov r0, r0)",
|
||||
input: "00 00 a0 e1",
|
||||
expectedMatch: /mov\s+r0,\s*r0/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 bx lr",
|
||||
input: "1e ff 2f e1",
|
||||
expectedMatch: /bx\s+lr/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 push {fp, lr}",
|
||||
input: "00 48 2d e9",
|
||||
expectedMatch: /push\s+\{fp,\s*lr\}/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 add fp, sp, #4",
|
||||
input: "04 b0 8d e2",
|
||||
expectedMatch: /add\s+fp,\s*sp/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 ldr r0, [r1]",
|
||||
input: "00 00 91 e5",
|
||||
expectedMatch: /ldr\s+r0,\s*\[r1\]/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 str r0, [r1]",
|
||||
input: "00 00 81 e5",
|
||||
expectedMatch: /str\s+r0,\s*\[r1\]/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 bl (branch link)",
|
||||
input: "00 00 00 eb",
|
||||
expectedMatch: /bl\s+/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 mul r0, r1, r2",
|
||||
input: "91 02 00 e0",
|
||||
expectedMatch: /mul\s+r0,\s*r1,\s*r2/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ==================== ARM32 THUMB TESTS ====================
|
||||
{
|
||||
name: "Disassemble ARM: Thumb mov r0, r0",
|
||||
input: "00 46",
|
||||
expectedMatch: /mov\s+r0,\s*r0/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "Thumb", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: Thumb bx lr",
|
||||
input: "70 47",
|
||||
expectedMatch: /bx\s+lr/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "Thumb", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: Thumb push {r4, lr}",
|
||||
input: "10 b5",
|
||||
expectedMatch: /push\s+\{r4,\s*lr\}/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "Thumb", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: Thumb pop {r4, pc}",
|
||||
input: "10 bd",
|
||||
expectedMatch: /pop\s+\{r4,\s*pc\}/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "Thumb", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ==================== ARM64 TESTS ====================
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 ret",
|
||||
input: "c0 03 5f d6",
|
||||
expectedMatch: /ret/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 mov x0, #0",
|
||||
input: "00 00 80 d2",
|
||||
expectedMatch: /mov[z]?\s+x0,\s*#0/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 stp x29, x30, [sp, #-16]!",
|
||||
input: "fd 7b bf a9",
|
||||
expectedMatch: /stp\s+x29,\s*x30,\s*\[sp/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 ldp x29, x30, [sp], #16",
|
||||
input: "fd 7b c1 a8",
|
||||
expectedMatch: /ldp\s+x29,\s*x30,\s*\[sp\]/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 add x0, x1, x2",
|
||||
input: "20 00 02 8b",
|
||||
expectedMatch: /add\s+x0,\s*x1,\s*x2/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 sub x0, x1, x2",
|
||||
input: "20 00 02 cb",
|
||||
expectedMatch: /sub\s+x0,\s*x1,\s*x2/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 mul x0, x1, x2",
|
||||
input: "20 7c 02 9b",
|
||||
expectedMatch: /mul\s+x0,\s*x1,\s*x2/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 ldr x0, [x1]",
|
||||
input: "20 00 40 f9",
|
||||
expectedMatch: /ldr\s+x0,\s*\[x1\]/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 str x0, [x1]",
|
||||
input: "20 00 00 f9",
|
||||
expectedMatch: /str\s+x0,\s*\[x1\]/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 bl (branch link)",
|
||||
input: "00 00 00 94",
|
||||
expectedMatch: /bl\s+/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 cbz x0",
|
||||
input: "00 00 00 b4",
|
||||
expectedMatch: /cbz\s+x0/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 cbnz x0",
|
||||
input: "00 00 00 b5",
|
||||
expectedMatch: /cbnz\s+x0/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 sub sp, sp, #0x20",
|
||||
input: "ff 83 00 d1",
|
||||
expectedMatch: /sub\s+sp,\s*sp/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 add sp, sp, #0x20",
|
||||
input: "ff 83 00 91",
|
||||
expectedMatch: /add\s+sp,\s*sp/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ==================== MULTI-INSTRUCTION TESTS ====================
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 multiple instructions",
|
||||
input: "00 48 2d e9 04 b0 8d e2 00 00 a0 e1 00 88 bd e8",
|
||||
expectedMatch: /push.*\n.*add.*\n.*mov.*\n.*pop/s,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 function prologue/epilogue",
|
||||
input: "fd 7b bf a9 fd 03 00 91 00 00 80 52 fd 7b c1 a8 c0 03 5f d6",
|
||||
expectedMatch: /stp.*\n.*mov.*\n.*mov.*\n.*ldp.*\n.*ret/s,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ==================== ADDRESS TESTS ====================
|
||||
{
|
||||
name: "Disassemble ARM: ARM64 with start address 0x1000",
|
||||
input: "c0 03 5f d6",
|
||||
expectedMatch: /0x00001000/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 4096, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 with start address 0x8000",
|
||||
input: "00 00 a0 e1",
|
||||
expectedMatch: /0x00008000/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Little Endian", 32768, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ==================== ENDIANNESS TESTS ====================
|
||||
{
|
||||
name: "Disassemble ARM: ARM32 Big Endian",
|
||||
input: "e1 a0 00 00",
|
||||
expectedMatch: /mov\s+r0,\s*r0/,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM (32-bit)", "ARM", "Big Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ==================== EDGE CASES ====================
|
||||
{
|
||||
name: "Disassemble ARM: Empty input",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Disassemble ARM",
|
||||
args: ["ARM64 (AArch64)", "ARM", "Little Endian", 0, true, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
199
tests/operations/tests/TextIntegerConverter.mjs
Normal file
199
tests/operations/tests/TextIntegerConverter.mjs
Normal file
@ -0,0 +1,199 @@
|
||||
/**
|
||||
* Text-Integer Conversion tests.
|
||||
*
|
||||
* @author p-leriche [philip.leriche@cantab.net]
|
||||
*
|
||||
* @copyright Crown Copyright 2025
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Text-Integer Conversion quoted string to decimal",
|
||||
input: "\"ABC\"",
|
||||
expectedOutput: "4276803",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion quoted string to hexadecimal",
|
||||
input: "\"ABC\"",
|
||||
expectedOutput: "0x414243",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Hexadecimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion single quoted string to decimal",
|
||||
input: "'Hello'",
|
||||
expectedOutput: "310939249775",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion decimal to string",
|
||||
input: "4276803",
|
||||
expectedOutput: "ABC",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["String"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion hexadecimal to string",
|
||||
input: "0x48656C6C6F",
|
||||
expectedOutput: "Hello",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["String"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion round-trip string.decimal.string",
|
||||
input: "\"Test\"",
|
||||
expectedOutput: "Test",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Decimal"],
|
||||
},
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["String"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion round-trip string.hex.string",
|
||||
input: "\"CyberChef\"",
|
||||
expectedOutput: "CyberChef",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Hexadecimal"],
|
||||
},
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["String"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion implicit round trip string-string Latin-1",
|
||||
input: "U+00FF",
|
||||
expectedOutput: "U+00FF", // U+00FF (Latin small letter y with diaeresis)
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Unescape Unicode Characters",
|
||||
args: ["U+"],
|
||||
},
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["String"],
|
||||
},
|
||||
{
|
||||
op: "Escape Unicode Characters",
|
||||
args: ["U+", false, 4, true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion unquoted text to decimal",
|
||||
input: "Hi",
|
||||
expectedOutput: "18537",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion single character",
|
||||
input: "\"A\"",
|
||||
expectedOutput: "65",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion hex to decimal conversion",
|
||||
input: "0xFF",
|
||||
expectedOutput: "255",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion decimal to hex conversion",
|
||||
input: "255",
|
||||
expectedOutput: "0xff",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Hexadecimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion large number to string",
|
||||
input: "113091951015816448506195587157728348242683688608116",
|
||||
expectedOutput: "Mary had a little cat",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["String"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion whitespace handling (quoted)",
|
||||
input: "\" test \"",
|
||||
expectedOutput: "2314978187545944096",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text-Integer Conversion non-Latin1 character in input",
|
||||
input: "61 ce 93 61",
|
||||
expectedOutput:
|
||||
`Character at position 1 exceeds Latin-1 range (0-255).
|
||||
Only ASCII and Latin-1 characters are supported.`,
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["Auto"]
|
||||
},
|
||||
{
|
||||
op: "Text-Integer Conversion",
|
||||
args: ["Decimal"],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
Loading…
x
Reference in New Issue
Block a user