97/fw/protect/protect05.dpr
2025-02-22 18:50:46 +03:00

164 lines
3.2 KiB
ObjectPascal

program protect05;
{$R-}
{$APPTYPE CONSOLE}
uses
Classes,
SysUtils;
function GetFileSize(const FileName: String): Cardinal;
var
AFile: File of Byte;
begin
AssignFile(AFile, FileName);
Reset(AFile);
try
Result := System.FileSize(AFile);
finally
CloseFile(AFile);
end;
end;
procedure help;
begin
writeln('Usage:');
writeln(' protect05.exe <INPUT FILE>');
writeln;
end;
function bit(const aValue: Cardinal; const BitPos: Byte): byte;
begin
if ((aValue and (1 shl BitPos)) <> 0) then
result:= 1
else
result:= 0;
end;
const
MAX_BUF_SIZE = 1024 * 15;
var
data_len: longint;
o_file_name, i_file_name: string;
o_file, i_file: file of byte;
b,i, readed: longint;
buf_in, buf_out: array of byte;
CODE, D, D0_in, D0_out, todo: byte;
unprotected: boolean;
begin
writeln('PROTECT05: Sprinter-97 FW bitstream protector/decoder');
writeln('Copyright (c) 2024 Sprinter Team');
// check incoming values
if ParamCount < 1 then
begin
help;
exit;
end;
i_file_name:= ParamStr(1);
if trim(i_file_name) = '' then
begin
writeln('ERROR: input file name is not specified');
exit;
end;
// check buffer size
data_len:= GetFileSize(i_file_name);
if (data_len > MAX_BUF_SIZE) then
begin
writeln('ERROR: DATA_LENGTH='+inttostr(data_len)+', MAX_BUF_SIZE='+inttostr(MAX_BUF_SIZE));
exit;
end;
// create buffers
SetLength(buf_in, MAX_BUF_SIZE);
FillChar(buf_in[0], length(buf_in), 0);
SetLength(buf_out, MAX_BUF_SIZE);
FillChar(buf_out[0], length(buf_out), 0);
// load src file
{$I-}
FileMode:= fmOpenRead;
AssignFile(i_file, i_file_name);
reset(i_file);
seek(i_file, 0);
BlockRead(i_file, buf_in[0], length(buf_in), readed);
CloseFile(i_file);
{$I+}
i:= IOResult;
if (i > 0) then
begin
writeln('ERROR: IOResult='+inttostr(i)+' during loading input file. Readed '+inttostr(readed));
exit;
end;
writeln('readed '+inttostr(readed)+' bytes');
data_len:= readed;
unprotected:= false;
if (buf_in[0] = $FF) and (buf_in[1] = $FF) and (buf_in[2] = $62) and (buf_in[3] = $7B) then
unprotected:= true;
// protect / unprotect
CODE:= 0;
if unprotected then
writeln('protecting ...')
else
writeln('decoding ...');
for b:= 0 to data_len-1 do
begin
D:= buf_in[b];
for i:= 0 to 7 do
begin
D0_in:= bit(D, i);
D0_out:= bit(CODE,4) xor D0_in;
buf_out[b]:= buf_out[b] or (D0_out shl i);
if unprotected then
todo:= D0_in // protect
else
todo:= D0_out; // unprotect
CODE:= (CODE shl 1) or (bit(CODE,2) xor todo);
end;
// just header output
if b < 8 then
write(inttohex(buf_out[b])+' ');
end;
writeln;
// write buffer to output file
if unprotected then
o_file_name:= ParamStr(1)+'.protected'
else
o_file_name:= ParamStr(1)+'.decoded';
{$I-}
FileMode:= fmOpenReadWrite;
AssignFile(o_file, o_file_name);
reset(o_file);
if IOResult <> 0 then
rewrite(o_file);
seek(o_file, 0);
BlockWrite(o_file, buf_out[0], data_len);
CloseFile(o_file);
{$I+}
i:= IOResult;
if (i > 0) then
begin
writeln('ERROR: IOResult='+inttostr(i)+' during writing to output file');
exit;
end;
// finish
writeln('');
end.