Из модуля экспортируется только одна процедура: XORPass(UIN, CryptIV:longint; var Pass: array of byte);
Входные параметры: UIN - исходный UIN типа longint. CryptIV - зачение параметра CryptIV типа longint. Pass - зашифрованный пароль побайтно, начиная с младшего адреса. Тип - открытый массив байт, нижний индекс = 0, верхний, вообще говоря может быть любой больше или равный количеству байт в зашифрованном пароле минус один, но делать его больше 15 смысла не имеет. Параметр передаётся по ссылке, так как в процедуре он изменяется.
Пример вызова процедуры для нашего случая:
Var P: array of byte;
Begin
// Наш зашифрованный пароль 00 e8 6d 7c 68 34 c4 7f
// имеет длину восемь байт, поэтому SetLength(P, 8);
//Заносим байты зашифрованного пароля, начиная с младшего адреса
P[0]:=$00;
P[1]:=$e8;
P[2]:=$6d;
P[3]:=$7c;
P[4]:=$68;
P[5]:=$34;
P[6]:=$c4;
P[0]:=$7f;
//Сейчас P равно 0, 232, 109, 124, 104, 52, 196, 127
XORPass(891636, 16, P);
// Теперь ключ наложен и P равно 6, 0, 88, 97, 107, 101, 112, 0
Это уже почти наш расшифрованный пароль. Первое число - длина пароля, учитывая последний нулевой байт, который знаменует собой конец строки. Сама аська писалась на С, поэтому и формат строк соответствующий (так называемые Zero-Terminated строки). Второе - просто разделитель - нулевой байт. И, наконец, шесть оставшихся байт - открытый пароль и нулевой байт (конец строки). Осталось перевести эти числа в ASCII-символы.
#88 = "X", #97 = "a", #107 = "k", #101 = "e", #112 = "r". Наш пароль . Всё.
Остаётся дать ещё некоторые комментарии. Во-первых, в DAT-файле может встретиться несколько таких пар CryptIV - Password, которые, вообще говоря, могут давать разные пароли. Скорее всего, более поздний пароль находится ближе к хвосту файла, однако это не факт, и придётся отлавливать все такие пары, чтоб найти правильный пароль (если он вообще есть, так как можно же и не сохранять его в DAT-файле). Зачастую находится две-три пары, дающие один и тот же пароль.
Во-вторых, не известно точно с каким смещением после CryptIV нужно искать строку Password. Так как это смещение зависит, как мы увидели от длины прописанной почты (а возможно, и их количества). Я не могу дать точных рекомендаций, как лучше искать пары. Сам я в своей программе пошёл наиболее простым путём. Я ищу сначала CryptIV, если он есть, пытаюсь в следующих за ним 512 байтах найти подстроку Password. Надо сказать, это не самая удачная реализация, и бывают случаи, когда программа не находит пароль, хотя он есть.
В третьих, возможно, стоит искать не строку , а <99BCryptIV>, а то и вообще байты 39 39 42 43 72 79 70 74 49 56 00 68. Это <99BCryptIV> с последующими нулевым символом и буквой . У меня реализован последний вариант. Теоретически, это должно отсечь некоторые ложные срабатывания и слегка уменьшить время поиска.
В начале статьи я обещал, что мы будем знать ещё и Contact List. Раз ты дочитал до этого места, теперь будет совсем просто. На самом деле, мы получим даже больше, чем список контактов. У нас будут почти все UINы, которых клиент хоть раз добавлял к себе в список, просившие его авторизации или от которых пришло оповещение о добавлении (You Were Added). <Почти> - потому, что я этого точно не проверял, но думаю, что это так. И, разумеется, это всё может быть справедливо, только если не установлена опция в настройках аськи.
Формат хранения чужих уинов в DAT-файле очень прост. Это 9-тибайтовые поля следующего формата.
55h 49h 4eh 00h 69h Байт a Байт b Байт c Байт d
Как описывалось выше, уин вычисляется следующим образом:
UIN=( БайтA + БайтB * 256 + БайтC * 65536 + БайтD * 16777216 )
Выловив все записи такого вида, мы получим полный список уинов, успевших засветиться в хистори клиента.
Кроме того, зная этот формат, можно легко подделать свою или чужую хистори. Для этого достаточно лишь заменить один уин на другой. Можно устроить диалог с самим собой, запустив две аськи одновременно, а затем заменить у себя в DAT-файле свой второй уин, например, на приятельский. wink Вот пример: допустим, мы хотим заменить уин 123456 на 654321.
Переводим номера в шестнадцатеричный формат:
123456[10] =1E240[16]
654321[10]= 9FBF1[16]
Так как уины хранятся в формате DWORD (4 байта), то дополняем слева нулями чтоб получить восьмизначное число: 0001E240 и 0009FBF1.
Разбиваем на пары: 00 01 E2 40 и 00 09 FB F1. В соответствии с обратным порядком хранения слов, переставляем байты: 40 E2 01 00 и F1 FB 09 00.
Теперь осталось найти все строки
55 49 4E 00 69 40 E2 01 00
и заменить их на
55 49 4E 00 69 F1 FB 09 00.
исходник