The Gray Brotherhood Community

Содержание

Как пишутся PSW трояны
-----------------------
PSW это сокращение от password то есть пароль. PSW трой занимается тем что тащит интересующие нас данные от известной или известных(уж сколько автор алгоритмов от разных программ туда впихнул) программ, а это как обычно IM клиенты, mail клиенты, кеш браузеров ну итд. Примеры таких троев это всем известный Pinch, не менее известный Xinch, и прочие заточки троев под отдельные программы. Очень много PSW троев сейчас нацелено на кражу паролей от разных online игр(причём преимущественно китайских).Ну да статья не об этом и заострять внимание на том китайские там online игры или нет не буду, а расскажу о методах кражи данных.

Методы
--------

Методы кражи нужных данных, будь то логин, пароль или ещё чтото зависят от исследуемой программы. Программы которые дают сохранять пароли и при следующем перезапуске программы пароль не теряется где то его хранят. Таких программ очень много, примеры тому QIP,ICQ,Miranda,PSI,TotalCommander итд. Все эти программы хранят данные а каких то принадлижащих им файлах конфигурации, минибд, реестре итд, но в основном данные эти, программы хранят в файлах конфигурации.Например те программы которые хранят данных в файлах конфигурации должны как то защитить их и как то зашифровать(а некоторые и вовсе не шифруют PSI например), но весь смак в том что алгоритм шифрования обратимый, ведь программе же как то нужно будет потом восстановить UIN из конфига и показать вам его в опциях или например email адрес. Так вот один из методов заключается в нахождении и расшифровке алгоритма которым шифрует программа те или иные данные, а затем тупо их расшифровать и куда то отправить, а можно и не расшифровывать и слать прямо зашифрованными и расшифровывать самому.

Другой метод и не менее популярный это утягивание данных прямиком из памяти. Алгоритмы некоторых программ лень изучать и ведь если программа в открытом виде в памяти хранит нужные нам данные можно их оттуда скомуниздить Тот же самый QIP хранит данные прямо в памяти в открытом виде, mail.ru agent тоже, так что остаётся только сдампить процесс в файл и выдрать оттуда интересующие нас данные,а затем отправить.

Третий и тоже не менее популярный метод который используется для кражи данных это перехват трафика. В некоторых программах алгоритмы просто огромные и не хочется их изучать да и в памяти ничего у них нет интересного, но например те же клиенты для online игр не брезгуют посылкой GET или POST запросов на сервак с логином и пассом для авторизации там, причёи логин и пасс почти всегда идут в открытом виде. Так что же мешает поставить хуки на InternetConnectA/W HttpOpenRequestA/W HttpSendRequestA/W анализировать и писать в файл нужные нам данные а потом отправлять. Конечно программа может авторизироваться на сервере не по HTTP и тут уже нужно снифать весь траф и анализировать его(дабо это тоже не так сложно, намного сложнее анализировать), а затем уже по каким то признакам например выдирать нужные нам данные. Ну например логин идёт в открытом виде через 2 байта после MMMM:VB то мы спокойно можем на этом сакцентировать своё внимание и записывать нужное нам в файл.

Реверс
-------

Про кражу из памяти и про хуки я писать не буду так как про это много написано и про сплайсинг и про патчинг IAT и про то как сдампить процесс так что на этом внимание не хочется заострять. Я разберу конкретный пример для троев первого метода, то есть те которые используют дешифровку по обратимому алгоритму который прописан в программе. А реверсить буду я ни чтото,а саму Miranda IM.

Итак первым делом я скачал с сайта миранды последнюю версию. Восстанавливать будем пасс для UIN так что ставим миранду так:

Поставили и теперь начнём разбираться. Итак как же мы будем искать алгоритм. Первое что пришо мне на ум это при вписывании в поля UIN и PASS перехватить их и трассировать до самого алгоритма шифровки так как ведь пасс и уин запишутся в dat файл как раз зашифрованными. Начал я с пасса а UIN оставил на потом, так как без восстановления пасса UIN нахрен не нужен :)

Открываем миранду в OllyDbg. У меня стоит Shadow OllyDbg так что можете не париться а найти его и поставить себе дабо различий мало, просто стоит куча плагинов и олька пропатчена уже :) Если олька код не проанализировала автоматом то сделайте так:

Вообще я сначала не заглянул в импорт и хотел уже было начать разбираться с Condition BPX на TranslateMessage которое бы я поставил на нажатие клавиши либо левой кнопки мыши но потом я вспомнил про импорт и заглянул туда ;) Жмём Ctrl+N и видим там интересные для нас функции:

Эти функции получать данные из полей ввода(как они юзаются загляни в MSDN) и могут так же получить UIN и PASS при вводе в миранде. Обычно текст из полей ввода класса edit можно получить через GetDlgItemTextA/W или GetWindowTextA/W и в импорте миранды мне встретились как раз:

Мда какие из них получают текст хз надо ставить бряки на все и смотреть. Не буду вас мучать скажу сразу что текст из полей ввода UIN и PASS здесь получает GetDlgItemTextA, ставим на неё бряк:

Запускаем миранду нажатием F9. Вводим имя как будет называться профиль. Ага бряк сработал, но нам и так ясно что имя профиля не изменится и ловить нам нечего так что ещё раз F9. Появились поля для вообще UIN и PASS, заполняем поля. UIN я ввёл 57732109, а пасс взял самый сложный то бишь qwerty ;)

Нажимаем OK и опять программа прерывается на нашем бряке. Смотрим в стек:

Ага буфер куда запишутся данные располагается по адресу в памяти 0012F618 значит топаем туда.

После того как перешли смотрим в dump по данному адресу и видим что там херня какая то, но дак ведь она там и должна быть ведь функция то ещё не выполнилась :) Длеаем Execute till return, это выполнит код до первого RET который нам пстретится.

Теперь выполение прервалось так как дошли до RET, а по адресу 0012F618 расположился наш UIN

Отлично, но ведь нам нужен не UIN а PASS так что продолжаем выполнение программы нажав F9.Такс теперь опять произошёл останов, смотрим в стек и переходим в dump который указывает куда будет скопирован PASS. Сделать надо тоже самое как я и описал выше. Ctrl+G на на адрес и затем Ctrl+F9. Такс теперь у нас по адресу на который указывал Buffer лежит пароль вместо UIN. Оооооочень интересненько :)

Теперь нам надо оттрассировать программу до того места где начнёт мутировать пароль. Нажимаем F8 и попадаем в главный модуль.

Мдааа трейсить я чувствую предстоит долго. Вот какую закономерность я вывел, бряки на память я ставить не стал потому как начал с них и запутывался раза 4 подряд так что отбросил этот метод. Я заметил такую закономерность что после того как производятся какие то манипуляции со строкой а будь то наш UIN или PASS то они сразу записываются в dat файл который относится к нашему профилю. Этот файл я смотрел в TotalCommander через стандартный Lister и вот что там есть:

То есть UIN после каких то там преобразований записался в файл и так же будет с пассом. Я не долго думаю шёл по программе нащимая F8 и после прохождения каждого CALL смотрел не записалось ли чтото у меня в мой dat файл.Хочу заметить что есть такая удобная фишка, если вы стоите на вызове функции то бишь CALL и не знаете заходить в него или нажать F8 то просто нажмите Enter и окажетесть внутри функции. Для того чтобы вернуться нужно нажать знак минуса(-) и попадёте обратно, чтобы зайти в вызов CALL надимайте F7, ну это я вам так на всякий случай :) Так я дошёл до алгоритма и потратил на это около часа. Распологается он в этом вызове:

Переходим внутрь по F7

И в следующий же CALL опять заходим по F7

Расскажу что там написано. MOV EAX,DWORD PTR SS:[ESP+8] <--- В EAX пишется значение которое раполагается по адресу в стеке ESP+8 то есть смотрим значение регистра ESP и прибавляем к нему 8, там находится единица

После в EAX окажется 1

Теперь следующая команда
MOV ECX,DWORD PTR SS:[ESP+4] <--- В ECX поместится значение на которое сейчас указывает ESP+4, то есть как раньше только +4 и там находится пароль qwerty(он такой у меня)
Дальше идёт команда NEG,смотрю в справочник, цитирую:

(NEGate operand)
Изменить знак операнда
Схема команды:  neg источник 
Назначение: изменение знака (получение двоичного дополнения) источника.
Алгоритм работы:
выполнить вычитание (0 - источник) и поместить результат на место источника;
если источник=0, то его значение не меняется.
Применение:
Команда используется для формирования двоичного дополнения операнда в памяти или регистре. Операция двоичного дополнения предполагает инвертирование всех разрядов операнда с последующим сложением операнда с двоичной единицей. Если операнд отрицательный, то операция neg над ним означает получение его модуля.

То есть с EAX после команды NEG станет равен EAX = 0 - EAX. Запустим калькулятор и проверим что будет в EAX.

То есть должно быть FFFFFFFF, смотрим:

Такс дальше идёт команда SBB EAX,EAX. Смотрим что говорит справочник:

(SuBtract with Borrow)
Вычитание с заемом
Схема команды:  sbb операнд_1,операнд_2 
Назначение: целочисленное вычитание с учетом результата предыдущего вычитания командами sbb и sub (по состоянию флага переноса cf).
Алгоритм работы:
выполнить сложение операнд_2=операнд_2+(cf);
выполнить вычитание операнд_1=операнд_1-операнд_2;
Применение:
Команда sbb используется для выполнения вычитания старших частей значений многобайтных операндов с учетом возможного предыдущего заема при вычитании младших частей значений этих операндов.

