Сразу напишу, что чтиво читается очень тяжело – это черновой материал(а редактировать у меня этот пергамент нет желания), без реверса наверно проблематично будет понять, о чем я ниже написал, но я в конце попытался подвести общий итог, хз понятно будет или нет, короче кому нужно будет, думаю, без проблем разберется..
Вообще тут было два варианта создавать или не создавать тему(хотя все указывало на то чтобы не создавать судя по первой части), но я решил создать.. (сразу предвижу обращения по сабжу, просьба писать сразу ТЗ и цены – если не отвечу, значит что-то не устраивает, с теми кто пишет - стукни и оставляет свою аську, я вообще не общаюсь!)
И сразу большая просьба взглянуть на НАЗВАНИЕ РАЗДЕЛА, и не писать бредовых постов типа «че таг геморно» или «читал было интересно, но ничего не понял» или «что надо учить, только чтоб как можно меньше читать, а то лень читать много книг по ассемблеру и т.п.»
Если я пишу что инфа для нубов, то предполагается что у читающего есть понимание как юзать основной инструмент реверсера IDA, Ollydbg итд. и как минимум знания нескольких языков программирования ASM, C++, Delphi, Python, PHP, Web итд.
Кто-то может сказать этого слишком много для подобного сабжа - нет, если учитывать то, что тупо не убивать время на общение в аськах объясняя школоте элементарные вещи, которые гугляцца за секунду – лучше потратьте это время на изучение нового языка программирования, допустим: Python – 3 дня, ASM – 1 месяц, C++ - 1 месяц итд. (это минимальные сроки, все естественно зависит от скила)
Практика
Кто сказал, что пинчег мертв? %)))
И так создаем один билд пинча, настраиваем профиль AVZ(все выключаем и выберем папку где находится билд пинча, назовем профиль к примеру avz_pinch.prf(ну или avz.prf)), ибо вполне возможно, что придется делать перезапуск несколько раз
Жмем кнопку «Пуск»
В выхлопе видим такую сигну(может быть другая сигна, все зависит от версии пинча)
Ну что ж, имя сигны мы знаем, теперь поищем в какой базе находится эта сигна(это сузит круг поиска детекта до нужного)
Заходим в директорию с базами(X:\Antivirus\AVZ\avz4\Base\) и смотрим на имена баз и видим много mainXXX.avz(предположим, что main – это то, что нам нужно, если нет, то будем искать signfXXX.avz), далее ищем строки содержащие main в avz_unpacked.exe
В ИДЕ(IDA Pro Advanced – здесь всегда только этот инструмент юзается в качестве основного инструмента для реверса) юзаем поиск для строк
(Alt+T) и в строку поиска вбиваем main.*\.avz и отмечаем галочкой Regular expression и Find all occurences и жмем OK
После того как ИДА закончит поиск, появится окно с результатами поиска - кликаем двойным щелчком по первому найденному и мы должны попасть туда, где все только начинается %)))
Теперь нужно установить сигнатуры для Delphi 7, это максимально упростит реверс так как мы будем видеть где стандартные функции/код Delphi, а где реально код который нам нужен (я вот не помню по дефолту какие сигнатуры для Delphi есть в ИДЕ(кажется Delphi 5, ну на крайний случай можно и их установить), ну а для семерки можно тупо нагуглить)
(Shift+F5) и далее Apply new signature... и выбираем из списка..
чет не охота мне про этот RTFM(как ИДУ юзать) писать, поэтому далее все урезано будет
да и вообще я вначале описал подробно, как искать нужные куски кода, но получилось нудно, много и убого, поэтому решил, что просто куски кода если запостить, будет куда более наглядно и понятнее, да и найти подобный код в других версиях я думаю, не составит труда
Нас интересует конкретно этот код:
Здесь код намерено взят из версии 4.3, так как в более поздней версии код/адреса будут отличаться, что сделает более качественно понимание самой сути реверса в его практическом применении - ИМХО
Заходим в 004D5450(InitMainBaseAVZ) (так как по коду видно, что до InitMainBaseAVZ LStrCat соединяет строки(путь), а после InitMainBaseAVZ идет проверка на положительный результат)
Зайдя в 004D5450(InitMainBaseAVZ) мы увидим примерно такой код:
InitMainBaseAVZ, LoadBaseAVZ и UnpackAVZ(это я их так сам назвал для наглядности) естественно там не будет, но нас интересует System:
Object:
Object(void) и то что она возвращает
Дело в том, что Delphi юзает TObject всегда там, где все самое интересное, так как это база всего ООП Delphi
Запускаем AVZ в олечке(OLLYDBG – другой альтернативы для win32 нет, и тут без вариантов) и ставим бряк на адресе
004D54D8 89 45 F4 mov [ebp+var_C], eax
Еще и олечку нужно заставить показывать Delphi-код, для этого сохраняем(создаем в ИДЕ) avz.map и потом импортируем его в олю при помощи(для примера) плагина GODUP меню Map Loader(где скачать?, я уже в прошлые разы постил ссылки)
И жмем кнопку «Пуск» в AVZ
После того как остановимся в оле на бряке переходим на адрес(в окне регистров на выбранном регистре eax ПКМ->Follow in Dump) что в регистре eax(у меня 00B6231C) в окно дата и там переключаемся в окне CPU Dump ПКМ->Long->Address with ASCII dump на более удобный вид
Далее ПКМ->Backup->Create backup(это будет подсвечивать измененную память)
И трассируем по F8 и параллельно смотрим за окном дата и сразу после первого
004D54FD E8 FA B8 F4 FF call LoadBaseAVZ
Мы должны увидеть примерно такое:
Теперь на 00B62320 001BC908 ПКМ->Follow in Dump и переходим на адрес 001BC908
Там мы увидим загруженный код базы начинающийся с символов AVZ
Далее возвратимся назад(жмем клавишу минус на цифровой клаве)
И опять трассируем по F8. Сразу после:
004D5507 E8 10 F7 FF FF call UnpackAVZ
Опять изменится адрес
Переходим на 0020B010 и видим уже "распакованную" базу
Теперь нам надо проследить, куда он сложит инит данные, для этого ставим бряк на VirtualAlloc и жмем F9, ну а далее по накатанной трассируем до возвращения назад..
Но я делаю проще, так как Delphi юзает TObject то в регистре eax он передает указатель на него, а сталобыть сразу на в ходе в процедуру можно увидеть что из eax перемещается указатель в регистр ebх, и можно сразу в окне даты переходить поэтому адресу, бэкапить и трассировать наблюдая за появлением адреса, как только появится переходим на него и трассируем дальше до появления инициализированных данных с именем сигнатуры
Добавлено в [time]1290018917[/time]
Но можно сделать еще проще, просто проскролить немного ниже код и визуально увидеть вот такой код:
Поставить бряк на
004D59AD E8 AAFFF2FF CALL <System::__linkproc__ CopyRecord(void)>
И жмем F9
После срабатывания бряка, переходим на адрес(в окне регистров на выбранном регистре eax ПКМ->Follow in Dump) что в регистре eax(у меня 015B8008) в окно дата
И собственно сама "сигна" которую мы увидим:
А вот так выглядит наша структура("сигна") которую мы искали: (сам процесс поиска, в какой базе находится эта сигнатура я поскипал, но скажу лишь то, что находится она в main026.avz)
Нам осталось разобрать, что здесь зачем
Нам только пока известно для чего первое поле этой структуры, а именно указатель на строку с именем сигнатуры, которой мы видим в окне AVZ при детекте
Продолжим наши поиски.. если посмотреть на строку с сигной то можно заметить что там присутствуют символы >>>>>
Вот их мы и поищем в оле
Жмем Ctrl+G и вбиваем в появившемся окне адрес 401000
Жмем Ctrl+B и в поле ASCII вбиваем >>>>> и OK
После того как оля найдет эту строку жмем Ctrl+A(анализ кода) и видим такое
005BBB34 20 3E 3E 3E 3E 3E 20 00 ASCII " >>>>> ",0
Теперь ставим курсор на эту строку и жмем Ctrl+R и в появившемся окне выбираем
005BB5B2 PUSH <dword_5BBB34> ASCII " >>>>> "
И жмем Enter
Собственно мы в процедуре, которая создает/заполняет и сравнивает структуру
Удаляем все ранее поставленные бряки и ставим бряк не на 005BB18C, а на
005BB223 89 45 F0 mov [ebp+PTObject], eax
И повторяем все тоже самое что делали ранее, чтобы сразу видеть все важные для нас события
Начинаем трассировать по F8 и сразу после
005BB23A E8 41 AE F1 FF call CreateHash
Мы увидим в окне данных изменение – это собственно и есть та самая заполниная структура для детекта нашего пинча
Но мы на данный момент пропустим этот факт и двинемся дальше, чтобы понять, где это все сравнивается
Мы чуть далее после прыжка заходим в
005BB31D E8 7A 91 F1 FF call CompareHash
И видим следующий код
Подобный код очень часто генерирует компилятор Delphi, когда сравнивается 32bit`а с 64bit`ным размером файла
Посмотрим в Total Commander размер файла - он у нас 48057, что в шестнадцатеричном эквиваленте равно 0000BBB9
Также из кода видно, что сравниваются границы файла минимальной и максимальной, если попадаем в эти границы, то осуществляем следующее сравнение итд.
То есть следующие два поля нашей структуры означают минимальный и максимальный размер пинча
Добавлено в [time]1290018971[/time]
Осталось узнать, что это за такие эти оставшиеся 4 поля
Для этого мы переходим по адресу
005BB23A E8 41 AE F1 FF call CreateHash
И видим следующий код
Вот нас интересует после того как отработает CreateFileA мы попадаем на sub_4D618C
Вот мы туда заходим и видим код
Из этого кода видно, что высчитывается хэш из первых 2000 байт файла – это первое поле из оставшихся четырех полей нашей структуры и первый хеш, по которому и происходит детект
Далее по коду можно увидеть, что высчитывается хэш с КОНЦА ФАЙЛА по последним 2000 байтам – это второе поле из оставшихся четырех полей нашей структуры и второй хеш, по которому и происходит детект
Далее высчитывается хеш с 200 байт с 5000 позиции в файле – это третье поле из оставшихся четырех полей нашей структуры и третий хеш, по которому и происходит детект(если файл размером меньше 5000, то записывается просто 0)
Далее высчитывается хеш с 200 байт с 10000 позиции в файле – это четвертое поле из оставшихся четырех полей нашей структуры и четвертый хеш, по которому и происходит детект(если файл размером меньше 10000, то записывается просто 0)
Итог: Вот так просто без создания сигнатур происходит детект по хэшу
Теперь зная как нас детектят можно попытаться что-то сделать, чтобы нас не палили, попробуем заюзать метод изменение даты компиляции в файле описанный мной ранее и посмотрим что произойдет
Меняем дату у нашего пинча с помощью PETools и проверяем его еще раз AVZ, ба епт что мы видим %)))
Он нас задетектил и показал нам полный хэш
Ну, предположим, что вот такой измененный пинч попал на комп к нашей жертве, после чего этот зомбик может отправиться на сайт к "Зайчику", создать тему и запостить этот хеш, который они в следующей версии успешно добавят
(кстати, там у них много так вот создают темы, а аверы для них пишут скрипты по удалению живности у них с компов, ну и соответственно "обогащаются" сэмплами).
Так не пойдет естественно, нам надо как-то изменить пинч без напрягов и чтобы нас не палили – мы просто попробуем добавить один ноль в конец файла(ну к примеру, тем же WinHex), изменяя тем самым размер файла и соответственно уберем полностью детект - пробуем.. и действительно нас НЕ ОБНАРУЖИЛИ %)))
Ну это естественно до первого попадания(и такая "халява" закончится) к AVZ на сайтег, там они потом тупо расширят диапазон максимального и минимального размера файла и громко объявят всем и везде где только можно какие они нах умные и что они всех нах победилЕ %))) (ну это типа немного черного юмора)
Философия
Хмм.. а это уже становацца интересным; мы знаем что avz – это выкидыш поцелуйчека(KIS), остается только "как-то узнать", а не идентичный ли детект и у него %)))
Кстати на счет одинокого детекта, мну здесь когда-то давно видел топик - чел спрашивал как сделать чтобы не палился криптор, а потом выяснилось что палился сэмпл по иконке(кто-то из криптующих ап этом сообщил)
Так вот на 90% можно предположить(но не утверждать), что палится именно данным детектом по хэшу
Так как мы теперь знаем что если в конце файла в сэмпле код статичен, а у нас в конце обычно ресурсы лежат и иконки тоже, то один раз попав такой сэмпл к аверам.. ОНИ ЗАНЕСУТ ЕГО В БАЗЫ, и даже если мы изменим полностью код ЭТОГО ЖЕ КРИПТОРА, то конец файла, а именно там ресурсы и находятся чаще всего, то иконка и будут детектицца по хэшу..
А вот, нашел линк
http://xss.pro/index.php?topic=19024 - у судьбе закриптованых файлов
Так вот там в теме утверждалось что никуда сэмпл не отсылался кроме как на "наши хваленые сервисы", которые якобы не отсылают..(забавная ситуация неправда ли %))) даже если накрыть ДРУГИМ КРИПТОРОМ и заюзать туже иконку, то будет уже другой хэш и на это есть много причин!, начиная от той же разницы количества нулей в конце файла итд.. но тут даже не в этом смысл, так как там все равно было упоминание о том, что файл не юзался, а отправлялся чич-то для проверки на scan4you.biz (каг говорцца - делайте выводы господа сами)
Итог: рандомить надо все и в том числе даже ресурсы, чтобы нас вот так примитивно не детектили по хешу
P. S.
Добавил данный детект в OC
Также присвоил тулузе статус BETA, что позволяет иметь хоум пагу, а сталобыть принимать в личку багрепорты и сделать описание ее возможностей
http://demonteam.narod.ru/oc/oc.html
Вообще тут было два варианта создавать или не создавать тему(хотя все указывало на то чтобы не создавать судя по первой части), но я решил создать.. (сразу предвижу обращения по сабжу, просьба писать сразу ТЗ и цены – если не отвечу, значит что-то не устраивает, с теми кто пишет - стукни и оставляет свою аську, я вообще не общаюсь!)
И сразу большая просьба взглянуть на НАЗВАНИЕ РАЗДЕЛА, и не писать бредовых постов типа «че таг геморно» или «читал было интересно, но ничего не понял» или «что надо учить, только чтоб как можно меньше читать, а то лень читать много книг по ассемблеру и т.п.»
Если я пишу что инфа для нубов, то предполагается что у читающего есть понимание как юзать основной инструмент реверсера IDA, Ollydbg итд. и как минимум знания нескольких языков программирования ASM, C++, Delphi, Python, PHP, Web итд.
Кто-то может сказать этого слишком много для подобного сабжа - нет, если учитывать то, что тупо не убивать время на общение в аськах объясняя школоте элементарные вещи, которые гугляцца за секунду – лучше потратьте это время на изучение нового языка программирования, допустим: Python – 3 дня, ASM – 1 месяц, C++ - 1 месяц итд. (это минимальные сроки, все естественно зависит от скила)
Практика
Кто сказал, что пинчег мертв? %)))
И так создаем один билд пинча, настраиваем профиль AVZ(все выключаем и выберем папку где находится билд пинча, назовем профиль к примеру avz_pinch.prf(ну или avz.prf)), ибо вполне возможно, что придется делать перезапуск несколько раз
От себя добавлю что если(к примеру) имя у AVZ avz_unpacked.exe то и профиль по умолчанию надо называть соответственно avz_unpacked.prfиз справки AVZ:
У AVZ предусмотрена поддержка профиля по умолчанию. Этот профиль автоматически загружается при старте AVZ и должен располагаться в рабочей папке AVZ под именем "avz.prf"
Жмем кнопку «Пуск»
В выхлопе видим такую сигну(может быть другая сигна, все зависит от версии пинча)
Код:
3. Сканирование дисков
X:\quarantine\pinch.trojan >>>>> подозрение на Trojan-PSW.Win32.LdPinch.beo
Заходим в директорию с базами(X:\Antivirus\AVZ\avz4\Base\) и смотрим на имена баз и видим много mainXXX.avz(предположим, что main – это то, что нам нужно, если нет, то будем искать signfXXX.avz), далее ищем строки содержащие main в avz_unpacked.exe
В ИДЕ(IDA Pro Advanced – здесь всегда только этот инструмент юзается в качестве основного инструмента для реверса) юзаем поиск для строк
(Alt+T) и в строку поиска вбиваем main.*\.avz и отмечаем галочкой Regular expression и Find all occurences и жмем OK
После того как ИДА закончит поиск, появится окно с результатами поиска - кликаем двойным щелчком по первому найденному и мы должны попасть туда, где все только начинается %)))
Теперь нужно установить сигнатуры для Delphi 7, это максимально упростит реверс так как мы будем видеть где стандартные функции/код Delphi, а где реально код который нам нужен (я вот не помню по дефолту какие сигнатуры для Delphi есть в ИДЕ(кажется Delphi 5, ну на крайний случай можно и их установить), ну а для семерки можно тупо нагуглить)
(Shift+F5) и далее Apply new signature... и выбираем из списка..
чет не охота мне про этот RTFM(как ИДУ юзать) писать, поэтому далее все урезано будет
да и вообще я вначале описал подробно, как искать нужные куски кода, но получилось нудно, много и убого, поэтому решил, что просто куски кода если запостить, будет куда более наглядно и понятнее, да и найти подобный код в других версиях я думаю, не составит труда
Нас интересует конкретно этот код:
Код:
CODE:004D5292 8D 85 A4 FE FF FF lea eax, [ebp+var_15C]
CODE:004D5298 BA 1C 54 4D 00 mov edx, offset szMain_avz ; "main*.avz"
CODE:004D529D E8 62 FB F2 FF call System::__linkproc__ LStrCat(void)
CODE:004D52A2 8B 85 A4 FE FF FF mov eax, [ebp+var_15C]
CODE:004D52A8 8D 8D A8 FE FF FF lea ecx, [ebp+var_158]
CODE:004D52AE BA 3F 00 00 00 mov edx, 3Fh
CODE:004D52B3 E8 74 53 F3 FF call Sysutils::FindFirst(System::AnsiString,int,Sysutils::TSearchRec &)
CODE:004D52B8 8B F8 mov edi, eax
CODE:004D52BA 85 FF test edi, edi
CODE:004D52BC 75 4F jnz short loc_4D530D
CODE:004D52BE loc_4D52BE:
CODE:004D52BE 84 DB test bl, bl
CODE:004D52C0 74 32 jz short loc_4D52F4
CODE:004D52C2 8D 95 A0 FE FF FF lea edx, [ebp+var_160]
CODE:004D52C8 8B 46 04 mov eax, [esi+4]
CODE:004D52CB E8 54 41 FC FF call sub_499424
CODE:004D52D0 8D 85 A0 FE FF FF lea eax, [ebp+var_160]
CODE:004D52D6 8B 95 B4 FE FF FF mov edx, [ebp+var_14C]
CODE:004D52DC E8 23 FB F2 FF call System::__linkproc__ LStrCat(void)
CODE:004D52E1 8B 95 A0 FE FF FF mov edx, [ebp+var_160]
CODE:004D52E7 B1 01 mov cl, 1
CODE:004D52E9 8B C6 mov eax, esi
CODE:004D52EB E8 60 01 00 00 call InitMainBaseAVZ
CODE:004D52F0 84 C0 test al, al
CODE:004D52F2 75 04 jnz short loc_4D52F8
CODE:004D52F4 loc_4D52F4:
CODE:004D52F4 33 C0 xor eax, eax
CODE:004D52F6 EB 02 jmp short loc_4D52FA
CODE:004D52F8 loc_4D52F8:
CODE:004D52F8 B0 01 mov al, 1
CODE:004D52FA loc_4D52FA:
CODE:004D52FA 8B D8 mov ebx, eax
CODE:004D52FC 8D 85 A8 FE FF FF lea eax, [ebp+var_158]
CODE:004D5302 E8 75 53 F3 FF call Sysutils::FindNext(Sysutils::TSearchRec &)
CODE:004D5307 8B F8 mov edi, eax
CODE:004D5309 85 FF test edi, edi
CODE:004D530B 74 B1 jz short loc_4D52BE
CODE:004D530D loc_4D530D:
CODE:004D530D 8D 85 A8 FE FF FF lea eax, [ebp+var_158]
CODE:004D5313 E8 88 53 F3 FF call Sysutils::FindClose(Sysutils::TSearchRec &)
Заходим в 004D5450(InitMainBaseAVZ) (так как по коду видно, что до InitMainBaseAVZ LStrCat соединяет строки(путь), а после InitMainBaseAVZ идет проверка на положительный результат)
Зайдя в 004D5450(InitMainBaseAVZ) мы увидим примерно такой код:
Код:
CODE:004D54D3 E8 04 E8 F2 FF call System::TObject::TObject(void)
CODE:004D54D8 89 45 F4 mov [ebp+var_C], eax
CODE:004D54DB 33 C9 xor ecx, ecx
CODE:004D54DD 55 push ebp
CODE:004D54DE 68 38 5B 4D 00 push offset loc_4D5B38
CODE:004D54E3 64 FF 31 push dword ptr fs:[ecx]
CODE:004D54E6 64 89 21 mov fs:[ecx], esp
CODE:004D54E9 33 C9 xor ecx, ecx
CODE:004D54EB 55 push ebp
CODE:004D54EC 68 0C 5B 4D 00 push offset loc_4D5B0C
CODE:004D54F1 64 FF 31 push dword ptr fs:[ecx]
CODE:004D54F4 64 89 21 mov fs:[ecx], esp
CODE:004D54F7 8B 55 FC mov edx, [ebp+var_4]
CODE:004D54FA 8B 45 F4 mov eax, [ebp+var_C]
CODE:004D54FD E8 FA B8 F4 FF call LoadBaseAVZ
CODE:004D5502 33 D2 xor edx, edx
CODE:004D5504 8B 45 F4 mov eax, [ebp+var_C]
CODE:004D5507 E8 10 F7 FF FF call UnpackAVZ
CODE:004D550C 84 C0 test al, al
CODE:004D550E 75 4D jnz short loc_4D555D
CODE:004D5510 68 C0 5B 4D 00 push offset szAvz001Avz1109 ; "AVZ-001 $AVZ1109 "
CODE:004D5515 8D 95 70 FF FF FF lea edx, [ebp+var_90]
CODE:004D551B 8B 45 FC mov eax, [ebp+var_4]
CODE:004D551E E8 B9 53 F3 FF call Sysutils::ExtractFileName(System::AnsiString)
Дело в том, что Delphi юзает TObject всегда там, где все самое интересное, так как это база всего ООП Delphi
Запускаем AVZ в олечке(OLLYDBG – другой альтернативы для win32 нет, и тут без вариантов) и ставим бряк на адресе
004D54D8 89 45 F4 mov [ebp+var_C], eax
Еще и олечку нужно заставить показывать Delphi-код, для этого сохраняем(создаем в ИДЕ) avz.map и потом импортируем его в олю при помощи(для примера) плагина GODUP меню Map Loader(где скачать?, я уже в прошлые разы постил ссылки)
И жмем кнопку «Пуск» в AVZ
После того как остановимся в оле на бряке переходим на адрес(в окне регистров на выбранном регистре eax ПКМ->Follow in Dump) что в регистре eax(у меня 00B6231C) в окно дата и там переключаемся в окне CPU Dump ПКМ->Long->Address with ASCII dump на более удобный вид
Далее ПКМ->Backup->Create backup(это будет подсвечивать измененную память)
И трассируем по F8 и параллельно смотрим за окном дата и сразу после первого
004D54FD E8 FA B8 F4 FF call LoadBaseAVZ
Мы должны увидеть примерно такое:
Код:
CPU Dump
Address Value ASCII Comments
00B6231C 0041B7AC
00B62320 001BC908
00B62324 0000CFBD
00B62328 00000000
00B6232C 0000E000
Там мы увидим загруженный код базы начинающийся с символов AVZ
Далее возвратимся назад(жмем клавишу минус на цифровой клаве)
И опять трассируем по F8. Сразу после:
004D5507 E8 10 F7 FF FF call UnpackAVZ
Опять изменится адрес
Код:
CPU Dump
Address Value ASCII Comments
00B6231C 0041B7AC
00B62320 0020B010
00B62324 000124A4
00B62328 000124A4
00B6232C 00014000
Теперь нам надо проследить, куда он сложит инит данные, для этого ставим бряк на VirtualAlloc и жмем F9, ну а далее по накатанной трассируем до возвращения назад..
Но я делаю проще, так как Delphi юзает TObject то в регистре eax он передает указатель на него, а сталобыть сразу на в ходе в процедуру можно увидеть что из eax перемещается указатель в регистр ebх, и можно сразу в окне даты переходить поэтому адресу, бэкапить и трассировать наблюдая за появлением адреса, как только появится переходим на него и трассируем дальше до появления инициализированных данных с именем сигнатуры
Добавлено в [time]1290018917[/time]
Но можно сделать еще проще, просто проскролить немного ниже код и визуально увидеть вот такой код:
Код:
004D598C > 33C0 XOR EAX,EAX
004D598E 8945 98 MOV DWORD PTR SS:[EBP-68],EAX
004D5991 > 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
004D5994 8BD0 MOV EDX,EAX
004D5996 C1E0 05 SHL EAX,5
004D5999 03C2 ADD EAX,EDX
004D599B 8B53 0C MOV EDX,DWORD PTR DS:[EBX+C]
004D599E 8D0402 LEA EAX,DWORD PTR DS:[EDX+EAX]
004D59A1 8D95 7BFFFFFF LEA EDX,DWORD PTR SS:[EBP-85]
004D59A7 8B0D 80364D00 MOV ECX,DWORD PTR DS:[<off_4D3680>]
004D59AD E8 AAFFF2FF CALL <System::__linkproc__ CopyRecord(void)>
004D59B2 FF45 D8 INC DWORD PTR SS:[EBP-28]
004D59B5 FF4D CC DEC DWORD PTR SS:[EBP-34]
004D59B8 ^ 0F85 09FDFFFF JNZ <loc_4D56C7>
004D59AD E8 AAFFF2FF CALL <System::__linkproc__ CopyRecord(void)>
И жмем F9
После срабатывания бряка, переходим на адрес(в окне регистров на выбранном регистре eax ПКМ->Follow in Dump) что в регистре eax(у меня 015B8008) в окно дата
И собственно сама "сигна" которую мы увидим:
Код:
CPU Dump
Address Value Comments
015B8008 01687A0C ; ASCII "AdTool.Win32.WhenU.g"
015B800C 00381978
015B8010 00381978
015B8014 096A17F0
015B8018 0B1D750B
015B801C 001E3426
015B8020 00237B05
Код:
CPU Dump
Address Value Comments
10A047DA 041CB7E4 ; ASCII "Trojan-PSW.Win32.LdPinch.beo"
10A047DE 0000BBB9
10A047E2 0000BBB9
10A047E6 0671FD9E
10A047EA 0A3AF097
10A047EE 002F7EEB
10A047F2 001BDF49
Нам только пока известно для чего первое поле этой структуры, а именно указатель на строку с именем сигнатуры, которой мы видим в окне AVZ при детекте
Продолжим наши поиски.. если посмотреть на строку с сигной то можно заметить что там присутствуют символы >>>>>
Вот их мы и поищем в оле
Жмем Ctrl+G и вбиваем в появившемся окне адрес 401000
Жмем Ctrl+B и в поле ASCII вбиваем >>>>> и OK
После того как оля найдет эту строку жмем Ctrl+A(анализ кода) и видим такое
005BBB34 20 3E 3E 3E 3E 3E 20 00 ASCII " >>>>> ",0
Теперь ставим курсор на эту строку и жмем Ctrl+R и в появившемся окне выбираем
005BB5B2 PUSH <dword_5BBB34> ASCII " >>>>> "
И жмем Enter
Собственно мы в процедуре, которая создает/заполняет и сравнивает структуру
Код:
CODE:005BB18C 55 push ebp
CODE:005BB18D 8B EC mov ebp, esp
CODE:005BB18F 51 push ecx
CODE:005BB190 B9 14 00 00 00 mov ecx, 14h
CODE:005BB195 loc_5BB195:
CODE:005BB195 6A 00 push 0
CODE:005BB197 6A 00 push 0
CODE:005BB199 49 dec ecx
CODE:005BB19A 75 F9 jnz short loc_5BB195
CODE:005BB19C 87 4D FC xchg ecx, [ebp+FileName]
CODE:005BB19F 53 push ebx
CODE:005BB1A0 56 push esi
CODE:005BB1A1 57 push edi
CODE:005BB1A2 88 4D FB mov [ebp+var_5], cl
CODE:005BB1A5 89 55 FC mov [ebp+FileName], edx
CODE:005BB1A8 8B F0 mov esi, eax
CODE:005BB1AA 8B 5D 08 mov ebx, [ebp+arg_0]
CODE:005BB1AD 8B 45 FC mov eax, [ebp+FileName]
CODE:005BB1B0 E8 37 9E E4 FF call System::__linkproc__ LStrAddRef(void *)
CODE:005BB1B5 8B 45 0C mov eax, [ebp+arg_4]
CODE:005BB1B8 E8 1B B1 E4 FF call System::__linkproc__ DynArrayAddRef(void)
CODE:005BB1BD 8D 45 C7 lea eax, [ebp+var_39]
CODE:005BB1C0 8B 15 80 36 4D 00 mov edx, off_4D3680
CODE:005BB1C6 E8 5D A4 E4 FF call System::__linkproc__ InitializeRecord(void *,void *)
CODE:005BB1CB 33 C0 xor eax, eax
CODE:005BB1CD 55 push ebp
CODE:005BB1CE 68 19 BA 5B 00 push offset loc_5BBA19
CODE:005BB1D3 64 FF 30 push dword ptr fs:[eax]
CODE:005BB1D6 64 89 20 mov fs:[eax], esp
CODE:005BB1D9 C7 45 F4 FF FF FF FF mov [ebp+var_C], 0FFFFFFFFh
CODE:005BB1E0 E8 C7 BE E4 FF call @GetTls
CODE:005BB1E5 80 B8 18 00 00 00 00 cmp byte ptr [eax+18h], 0
CODE:005BB1EC 0F 85 D8 07 00 00 jnz loc_5BB9CA
CODE:005BB1F2 A1 AC 9D 5C 00 mov eax, ds:dword_5C9DAC
CODE:005BB1F7 83 38 00 cmp dword ptr [eax], 0
CODE:005BB1FA 7E 0D jle short loc_5BB209
CODE:005BB1FC A1 AC 9D 5C 00 mov eax, ds:dword_5C9DAC
CODE:005BB201 8B 00 mov eax, [eax]
CODE:005BB203 50 push eax ; dwMilliseconds
CODE:005BB204 E8 5B 48 E5 FF call Sleep
CODE:005BB209 loc_5BB209:
CODE:005BB209 8B 96 B8 05 00 00 mov edx, [esi+5B8h]
CODE:005BB20F 42 inc edx
CODE:005BB210 8B C6 mov eax, esi
CODE:005BB212 E8 61 36 00 00 call sub_5BE878
CODE:005BB217 B2 01 mov dl, 1
CODE:005BB219 A1 5C 38 4D 00 mov eax, off_4D385C
CODE:005BB21E E8 B9 8A E4 FF call System::TObject::TObject(void)
CODE:005BB223 89 45 F0 mov [ebp+PTObject], eax
CODE:005BB226 33 D2 xor edx, edx
CODE:005BB228 55 push ebp
CODE:005BB229 68 C3 B9 5B 00 push offset loc_5BB9C3
CODE:005BB22E 64 FF 32 push dword ptr fs:[edx]
CODE:005BB231 64 89 22 mov fs:[edx], esp
CODE:005BB234 8B 55 FC mov edx, [ebp+FileName]
CODE:005BB237 8B 45 F0 mov eax, [ebp+PTObject]
CODE:005BB23A E8 41 AE F1 FF call CreateHash
CODE:005BB23F 84 C0 test al, al
CODE:005BB241 0F 85 C2 00 00 00 jnz loc_5BB309
[...]
CODE:005BB309 E8 9E BD E4 FF call @GetTls
CODE:005BB30E 8B 80 30 00 00 00 mov eax, [eax+30h]
CODE:005BB314 8D 4D C7 lea ecx, [ebp+var_39]
CODE:005BB317 8B 55 F0 mov edx, [ebp+PTObject]
CODE:005BB31A 83 C2 04 add edx, 4
CODE:005BB31D E8 7A 91 F1 FF call CompareHash
CODE:005BB322 89 45 F4 mov [ebp+var_C], eax
CODE:005BB325 8B 45 F4 mov eax, [ebp+var_C]
CODE:005BB328 83 E8 01 sub eax, 1
CODE:005BB32B 72 12 jb short loc_5BB33F
CODE:005BB32D 0F 84 F4 00 00 00 jz loc_5BB427
CODE:005BB333 48 dec eax
CODE:005BB334 0F 84 B2 02 00 00 jz loc_5BB5EC
CODE:005BB33A E9 B0 03 00 00 jmp loc_5BB6EF
005BB223 89 45 F0 mov [ebp+PTObject], eax
И повторяем все тоже самое что делали ранее, чтобы сразу видеть все важные для нас события
Начинаем трассировать по F8 и сразу после
005BB23A E8 41 AE F1 FF call CreateHash
Мы увидим в окне данных изменение – это собственно и есть та самая заполниная структура для детекта нашего пинча
Но мы на данный момент пропустим этот факт и двинемся дальше, чтобы понять, где это все сравнивается
Мы чуть далее после прыжка заходим в
005BB31D E8 7A 91 F1 FF call CompareHash
И видим следующий код
Код:
CODE:004D44F7 8D 1C 76 lea ebx, [esi+esi*2]
CODE:004D44FA 8B 44 DF 21 mov eax, [edi+ebx*8+21h]
CODE:004D44FE 33 D2 xor edx, edx
CODE:004D4500 52 push edx
CODE:004D4501 50 push eax
CODE:004D4502 8B 45 B6 mov eax, [ebp-4Ah]
CODE:004D4505 99 cdq
CODE:004D4506 3B 54 24 04 cmp edx, [esp+4]
CODE:004D450A 75 0D jnz short loc_4D4519
CODE:004D450C 3B 04 24 cmp eax, [esp]
CODE:004D450F 5A pop edx
CODE:004D4510 58 pop eax
CODE:004D4511 0F 82 63 02 00 00 jb loc_4D477A
CODE:004D4517 EB 08 jmp short loc_4D4521
CODE:004D4519 loc_4D4519:
CODE:004D4519 5A pop edx
CODE:004D451A 58 pop eax
CODE:004D451B 0F 8C 59 02 00 00 jl loc_4D477A
Посмотрим в Total Commander размер файла - он у нас 48057, что в шестнадцатеричном эквиваленте равно 0000BBB9
Также из кода видно, что сравниваются границы файла минимальной и максимальной, если попадаем в эти границы, то осуществляем следующее сравнение итд.
То есть следующие два поля нашей структуры означают минимальный и максимальный размер пинча
Добавлено в [time]1290018971[/time]
Осталось узнать, что это за такие эти оставшиеся 4 поля
Для этого мы переходим по адресу
005BB23A E8 41 AE F1 FF call CreateHash
И видим следующий код
Код:
CODE:004D60D1 6A 00 push 0 ; hTemplateFile
CODE:004D60D3 68 80 00 00 10 push 10000080h ; dwFlagsAndAttributes
CODE:004D60D8 6A 03 push 3 ; dwCreationDisposition
CODE:004D60DA 6A 00 push 0 ; lpSecurityAttributes
CODE:004D60DC 6A 01 push 1 ; dwShareMode
CODE:004D60DE 68 00 00 00 80 push 80000000h ; dwDesiredAccess
CODE:004D60E3 8B 45 FC mov eax, [ebp+var_4]
CODE:004D60E6 E8 11 EF F2 FF call System::__linkproc__ LStrToPChar(System::AnsiString)
CODE:004D60EB 8B F0 mov esi, eax
CODE:004D60ED 56 push esi ; lpFileName
CODE:004D60EE E8 65 13 F3 FF call CreateFileA
CODE:004D60F3 89 45 F4 mov [ebp+hObject], eax
CODE:004D60F6 83 7D F4 FF cmp [ebp+hObject], 0FFFFFFFFh
CODE:004D60FA 75 1B jnz short loc_4D6117
CODE:004D60FC 6A 00 push 0 ; hTemplateFile
CODE:004D60FE 68 00 00 00 02 push 2000000h ; dwFlagsAndAttributes
CODE:004D6103 6A 03 push 3 ; dwCreationDisposition
CODE:004D6105 6A 00 push 0 ; lpSecurityAttributes
CODE:004D6107 6A 00 push 0 ; dwShareMode
CODE:004D6109 68 00 00 02 00 push 20000h ; dwDesiredAccess
CODE:004D610E 56 push esi ; lpFileName
CODE:004D610F E8 44 13 F3 FF call CreateFileA
CODE:004D6114 89 45 F4 mov [ebp+hObject], eax
CODE:004D6117 loc_4D6117:
CODE:004D6117 83 7D F4 FF cmp [ebp+hObject], 0FFFFFFFFh
CODE:004D611B 74 38 jz short loc_4D6155
CODE:004D611D 33 C0 xor eax, eax
CODE:004D611F 55 push ebp
CODE:004D6120 68 42 61 4D 00 push offset loc_4D6142
CODE:004D6125 64 FF 30 push dword ptr fs:[eax]
CODE:004D6128 64 89 20 mov fs:[eax], esp
CODE:004D612B 8B 55 F4 mov edx, [ebp+hObject]
CODE:004D612E 8B C3 mov eax, ebx
CODE:004D6130 E8 57 00 00 00 call sub_4D618C
Вот мы туда заходим и видим код
Код:
CODE:004D618C 53 push ebx
CODE:004D618D 56 push esi
CODE:004D618E 57 push edi
CODE:004D618F 55 push ebp
CODE:004D6190 83 C4 C4 add esp, 0FFFFFFC4h
CODE:004D6193 8B EA mov ebp, edx
CODE:004D6195 8B D8 mov ebx, eax
CODE:004D6197 C6 04 24 00 mov [esp+4Ch+var_4C], 0
CODE:004D619B 33 C0 xor eax, eax
CODE:004D619D 89 43 1A mov [ebx+1Ah], eax
CODE:004D61A0 33 C0 xor eax, eax
CODE:004D61A2 89 43 16 mov [ebx+16h], eax
CODE:004D61A5 33 C0 xor eax, eax
CODE:004D61A7 89 43 1E mov [ebx+1Eh], eax
CODE:004D61AA 6A 00 push 0 ; lpFileSizeHigh
CODE:004D61AC 55 push ebp ; hFile
CODE:004D61AD E8 E6 13 F3 FF call GetFileSize
CODE:004D61B2 85 C0 test eax, eax
CODE:004D61B4 79 05 jns short loc_4D61BB
CODE:004D61B6 E8 89 DA F2 FF call Error
CODE:004D61BB loc_4D61BB:
CODE:004D61BB 89 43 08 mov [ebx+8], eax; <=====
CODE:004D61BE 8B C5 mov eax, ebp
CODE:004D61C0 85 C0 test eax, eax
CODE:004D61C2 79 05 jns short loc_4D61C9
CODE:004D61C4 E8 7B DA F2 FF call Error
CODE:004D61C9 loc_4D61C9: ; dwMoveMethod
CODE:004D61C9 33 C9 xor ecx, ecx
CODE:004D61CB 33 D2 xor edx, edx ; lDistanceToMove
CODE:004D61CD E8 02 41 F3 FF call SetFilePointer_1
CODE:004D61D2 6A 00 push 0 ; lpOverlapped
CODE:004D61D4 8D 44 24 14 lea eax, [esp+50h+NumberOfBytesRead]
CODE:004D61D8 50 push eax ; lpNumberOfBytesRead
CODE:004D61D9 68 D0 07 00 00 push 7D0h ; nNumberOfBytesToRead
CODE:004D61DE 8D 43 32 lea eax, [ebx+32h]
CODE:004D61E1 50 push eax ; lpBuffer
CODE:004D61E2 55 push ebp ; hFile
CODE:004D61E3 E8 50 15 F3 FF call ReadFile
CODE:004D61E8 85 C0 test eax, eax
CODE:004D61EA 0F 84 ED 03 00 00 jz loc_4D65DD
[...]
CODE:004D62FF 33 C0 xor eax, eax
CODE:004D6301 83 7C 24 10 00 cmp [esp+4Ch+NumberOfBytesRead], 0
CODE:004D6306 76 1B jbe short loc_4D6323
CODE:004D6308 8B 7C 24 10 mov edi, [esp+4Ch+NumberOfBytesRead]
CODE:004D630C 4F dec edi
CODE:004D630D 85 FF test edi, edi
CODE:004D630F 7C 12 jl short loc_4D6323
CODE:004D6311 47 inc edi
CODE:004D6312 33 F6 xor esi, esi
CODE:004D6314 calcHash:
CODE:004D6314 33 D2 xor edx, edx
CODE:004D6316 8A 54 33 32 mov dl, [ebx+esi+32h]
CODE:004D631A 0F AF D6 imul edx, esi
CODE:004D631D 03 C2 add eax, edx
CODE:004D631F 46 inc esi
CODE:004D6320 4F dec edi
CODE:004D6321 75 F1 jnz short calcHash
CODE:004D6323 loc_4D6323:
CODE:004D6323 89 43 22 mov [ebx+22h], eax; <=====
Далее по коду можно увидеть, что высчитывается хэш с КОНЦА ФАЙЛА по последним 2000 байтам – это второе поле из оставшихся четырех полей нашей структуры и второй хеш, по которому и происходит детект
Далее высчитывается хеш с 200 байт с 5000 позиции в файле – это третье поле из оставшихся четырех полей нашей структуры и третий хеш, по которому и происходит детект(если файл размером меньше 5000, то записывается просто 0)
Далее высчитывается хеш с 200 байт с 10000 позиции в файле – это четвертое поле из оставшихся четырех полей нашей структуры и четвертый хеш, по которому и происходит детект(если файл размером меньше 10000, то записывается просто 0)
Итог: Вот так просто без создания сигнатур происходит детект по хэшу
Теперь зная как нас детектят можно попытаться что-то сделать, чтобы нас не палили, попробуем заюзать метод изменение даты компиляции в файле описанный мной ранее и посмотрим что произойдет
Меняем дату у нашего пинча с помощью PETools и проверяем его еще раз AVZ, ба епт что мы видим %)))
Код:
3. Сканирование дисков
X:\quarantine\pinch.trojan >>> подозрение на Trojan-PSW.Win32.LdPinch.beo ( 06720C6B 0A3AF097 002F7EEB 001BDF49 48057)
Ну, предположим, что вот такой измененный пинч попал на комп к нашей жертве, после чего этот зомбик может отправиться на сайт к "Зайчику", создать тему и запостить этот хеш, который они в следующей версии успешно добавят
Так не пойдет естественно, нам надо как-то изменить пинч без напрягов и чтобы нас не палили – мы просто попробуем добавить один ноль в конец файла(ну к примеру, тем же WinHex), изменяя тем самым размер файла и соответственно уберем полностью детект - пробуем.. и действительно нас НЕ ОБНАРУЖИЛИ %)))
Ну это естественно до первого попадания(и такая "халява" закончится) к AVZ на сайтег, там они потом тупо расширят диапазон максимального и минимального размера файла и громко объявят всем и везде где только можно какие они нах умные и что они всех нах победилЕ %))) (ну это типа немного черного юмора)
Философия
Хмм.. а это уже становацца интересным; мы знаем что avz – это выкидыш поцелуйчека(KIS), остается только "как-то узнать", а не идентичный ли детект и у него %)))
Кстати на счет одинокого детекта, мну здесь когда-то давно видел топик - чел спрашивал как сделать чтобы не палился криптор, а потом выяснилось что палился сэмпл по иконке(кто-то из криптующих ап этом сообщил)
Так вот на 90% можно предположить(но не утверждать), что палится именно данным детектом по хэшу
Так как мы теперь знаем что если в конце файла в сэмпле код статичен, а у нас в конце обычно ресурсы лежат и иконки тоже, то один раз попав такой сэмпл к аверам.. ОНИ ЗАНЕСУТ ЕГО В БАЗЫ, и даже если мы изменим полностью код ЭТОГО ЖЕ КРИПТОРА, то конец файла, а именно там ресурсы и находятся чаще всего, то иконка и будут детектицца по хэшу..
А вот, нашел линк
http://xss.pro/index.php?topic=19024 - у судьбе закриптованых файлов
Так вот там в теме утверждалось что никуда сэмпл не отсылался кроме как на "наши хваленые сервисы", которые якобы не отсылают..(забавная ситуация неправда ли %))) даже если накрыть ДРУГИМ КРИПТОРОМ и заюзать туже иконку, то будет уже другой хэш и на это есть много причин!, начиная от той же разницы количества нулей в конце файла итд.. но тут даже не в этом смысл, так как там все равно было упоминание о том, что файл не юзался, а отправлялся чич-то для проверки на scan4you.biz (каг говорцца - делайте выводы господа сами)
Итог: рандомить надо все и в том числе даже ресурсы, чтобы нас вот так примитивно не детектили по хешу
P. S.
Добавил данный детект в OC
Также присвоил тулузе статус BETA, что позволяет иметь хоум пагу, а сталобыть принимать в личку багрепорты и сделать описание ее возможностей
http://demonteam.narod.ru/oc/oc.html