Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Синтаксис
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 06.07.2017, 21:14
Shaft Shaft вне форума
Новичок
 
Регистрация: 15.05.2013
Сообщения: 74
Версия Delphi: 7/10.4
Репутация: 12
По умолчанию Нужна помощь с определением алгоритма шифрования

Всем привет! Нужно поправить в игре некоторый текст. Файл локализации чем то закодирован, если есть люди разбирающиеся в криптографии, помогите пожалуйста расшифровать.

Игра: Рандеву с незнакомкой 4, год выхода: 2002, написана на Delphi.

Пример закодированной строки: 040,/ ,<15. Ооибгт-ДЯааиувЮдЯь,э рнлэ* Ятъ-коиппжяслыиусоемлииснл.

Она же, раскодированная: Привет. Давай угадаю, я сплю, а ты - мой приятный утренний сон.

Также прикреплю весь файл локализации.

Интересно что слову привет соответствует Ооибгт, что за цифры до этого, не удалось выяснить.
Вложения
Тип файла: txt icon6@.txt (32.6 Кбайт, 2 просмотров)
Ответить с цитированием
  #2  
Старый 07.07.2017, 21:07
Shaft Shaft вне форума
Новичок
 
Регистрация: 15.05.2013
Сообщения: 74
Версия Delphi: 7/10.4
Репутация: 12
По умолчанию

Сегодня ковырял экзешник в DelphiDecompiler, он использует ComObj и OleServer, при этом в папках игры нет ни одного вордовского документа, возможно эта информация поможет, известно что разработчики данной игры любят для защиты поменять пару байт, например видео у них защищено заменой первого байта на произвольный.
Ответить с цитированием
  #3  
Старый 08.07.2017, 19:03
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

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

Это я понимаю, я имел ввиду что может этот как то через OLE загружается, так как в папке кроме этого файла только графика и аудио. Разработчики те еще "шифраторы", я уже сообщил как мощно они зашифровали видео, а этот файл локализации у них вообще в формате bmp, это я на txt сам поменял. Известно что длина строки одинаковая и зашифрованная и расшифрованная. Тут может быть вообще нет шифрования, может кодировка другая, или файл не текстовый а на подобии ворда что то. Третий день уже ковыряюсь, чем только не пытался открыть
Ответить с цитированием
  #5  
Старый 08.07.2017, 22:52
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,051
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

1. ComObj и OleServer совершенно не обязательно связаны с офисом. Они просто относяться к технологии COM. Через нее,в т.ч. используется DirectX. И проигрывание видео тоже через COM можно играть (кодеки).
2. Расширение файла никак не завязано на его содержимое, так что хоть горшком назови.
3. Если длинна строки до шифрования и после одинаковая, то, скорее всего, используется какое-то достаточно простое симетричное шифрование. Что можно попробовать. Если известна какая-то строка в шифрованном и расшифрованном виде, то можно попробовать проверить на простой XOR. Т.е. если поXORить строку с ее же зашифрованной версией, то, по идее, ты получишь пароль. Соответсвенно, этот пароль можно попробовать применить к другой строке и посмотреть, получается ли расшифровка. Однако, т.к. мы не знаем где начало зашифрованного блока, то, возможно, надо будет этот пароль "подвигать" по строке что бы найти правильное положение.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Shaft (11.07.2017)
  #6  
Старый 08.07.2017, 23:17
Shaft Shaft вне форума
Новичок
 
Регистрация: 15.05.2013
Сообщения: 74
Версия Delphi: 7/10.4
Репутация: 12
По умолчанию

Это вариант, завтра буду пробовать. Первая строка известна и шифрованная и расшифрованная, я пока не уверен но по моему результат шифрования зависит от длины строки. Известно что в первой строке слово Ооибгт это Привет, поиграл я сегодня в эту игру, там целая куча приветов а в шифрованном файле слово Ооибгт встречается только 2 раза, и в обоих случаях длина строки равна 63. Еще известно что если в шифрованном файле длину строки уменьшить или увеличить хотя бы на 1 символ, то игра зависает, а если менять буквы с сохранением длины строки, то неправильно расшифровывает, но не всю строку а только измененные буквы.
Ответить с цитированием
  #7  
Старый 09.07.2017, 19:13
Shaft Shaft вне форума
Новичок
 
Регистрация: 15.05.2013
Сообщения: 74
Версия Delphi: 7/10.4
Репутация: 12
По умолчанию

