|
<?php |
|
|
|
/* |
|
* Semi-auto restore Princess Connect ReDive (PC-DMM) C# dll |
|
* Step I: Run game and use Live RAM Caputurer ( http://www.forensicswiki.org/wiki/Belkasoft_Live_RAM_Capturer ) |
|
* Step II: Use volatility to <pslist> and then <ramdump> ( https://github.com/volatilityfoundation/volatility ) |
|
* Step III: Use this script |
|
*/ |
|
|
|
if (!file_exists('Assembly-CSharp.dll')) { |
|
echo 'no dll'; |
|
exit; |
|
} |
|
if (empty($argv[1]) || !file_exists($argv[1])) { |
|
echo 'no input'; |
|
exit; |
|
} |
|
echo "Reading zero gaps..."; |
|
$out = fopen('Assembly-CSharp.dll', 'rb+'); |
|
$offset = 0; |
|
$blocks = 0; |
|
$zb = str_repeat("\0", 16); |
|
$zeroblocks = []; |
|
while(1) { |
|
$chk = fread($out, 16); |
|
if ($chk == '') break; |
|
if ($chk == $zb) { |
|
$blocks++; |
|
} else { |
|
if ($blocks > 5) { |
|
$zeroblocks[] = [ |
|
'start' => $offset - $blocks*16, |
|
'end' => $offset, |
|
'len' => $blocks*16 |
|
]; |
|
} |
|
$blocks = 0; |
|
} |
|
$offset += 16; |
|
} |
|
|
|
usort($zeroblocks, function ($b, $a) {return $a['len'] - $b['len'];}); |
|
$biggestgap = $zeroblocks[0]; |
|
//print_r($biggestgap); |
|
if ($biggestgap['len'] < 1024*1024) { |
|
echo "too small gap: ".$biggestgap['len']; |
|
exit; |
|
} |
|
echo "found at 0x".dechex($biggestgap['start'])." len: 0x".dechex($biggestgap['len'])."\n"; |
|
|
|
|
|
echo "Finding keyword offset..."; |
|
exec('D:/cygwin64/bin/grep -F TUTORIAL_MAIN_STORY_RELEASE -b -m 1 -o -a '.$argv[1], $output); |
|
if (empty($output)) { |
|
echo 'empty search'; |
|
exit; |
|
} |
|
$inoffset = intval(explode(':', $output[0])[0]); |
|
echo "memory dump: 0x".dechex($inoffset).', '; |
|
|
|
$output = []; |
|
exec('D:/cygwin64/bin/grep -F TUTORIAL_MAIN_STORY_RELEASE -b -m 1 -o -a Assembly-CSharp.dll', $output); |
|
if (empty($output)) { |
|
echo 'empty search'; |
|
exit; |
|
} |
|
$outoffset = intval(explode(':', $output[0])[0]); |
|
echo "original file: 0x".dechex($outoffset)."\n"; |
|
|
|
echo "Applying...\n"; |
|
$in = fopen($argv[1], 'rb'); |
|
fseek($in, $inoffset - ($outoffset - $biggestgap['start']), SEEK_SET); |
|
fseek($out, $biggestgap['start'], SEEK_SET); |
|
for ($i = 0; $i < $biggestgap['len']; $i += 16) { |
|
if ($i % 4096 == 0)printf("\r%x", $biggestgap['start'] + $i); |
|
$buf = fread($in, 16); |
|
fwrite($out, $buf); |
|
} |
|
echo "\nDone\n"; |