[Из песочницы] Trojan-Downloader.Win32.Cabby.cemx — Часть первая — Распаковка

Привет Хабр! Скажу сразу: я не вирусный аналитик и не занимаюсь этой деятельностью профессионально. Работаю сетевым инженером в одной из компаний в группе компаний из трех букв. Так что прошу строго не судить и отнестись с пониманием.

Цель данной статьи — не экспресс анализ вредоносного ПО с целью написания отчета о высокоуровневой логике его работы, а погружение в реверс-инжиниринг с головой для повышения своих знаний и опыта. Поэтому пройдемся по всему алгоритму распаковки подробно.

Сразу предупрежу, будет много картинок и листингов дизассемблированного кода.

Готов к конструктивной критике и буду рад вашим советам по оптимизации моих мыслей.В недалеком прошлом в нашу компанию проник нашумевший CTB-Locker, что заинтересовало нашу службу информационной безопасности: почему не сработали антивирусы и фильтрация веб-трафика? Что конкретно делает данный зловред, хорошо описано на securelist. С этим все ясно и не имеет смысла проводить повторный анализ того, что и так неплохо описано.

С целью понимания причин инцидента рассмотрим именно вектор распространения данного зловреда.

Как это выглядит с точки зрения пользователя:

Пришло письмо с вложенным архивом .cab; Пользователь открывает архив и запускает из него .scr; Открывается .rtf файл с непонятными и неинтересными данными; Пользователь спокойно закрывает данный файл и продолжает работу; Через некоторое время на рабочем столе выскакивает окно CTB-Locker’а с печальной для пользователя информацией. ДекриптИтак, достаем из .cab архива злой и кусающийся .scr. Открываем его в Immunity Debugger и, нажав пару раз на F9, попадаем на Entry Point 0×4021C6, не встретив на пути каких-либо приемов антиотладки — уже хорошо.feb371033bef4bc994749278c3060cf8.png

Полистав немного листинг и окинув взглядом импорт не нашел ничего внятного и «полезного». Ничего связанного с сетевой деятельностью — наводит на мысль, что что-то спрятано глубже. Пакер?

Что нам на это поведает PEiD:

2c1dfea355ab46cba0be6048eca78f04.png

Ни один известный пакер не обнаружен. Кроме того, анализ энтропии говорит нам, что файл скорее всего не упакован. Но давайте смотреть дальше…

Потрейсив немного код, натыкаемся на первую манипуляцию с памятью. Переменные, передаваемые в HeapCreate, не особо хитро завуалированы:

e9b43bdda47249d390043e3f353a3303.png

Размер выделяемой памяти 0×6D0. flOptions = 0×40000, что говорит о том, что область памяти будет исполняемой. Ок, наблюдаем за выделенным участком памяти, установив на него Memory BP на запись, и обнаруживаем цикл расшифровки и копирования данных из секции .data в выделенную память (кстати, находится почти сразу за HeapCreate):

00401F4A. 85DB TEST EBX, EBX00401F4C. 0F84 67010000 JE g_r_pice.004020B900401F52. 01C0 ADD EAX, EAX00401F54. 811D C8404000 >SBB DWORD PTR DS:[4040C8],0CE00401F5E. 82C4 40 ADD AH,4000401F61. 83C8 4A OR EAX,4A00401F64. 31F6 XOR ESI, ESI00401F66. 0B37 OR ESI, DWORD PTR DS:[EDI] < — Загрузка данных для расшифровки из тела вируса00401F68. 18E4 SBB AH,AH00401F6A. 8315 28414000 >ADC DWORD PTR DS:[404128],3300401F71. 8115 E6404000 >ADC DWORD PTR DS:[4040E6],0A300401F7B. 8315 95404000 >ADC DWORD PTR DS:[404095],2500401F82. F8 CLC00401F83. 83D7 04 ADC EDI,400401F86. 34 F0 XOR AL,0F000401F88. 1305 E9404000 ADC EAX, DWORD PTR DS:[4040E9]00401F8E. 1905 48414000 SBB DWORD PTR DS:[404148], EAX00401F94. 8335 A2414000 >XOR DWORD PTR DS:[4041A2],2B00401F9B. 3105 41414000 XOR DWORD PTR DS:[404141], EAX00401FA1. F8 CLC00401FA2. 83DE 07 SBB ESI,700401FA5. 8325 E0404000 >AND DWORD PTR DS:[4040E0],6A00401FAC. 82CC E9 OR AH, FFFFFFE900401FAF. 2105 68404000 AND DWORD PTR DS:[404068], EAX00401FB5. 83C8 EE OR EAX, FFFFFFEE00401FB8. 83F0 FF XOR EAX, FFFFFFFF00401FBB. F7DE NEG ESI00401FBD. 810D 07414000 >OR DWORD PTR DS:[404107],0C200401FC7. C705 0D404000 >MOV DWORD PTR DS:[40400D],0B800401FD1. 3105 C0404000 XOR DWORD PTR DS:[4040C0], EAX00401FD7. 83C0 05 ADD EAX,500401FDA. 29D6 SUB ESI, EDX00401FDC. 11C0 ADC EAX, EAX00401FDE. 1305 2D414000 ADC EAX, DWORD PTR DS:[40412D]00401FE4. 83E8 2B SUB EAX,2B00401FE7. 1305 29404000 ADC EAX, DWORD PTR DS:[404029]00401FED. 83D8 3E SBB EAX,3E00401FF0. 822D BA404000 >SUB BYTE PTR DS:[4040BA],-7900401FF7. F8 CLC00401FF8. 83D6 01 ADC ESI,100401FFB. 83F0 B7 XOR EAX, FFFFFFB700401FFE. 3105 4E414000 XOR DWORD PTR DS:[40414E], EAX00402004. 810D ED404000 >OR DWORD PTR DS:[4040ED],0A50040200E. 31C0 XOR EAX, EAX00402010. 31C0 XOR EAX, EAX00402012. 29D2 SUB EDX, EDX00402014. 29F2 SUB EDX, ESI00402016. F7DA NEG EDX00402018. 31C0 XOR EAX, EAX0040201A. 8335 DE414000 >XOR DWORD PTR DS:[4041DE],6400402021. 3105 66404000 XOR DWORD PTR DS:[404066], EAX00402027. 31C0 XOR EAX, EAX00402029. 83D0 CC ADC EAX,-340040202C. 2B05 33414000 SUB EAX, DWORD PTR DS:[404133]00402032. C1C2 03 ROL EDX,300402035. 1305 4D404000 ADC EAX, DWORD PTR DS:[40404D]0040203B. 11C0 ADC EAX, EAX0040203D. 83C8 B4 OR EAX, FFFFFFB400402040. 19C0 SBB EAX, EAX00402042. C1C2 05 ROL EDX,500402045. 0105 4B404000 ADD DWORD PTR DS:[40404B], EAX0040204B. 2B05 3C404000 SUB EAX, DWORD PTR DS:[40403C]00402051. 1305 B0404000 ADC EAX, DWORD PTR DS:[4040B0]00402057. C705 C4404000 >MOV DWORD PTR DS:[4040C4],0B900402061. 56 PUSH ESI00402062. 8F01 POP DWORD PTR DS:[ECX] < — Сохранение в выделенный участок памяти00402064. 83E0 0E AND EAX,0E00402067. 1905 F8414000 SBB DWORD PTR DS:[4041F8],EAX0040206D. 2905 45404000 SUB DWORD PTR DS:[404045],EAX00402073. A3 8F404000 MOV DWORD PTR DS:[40408F],EAX00402078. A3 AF404000 MOV DWORD PTR DS:[4040AF],EAX0040207D. 83C1 04 ADD ECX,400402080. 2905 18414000 SUB DWORD PTR DS:[404118],EAX00402086. 19C0 SBB EAX,EAX00402088. 83D0 D9 ADC EAX,-270040208B. 0905 3C404000 OR DWORD PTR DS:[40403C],EAX00402091. 19C0 SBB EAX,EAX00402093. 8D5B FC LEA EBX,DWORD PTR DS:[EBX-4]00402096. 83D8 12 SBB EAX,1200402099. 2105 15414000 AND DWORD PTR DS:[404115],EAX0040209F. C705 AE414000 >MOV DWORD PTR DS:[4041AE],33004020A9. C705 18404000 >MOV DWORD PTR DS:[404018],0DA004020B3. 68 4A1F4000 PUSH g_r_pice.00401F4A004020B8. C3 RETN