Расшифровать так и не удалось.
Что удалось выяснить:
-Результат шифрования зависит от длины строки.
-В левой части те цифры которые я ранее писал что неизвестны, судя по всему содержат какую то системную информацию, при их замене игра не зависает но и строку не расшифровывает, в интерфейсе игры на месте строки будет пустое место, даже если их скопировать от другой строки. В общем левая часть подходит только к определенной правой.
-Интересно что если в шифрованной строке все символы заменить на 0 то в игре будет выглядеть так "1201201201201201201201201201201201201201201201201 20120120120120" причем любая стока, можно весь файл заменить и все строки в игре будут такие. При этом не важно какой длины строка, вот это совсем не понятно как так.
Ответить с цитированием
  #8  
Старый 09.07.2017, 20:09
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Цитата:
Ооибгт это Привет
Цитата:
120120
О плюс 1 по алфавиту равно "П"
о плюс 2 по алфавиту равно "р"
и плюс 0 по алфавиту равно "и"
б плюс 1 по алфавиту равно "в"
г плюс 2 по алфавиту равно "е"
т плюс 0 по алфавиту равно "т"
То есть к первой букве строки прибавляется 1, ко второй - два, к третьей - 0 и далее по кругу. Не буквенные символы (пробелы, знаки препинания) - не знаю, может тоже так "шифруются". На границе алфавита большая "Я" превращается в "а", значит скорее всего там просто str[i] + x, без проверок по алфавиту и иных усложнений.
В начале строки скорее всего в каком-то виде закодирован "номер" строки (грубо говоря, где она используется в самой программе) и её длина.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 09.07.2017 в 20:19.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
Shaft (11.07.2017)
  #9  
Старый 11.07.2017, 06:52
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Вот релиз G-кодом по предложенному алгоритму, в Мемо1 загружен исходный текстовый файл, в Мемо2 расшифровка
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
 i,j,b: integer;
 s, s1: string;
begin
 Memo2.Clear;

 for i := 0 to Memo1.Lines.Count do
  begin
   s1:= '';
   s:= Memo1.Lines[i];
   b:= 1;
   if (Length(s) > 0) then
    begin
     if (s[1] = ')') or (s[4] = ',') then
       for j := 1 to Length(s) do
        begin
         s1:= s1 + chr(byte(s[j])+b);
         inc(b);
         if b > 2 then b:= 0;
        end;

     case s[4] of

      '+':
       for j := 3 to Length(s) do
        begin
         s1:= s1 + chr(byte(s[j])+b);
         inc(b);
         if b > 3 then b:= 1;
        end;

      '*':
       begin
        b:= 2;
        for j := 3 to Length(s) do
         begin
          s1:= s1 + chr(byte(s[j])+b);
          inc(b);
          if b > 4 then b:= 2;
         end;
       end;
     end;{case}
    end;
  Memo2.Lines.Add(s1);
 end;
end;
для простоты немного подрезается начало некоторых строк
Ответить с цитированием
Этот пользователь сказал Спасибо Alegun за это полезное сообщение:
Shaft (11.07.2017)
  #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, проверен, работает, расшифровывает весь файл целиком, но назад зашифровать не удается, в некоторых строках системная часть не вся, без системной части игра отказывается показывать диалог, не зависает, просто на его месте пусто.

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

Мой код допиленый по примеру Alegun, расшифровывает весь файл целиком вместе с системной частью.
Код:
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:='';
  if Length(s)<4 then Exit;
  if (s[1] = ')') or (s[4] = ',') then Result:=Encrypt_(s,Key1);
  if s[4]='+' then Result:=Encrypt_(s,Key2);
  if s[4]='*' then Result:=Encrypt_(s,Key3);
end;

procedure StartDecode;
var
  sl:TStringList;
  I:Integer;
begin
  sl:=TStringList.Create;
  sl.LoadFromFile('icon6@.bmp');
  for I:=0 to sl.Count-1 do
    mmo1.Lines.Add(Encrypt(sl[i]));
  sl.Free;
end;
Чтобы обратно зашифровать нужно в функции Encrypt_ сложение заменить на вычитание.
P.S. Пробовал Рандеву с незнакомкой 9, тоже работает, судя по всему во всех частях один и тот же ключ и алгоритм.

Последний раз редактировалось Shaft, 11.07.2017 в 15:01.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 23:46.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter