mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-21 23:36:16 -04:00
commit
caae0ec5ca
8 changed files with 248 additions and 3 deletions
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "6.4.6",
|
"version": "6.5.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "6.4.6",
|
"version": "6.5.0",
|
||||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||||
"author": "n1474335 <n1474335@gmail.com>",
|
"author": "n1474335 <n1474335@gmail.com>",
|
||||||
"homepage": "https://gchq.github.io/CyberChef",
|
"homepage": "https://gchq.github.io/CyberChef",
|
||||||
|
|
|
@ -288,6 +288,7 @@ const Categories = [
|
||||||
"XPath expression",
|
"XPath expression",
|
||||||
"JPath expression",
|
"JPath expression",
|
||||||
"CSS selector",
|
"CSS selector",
|
||||||
|
"PHP Deserialize",
|
||||||
"Microsoft Script Decoder",
|
"Microsoft Script Decoder",
|
||||||
"Strip HTML tags",
|
"Strip HTML tags",
|
||||||
"Diff",
|
"Diff",
|
||||||
|
|
|
@ -26,6 +26,7 @@ import JS from "../operations/JS.js";
|
||||||
import MAC from "../operations/MAC.js";
|
import MAC from "../operations/MAC.js";
|
||||||
import MorseCode from "../operations/MorseCode.js";
|
import MorseCode from "../operations/MorseCode.js";
|
||||||
import NetBIOS from "../operations/NetBIOS.js";
|
import NetBIOS from "../operations/NetBIOS.js";
|
||||||
|
import PHP from "../operations/PHP.js";
|
||||||
import PublicKey from "../operations/PublicKey.js";
|
import PublicKey from "../operations/PublicKey.js";
|
||||||
import Punycode from "../operations/Punycode.js";
|
import Punycode from "../operations/Punycode.js";
|
||||||
import Rotate from "../operations/Rotate.js";
|
import Rotate from "../operations/Rotate.js";
|
||||||
|
@ -3845,6 +3846,19 @@ const OperationConfig = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"PHP Deserialize": {
|
||||||
|
module: "Default",
|
||||||
|
description: "Deserializes PHP serialized data, outputting keyed arrays as JSON.<br><br>This function does not support <code>object</code> tags.<br><br>Example:<br><code>a:2:{s:1:"a";i:10;i:0;a:1:{s:2:"ab";b:1;}}</code><br>becomes<br><code>{"a": 10,0: {"ab": true}}</code><br><br><u>Output valid JSON:</u> JSON doesn't support integers as keys, whereas PHP serialization does. Enabling this will cast these integers to strings. This will also escape backslashes.",
|
||||||
|
inputType: "string",
|
||||||
|
outputType: "string",
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "Output valid JSON",
|
||||||
|
type: "boolean",
|
||||||
|
value: PHP.OUTPUT_VALID_JSON
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import NetBIOS from "../../operations/NetBIOS.js";
|
||||||
import Numberwang from "../../operations/Numberwang.js";
|
import Numberwang from "../../operations/Numberwang.js";
|
||||||
import OS from "../../operations/OS.js";
|
import OS from "../../operations/OS.js";
|
||||||
import OTP from "../../operations/OTP.js";
|
import OTP from "../../operations/OTP.js";
|
||||||
|
import PHP from "../../operations/PHP.js";
|
||||||
import QuotedPrintable from "../../operations/QuotedPrintable.js";
|
import QuotedPrintable from "../../operations/QuotedPrintable.js";
|
||||||
import Rotate from "../../operations/Rotate.js";
|
import Rotate from "../../operations/Rotate.js";
|
||||||
import SeqUtils from "../../operations/SeqUtils.js";
|
import SeqUtils from "../../operations/SeqUtils.js";
|
||||||
|
@ -28,7 +29,6 @@ import Tidy from "../../operations/Tidy.js";
|
||||||
import Unicode from "../../operations/Unicode.js";
|
import Unicode from "../../operations/Unicode.js";
|
||||||
import UUID from "../../operations/UUID.js";
|
import UUID from "../../operations/UUID.js";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default module.
|
* Default module.
|
||||||
*
|
*
|
||||||
|
@ -155,6 +155,7 @@ OpModules.Default = {
|
||||||
"Conditional Jump": FlowControl.runCondJump,
|
"Conditional Jump": FlowControl.runCondJump,
|
||||||
"Return": FlowControl.runReturn,
|
"Return": FlowControl.runReturn,
|
||||||
"Comment": FlowControl.runComment,
|
"Comment": FlowControl.runComment,
|
||||||
|
"PHP Deserialize": PHP.runDeserialize,
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
160
src/core/operations/PHP.js
Normal file
160
src/core/operations/PHP.js
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/**
|
||||||
|
* PHP operations.
|
||||||
|
*
|
||||||
|
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
|
||||||
|
* @copyright Jarmo van Lenthe
|
||||||
|
* @license Apache-2.0
|
||||||
|
*
|
||||||
|
* @namespace
|
||||||
|
*/
|
||||||
|
const PHP = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constant
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
OUTPUT_VALID_JSON: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHP Deserialize operation.
|
||||||
|
*
|
||||||
|
* This Javascript implementation is based on the Python implementation by
|
||||||
|
* Armin Ronacher (2016), who released it under the 3-Clause BSD license.
|
||||||
|
* See: https://github.com/mitsuhiko/phpserialize/
|
||||||
|
*
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
runDeserialize: function (input, args) {
|
||||||
|
/**
|
||||||
|
* Recursive method for deserializing.
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
function handleInput() {
|
||||||
|
/**
|
||||||
|
* Read `length` characters from the input, shifting them out the input.
|
||||||
|
* @param length
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function read(length) {
|
||||||
|
let result = "";
|
||||||
|
for (let idx = 0; idx < length; idx++) {
|
||||||
|
let char = inputPart.shift();
|
||||||
|
if (char === undefined) {
|
||||||
|
throw "End of input reached before end of script";
|
||||||
|
}
|
||||||
|
result += char;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read characters from the input until `until` is found.
|
||||||
|
* @param until
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function readUntil(until) {
|
||||||
|
let result = "";
|
||||||
|
for (;;) {
|
||||||
|
let char = read(1);
|
||||||
|
if (char === until) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
result += char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read characters from the input that must be equal to `expect`
|
||||||
|
* @param expect
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function expect(expect) {
|
||||||
|
let result = read(expect.length);
|
||||||
|
if (result !== expect) {
|
||||||
|
throw "Unexpected input found";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to handle deserialized arrays.
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
|
function handleArray() {
|
||||||
|
let items = parseInt(readUntil(":"), 10) * 2;
|
||||||
|
expect("{");
|
||||||
|
let result = [];
|
||||||
|
let isKey = true;
|
||||||
|
let lastItem = null;
|
||||||
|
for (let idx = 0; idx < items; idx++) {
|
||||||
|
let item = handleInput();
|
||||||
|
if (isKey) {
|
||||||
|
lastItem = item;
|
||||||
|
isKey = false;
|
||||||
|
} else {
|
||||||
|
let numberCheck = lastItem.match(/[0-9]+/);
|
||||||
|
if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
|
||||||
|
result.push("\"" + lastItem + "\": " + item);
|
||||||
|
} else {
|
||||||
|
result.push(lastItem + ": " + item);
|
||||||
|
}
|
||||||
|
isKey = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect("}");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let kind = read(1).toLowerCase();
|
||||||
|
|
||||||
|
switch (kind) {
|
||||||
|
case "n":
|
||||||
|
expect(";");
|
||||||
|
return "";
|
||||||
|
|
||||||
|
case "i":
|
||||||
|
case "d":
|
||||||
|
case "b": {
|
||||||
|
expect(":");
|
||||||
|
let data = readUntil(";");
|
||||||
|
if (kind === "b") {
|
||||||
|
return (parseInt(data, 10) !== 0);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "a":
|
||||||
|
expect(":");
|
||||||
|
return "{" + handleArray() + "}";
|
||||||
|
|
||||||
|
case "s": {
|
||||||
|
expect(":");
|
||||||
|
let length = readUntil(":");
|
||||||
|
expect("\"");
|
||||||
|
let value = read(length);
|
||||||
|
expect("\";");
|
||||||
|
if (args[0]) {
|
||||||
|
return "\"" + value.replace(/"/g, "\\\"") + "\"";
|
||||||
|
} else {
|
||||||
|
return "\"" + value + "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw "Unknown type: " + kind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let inputPart = input.split("");
|
||||||
|
return handleInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PHP;
|
|
@ -25,6 +25,7 @@ import "./tests/operations/Hash.js";
|
||||||
import "./tests/operations/Image.js";
|
import "./tests/operations/Image.js";
|
||||||
import "./tests/operations/MorseCode.js";
|
import "./tests/operations/MorseCode.js";
|
||||||
import "./tests/operations/MS.js";
|
import "./tests/operations/MS.js";
|
||||||
|
import "./tests/operations/PHP.js";
|
||||||
import "./tests/operations/StrUtils.js";
|
import "./tests/operations/StrUtils.js";
|
||||||
import "./tests/operations/SeqUtils.js";
|
import "./tests/operations/SeqUtils.js";
|
||||||
|
|
||||||
|
|
68
test/tests/operations/PHP.js
Normal file
68
test/tests/operations/PHP.js
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
* PHP tests.
|
||||||
|
*
|
||||||
|
* @author Jarmo van Lenthe
|
||||||
|
*
|
||||||
|
* @copyright Crown Copyright 2017
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../TestRegister.js";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "PHP Deserialize empty array",
|
||||||
|
input: "a:0:{}",
|
||||||
|
expectedOutput: "{}",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "PHP Deserialize",
|
||||||
|
args: [true],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PHP Deserialize integer",
|
||||||
|
input: "i:10;",
|
||||||
|
expectedOutput: "10",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "PHP Deserialize",
|
||||||
|
args: [true],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PHP Deserialize string",
|
||||||
|
input: "s:17:\"PHP Serialization\";",
|
||||||
|
expectedOutput: "\"PHP Serialization\"",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "PHP Deserialize",
|
||||||
|
args: [true],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PHP Deserialize array (JSON)",
|
||||||
|
input: "a:2:{s:1:\"a\";i:10;i:0;a:1:{s:2:\"ab\";b:1;}}",
|
||||||
|
expectedOutput: "{\"a\": 10,\"0\": {\"ab\": true}}",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "PHP Deserialize",
|
||||||
|
args: [true],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PHP Deserialize array (non-JSON)",
|
||||||
|
input: "a:2:{s:1:\"a\";i:10;i:0;a:1:{s:2:\"ab\";b:1;}}",
|
||||||
|
expectedOutput: "{\"a\": 10,0: {\"ab\": true}}",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "PHP Deserialize",
|
||||||
|
args: [false],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
Loading…
Add table
Add a link
Reference in a new issue