Говорим отладчику дизассемблировать целевую область памяти и получаем ожидаемый результат — вполне себе исполняемый код:

b3359552e6ee493aa5ae33f7d61b08a4.png

Переход к расшифрованному коду не заставил себя ждать:

45e6bc0e4a6d4e698e9529a108a75af8.png

В самом начале встречаем интересный метод передачи параметров процедурам. Рассмотрим на примере первой такой функции. Как видно происходит вызов функции LoadLibrary, в которую необходимо передать строковую переменную имени библиотеки для загрузки.

02120000 8B7424 04 MOV ESI, DWORD PTR SS:[ESP+4]02120004 55 PUSH EBP02120005 E8 DF010000 CALL 021201E90212000A 58 POP EAX0212000B 50 PUSH EAX0212000C FFD6 CALL ESI     ; kernel32.LoadLibraryA

Перед указанной функцией происходит вызов процедуры «CALL 021001E9». Вот, что она из себя представляет: 021201E9 58 POP EAX     ; 0210000A021201EA FFD0 CALL EAX

Что же в этот момент происходит? При вызове «CALL 021001E9» в стек помещается адрес следующей после этого вызова инструкции для возврата из процедуры. После вызова из стека извлекается адрес возврата и помещается в EAX. Далее происходит вызов «CALL EAX», который в свою очередь снова помещает в стек адрес следующей инструкции для возврата. Смотрим в дампе — видим имя библиотеки: 1acad2c797854d0aa1081cf125ff6e0e.png

Далее по листингу еще не раз встречается такой метод.

Следующий интересный момент — процедура поиска необходимых функций из подключенной библиотеки. Среди параметров, передаваемых в процедуру — указатель на непонятный набор байтов, полученный вышеописанным методом, далее разберемся зачем и что это. Итак, сама процедура:

0212034B 60 PUSHAD0212034C EB 07 JMP SHORT 021203550212034E AD LODS DWORD PTR DS:[ESI] < — Алгоритм прохода по заголовкам подключенной DLL с целью поиска таблицы экспорта0212034F ^E2 FD LOOPD SHORT 0212034E02120351 8D3403 LEA ESI,DWORD PTR DS:[EBX+EAX]02120354 C3 RETN02120355 8BE8 MOV EBP,EAX02120357 8BF3 MOV ESI,EBX02120359 B9 10000000 MOV ECX,100212035E E8 EBFFFFFF CALL 0212034E02120363 B9 1F000000 MOV ECX,1F02120368 E8 E1FFFFFF CALL 0212034E0212036D 56 PUSH ESI0212036E B9 07000000 MOV ECX,702120373 E8 D6FFFFFF CALL 0212034E02120378 8BD0 MOV EDX,EAX0212037A 8B3424 MOV ESI,DWORD PTR SS:[ESP]0212037D B9 09000000 MOV ECX,902120382 E8 C7FFFFFF CALL 0212034E02120387 8BFE MOV EDI,ESI02120389 8BCA MOV ECX,EDX0212038B E8 BEFFFFFF CALL 0212034E02120390 33C0 XOR EAX,EAX02120392 50 PUSH EAX02120393 C1C8 07 ROR EAX,7 < — Вычисление хеш-суммы от имени функции из таблицы экспорта DLL02120396 C10424 0D ROL DWORD PTR SS:[ESP],0D0212039A 010424 ADD DWORD PTR SS:[ESP],EAX0212039D AC LODS BYTE PTR DS:[ESI]0212039E 84C0 TEST AL,AL021203A0 ^75 F1 JNZ SHORT 02120393021203A2 58 POP EAX021203A3 8BF7 MOV ESI,EDI021203A5 3BC5 CMP EAX,EBP < — Сравнение полученной хеш-суммы со значением в памяти021203A7 74 03 JE SHORT 021203AC021203A9 4A DEC EDX021203AA ^75 DD JNZ SHORT 02120389021203AC 8B3424 MOV ESI,DWORD PTR SS:[ESP] < — Если хеш совпал, то происходит поиск и возврат адреса искомой функции021203AF B9 0A000000 MOV ECX,0A021203B4 E8 95FFFFFF CALL 0212034E021203B9 0FB70C56 MOVZX ECX,WORD PTR DS:[ESI+EDX*2]021203BD 5E POP ESI021203BE 51 PUSH ECX021203BF B9 08000000 MOV ECX,8021203C4 E8 85FFFFFF CALL 0212034E021203C9 59 POP ECX021203CA E8 7FFFFFFF CALL 0212034E021203CF 897424 1C MOV DWORD PTR SS:[ESP+1C],ESI021203D3 61 POPAD021203D4 C3 RETN

