IPB

Добро пожаловать, гость ( Вход | Регистрация )

 
Reply to this topicStart new topic
> Meet The Robinsons [.HOG], Контрольная сумма / хэш
-=CHE@TER=-
Apr 1 2011, 18:50
Сообщение #1


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Переношу все междусобойчики из ЛС сюда. У меня уже места для писем нет, запарился себе размер яшика увеличивать, да и неудобно в ЛС.
Товарищ Siberian GRemlin, пожалуйста, в будущем создавай тему, а не пиши мне.
Я всегда смотрю файлы которые кто-либо из нас выкладывает, так что если ты или кто-то другой что-то спросил, а я не ответил, это значит только что я ничего не могу сказать по этому формату. Мне нечего добавить и т.д.
Надеюсь на понимание и что мне никто в будущем не будет писать в ЛС, а создавать отдельную тему...

Но вернёмся к игре. Siberian GRemlin жаждет узнать алгоритм подсчёта контрольной суммы.
Нужно это ему, видимо, для перепаковки архива и создания русификатора.
Далее идёт описание формата (я его немного дополнил, кстати), так что я сразу задам свои вопросы ему:
1) Зачем тебе сдалась эта контрольная сумма? Я поменял её у пары файлов из "Data\say.hog", но игра на это никак не отреагировала. Т.е. никакой ошибки не было.
2) noDVD игры упакован UPX'ом со стёртой сигнатурой, но я его распаковал. Получилось из 8 Мб целых 28. Если кто-нибудь ещё будет смотреть игру - могу выложить его, чтобы не распаковывать. Так вот под отладчиком я нашёл место где читается, к примеру, тот же "Data\say.hog" (он целиком в память засовывается), но проблема в том, что, видимо, из-за криво снятой защиты я не могу поставить бряк на обращение к этой памяти. В частности к ячейке с контрольной суммой. При попытке это сделать Олька говорит что мой бряк инвалид и она поэтому она его убивает. 28 Мб - это не фигушки воробьям показывать и найти там код проверки вручную очень сложно.
Так что вернёмся к вопросу №1: зачем нужна контрольная сумма, если игра её игнорирует? Если не игнорирует, скажи где и что поменять, чтобы игра выбросила сообщение-ошибку. Тогда уже можно будет идти-отлаживать от него вверх и найти место подсчёта контрольной суммы.

Формат .HOG файлов такой:
DWORD - singature/version // сигнатура или версия - игра всегда проверяет, чтобы было равно $20001 (см. код на .5DA88C)
DWORD - TOC offs // смещение до таблицы содержимого (TOC)
DWORD - zero // всегда ноль, вроде бы
DWORD - hash/crc(1) // контрольная сумма для заголовка (???)
DWORD - files count // количество файлов в архиве
DWORD - unknown // неизвестно, какой-то размер похоже, но я не понял что это (???)
DWORD - hash/crc(2) // второе непонятное число (???)

Формат TOC:
DWORD - name // смещение до начала ACSIIZ имени файла - это то, что ты принял за ID
DWORD - offs // смещение до данных файла
DWORD - size // размер файла
DWORD - hash/crc(3) // это самое, что непонятно как считается (???)

Далее идут друг за другом ASCIIZ имена.

С именами, кстати, всё просто - если ты делаешь FileMapping() или прочитал весь файл в память, то не нужно читать по одному байту, пока не 0, можно проще:

PTR_START, FileName: PChar;
...
FileName:=PTR_START; // присваиваем указатель на начало архива
Inc(FileName, TOC[I].name); // сдвигаем его до имени файла
WriteLn(FileName); // получили имя текущего, I-того, файла

Ссылки на игру:
_ttp://ifolder.ru/22688282
_ttp://ifolder.ru/22687944
_ttp://ifolder.ru/22688054
_ttp://ifolder.ru/22687760
_ttp://ifolder.ru/22688384


Код распаковщика за авторством Siberian GRemlin'а:
показать
CODE
Program unpk;
{$APPTYPE CONSOLE}
Uses Windows, SysUtils, Classes;
{
[!] SecuROM Detected - Version 07.31.0011
[CompilerDetect] -> Visual C++ 7.1 (Visual Studio 2003)
}
type
  Tmass = record
    ID, CRC,
    FileOffset,
    FileSize: dword;
    FileName: String;
  end;

