MBCompilerOnline/classes/bas.class.php
2024-05-11 18:42:44 +03:00

326 lines
14 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*
* ****************************************************************
CREATE BY HoldFast
Андрей Рейгант
http://vk.com/holdfast
MBTEAM.RU
* ****************************************************************
Коды ответов:
-1: неверный BAS-файл
-2: файл нельзя декмопилировать, поскольку он обфусцирован
0: файл успешно обфусцирован
* ****************************************************************
Пример:
-----------------------------------------------------------------
$bas = new BAS('Autorun.bas'); ///Открываем BAS
$code = $bas->decompile(); //$code - декомпилированный код BAS
echo $code;
-----------------------------------------------------------------
$bas->obfuscation('newbas.bas'); //обфусцировать открытый BAS, и сохранить
его с именем newbas.bas
*/
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(
" 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"
);
///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) {
return -1;
} else {
$isDIM = false;
$varnum = hexdec($this->readShort($this->data)); ///number variable
$varname = [];
$main = '';
for ($i = 0; $i < $varnum; $i++) { //read variable name
$num = hexdec($this->readShort($this->data)); ///name length
for ($ii = 0; $ii < $num; $ii++) {
$varname[$i] = $varname[$i] ?? '';
$varname[$i] .= substr($this->data, 0, 1);
$this->readByte($this->data);
}
/// 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);
}
}
$codeln = hexdec($this->readShort($this->data));
if ($codeln != strlen($this->data)) {
$this->init();
return -2;
}
///read code
while (strlen($this->data) > 0) {
$line = "";
$line .= hexdec($this->readShort($this->data)); //write number of line
$lineS = hexdec($this->readByte($this->data)); //length line
$isl = 1;
unset($lims);
for ($ii = 0; $ii < $lineS - 4; $ii++) { ///read operators
$lims[$ii] = $this->readByte($this->data);
}
$cur = 0; //position of read
while ($cur < count($lims)) { //decompilation start
$opType = $lims[$cur];
$cur++;
if (hexdec($opType) == 0xfc) { /// variable
$varNum = hexdec($lims[$cur]);
$limsIndex = $cur - 2;
if (array_key_exists($limsIndex, $lims) && hexdec($lims[$limsIndex]) == 16)
$line .= " ";
if ($isl == 1) {
$line .= " " . $varname[$varNum];
} else {
$line .= $varname[$varNum];
}
$cur++;
} else { ///operator
$isl = 0;
switch (hexdec($opType)) {
case 0x0e:
$line .= " REM ";
$str = hexdec($lims[$cur]); /// len
$cur++;
for ($i = 0; $i < $str; $i++) {
$line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur])));
$cur++;
}
break;
case 0xfd:
$line .= "\"";
$str = hexdec($lims[$cur]);
$cur++;
for ($i = 0; $i < $str; $i++) {
$line .= str_replace('"', '\"', iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur]))));
$cur++;
}
$line .= "\"";
break;
case 0x30:
$line .= " DATA ";
$str = hexdec($lims[$cur]);
$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;
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++;
}
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) {
switch ($this->readInt($this->data)) {
case '4d420001':
$version = 1;
break;
case '4d420191':
$version = 2;
break;
default:
$version = 0;
break;
}
if ($version == 0) {
return -1;
} else {
$main = "";
if ($version == 1)
$main .= pack('H*', "4d420001"); //writeHex
else
$main .= pack('H*', "4d420191");
$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));
}
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));
}
}
$leng = hexdec($this->readShort($this->data));
if ($version == 1)
$main .= pack('n*', $leng + 7);
else
$main .= pack('n*', $leng + 1);
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));
}
function readByte($text, $dec = true) {
$this->data = substr($text, 1, strlen($text));
if ($dec)
return bin2hex(substr($text, 0, 1));
else
return substr($text, 0, 1);
}
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;
}
}