Теперь понятно, данная процедура получает указатель на некую хеш-сумму и адрес DLL, в которой необходимо провести поиск функции. Далее логика по порядку: По заголовкам PE вычисляется адрес таблицы экспорта целевой DLL; Берется имя каждой функции из таблицы экспорта и вычисляется некая хеш-сумма; Проверяется совпадение вычисленной хеш-суммы и полученной в параметре; Если хеш-суммы совпали вычисляется и возвращается адрес найденной функции. По мере поиска необходимых функций происходит перезапись исходных хеш-сумм на реальные адреса: c24811ee01964569ba3d679cf566e31d.png

Затем с помощью «GetProcAddress» находятся адреса еще трех функций: HeapAlloc, HeapFree и GetTickCount.

02120039 5F POP EDI0212003A 83C7 0D ADD EDI,0D0212003D 57 PUSH EDI0212003E 53 PUSH EBX0212003F FF55 08 CALL DWORD PTR SS:[EBP+8]02120042 8906 MOV DWORD PTR DS:[ESI], EAX02120044 83C7 0A ADD EDI,0A02120047 57 PUSH EDI02120048 53 PUSH EBX02120049 FF55 08 CALL DWORD PTR SS:[EBP+8]0212004C 8946 04 MOV DWORD PTR DS:[ESI+4], EAX0212004F 83C7 09 ADD EDI,902120052 57 PUSH EDI02120053 53 PUSH EBX02120054 FF55 08 CALL DWORD PTR SS:[EBP+8]     ; kernel32.GetProcAddress02120057 8946 08 MOV DWORD PTR DS:[ESI+8], EAX

Найденные адреса дописываются в конец уже сформированного массива адресов используемых API: b2e1559f3e63469f9c69af72914c75b0.png

Массив используемых функций сформирован, после чего сразу начинается его использование с выделения новой области памяти такого же размера, как и в прошлый раз — 0×6D0:

16da64fb7024432492b09826136eb570.png

flProtect = 0×40, что снова говорит о возможности исполнения кода в выделяемом участке памяти.После «VirtualAlloc» сразу встречаем цикл копирования текущего участка памяти в новый, при этом сохранив в стек адрес возврата для «RETN» на смещение 0×81:

7474ea6f9aba41689db0f7ed32f9aba2.png

«RETN» переносит исполнение кода на новый участок памяти, который выглядит так:

00220081 E8 CB050000 CALL 0022065100220086 5D POP EBP00220087 5E POP ESI00220088 873424 XCHG DWORD PTR SS:[ESP], ESI0022008B 56 PUSH ESI0022008C E8 2E050000 CALL 002205BF00220091 E8 6C050000 CALL 00220602

