244 lines
9.1 KiB
PHP
244 lines
9.1 KiB
PHP
<?php
|
|
header('Content-Type: application/json');
|
|
require_once __DIR__ . '/db/config.php';
|
|
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
|
|
if (!$input || empty($input['code'])) {
|
|
echo json_encode(['success' => false, 'error' => 'No code provided']);
|
|
exit;
|
|
}
|
|
|
|
$code = $input['code'];
|
|
|
|
class LuartexExtremeVM {
|
|
private $rawCode;
|
|
private $opcodes = [];
|
|
private $constants = [];
|
|
private $instructions = [];
|
|
private $keys = [];
|
|
|
|
public function __construct($code) {
|
|
$this->rawCode = $code;
|
|
$this->keys = [rand(128, 255), rand(128, 255), rand(128, 255), rand(128, 255)];
|
|
$this->setupOpcodes();
|
|
}
|
|
|
|
private function setupOpcodes() {
|
|
$ops = [
|
|
'LOADK', 'GETGLOBAL', 'SETGLOBAL', 'CALL', 'MOVE',
|
|
'ADD', 'SUB', 'MUL', 'DIV', 'MOD', 'POW',
|
|
'JMP', 'EQ', 'LT', 'LE', 'RETURN', 'GETTABLE', 'SETTABLE', 'NEWTABLE',
|
|
'CLOSURE', 'VARARG', 'FORPREP', 'FORLOOP'
|
|
];
|
|
shuffle($ops);
|
|
foreach ($ops as $index => $op) {
|
|
$this->opcodes[$op] = $index + 100;
|
|
}
|
|
}
|
|
|
|
private function genVar() {
|
|
$chars = 'iI1l';
|
|
$res = '_';
|
|
for($i=0; $i<16; $i++) $res .= $chars[rand(0, 3)];
|
|
return $res;
|
|
}
|
|
|
|
private function toLuaTable($data) {
|
|
if (is_array($data)) {
|
|
$isList = true;
|
|
$expectedKey = 0;
|
|
foreach ($data as $k => $v) {
|
|
if ($k !== $expectedKey++) {
|
|
$isList = false;
|
|
break;
|
|
}
|
|
}
|
|
if ($isList) {
|
|
$parts = [];
|
|
foreach ($data as $v) {
|
|
$parts[] = $this->toLuaTable($v);
|
|
}
|
|
return '{' . implode(',', $parts) . '}';
|
|
} else {
|
|
$parts = [];
|
|
foreach ($data as $k => $v) {
|
|
$key = is_string($k) ? "['" . addslashes($k) . "']" : "[$k]";
|
|
$parts[] = $key . '=' . $this->toLuaTable($v);
|
|
}
|
|
return '{' . implode(',', $parts) . '}';
|
|
}
|
|
} elseif (is_string($data)) {
|
|
return '"' . addslashes($data) . '"';
|
|
} elseif (is_bool($data)) {
|
|
return $data ? 'true' : 'false';
|
|
} elseif (is_null($data)) {
|
|
return 'nil';
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
private function addConst($val) {
|
|
$idx = array_search($val, $this->constants);
|
|
if ($idx === false) {
|
|
$this->constants[] = $val;
|
|
$idx = count($this->constants) - 1;
|
|
}
|
|
return $idx;
|
|
}
|
|
|
|
private function encrypt($data) {
|
|
if (is_string($data)) {
|
|
$out = [];
|
|
for ($i = 0; $i < strlen($data); $i++) {
|
|
$out[] = ord($data[$i]) ^ $this->keys[$i % 4];
|
|
}
|
|
return $out;
|
|
}
|
|
return (int)$data ^ $this->keys[0];
|
|
}
|
|
|
|
private function compile() {
|
|
$this->addConst("Luartex V3.5 Hardened VM");
|
|
preg_match_all('/([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)?)\s*\((.*?)\)/', $this->rawCode, $matches);
|
|
if (isset($matches[1]) && !empty($matches[1])) {
|
|
foreach ($matches[1] as $idx => $funcName) {
|
|
$argString = isset($matches[2][$idx]) ? trim($matches[2][$idx]) : '';
|
|
$fIdx = $this->addConst($funcName);
|
|
$this->instructions[] = [$this->opcodes['GETGLOBAL'], 0, $fIdx];
|
|
if (empty($argString)) {
|
|
$this->instructions[] = [$this->opcodes['CALL'], 0, 0];
|
|
} elseif (preg_match('/^["\'](.*)["\']$/', $argString, $m)) {
|
|
$vIdx = $this->addConst($m[1]);
|
|
$this->instructions[] = [$this->opcodes['LOADK'], 1, $vIdx];
|
|
$this->instructions[] = [$this->opcodes['CALL'], 0, 1];
|
|
} elseif (is_numeric($argString)) {
|
|
$vIdx = $this->addConst((float)$argString);
|
|
$this->instructions[] = [$this->opcodes['LOADK'], 1, $vIdx];
|
|
$this->instructions[] = [$this->opcodes['CALL'], 0, 1];
|
|
} else {
|
|
$this->instructions[] = [$this->opcodes['CALL'], 0, 0];
|
|
}
|
|
}
|
|
} else {
|
|
$this->addConst("Luartex Protection Active");
|
|
}
|
|
for ($i=0; $i<10; $i++) {
|
|
$this->instructions[] = [$this->opcodes['MOVE'], rand(0, 50), rand(0, 50)];
|
|
}
|
|
$this->instructions[] = [$this->opcodes['RETURN'], 0, 0];
|
|
}
|
|
|
|
public function build() {
|
|
$this->compile();
|
|
$encryptedConsts = [];
|
|
foreach ($this->constants as $c) {
|
|
$encryptedConsts[] = $this->encrypt($c);
|
|
}
|
|
$encryptedInsts = [];
|
|
foreach ($this->instructions as $inst) {
|
|
$encryptedInsts[] = [
|
|
(int)$inst[0] ^ $this->keys[0],
|
|
(int)$inst[1] ^ $this->keys[1],
|
|
(int)$inst[2] ^ $this->keys[2]
|
|
];
|
|
}
|
|
|
|
$v_v = $this->genVar();
|
|
$v_k = $this->genVar();
|
|
$v_s = $this->genVar();
|
|
$v_i = $this->genVar();
|
|
$v_c = $this->genVar();
|
|
$v_o = $this->genVar();
|
|
$v_d = $this->genVar();
|
|
$v_g = $this->genVar();
|
|
$v_x = $this->genVar();
|
|
$v_e = $this->genVar();
|
|
$v_p = $this->genVar();
|
|
$v_r = $this->genVar();
|
|
$v_l = $this->genVar();
|
|
|
|
$k_str = implode(',', $this->keys);
|
|
$consts_table = $this->toLuaTable($encryptedConsts);
|
|
$insts_table = $this->toLuaTable($encryptedInsts);
|
|
$opcodes_table = $this->toLuaTable($this->opcodes);
|
|
|
|
$lua = "-- ts was obfuscated by Luartex V3.2\n";
|
|
$lua .= "local " . $v_v . " = {C = " . $consts_table . ", I = " . $insts_table . ", O = " . $opcodes_table . "}; ";
|
|
$lua .= "local " . $v_k . " = {" . $k_str . "}; ";
|
|
$lua .= "return (function(...) ";
|
|
$lua .= "local " . $v_e . " = getfenv and getfenv() or _G; ";
|
|
$lua .= "local " . $v_p . " = tick(); ";
|
|
$lua .= "local function " . $v_g . "(_f) ";
|
|
$lua .= "if debug and debug.info then ";
|
|
$lua .= "local _s, _l = debug.info(_f or print, 'sl'); if _s ~= '[C]' then while true do " . $v_p . " = " . $v_p . " + 1 end end ";
|
|
$lua .= "end ";
|
|
$lua .= "if tick() - " . $v_p . " > 10 then while true do end end ";
|
|
$lua .= "end; ";
|
|
$lua .= "local function " . $v_x . "(_t) ";
|
|
$lua .= "if type(_t) == 'table' then ";
|
|
$lua .= "local _r = ''; for _j = 1, #_t do ";
|
|
$lua .= "local _idx = ((_j - 1) % 4) + 1; ";
|
|
$lua .= "_r = _r .. string.char(bit32.bxor(_t[_j], " . $v_k . "[_idx])) ";
|
|
$lua .= "end return _r ";
|
|
$lua .= "end return bit32.bxor(_t, " . $v_k . "[1]) ";
|
|
$lua .= "end; ";
|
|
$lua .= "local " . $v_r . " = {}; ";
|
|
$lua .= "local " . $v_l . " = 1; ";
|
|
$lua .= "while " . $v_l . " <= #" . $v_v . ".I do ";
|
|
$lua .= "local " . $v_i . " = " . $v_v . ".I[" . $v_l . "]; ";
|
|
$lua .= "local " . $v_o . " = bit32.bxor(" . $v_i . "[1], " . $v_k . "[1]); ";
|
|
$lua .= "local " . $v_a . " = bit32.bxor(" . $v_i . "[2], " . $v_k . "[2]); ";
|
|
$lua .= "local " . $v_b . " = bit32.bxor(" . $v_i . "[3], " . $v_k . "[3]); ";
|
|
|
|
$lua .= "if " . $v_o . " == " . $this->opcodes['GETGLOBAL'] . " then ";
|
|
$lua .= "local _gn = " . $v_x . "(" . $v_v . ".C[" . $v_b . "+1]); ";
|
|
$lua .= "local _gv = " . $v_e . "; for _p in _gn:gmatch('[^%.]+') do _gv = _gv[_p] end; ";
|
|
$lua .= $v_r . "[" . $v_a . "] = _gv; ";
|
|
$lua .= "elseif " . $v_o . " == " . $this->opcodes['LOADK'] . " then ";
|
|
$lua .= $v_r . "[" . $v_a . "] = " . $v_x . "(" . $v_v . ".C[" . $v_b . "+1]); ";
|
|
$lua .= "elseif " . $v_o . " == " . $this->opcodes['CALL'] . " then ";
|
|
$lua .= $v_g . "(" . $v_r . "[" . $v_a . "]); ";
|
|
$lua .= "if " . $v_b . " == 0 then " . $v_r . "[" . $v_a . "]() else " . $v_r . "[" . $v_a . "](" . $v_r . "[" . $v_a . "+1]) end; ";
|
|
$lua .= "elseif " . $v_o . " == " . $this->opcodes['RETURN'] . " then ";
|
|
$lua .= "return; ";
|
|
$lua .= "end; ";
|
|
|
|
$lua .= $v_l . " = " . $v_l . " + 1; ";
|
|
$lua .= "end; ";
|
|
$lua .= "end)(...)";
|
|
|
|
return [
|
|
'success' => true,
|
|
'protected_code' => $lua,
|
|
'stats' => [
|
|
'original_size' => strlen($this->rawCode),
|
|
'protected_size' => strlen($lua),
|
|
'vm_version' => '3.5-delta',
|
|
'protection_level' => 'extreme'
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
try {
|
|
$vm = new LuartexExtremeVM($code);
|
|
$result = $vm->build();
|
|
|
|
// Log obfuscation
|
|
try {
|
|
$stmt = db()->prepare("INSERT INTO scripts (original_size, protected_size, settings) VALUES (?, ?, ?)");
|
|
$stmt->execute([
|
|
$result['stats']['original_size'],
|
|
$result['stats']['protected_size'],
|
|
json_encode(['protection' => 'extreme'])
|
|
]);
|
|
} catch (Exception $e) {
|
|
// Ignore DB errors
|
|
}
|
|
|
|
echo json_encode($result);
|
|
} catch (Exception $e) {
|
|
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
|
}
|