Динамический анализа кода с помощью x64dbg и IDA Pro

Динамический анализа кода x64dbg IDA Pro

В прошлом 2022 сразу нес­коль­ко компаний по созданию анти­вирус­ного ПО опуб­ликова­ли статьи про бек­дор из семей­ства PlugX, который называется Talisman. В сегодняшней статье, на при­мере это­го тро­яна мы рассмотрим способ выпол­нения динами­чес­кого ана­лиза вре­донос­ного ПО.

Еще по теме: Взлом программы macOS с помощью IDA и Hiew

Динамический анализа кода с помощью x64dbg и IDA Pro

Прис­тупим к под­робно­му иссле­дова­нию кода. Про­цесс динами­чес­кого ана­лиза будем про­водить с исполь­зовани­ем ути­литы x64dbg. Ана­лиз псев­докода выпол­ним в IDA Pro с уста­нов­ленным пла­гином HexRays. В про­цес­се ана­лиза вре­донос­ных прог­рамм необ­ходимо ком­биниро­вать исполь­зуемые инс­тру­мен­ты для получе­ния наибо­лее пол­ного резуль­тата.

Прог­рамма SNAC.EXE пред­став­ляет собой безопас­ный исполня­емый файл, который име­ет валид­ную циф­ровую под­пись. Его основная задача — заг­рузка динами­чес­кой биб­лиоте­ки WGXMAN.DLL методом DLL Side-loading. Пос­ле заг­рузки биб­лиоте­ки выпол­нение переда­ется на фун­кцию экспор­та DllMain. Далее динами­чес­кая биб­лиоте­ка рас­шифро­выва­ет исполня­емый код в фай­ле SNAC.LOG и переда­ет выпол­нение на него.

Прис­тупим к ана­лизу, для это­го заг­рузим исполня­емый файл SNAC.EXE в ути­литу x64dbg, в которой будем про­водить отладку. Так­же заг­рузим динами­чес­кую биб­лиоте­ку WGXMAN.DLL в IDA.

Для про­веде­ния динами­чес­кого ана­лиза необ­ходимо най­ти точ­ку оста­нова, с которой начина­ется выпол­нение основных фун­кций прог­раммы. Для это­го про­ана­лизи­руем код заг­ружа­емой биб­лиоте­ки и най­дем фун­кцию, под­ходящую для этой цели.

В IDA откры­ваем вклад­ку File → Open и выбира­ем файл WGXMAN.DLL. Пос­ле заг­рузки фай­ла мы попада­ем на фун­кцию DllMain. Далее деком­пилиру­ем код, исполь­зуя пла­гин HexRays, для это­го нажима­ем кла­вишу F5. И син­хро­низи­руем ана­лиз кода во вклад­ке IDA View A и Pseudocode A, для чего перене­сем вклад­ку Pseudocode A в пра­вую часть вклад­ки IDA View A. Нажати­ем пра­вой кноп­ки мыши выберем Syncronize with → IDA View A, теперь при выборе учас­тка кода он будет под­све­чивать­ся в каж­дой вклад­ке.

Учас­ток кода фун­кции DllMain
Учас­ток кода фун­кции DllMain

Пе­рехо­дим в фун­кцию sub_6FE443C, эта фун­кция и будет точ­кой вхо­да во вре­мя динами­чес­кой отладки. Про­ана­лизи­руем ее.

Код фун­кции sub_6FE443C
Код фун­кции sub_6FE443C

Фун­кция sub_6FE420 слу­жит для получе­ния спис­ка фун­кций экспор­та динами­чес­кой биб­лиоте­ки kernel32.dll.

Со­дер­жимое фун­кции sub_6FE42A0
Со­дер­жимое фун­кции sub_6FE42A0

Нач­нем отладку в x64dbg. Для это­го перей­дем к фун­кции sub_6FE443C нажати­ем сочета­ния кла­виш Ctrl-G, затем наберем адрес фун­кции и раз­берем алго­ритм рас­шифров­ки кон­стант.

Пе­реход по адре­су 6FE443C
Пе­реход по адре­су 6FE443C

Пос­тавим точ­ку оста­нова на вход фун­кции. Наж­мем F7 для захода в фун­кцию и уви­дим инте­ресу­ющие нас кон­стан­ты.

Кон­троль­ные сум­мы фун­кций экспор­та биб­лиоте­ки kernel32.dll
Кон­троль­ные сум­мы фун­кций экспор­та биб­лиоте­ки kernel32.dll
На­чало отладки вре­доно­са
На­чало отладки вре­доно­са

Зай­дем в фун­кцию call wgxman.6FE42D4 и раз­берем механизм поис­ка экспортных фун­кций биб­лиоте­ки kernel32.dll.

Ал­горитм дешиф­рования кон­стант
Ал­горитм дешиф­рования кон­стант
Псев­докод фун­кции дешиф­рования
Псев­докод фун­кции дешиф­рования

В фун­кции sub_6FE42D4 рас­положен алго­ритм пре­обра­зова­ния фун­кции экспор­та биб­лиоте­ки kernel32.dll. Име­на экспор­тиру­емых фун­кций не хра­нят­ся в откры­том виде, поэто­му тро­яну сле­дует сна­чала при­вес­ти их в при­год­ный для исполь­зования вид. Для это­го на вход фун­кции sub_6DE42D4 пос­тупа­ет кон­стан­та и спи­сок фун­кций экспор­та биб­лиоте­ки kernek32.dll, далее из наз­вания фун­кции экспор­та счи­тыва­ется сим­вол, пре­обра­зует­ся по алго­рит­му ROR со сме­щени­ем 7, а затем сум­ма всех пре­обра­зован­ных сим­волов скла­дыва­ется.

На­пишем этот алго­ритм пре­обра­зова­ния в виде прог­раммы на Python. Спи­сок фун­кций экспор­та возь­мем с сай­та geoffchappell.com.

За­пус­тив прог­рамму, мы получим сле­дующий резуль­тат.

Вы­вод фун­кции декоди­рова­ния кон­стант
Вы­вод фун­кции декоди­рова­ния кон­стант

Пре­обра­зуем псев­докод в чита­емый фор­мат, вос­поль­зовав­шись воз­можнос­тями IDA Pro. Горячая кла­виша N поз­воля­ет пере­име­новать перемен­ные в псев­докоде IDA.

Пре­обра­зован­ный псев­докод фун­кции 6FE443C
Пре­обра­зован­ный псев­докод фун­кции 6FE443C

Пос­ле про­вер­ки того, что имя запущен­ного исполня­емо­го фай­ла содер­жит .NAC., управле­ние переда­ется по адре­су 06FE44E1.

Мы разоб­рали метод запуты­вания наз­ваний фун­кций вре­доно­сом. Теперь перей­дем к учас­тку кода, где рас­шифро­выва­ется файл SNAC.LOG. Для это­го най­дем фун­кцию CreateFileA, вос­поль­зовав­шись сочета­нием кла­виш Ctrl-G.

Пе­реход на фун­кцию CreateFileA
Пе­реход на фун­кцию CreateFileA

По адре­су 0x6FE43C8 про­исхо­дит вызов фун­кции CreateFileA, а в регис­тре EAX содер­жится путь к фай­лу SNAC.LOG.

Учас­ток кода вызова фун­кций CreateFileA, GetFileSize, VirtualAlloc
Учас­ток кода вызова фун­кций CreateFileA, GetFileSize, VirtualAlloc

Да­лее вре­донос получа­ет раз­мер фай­ла SNAC.LOG с исполь­зовани­ем фун­кции GetFileSize. Затем про­исхо­дит выделе­ние памяти с помощью фун­кции VirtualAlloc.

Про­дол­жаем отла­живать код: нажима­ем F8 и спус­каем­ся к адре­су фун­кции ReadFile.

Вы­зов фун­кции ReadFile
Вы­зов фун­кции ReadFile

Пе­рей­дем к зна­чению в памяти ds:[edi+0x3C] (параметр lpBuffer фун­кции ReadFile). Так как по это­му адре­су хра­нят­ся зна­чения, нажима­ем пра­вой кноп­кой мыши на [edi+0x3c] и перехо­дим на вклад­ку «Перей­ти к дам­пу → Зна­чение [edi+0x3C]». Пос­ле выпол­нения фун­кции по тому адре­су сох­ранит­ся содер­жимое фай­ла SNAC.LOG.

Ад­рес в памяти содер­жимого фай­ла SNAC.LOG
Ад­рес в памяти содер­жимого фай­ла SNAC.LOG

По адре­су 0x00550000 хра­нит­ся содер­жимое фай­ла SNAC.LOG. Нажима­ем F8 и дви­гаем­ся даль­ше. Находим учас­ток кода, в котором рас­шифро­выва­ется этот файл.

Ал­горитм рас­шифро­вания фай­ла SNAC.LOG
Ал­горитм рас­шифро­вания фай­ла SNAC.LOG

В регистр ESI переда­ются зна­чения по адре­су [edi+3c] (там хра­нит­ся содер­жимое фай­ла SNAC.LOG), далее с каж­дым бай­том фай­ла про­исхо­дит сле­дующее пре­обра­зова­ние. Сна­чала из него вычита­ется зна­чение 0x48, далее выпол­няет­ся опе­рация XOR со зна­чени­ем 0x19, и, наконец, получен­ный резуль­тат скла­дыва­ется со зна­чени­ем 0xA7. Далее выпол­нение кода переда­ется на рас­шифро­ван­ные зна­чения и вызыва­ется фун­кция call esi. Пос­тавим точ­ку оста­нова на этом вызове.

Да­вай напишем на Python код рас­шифров­ки фай­ла SNAC.LOG и заг­рузим рас­шифро­ван­ный файл в IDA Pro.

По­лучен­ный рас­шифро­ван­ный файл SNAC_DECODE.LOG заг­рузим в IDA Pro и раз­берем его код.

Учас­ток кода рас­шифро­ван­ного фай­ла SNAC.LOG
Учас­ток кода рас­шифро­ван­ного фай­ла SNAC.LOG

Как вид­но из рисун­ка, про­исхо­дит запуск фун­кции sub_269DD, в качес­тве вто­рого аргу­мен­та переда­ется раз­мер фай­ла SNAC.LOG, рав­ный 159981 бай­ту. При выпол­нении это­го кода про­исхо­дит поиск WinAPI-фун­кции GetProcAddress.

По­иск фун­кции GetProcAddress
По­иск фун­кции GetProcAddress

Да­лее вре­донос получа­ет адре­са сле­дующих фун­кций: LoadLibraryA, VirtualAlloc, VirtualFree, ExitThread, RtlDecompressBuffer, memcpy.

По­луче­ние адре­сов фун­кций
По­луче­ние адре­сов фун­кций

За­тем про­исхо­дят сле­дующие пре­обра­зова­ния.

Пре­обра­зова­ние дан­ных
Пре­обра­зова­ние дан­ных

На рисун­ке выше показан алго­ритм рас­шифров­ки полез­ной наг­рузки, спря­тан­ной внут­ри динами­чес­кой биб­лиоте­ки. С целью замед­ления рас­шифров­ки пять раз вызыва­ется фун­кция Sleep, затем рас­шифро­ван­ный буфер рас­паковы­вает­ся с помощью фун­кции RtlDecompressBuffer. Пре­обра­зован­ные дан­ные будут сох­ранены в перемен­ной v29, для которой выделя­ется память с помощью фун­кции VirtualAlloc. Наша задача при отладке попасть на фун­кцию RtlDecompressBuffer, перей­ти про адре­су перемен­ной v29 и сох­ранить область памяти. Так мы получим основную полез­ную наг­рузку вре­доно­са PlugX.

Прис­тупа­ем к отладке. Мы оста­нав­ливались на опе­ран­де call esi. Заходим в фун­кцию, нажима­ем кла­вишу F7, а затем F8. Про­ходим этап получе­ния адре­сов фун­кций, далее, минуя этап рас­шифров­ки полез­ной наг­рузки, оста­новим­ся перед запус­ком фун­кции RtlDecompressBuffer. Эту фун­кцию мож­но отыс­кать, спус­каясь вниз по учас­тку кода либо перей­дя на ее вызов. Для это­го мож­но исполь­зовать сочета­ние кла­виш Ctrl-G в x64dbg, пос­ле чего сле­дует ввес­ти наз­вание фун­кции, на которую мы хотим перей­ти.

Вы­зов фун­кции RtlDecompressBuffer
Вы­зов фун­кции RtlDecompressBuffer

В регис­тре ESI хра­нят­ся пре­обра­зован­ные дан­ные (параметр UncompressBuffer). Щел­кнем пра­вой кноп­кой мыши на этом регис­тре, затем наж­мем «Перей­ти к дам­пу → esi» и получим основную наг­рузку вре­доно­са PlugX.

Ос­новная наг­рузка модуля PlugX Talisman
Ос­новная наг­рузка модуля PlugX Talisman

Сох­раним получен­ный код, для это­го щел­кнем пра­вой кноп­кой мыши на регис­тре ESI и выберем в открыв­шемся меню пункт «Перей­ти к кар­те памяти».

Кар­та памяти
Кар­та памяти

Наж­мем пра­вую кноп­ку мыши, что­бы сох­ранить дамп в файл. Мы выг­рузили основную наг­рузку вре­доно­са. Чуть поз­же мы заг­рузим ее в IDA Pro и раз­берем фун­кци­онал, а для начала пос­мотрим, что про­исхо­дит пос­ле рас­шифров­ки полез­ной наг­рузки. В отладчи­ке спус­каем­ся нем­ного ниже (F8) и попада­ем на фор­мирова­ние внут­ренней струк­туры вре­доно­са.

Фор­мирова­ние струк­туры PlugX Talisman
Фор­мирова­ние струк­туры PlugX Talisman

Спус­тимся до учас­тка кода mov dword ptr ds:[esi],CF455089 и перей­дем к дам­пу по адре­су в регис­тре ESI. Для это­го наводим кур­сор на регистр [esi], нажима­ем пра­вую кноп­ку мыши и откры­ваем дамп.

Ком­пании Trellix и «Док­тор Веб» опи­сыва­ли схо­жие струк­туры PlugX, но мы раз­берем их самос­тоятель­но.

Опи­сание струк­туры Talisman
Опи­сание струк­туры Talisman

 

Дамп памяти струк­туры Talisman
Дамп памяти струк­туры Talisman

Пер­вые 4 бай­та содер­жат зна­чение 0xCF455089, которое явля­ется сиг­натурой струк­туры. Раз­мер кон­фигура­ции Talisman равен 0x1924 байт, а зашиф­рован­ный учас­ток кон­фигура­ции хра­нит­ся по адре­су 0x610013 (в тво­ем отладчи­ке адрес будет отли­чать­ся).

Пе­рей­дем по адре­су 0x610013, для это­го наж­мем пра­вую кноп­ку мыши и в открыв­шемся меню выберем пункт «Перей­ти к дам­пу DWORD».

Со­дер­жимое зашиф­рован­ной кон­фигура­ции PlugX Talisman
Со­дер­жимое зашиф­рован­ной кон­фигура­ции PlugX Talisman

Ско­пиру­ем получен­ное зна­чение и сох­раним в файл encrypt_talisman.txt.

На­чало и конец кон­фигура­ции Talisman
На­чало и конец кон­фигура­ции Talisman

Мы наш­ли кон­фигура­цию Talisman, теперь оты­щем учас­ток кода, который его рас­шифро­выва­ет.

Для это­го заг­рузим сох­ранен­ный дамп полез­ной наг­рузки PlugX Talisman в IDA Pro. Нам извес­тно, что дли­на кон­фигура­ции сос­тавля­ет 0x1924 байт, а сиг­натура кон­фигура­ции име­ет вид 0xCF455089. Най­дем учас­ток кода, где про­исхо­дит срав­нение сиг­натуры и объ­ема памяти кон­фигура­ции.

В IDA Pro откры­ваем вклад­ку Search → Sequence of bytes и вво­дим зна­чение 0x1924.

По­иск количес­тва байт кон­фигура­ции
По­иск количес­тва байт кон­фигура­ции

 

Спи­сок най­ден­ных учас­тков кода срав­нения объ­ема кон­фигура­ции
Спи­сок най­ден­ных учас­тков кода срав­нения объ­ема кон­фигура­ции

Пе­рехо­дим в фун­кцию sub_100243A0 и находим срав­нение сиг­натуры Talisman, а так­же раз­мера фай­ла кон­фигура­ции.

Учас­ток кода рас­шифров­ки струк­туры Talisman
Учас­ток кода рас­шифров­ки струк­туры Talisman

Фун­кция sub_1000A710, которую мы пере­име­нова­ли в Decrypt_Config_Talisman, содер­жит учас­ток кода рас­шифров­ки струк­туры бек­дора.

Ал­горитм рас­шифров­ки кон­фигура­ции
Ал­горитм рас­шифров­ки кон­фигура­ции

Дан­ный учас­ток кода схож с модулем PlugX.38. Давай напишем на Python алго­ритм рас­шифров­ки кон­фигура­ции, которую мы сох­ранили в файл encrypt_talisman.txt.

За­пус­тив скрипт, мы получа­ем сле­дующие зна­чения.

Со­дер­жимое кон­фигура­ции PlugX Talisman
Со­дер­жимое кон­фигура­ции PlugX Talisman

Раз­мер кон­фигура­ции сос­тавля­ет 0x1924 байт, она содер­жит спи­сок панелей управле­ния и C2-сер­веров (dhsg123.jkub.com). А вот и дру­гие получен­ные нами полез­ные дан­ные:

  • до­маш­ний каталог вре­доно­са — %ALLUSERSPROFILE%\SymantecSNAC;
  • мь­ютекс соз­дава­емо­го про­цес­са — Global\ReStart0;
  • це­левой про­цесс, в который будет внед­рять­ся вре­донос — %SystemRoot%\system32\nslookup.exe;
  • имя отоб­ража­емой служ­бы — SymantecSNAC;
  • иден­тифика­тор ком­пании — TEST.

На текущем эта­пе мы рас­шифро­вали кон­фигура­цию PlugX Talisman, теперь раз­берем основную наг­рузку DLL PlugX, которую извлек­ли из памяти.

Ана­лизи­руя код основной наг­рузки PlugX, мож­но обна­ружить сле­дующие исполь­зуемые пла­гины, рас­положен­ные в фун­кции sub_1000B9F0.

Спи­сок пла­гинов вре­доно­са
Спи­сок пла­гинов вре­доно­са

Пос­ле запус­ка полез­ной наг­рузки вре­донос соз­дает сле­дующие токены:

  • SeDebugPrivilege — эта при­виле­гия поз­воля­ет про­цес­су под­клю­чать­ся к любому про­цес­су или ядру как отладчик;
  • SeTcbPrivilege — поз­воля­ет про­цес­су оли­цет­ворить любого поль­зовате­ля без про­вер­ки под­линнос­ти, таким обра­зом про­цесс может получить дос­туп к тем же локаль­ным ресур­сам, что и этот поль­зователь.

Да­лее вре­донос соз­дает основной поток, который называ­ется bootProc.

Учас­ток кода соз­дания токенов
Учас­ток кода соз­дания токенов

Так­же в основной наг­рузке PlugX все фун­кции Windows API вызыва­ются динами­чес­ки на осно­ве алго­рит­ма CRC32 от наз­ваний фун­кций. Но в алго­рит­ме необ­ходимо добавить завер­шающий нулевой байт. Алго­ритм поис­ка фун­кций пред­став­лен ниже.

Ра­зыме­нова­ние фун­кции gethostbyname из биб­лиоте­ки ws2_32.dll
Ра­зыме­нова­ние фун­кции WSAIoctl биб­лиоте­ки ws2_32.dll

В ходе ана­лиза мы рас­шифро­вали файл SNAC.LOG, кон­фигура­цию PlugX Talisman, в которой хра­нят­ся све­дения о C2-сер­верах, а так­же рас­шифро­вали основную наг­рузку PlugX: она пред­став­ляет собой DLL, заг­ружа­емую в память про­цес­са SNAC.exe.

ПОЛЕЗНЫЕ ССЫЛКИ:

Дима (Kozhuh)

Эксперт в кибербезопасности. Работал в ведущих компаниях занимающихся аналитикой компьютерных угроз. Анонсы новых статей в Телеграме.

Добавить комментарий