Procedure Extract(name:string);
var
  Mstr,OutStr: TFileStream;
  i, Offset{, Unknown}: Integer;
  FilesMass: array of TMass;
//  path,p: string;
  b:byte;
begin
  if FileExists(name) then begin
    Mstr:=TFileStream.Create(name, fmOpenRead);
    Mstr.Position:=$4;
    Mstr.ReadBuffer(Offset, 4); //начало таблицы или размер заголовка
    Mstr.Position:=$10;
    Mstr.ReadBuffer(i, 4); //кол-во файлов
    SetLength(FilesMass,i);

    Mstr.Position:=Offset;

    for i:=0 to Length(FilesMass)-1 do begin
      Mstr.ReadBuffer(FilesMass[i].ID, 4);
      Mstr.ReadBuffer(FilesMass[i].FileOffset, 4);
      Mstr.ReadBuffer(FilesMass[i].FileSize, 4);
      Mstr.ReadBuffer(FilesMass[i].CRC, 4);
    end;
    for i:=0 to Length(FilesMass)-1 do begin
      FilesMass[i].FileName:='';
      Repeat
        Mstr.ReadBuffer(B,1);
        if B<>0 then FilesMass[i].FileName:=FilesMass[i].FileName+chr(B);
      Until B=0;
      WriteLn(FilesMass[i].FileName,' : CRC = ',IntToHex(FilesMass[i].CRC,8));
    end;
    for i:=0 to Length(FilesMass)-1 do begin
      Mstr.Position:= FilesMass[i].FileOffset;
      OutStr:=TFileStream.Create(FilesMass[i].FileName, fmCreate);
      OutStr.CopyFrom(Mstr,FilesMass[i].FileSize);
      OutStr.Free;
    end;
    Mstr.Free;
  end;
  writeln('Completed!');
end;

Begin
  If ParamCount = 1 Then Extract(ParamStr(1));
End.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Apr 1 2011, 19:30
Сообщение #2


Advanced Member
***

Группа: CTPAX-X
Сообщений: 537
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 221 раз(а)



При несовпадении контрольной суммы игра не выдаёт сообщений, а просто игнорирует этот файл, т.е. при перепаковке архива со звуками игра становится немой.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Apr 1 2011, 19:45
Сообщение #3


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Я подозревал, что что-то такое примерно и происходит.
Хм, как же тогда к вычислению суммы-то подобраться...
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Sep 10 2011, 02:59
Сообщение #4


Advanced Member
***

Группа: CTPAX-X
Сообщений: 537
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 221 раз(а)



Один человек поделился алгоритмом
CODE
Byte stream divided into blocks (3 dwords == 12 bytes):

[ x x x x x x x x x x x x ] ... [ x x x x x 0 0 0 0 0 0 0 ]
   \   /   \   /   \   /          |                     |
     1       2       3            |                     |
         full block               last block filled with trailing zeros


#define f_r(a, b, c, n)  (a)-=(b)+(c); (a)^=(b)>>(n)
#define f_l(a, b, c, n)  (a)-=(b)+(c); (a)^=(b)<<(n)

#define f_x(a, b, c, n1, n2, n3)   f_r(a,b,c,n1); \
                                   f_l(c,a,b,n2); \
                                   f_r(b,c,a,n3)

Инициализация {
  a=b=0x9E3779B9; c=0;
}

Каждый полный блок {
  a+=p[0];
  b+=p[1];
  c+=p[2];

  f_x(a, c, b, 13,  8, 13);
  f_x(a, c, b, 12, 16,  5);
  f_x(a, c, b,  3, 10, 15);
}

Последний блок [0..11] {
  memcpy(t, p, n);     // rep movsd / rep movsb

  a+=t[0];
  b+=t[1];
  c+=(t[2]<<8) + k;

  f_x(a, c, b, 13,  8, 13);
  f_x(a, c, b, 12, 16,  5);
  f_x(a, c, b,  3, 10, 15);

// ! c - our karma !
}

DWORD  a, b, c;         // just variables
DWORD  n;               // amount of bytes in the last block
DWORD  k;               // total amount of bytes in our stream
DWORD *p;               // pointer to a block of 3 dwords
DWORD  t[3] = {0,0,0};  // temporary array on stack


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0 -

 



Упрощённая версия Сейчас: 16th November 2024 - 03:58