«CALL 00220651» — уже известная нам процедура, которая хитрым образом возвращает нам адрес массива с адресами восстановленных функций.«CALL 002205BF» — проверяет валидность загруженного в память процесса по сигнатурам «MZ» и «PE». 002205BF 66:33F6 XOR SI, SI002205C2 66: BA 4D5A MOV DX,5A4D002205C6 66: AD LODS WORD PTR DS:[ESI]002205C8 66:33D0 XOR DX, AX002205CB 74 08 JE SHORT 002205D5002205CD 81EE 02100000 SUB ESI,1002002205D3 ^EB ED JMP SHORT 002205C2002205D5 8D5E FE LEA EBX, DWORD PTR DS:[ESI-2]002205D8 84FF TEST BH, BH002205DA ^75 F1 JNZ SHORT 002205CD002205DC 8B76 3A MOV ESI, DWORD PTR DS:[ESI+3A]002205DF 66: BA 5045 MOV DX,4550002205E3 8D341E LEA ESI, DWORD PTR DS:[ESI+EBX]002205E6 66: AD LODS WORD PTR DS:[ESI]002205E8 66:33D0 XOR DX, AX002205EB ^75 E0 JNZ SHORT 002205CD002205ED C3 RETN

«CALL 00220602» — выделяет новый участок памяти размером 0×2C00 (теперь только для чтения/записи), находит полное имя файла, запустившего текущий процесс и открывает файл для чтения 00220602 8B7D 70 MOV EDI, DWORD PTR SS:[EBP+70]      ; SS:[002206C4]=00002C0000220605 6A 04 PUSH 400220607 68 00100000 PUSH 10000022060C 57 PUSH EDI0022060D 6A 00 PUSH 00022060F FF55 10 CALL DWORD PTR SS:[EBP+10]     ; kernel32.VirtualAlloc00220612 8BF0 MOV ESI, EAX00220614 81EC 04010000 SUB ESP,1040022061A 8BFC MOV EDI, ESP0022061C 68 04010000 PUSH 10400220621 57 PUSH EDI00220622 53 PUSH EBX      ;0040000000220623 FF55 20 CALL DWORD PTR SS:[EBP+20]     ; kernel32.GetModuleFileNameA00220626 6A 00 PUSH 000220628 68 80000000 PUSH 800022062D 6A 03 PUSH 30022062F 6A 00 PUSH 000220631 6A 01 PUSH 100220633 68 00000080 PUSH 8000000000220638 57 PUSH EDI00220639 FF55 24 CALL DWORD PTR SS:[EBP+24]     ; kernel32.CreateFileA0022063C 81C4 04010000 ADD ESP,10400220642 C3 RETN

После возврата хендла на открытый файл устанавливается указатель со смещением 0×6263:

00220096 8BF8 MOV EDI, EAX00220098 6A 00 PUSH 00022009A 6A 00 PUSH 00022009C FF75 6C PUSH DWORD PTR SS:[EBP+6C]      ; SS:[002206C0]=000062630022009F 57 PUSH EDI002200A0 FF55 28 CALL DWORD PTR SS:[EBP+28]     ; kernel32.SetFilePointer

В HEX редакторе можно посмотреть, что по данному смещению действительно хранятся какие-то данные, скорее всего зашифрованные: 7ba5ff05904346438277cd65afe056e0.pngСчитывание данных из файла размером 0×2C00 по указанному смещению в созданный ранее сегмент памяти:

002200A3 8B4D 70 MOV ECX, DWORD PTR SS:[EBP+70]      ; SS:[002206C4]=00002C00002200A6 6A 00 PUSH 0002200A8 54 PUSH ESP002200A9 58 POP EAX002200AA FF3424 PUSH DWORD PTR SS:[ESP]      ; Stack SS:[0018FF28]=0000005C002200AD 50 PUSH EAX002200AE 51 PUSH ECX002200AF 56 PUSH ESI      ;00230000002200B0 57 PUSH EDI002200B1 FF55 2C CALL DWORD PTR SS:[EBP+2C]     ; kernel32.ReadFile

Далее вызывается процедура расшифровки скопированных данных:

942272c8946d49cd8710e00dbf545b2a.png

Весь листинг процедуры показывать не буду, вот цикл расшифровки:

00220505 3B75 60 CMP ESI, DWORD PTR SS:[EBP+60]00220508 75 0D JNZ SHORT 002205170022050A 0375 64 ADD ESI, DWORD PTR SS:[EBP+64]0022050D 037D 64 ADD EDI, DWORD PTR SS:[EBP+64]00220510 2B4D 64 SUB ECX, DWORD PTR SS:[EBP+64]00220513 85C9 TEST ECX, ECX00220515 74 12 JE SHORT 0022052900220517 AD LODS DWORD PTR DS:[ESI] < — чтение, расшифровка, запись00220518 50 PUSH EAX00220519 05 224AFE8D ADD EAX,8DFE4A220022051E 0FC8 BSWAP EAX00220520 33C2 XOR EAX,EDX00220522 5A POP EDX00220523 AB STOS DWORD PTR ES:[EDI]00220524 83E9 03 SUB ECX,300220527 ^E2 DC LOOPD SHORT 00220505

После расшифровки в дампе можно наблюдать такую картину:

309dc90bea624ea080551a50f5dba7b4.png

Сигнатуры «MZ» и «PE» подсказывают, что мы близки к цели.

Формирование новых заголовков и секций текущего процесса.После расшифровки происходит перезапись 512 байт в ImageBase текущего процесса расшифрованными данными (естественно предварительно поменяв права на целевую область памяти на RW):

b7c7de2cd02248acb79409d820d447d2.png

Итог — старые заголовки и таблица секций переписана новыми. Как видно из новой таблицы секций — будет две секции ».text» и ».rsrc»:

5abb92d09f0d462f9706224ed1240241.png

Далее переходим к следующему коду:

00220101 0349 3C ADD ECX, DWORD PTR DS:[ECX+3C]00220104 8D79 18 LEA EDI, DWORD PTR DS:[ECX+18]00220107 8B57 20 MOV EDX, DWORD PTR DS:[EDI+20]0022010A 0FB741 14 MOVZX EAX, WORD PTR DS:[ECX+14]0022010E 03F8 ADD EDI, EAX00220110 0FB749 06 MOVZX ECX, WORD PTR DS:[ECX+6]00220114 60 PUSHAD < — начало цикла формирования новых секций00220115 8B47 08 MOV EAX,DWORD PTR DS:[EDI+8]00220118 85C0 TEST EAX,EAX0022011A 74 42 JE SHORT 0022015E0022011C E8 CD040000 CALL 002205EE00220121 8BC8 MOV ECX,EAX00220123 8B47 24 MOV EAX,DWORD PTR DS:[EDI+24]00220126 E8 AA020000 CALL 002203D50022012B 0377 14 ADD ESI,DWORD PTR DS:[EDI+14]0022012E FF77 10 PUSH DWORD PTR DS:[EDI+10]00220131 8B7F 0C MOV EDI,DWORD PTR DS:[EDI+C]00220134 03FB ADD EDI,EBX00220136 5B POP EBX00220137 50 PUSH EAX00220138 8BD4 MOV EDX,ESP0022013A 52 PUSH EDX0022013B 50 PUSH EAX0022013C 51 PUSH ECX0022013D 57 PUSH EDI0022013E 51 PUSH ECX0022013F 52 PUSH EDX00220140 6A 04 PUSH 400220142 51 PUSH ECX00220143 57 PUSH EDI00220144 FF55 0C CALL DWORD PTR SS:[EBP+C]00220147 59 POP ECX00220148 33C0 XOR EAX,EAX0022014A 57 PUSH EDI0022014B F3:AA REP STOS BYTE PTR ES:[EDI] < — обнуление основной области памяти процесса0022014D 5F POP EDI0022014E 85F6 TEST ESI,ESI00220150 74 08 JE SHORT 0022015A00220152 85DB TEST EBX,EBX00220154 74 04 JE SHORT 0022015A00220156 8BCB MOV ECX,EBX00220158 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] < — Запись новой секции0022015A FF55 0C CALL DWORD PTR SS:[EBP+C]0022015D 58 POP EAX0022015E 61 POPAD0022015F 83C7 28 ADD EDI,2800220162 ^E2 B0 LOOPD SHORT 00220114

В самом начале производится поиск таблицы секций. Далее по циклу находится RawData и VirtualSize каждой секции, обнуление основных участков памяти и запись новых секции. Тем самым формируется новое «тело» текущего процесса.Далее встречаем вызов процедуры:

00220169 E8 AE000000 CALL 0022021C

Она выполняет восстановление IAT (Import Address Table) в начале секции ».text». Итог работы процедуры: 373f346193f248a69e4430f4209ccb66.pngДалее освобождается память, в которой ранее хранились данные для формирования нового окружения процесса (0×00230000):

002201BD FF55 14 CALL DWORD PTR SS:[EBP+14]     ; kernel32.VirtualFree

Подошли к эпилогу — извлечение OEP:

322d99d6ec10422d803f4dfc9b828692.png

И переход к OEP:

eab3edb3712e42e5a45af139a57ffe2e.png

Говорим отладчику проанализировать код и получаем красивый и читаемый листинг уже распакованного downloader’а, в котором уже различимы строки, используемые для загрузки основного функционального модуля:

37c6049005574b8e80c690451899d28f.png

Общая логика декриптора 9e5ad26732bd43cca9f66a024467d308.pngВыделение области памяти с правами RWE, размером 0×6D0 (1744 байта) с помощью HeapCreate. Расшифровка и копирование данных из секции .data (0×00408E63 — 0×00409532) в выделенную память; Перенос исполнения кода на нулевое смещение выделенной памяти; Поиск необходимых API функций и создание массива с их адресами по смещению 0×654 в текущей области памяти; Создание нового участка памяти с правами RWE, того же размера 0×6D0 (1744 байта) с помощью VirtualAlloc. Копирование содержимого текущего участка памяти в новый; Перенос исполнения кода на новый участок памяти по смещению 0×81 методом «PUSH — RETN»; Выделение нового участка памяти размером 0×2C00 (11 264 байта) с правами RW; Открытие исходного файла для чтения. Копирование данных (с файловым смещением 0×6263 — 0×8E62) из файла в новый участок памяти; Расшифровка скопированных данных; Формирование нового окружения процесса; Переход к OEP (0×004019BA). Дамп процесса Остается сделать дамп процесса для получения исполняемого распакованного файла вируса. Чтобы не заниматься ручным фиксом после дампа я воспользовался плагином OllyDumpEx для Immunity Debugger: d056590f7a454583871096b8b7a3495a.png

Полученный исполняемый файл при запуске имеет следующую структуру:

9ae9f6ffa5e140eca0d0573274835d3c.png

Заключение В ходе проделанной работы получили распакованный исполняемый файл Downloader’а. Да, можно было бы сократить описание, пройдясь по ключевым точкам копирования и расшифровки данных и переходу к OEP. В боевых условиях при анализе вредоносного ПО наверняка редко разбирают логику декриптора подробно. Но напомню, цель статьи — погрузиться в реверсинг и, как бонус, понять, как работают протекторы вредоносного ПО.Цель, которой я так и не смог достичь в данной статье — локализация основных моментов протектора, которые отвечают за «обман» эмулятора антивируса. Данные конструкции наверняка присутствуют в декрипторе. Если кто подскажет, как их идентифицировать — буду признателен.

Во второй части статьи рассмотрим функциональную нагрузку Downloader’а и каким образом запускается сам шифровальщик CTB-Locker. Не обещаю, что она появится на днях, т.к. ограничен во времени, да и не отрицаю своего малого опыта в данной сфере — с некоторыми моментами разбираюсь по ходу написания статей, что тоже отнимает время.

© Habrahabr.ru