Показать сообщение отдельно
  #10  
Старый 11.07.2017, 12:55
Shaft Shaft вне форума
Новичок
 
Регистрация: 15.05.2013
Сообщения: 74
Версия Delphi: 7/10.4
Репутация: 12
По умолчанию

Алгоритм разгадан верно, большое спасибо.
Вот что удалось выяснить:
-Оказывается используется еще 2 ключа кроме "120", они были подобраны по представленному примеру, так же известно что данный алгоритм используется еще в 3х частях этой игры(и возможно во всех остальных), была написана процедура поиска ключа(нужно знать хотя бы одно слово в шифрованном и расшифрованном виде).
-Была написана процедура расшифровки.
-Выяснено за что отвечает левая системная часть строки. Пример строки расшифрованной вместе с левой частью: 160-3 ->160 Кто ты? Что с тобой случилось? Может расскажешь, что все это значит?
где 160-3 Номер сцены-номер диалога, ->160 к какой сцене ведет диалог(если числа одинаковые значит выбор варианта не верный и игрок не продвигается дальше).
-Некоторые строки разбиты на 2 части, каждая вторая часть начинается на * то есть если во время чтения и расшифровки файла обнаруживается что строка начинается на * то значит ее надо склеить с предыдущей.

Код расшифровки:
Код:
function Encrypt_(s:string; EncodeTable:array of Integer):string;
var
  i,KeyL:Integer;
begin
  Result:='';
  KeyL:=0;
  for i:=1 to Length(s) do
  begin
    if KeyL>2 then KeyL:=0;
    Result:=Result+Char(Ord(s[i])+EncodeTable[KeyL]);
    Inc(KeyL);
  end;
end;

function Encrypt(s:string):string;
const Key1:array[0..2] of Integer=(1,2,0);
      Key2:array[0..2] of Integer=(2,3,1);
      Key3:array[0..2] of Integer=(3,4,2);
begin
  Result:=Encrypt_(s,Key1);//Подставить нужный ключ
end;
Расшифровывается полностью вся строка включая знаки препинания, пробелы, и заглавные буквы.

Код поиска ключа:
Код:
procedure FindKey;
var
  i:Integer;
  Key:array of Integer;
  EncS,DecS,Check:string;
begin
  EncS:='кдираЮ';//Шифрованная
  DecS:='никуда';//Расшифрованная
  SetLength(Key,3);
  Key[0]:=0;
  Key[1]:=0;
  Key[2]:=0;

  for i:=1 to 1000 do
  begin
    if (Key[0]>=9) and (Key[1]>=9) and (Key[2]>=9) then Break;
    if Key[2]<9 then Inc(Key[2]) else
    begin
      Key[2]:=0;
      if Key[1]<9 then Inc(Key[1]) else
      begin
        Key[1]:=0;
        if Key[0]<9 then Inc(Key[0]);
      end;  
    end;
    Check:=Encrypt_(EncS,Key);
    if Check=DecS then
      WriteLn('Key Found - '+IntToStr(Key[0])+IntToStr(Key[1])+IntToStr(Key[2]));
  end;
end;

Еще как я уже говорил видео зашифровано заменой первого байта, оно мне в принципе было не нужно но ради интереса сделал, пусть оно тут полежит, а то как выяснилось в поисковиках относительно этой серии игр, расшифровка видео самый популярный запрос.
Код расшифровки видео:
Код:
procedure EncodeVideo;
var
  ms:TMemoryStream;
  B:Byte;
begin
  ms:=TMemoryStream.Create;
  ms.LoadFromFile('Video.cmk');
  ms.Position:=1;
  ms.ReadBuffer(B,SizeOf(B));
  if B=$7C then
  begin
    B:=$49;
    ms.Position:=1;
    ms.WriteBuffer(B,SizeOf(B));
    ms.SaveToFile('Video.avi');
  end;
  ms.Free;
end;

Осталось неразгаданным почему игра зависала при изменении длины шифрованной строки, игра просто валится и все, никаких ошибок не выдает, если запускать в OllyDbg то олька выдает '' is not a valid integer value. Но это в принципе уже не важно, то что мне нужно было изменить я изменил, и все нормально работает. Еще раз всем большое спасибо за помощь!

P.S. Код представленный Alegun, проверен, работает, расшифровывает весь файл целиком, но назад зашифровать не удается, в некоторых строках системная часть не вся, без системной части игра отказывается показывать диалог, не зависает, просто на его месте пусто.
Ответить с цитированием