MBCompilerOnline/classes/bas.class.php

326 lines
14 KiB
PHP
Raw Permalink Normal View History

2024-05-11 17:47:33 +03:00
<?php
2024-05-11 18:42:44 +03:00
/*
* ****************************************************************
CREATE BY HoldFast
Андрей Рейгант
http://vk.com/holdfast
MBTEAM.RU
* ****************************************************************
2024-05-11 17:47:33 +03:00
Коды ответов:
2024-05-11 18:42:44 +03:00
-1: неверный BAS-файл
2024-05-11 17:47:33 +03:00
-2: файл нельзя декмопилировать, поскольку он обфусцирован
0: файл успешно обфусцирован
2024-05-11 18:42:44 +03:00
* ****************************************************************
Пример:
-----------------------------------------------------------------
$bas = new BAS('Autorun.bas'); ///Открываем BAS
$code = $bas->decompile(); //$code - декомпилированный код BAS
echo $code;
-----------------------------------------------------------------
$bas->obfuscation('newbas.bas'); //обфусцировать открытый BAS, и сохранить
его с именем newbas.bas
2024-05-11 17:47:33 +03:00
*/
class BAS {
public $file;
public $data;
function __construct($files) {
$this->file = $files;
$this->init();
}
function init() {
$this->data = file_get_contents($this->file);
}
function decompile() {
$ops = array(
2024-05-11 18:42:44 +03:00
" STOP ", " POP ", " RETURN ", " END ", " NEW ", " RUN ", " DIR ", " DEG ", " RAD ", " BYE ", " GOTO ",
" GOSUB ", " SLEEP ", " PRINT ", " REM ", " DIM ", " IF ", " THEN ", " CLS ", " PLOT ", " DRAWLINE ",
" FILLRECT ", " DRAWRECT ", " FILLROUNDRECT ", " DRAWROUNDRECT ", " FILLARC ",
" DRAWARC ", " DRAWSTRING ", " SETCOLOR ", " BLIT ", " FOR ", " TO ", " STEP ", " NEXT ", " INPUT ",
" LIST ", " ENTER ", " LOAD ", " SAVE ", " DELETE ", " EDIT ", " TRAP ", " OPEN ", " CLOSE ",
" NOTE ", " POINT ", " PUT ", " GET ", " DATA ", " RESTORE ", " READ ", "=", "<>", "<", "<=",
">", ">=", "(", ")", ",", "+", "-", "-", "*", "/", "^", " BITAND ", " BITOR ", " BITXOR ", " NOT ",
" AND ", " OR ", "SCREENWIDTH", "SCREENHEIGHT", " ISCOLOR ", " NUMCOLORS ", "STRINGWIDTH", "STRINGHEIGHT",
"LEFT$", "MID$", "RIGHT$", "CHR$", "STR$", "LEN", "ASC", "VAL", " UP ", " DOWN ", " LEFT ", " RIGHT ",
" FIRE ", " GAMEA ", " GAMEB ", " GAMEC ", " GAMED ", " DAYS ", " MILLISECONDS ",
" YEAR ", " MONTH ", " DAY ", " HOUR ", " MINUTE ", " SECOND ", " MILLISECOND ", "RND", " ERR ",
" FRE ", "MOD", "EDITFORM ", "GAUGEFORM ", "CHOICEFORM", "DATEFORM", "MESSAGEFORM",
"LOG", "EXP", "SQR", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "ABS", "=", "#", " PRINT ",
" INPUT ", ":", " GELGRAB ", " DRAWGEL ", " SPRITEGEL ", " SPRITEMOVE ", " SPRITEHIT ",
"READDIR$", "PROPERTY$", " GELLOAD ", " GELWIDTH", " GELHEIGHT", " PLAYWAV ", " PLAYTONE ",
" INKEY", "SELECT", "ALERT ", " SETFONT ", " MENUADD ", " MENUITEM", " MENUREMOVE ",
" CALL ", " ENDSUB ", " REPAINT", "SENDSMS ", " RAND", " ALPHAGEL ", " COLORALPHAGEL ", " PLATFORMREQUEST ", " DELGE L", " DELSPRITE ", "MKDIR"
2024-05-11 17:47:33 +03:00
);
2024-05-11 18:42:44 +03:00
///version of BAS
switch ($this->readInt($this->data)) {
case '4d420001':
$version = 1;
break;
case '4d420191':
$version = 2;
break;
default:
$version = 0;
break;
}
if ($version == 0) {
2024-05-11 17:47:33 +03:00
return -1;
} else {
$isDIM = false;
2024-05-11 18:42:44 +03:00
$varnum = hexdec($this->readShort($this->data)); ///number variable
2024-05-11 17:47:33 +03:00
$varname = [];
$main = '';
2024-05-11 18:42:44 +03:00
for ($i = 0; $i < $varnum; $i++) { //read variable name
$num = hexdec($this->readShort($this->data)); ///name length
2024-05-11 17:47:33 +03:00
for ($ii = 0; $ii < $num; $ii++) {
$varname[$i] = $varname[$i] ?? '';
$varname[$i] .= substr($this->data, 0, 1);
$this->readByte($this->data);
}
2024-05-11 18:42:44 +03:00
/// end read variable name
$this->readByte($this->data); // variable type
}
//float
if ($version == 2) {
$floatnum = hexdec($this->readShort($this->data));
for ($i = 0; $i < $floatnum; $i++) {
$byte[3] = $this->readByte($this->data, false);
$byte[2] = $this->readByte($this->data, false);
$byte[1] = $this->readByte($this->data, false);
$byte[0] = $this->readByte($this->data, false);
$tfloat = unpack('f', $byte[0] . $byte[1] . $byte[2] . $byte[3]); //uncpack float
$float[$i] = round($tfloat[1], 7);
}
2024-05-11 17:47:33 +03:00
}
2024-05-11 18:42:44 +03:00
$codeln = hexdec($this->readShort($this->data));
2024-05-11 17:47:33 +03:00
if ($codeln != strlen($this->data)) {
$this->init();
return -2;
}
2024-05-11 18:42:44 +03:00
///read code
2024-05-11 17:47:33 +03:00
while (strlen($this->data) > 0) {
$line = "";
2024-05-11 18:42:44 +03:00
$line .= hexdec($this->readShort($this->data)); //write number of line
$lineS = hexdec($this->readByte($this->data)); //length line
2024-05-11 17:47:33 +03:00
$isl = 1;
unset($lims);
2024-05-11 18:42:44 +03:00
for ($ii = 0; $ii < $lineS - 4; $ii++) { ///read operators
2024-05-11 17:47:33 +03:00
$lims[$ii] = $this->readByte($this->data);
}
2024-05-11 18:42:44 +03:00
$cur = 0; //position of read
while ($cur < count($lims)) { //decompilation start
2024-05-11 17:47:33 +03:00
$opType = $lims[$cur];
$cur++;
2024-05-11 18:42:44 +03:00
if (hexdec($opType) == 0xfc) { /// variable
2024-05-11 17:47:33 +03:00
$varNum = hexdec($lims[$cur]);
$limsIndex = $cur - 2;
if (array_key_exists($limsIndex, $lims) && hexdec($lims[$limsIndex]) == 16)
$line .= " ";
if ($isl == 1) {
$line .= " " . $varname[$varNum];
2024-05-11 18:42:44 +03:00
} else {
2024-05-11 17:47:33 +03:00
$line .= $varname[$varNum];
2024-05-11 18:42:44 +03:00
}
2024-05-11 17:47:33 +03:00
$cur++;
2024-05-11 18:42:44 +03:00
} else { ///operator
2024-05-11 17:47:33 +03:00
$isl = 0;
switch (hexdec($opType)) {
case 0x0e:
2024-05-11 18:42:44 +03:00
$line .= " REM ";
$str = hexdec($lims[$cur]); /// len
2024-05-11 17:47:33 +03:00
$cur++;
for ($i = 0; $i < $str; $i++) {
$line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur])));
$cur++;
}
break;
case 0xfd:
$line .= "\"";
2024-05-11 18:42:44 +03:00
$str = hexdec($lims[$cur]);
2024-05-11 17:47:33 +03:00
$cur++;
for ($i = 0; $i < $str; $i++) {
2024-05-11 18:42:44 +03:00
$line .= str_replace('"', '\"', iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur]))));
2024-05-11 17:47:33 +03:00
$cur++;
}
$line .= "\"";
break;
case 0x30:
$line .= " DATA ";
2024-05-11 18:42:44 +03:00
$str = hexdec($lims[$cur]);
2024-05-11 17:47:33 +03:00
$cur++;
for ($i = 0; $i < $str; $i++) {
$line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur])));
$cur++;
}
break;
case 0xf6:
$line .= "=";
break;
case 0xf8:
$line .= hexdec($lims[$cur]);
$cur++;
break;
case 0xf7:
$line .= "(";
continue 2;
case 0xf9:
$line .= hexdec($lims[$cur]);
$cur++;
break;
case 0xfa:
$line .= (hexdec($lims[$cur]) * 256 + hexdec($lims[$cur + 1]));
$cur = $cur + 2;
break;
case 0xfb:
$line .= (hexdec($lims[$cur]) * 16777216 + hexdec($lims[$cur + 1]) * 65536 + hexdec($lims[$cur + 2]) * 256 + hexdec($lims[$cur + 3]));
$cur = $cur + 4;
break;
2024-05-11 18:42:44 +03:00
case 0xfe: //float
if ($version == 1) {
$exp = (int) $this->tosbyte(hexdec($lims[$cur + 3]));
$m = (hexdec($lims[$cur]) * 65536 + hexdec($lims[$cur + 1]) * 256 + hexdec($lims[$cur + 2])) / 500000;
$e = 1;
if ($exp > 0) {
$d = 1;
for ($i = 0; $i < $exp; $i++)
$d = $d * 10;
$e = $d;
}
if ($exp < 0) {
$d = 1;
for ($i = $exp; $i < 0; $i++)
$d = $d / 10;
$e = $d;
}
$line .= (float) ($m * $e);
$cur = $cur + 4;
} else {
$line .= $float[hexdec($lims[$cur])];
$cur++;
2024-05-11 17:47:33 +03:00
}
break;
default:
$line .= $ops[hexdec($opType)];
if ($opType == 15 || ($ops[$opType] ?? '') == ' READ ') {
$isDIM = true;
}
break;
}
}
}
$this->readByte($this->data);
$line .= "\r\n";
$main .= $line;
}
$this->init();
return $main;
}
}
function obfuscation($name) {
2024-05-11 18:42:44 +03:00
switch ($this->readInt($this->data)) {
case '4d420001':
$version = 1;
break;
case '4d420191':
$version = 2;
break;
default:
$version = 0;
break;
}
if ($version == 0) {
2024-05-11 17:47:33 +03:00
return -1;
} else {
$main = "";
2024-05-11 18:42:44 +03:00
if ($version == 1)
$main .= pack('H*', "4d420001"); //writeHex
else
$main .= pack('H*', "4d420191");
2024-05-11 17:47:33 +03:00
$varnum = hexdec($this->readShort($this->data));
$main .= pack('n*', $varnum); //writeShort
for ($i = 0; $i < $varnum; $i++) { //пропуск переменных
$this->readUTF($this->data);
$main .= $this->writeUTF(" ");
$main .= pack('H*', $this->readByte($this->data));
}
2024-05-11 18:42:44 +03:00
if ($version == 2) { //пропуск float для MB191
$floatnum = hexdec($this->readShort($this->data));
$main .= pack('n*', $floatnum);
for ($i = 0; $i < $varnum; $i++) {
$main .= pack('H*', $this->readInt($this->data));
}
}
2024-05-11 17:47:33 +03:00
$leng = hexdec($this->readShort($this->data));
2024-05-11 18:42:44 +03:00
if ($version == 1)
$main .= pack('n*', $leng + 7);
else
$main .= pack('n*', $leng + 1);
2024-05-11 17:47:33 +03:00
for ($i = 0; $i < $leng; $i++) {
$main .= pack('H*', $this->readByte($this->data));
}
$main .= pack('H*', "FFFF");
file_put_contents($name, $main);
}
$this->init();
return 0;
}
function tosbyte($byte) {
if (0 <= $byte && $byte <= 63)
return (int) $byte;
if (64 <= $byte && $byte <= 191)
return (int) (-(128 - $byte));
if (192 <= $byte && $byte <= 255)
return (int) (-(256 - $byte));
return 0;
}
function readInt($text) {
$this->data = substr($text, 4, strlen($text));
return bin2hex(substr($text, 0, 4));
}
function readShort($text) {
$this->data = substr($text, 2, strlen($text));
return bin2hex(substr($text, 0, 2));
}
2024-05-11 18:42:44 +03:00
function readByte($text, $dec = true) {
2024-05-11 17:47:33 +03:00
$this->data = substr($text, 1, strlen($text));
2024-05-11 18:42:44 +03:00
if ($dec)
return bin2hex(substr($text, 0, 1));
else
return substr($text, 0, 1);
2024-05-11 17:47:33 +03:00
}
function readUTF() {
$to = hexdec($this->readShort($this->data));
$bombom = "";
while ($to <> 0) {
$bombom .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($this->readByte($this->data))));
$to--;
}
return $bombom;
}
function writeUTF($text) {
$pack = pack('n*', mb_strlen($text));
$pack .= pack('a*', $text);
return $pack;
}
}