Помечу для наглядности вам так SBB EAX,EAX2
Значит в EAX будет результат выполнения команды EAX2 = EAX + (CF), а в EAX = EAX - EAX2
СF - это влаг переноса и сейчас он активен, считаем с помощью calc что получится:
EAX2 = FFFFFFFF + 1
EAX2 = 00000000

EAX = FFFFFFFF - 0
EAX = FFFFFFFF
Значит EAX не изменится и так и останется равным FFFFFFFF
Дальше идёт команда AND EAX,0A <--- Это элементарно так что обьяснять не буду
Далее ADD EAX,-5 <--- сложение EAX+(-5), так как в EAX сейчас только 0000000A а это равно 10 то 10-5 равно 5

Идём дальше и видим команду MOV DL,BYTE PTR DS:[ECX] <--- Скопирует один байт в регистр DL из памяти, адрес которой хранится в ECX. Смотрим в DUMP и видим там наш пасс qwerty

TEST DL,DL <--- Здесь идёт сравнение на 0 то есть на конец строки и если строка кончилась то просто будет переход на который указывает JE,а если нет то идём дальше по коду
ADD DL,AL <--- Складываем DL+AL то есть в DL сейчас 71,а точнее первый символ нашего пасса равный "q", а в AL как и было 5, происходит сложение то есть будет 76 и следующей командой
MOV BYTE PTR DS:[ECX],DL <--- Из регистра DL запишется значение 76 в память адрес котрой хранится в регистре ECX, но так как ECX не менялся за это время то будет перезатираться в памяти наш пароль qwerty

Как видно пасс и вправду начал мутировать и это продолжится с каждым символом до тех пор пока не будет достигнут конец строки

Теперь флаг Z равен 1 и произойдёт переход на RET
Так что же это получается.Если каждый байт наешего пароля шифруется по enc_pass[i] = pass[i]+5, то чтобы расшифровать нужно просто взять и вычесть из каждого байта зашифрованного пасса 5 то есть pass[i]=enc_pass[i]-5, так чтоли??? Хммм лезу в dat файл своего профиля и ищу там свой закодированный пасс "v|jwy~". Ага нашёл. Решил я написать на PHP как бы декодер, вот код.

И когда я выполнил его и увидел свой пароль qwerty я немного прихуел. Вот это защита...В профиле пароль хранится прямиком за словом Password так что ищите там если хотите потестить

Что ж теперь раз декодер поароля есть то и надо бы восстановит UIN ведь он тоже хранится в каком то алгоритме. Хммм закрывем ольку, удаляем dat файл и опять открываем миранду в OllyDbg. Ставим бряк на GetDlgItemTextA и запускаем по F9 программу.

Делая то же самое что и раньше после первого бряка я запустил по F9 программу опять и на получении UIN сработал бряк. Тем же макаром я трейсил программу до тех пор пока после какого то CALL в dat файле не оказалась запись UIN и рядом какие то 3 символа. Я опять перезапустил миранду в отлки предварительно удалив dat файл и нашёл всё таки то место после часа трейсинга. Функция memmove копирует из одного места в другое 4 байта и эти 4 байта и записываются в профиль. Ещё около часа я трейсил программу, а может даже и больше но потом мне это надоело так как алгоритм я так и не нарыл. Я подумал раз пишется UIN в 3 символа то значит это он же в HEX. Делаю новый профиль с UIN 123456789 и PASS qwerty. Открываю его в WinHex:

Затем я запустил калькулятор и вбил там 123456789, а потом посмотрел сколько это в HEX и это 75BCD15 я посмотрел на то что в профиле и подумал ууу ничего общего и уже хотел было закрыть да чтото остановило :) Сравните 2 числа

075BCD15 <---> 15CD5B07

UIN который лежит в dat файле надо перевернуть.Так значит алгоритм ещё проще чем с паролем :)

Теперь чтобы накатать троя надо как то прасить файл и по каким то признакам определять UIN после слова UIN идёт или нет, так же и с пассом, ведь в чистом dat файле то просто там сразу виден UIN и сразу виднеется Password а вот когда начнутся добавляться контакты, ставитсься плагины то слов Password и слов UIN будет оооочень много а файлики иногда доходят до 50 метров. Как пропарсить я так и не придумал так что тот кто придумает отпишитесь :)

--------------------
Заключение
--------------------

Вот в принципе и всё что я хотел рассказать про PSW трои и про то сколько трудов стот написать такого гиганта как тот же Pinch. Стоит ли он тех денег за которые его продавали? Я думаю обсалютно нет и сразу видно что автор продавал не ради наживы. Почти 6 часов у меня ушло на изучение всего что я вам тут описал. Много это или мало это не важно, так как я добился того чего хотел и попытался донести это до вас.

Article by: (с) def1v0r, 2008, specially for TGBR E-ZinoS #2

Содержание