Skip to content

Instantly share code, notes, and snippets.

@marijnvdwerf
Last active May 31, 2020 21:55
Show Gist options
  • Save marijnvdwerf/7750a617fb50170361f43e892af4198b to your computer and use it in GitHub Desktop.
Save marijnvdwerf/7750a617fb50170361f43e892af4198b to your computer and use it in GitHub Desktop.
RCT Classic encryption
{
"require": {
"mdurrant/php-binary-reader": "^1.0",
"symfony/var-dumper": "^5.0"
}
}
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "89a6b4172fa21ba1812ba1840708f8d8",
"packages": [
{
"name": "mdurrant/php-binary-reader",
"version": "1.0.9",
"source": {
"type": "git",
"url": "https://github.com/mdurrant/php-binary-reader.git",
"reference": "9abf18d7b361d0ae1cd80fc6782e59b313586db6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mdurrant/php-binary-reader/zipball/9abf18d7b361d0ae1cd80fc6782e59b313586db6",
"reference": "9abf18d7b361d0ae1cd80fc6782e59b313586db6",
"shasum": ""
},
"require": {
"php": ">=5.4"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"PhpBinaryReader\\": [
"src/",
"test/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matt Durrant",
"email": "[email protected]"
}
],
"description": "Lightweight binary reader for PHP",
"time": "2016-12-08T01:24:19+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "[email protected]"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2020-03-09T19:04:49+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v5.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "09de28632f16f81058a85fcf318397218272a07b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/09de28632f16f81058a85fcf318397218272a07b",
"reference": "09de28632f16f81058a85fcf318397218272a07b",
"shasum": ""
},
"require": {
"php": "^7.2.5",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"phpunit/phpunit": "<5.4.3",
"symfony/console": "<4.4"
},
"require-dev": {
"ext-iconv": "*",
"symfony/console": "^4.4|^5.0",
"symfony/process": "^4.4|^5.0",
"twig/twig": "^2.4|^3.0"
},
"suggest": {
"ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
"ext-intl": "To show region name in time zone dump",
"symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
},
"bin": [
"Resources/bin/var-dump-server"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"files": [
"Resources/functions/dump.php"
],
"psr-4": {
"Symfony\\Component\\VarDumper\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "[email protected]"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony mechanism for exploring and dumping PHP variables",
"homepage": "https://symfony.com",
"keywords": [
"debug",
"dump"
],
"time": "2020-04-12T16:45:47+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
<?php
require 'vendor/autoload.php';
$path = $argv[1];
$file = basename($path);
function rol32($value, $steps)
{
return (($value << $steps) | ($value >> (32 - $steps))) & 0xFFFFFFFF;
}
function unapplyMask($mask, \PhpBinaryReader\BinaryReader $br, $size)
{
$r10 = strlen($mask);
$ecx = 0; // offset into file?
$eax = $ecx * 7;
$edi = $ecx * 3;
$out = '';
for ($i = 0; $i < $size; $i++) {
$ecx = $eax % $r10;
$edi = $edi % $r10;
$eax = ($ecx + 1) % $r10;
$dl = $br->readUInt8();
$dl -= ord($mask[$eax]);
$dl = u8($dl);
$dl = $dl ^ ord($mask[$edi]);
$dl = ($dl + ord($mask[$ecx])) & 0xFF;
$out .= chr($dl);
$edi += 3;
$eax = $ecx + 7;
}
return $out;
}
/**
* @param $dl
* @return mixed
*/
function u8($dl)
{
if ($dl < 0) {
$packed = pack('c', $dl);
$unpacked = unpack('C', $packed);
$dl = $unpacked[1];
}
return $dl;
}
class Memory
{
private $var_18;
private $var_1C;
public function seed($esi, $edx)
{
if ($esi == 0) {
$this->var_18 = $edx;
} else if ($esi === 1) {
$this->var_1C = $edx;
}
}
public function randomFillMemory($size)
{
$buffer = '';
$r8d = 0xF7654321;
$edx = $size;
while ($edx > 0) {
$ecx = $this->var_1C ^ $r8d;
$r10d = $this->var_18;
$ecx = rol32($ecx, 25);
$ecx = ($ecx + $r10d) & 0xFFFFFFFF;
$this->var_18 = $ecx;
$r9d = $r10d >> 3;
$ecx = rol32($r10d, 29);
$this->var_1C = $ecx;
$buffer .= chr($r9d & 0xFF);
if ($edx < 2) break;
$buffer .= chr(($r10d >> 11) & 0xFF);
if ($edx < 3) break;
$buffer .= chr(($r10d >> 19) & 0xFF);
if ($edx < 4) break;
$buffer .= chr(($ecx >> 24) & 0xFF);
$edx -= 4;
}
return $buffer;
}
}
$edx = 0;
$rev = strrev($file);
$rev = str_split($rev, 1);
foreach ($rev as $char) {
$cl = ord($char);
$esi = ($edx << 5) & 0xFFFFFFFF;
$edx = (($edx + $esi) & 0xFFFFFFFF) ^ $cl;
}
$ebx = 0;
$fwd = str_split($file, 1);
foreach ($fwd as $char) {
$cl = ord($char);
$ecx = ($ebx << 5) & 0xFFFFFFFF;
$ebx = (($ebx + $ecx) & 0xFFFFFFFF) ^ $cl;
}
$memory = new Memory();
$memory->seed(0, $edx);
$memory->seed(1, $ebx);
$buffer = $memory->randomFillMemory(0x1000);
$brMask = new \PhpBinaryReader\BinaryReader($buffer);
$br = new \PhpBinaryReader\BinaryReader(fopen($path, 'rb'));
$out = unapplyMask($buffer, $br, $br->getEofPosition() - 4);
// Last 4 bytes are a checksum?
file_put_contents(basename($path, '.sea') . '.sc6', $out);
@janisozaur
Copy link

Is this going to get upstreamed?

@marijnvdwerf
Copy link
Author

Not by me at least. Feel free to implement it in C++.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment