Оглавление:
1. Вводная часть
2. Список возможных мест
• Аппаратные устройства
• Системный реестр
• Файлы в папке Windows
• Активные процессы
3. Практика
4. Выводы
1. Введение
В наш век бурно развивающейся ИТ-индустрии маскировка играет огромную роль. Малварь «с низкой социальной ответственностью» не хочет добровольно ложиться на операционный стол для трепанации кем-бы то нибыло своей тушки, а потому всеми силами пытается скрыть своё присутствие в системе. Инструментам статического и динамического анализа в виде дизассемблеров и отладчиков приходится воевать с довольно умным соперником – как показывает практика, зловредный код всегда идёт на шаг впереди. По этой причине, реверс-инженер должен распознавать в длинных листингах чужого кода последовательность действий, где просвечивается потенциальный обход виртуальных машин и песочниц.
Статический анализ вредоносного кода в IDA практически безопасен для исследователя, хотя в большинстве случаях профит от этого дела сомнителен и стремится к нулю. Обычно его используют на подготовительном этапе для просмотра взаимосвязей, перекрёстных ссылок, или списка импорта из системных DLL. А дальше приходится подключать уже тяжёлую артиллерию отладчиков, чтобы проследить ход событий в реальном времени. Если на данном этапе не оградить периметр своей хостовой системы, то вредоносный код выйдет из под контроля, что может привести к заражению ОС и потере конфиденциальных данных. Здесь и приходят на помощь виртуальные машины типа VirtualBox, VMware, или (менее производительные в данном контексте) эмуляторы Qemu, Bochs и иже с ними.
Этим инструментам реверсеров придают особых красок и песочницы Sandbox – этакая тестовая среда, в которой все действия подозрительного кода отслеживаются, все модифицированные файлы и настройки сохраняются, но в реальной хост-системе ничего не происходит. В хорошо настроенной песочнице без зазрения совести можно запускать любые файлы в полной уверенности, что на работоспособность ОС это никак не повлияет. Инструменты данного класса используют не только ради безопасности, но и для анализа всех действий зловреда, которые он выполняет после запуска своей тушки.
Однако любая уважающая себя малварь прекрасно осведомлена о внутреннем устройстве этих инструментов, поскольку как ни крути они являются программным обеспечением хоста, а значит при тщательных раскопках можно с лёгкостью найти их артефакты. По большому счёту, следы отладчиков, вирт.машин и песочниц невозможно скрыть в принципе, чем и спешит воспользоваться вирь. Если он обнаруживает хоть малейший намёк на неблагоприятную почву, то в целях маскировки может полность отказаться от «распространения флоры в особо-крупных..», тупо сделав себе харакири с запутывающей следы предсмертной надписью типа «В системе нет нужной мне библиотеки DLL», или просто провалившись в чёрную дыру. В списке ниже перечислены лишь наиболее известные способы обхода хакерами инструментов анализа, поскольку остальные являются их производными.
2. Координаты мест для раскопок
Вредоносные приложения используют различные методы для идентификации среды исполнения, а специфические её черты упрощают поиск. Как песочницы, так и вирт.машины обычно не могут на 100% точно эмулировать рабочую станцию пользователя – например ВМ имеют ограниченные системные ресурсы, свои драйверы и библиотеки DLL, часто используют жёстко прописанные имена пользователей и компьютеров, и т.д. Так почему-же не воспользоваться этим?
2.1. Аппаратные устройства
Сейчас типичная рабочая станция имеет как минимум: ЦП=2 ядра, ОЗУ=2 ГБ, и HDD=80/120 ГБ. Искусственный интеллект малвари может проверить, подчиняется ли среда этим ограничениям. Отметим, что в отличии от эмуляторов, вирт.машины и песочницы используют оригинальное имя вендора CPU, а потому делать на него ставку не имеет смысла. Частота процессора тоже отображается штатно, а вот ядро/core в большинстве случаях на ВМ одно, тонна оперативы, да динамически увеличивающийся хард примерно в 10..20 гигов. Это действительно только для вирт.машин, т.к. песочницы в этом плане полностью садятся на характеристики рабочей станции.
В дефолтных настройках ВМ девайсы имеют предсказуемые имена – например можно чекнуть модель HDD и DVDROM, производителя и название контроллера графики (включая разрешение дисплея в пикселях). Мы так-же можем искать определённые вирт.устройства, которых заведомо нет в типичной хостовой системе – это каналы Pipe и порты ALPC для связи гостя с хостом. Особое внимание нужно обратить и на MAC-адрес девайса сети, где первые три байта являются идентификатором производителя.
Скорость выполнения инструкций процессора сильно отличается от таковой на вирт.платформе, а потому, чтобы приблизить обстановку к реальной, любая ВМ перехватывает API системных таймеров. К примеру у функции Sleep() всего один аргумент в виде задержки в милли/сек – она останавливает активный поток, а по истечении указанного времени вновь пробуждает. Однако перехватив ВМ анализирует значение этого аргумента, и на выходе из функции возвращает в регистре
EAX
строго переданное нами время, хотя по вине относительно низкой частоты аппаратного таймера PIT=32.768 КГц, на реальной системе обязательно будут отклонения +/- 1%. Например если мы укажем Sleep(1000) для задержки в 1 сек, то на вирт.машине получим точно EAX=1000
, а на реальной чуть меньше EAX=990
, или наоборот больше EAX=1010
. Данный факт с определённой долей вероятности позволяет выявить работу кода на вирт.машине.Здесь нужно отметить, что малварь не лыком шита, и в запазухе у неё имеются масса других способов получения тиков системного времени. Она может узнать, перехвачена или нет пользовательская Sleep() или GetTickCount() – для этого достаточно прочитать несколько байт в прологе функции в памяти, после чего загрузить оригинал либы Kernel32.dll с диска, и найдя в ней нужную функцию сравнить два пролога. Если они отличаются, значит ВМ перехватила API сплайсингом и вредонос спускается на уровень ниже, чтобы отправить текущий поток в царство Морфея при помощи NtDelayExecution() из нативной библиотеки Ntdll.dll.
Код:
0: kd> u Sleep Пролог
kernel32!Sleep: ------------
00000000`7740efa8 ff2542e80700 jmp qword [kernel32!_imp_Sleep (00000000`7748d7f0)]
00000000`7740efae 90 nop
00000000`7740efaf 90 nop
00000000`7740efb0 90 nop
0: kd> u NtDelayExecution
ntdll!ZwDelayExecution:
00000000`77678e00 4c8bd1 mov r10,rcx
00000000`77678e03 b831000000 mov eax,31h
00000000`77678e08 0f05 syscall
00000000`77678e0a c3 ret
В малвари нового поколения встречается ещё один довольно хитрый приём – она вообще не обращается к API таймеров, а читает тики напрямую из доступной юзеру ядерной структуры KUSER_SHARED_DATA, которая проецируется Win всегда по одинаковому адресу
0x7ffe0000
как на х32, так и на х64. Поле TickCountQuad размером qword расположено в ней по смещению 0x320
.
Код:
0: kd> dt _KUSER_SHARED_DATA 0x7ffe0000 Tick.
ntdll!_KUSER_SHARED_DATA
+0x000 TickCountLowDeprecated : 0
+0x004 TickCountMultiplier : 0xf99a027
+0x320 TickCountQuad : 0x1e2423
+0x32c TickCountPad : 0
0: kd>
Как видим, по смещению(4) лежит множитель – он решает проблему совместимости одной структуры на 2 системы разной разрядности х32/64. Таким образом вместо вызова API GetTickCount() (возвращает кол-во милли/сек с момента запуска системы), можно смело брать тики из KUSER_SHARED_DATA, поскольку судя по листингам дизассма, эта API под катом проделывает то-же самое:
Код:
0: kd> u GetTickCount
kernel32!GetTickCount:
00000000`7730ef40 ff25f2e90700 jmp qword [kernel32!_imp_GetTickCount (00000000`7738d938)]
00000000`7730ef46 90 nop
0: kd> dps 00000000`7738d938 L5
00000000`7738d938 000007fe`fd101120 KERNELBASE!GetTickCount
00000000`7738d940 000007fe`fd108350 KERNELBASE!GlobalMemoryStatusEx
00000000`7738d948 000007fe`fd113730 KERNELBASE!GetVersion
00000000`7738d950 000007fe`fd13b560 KERNELBASE!GetWindowsDirectoryA
00000000`7738d958 00000000`00000000
;//--------------------------------- x64 ----------------------------
0: kd> u KERNELBASE!GetTickCount
KERNELBASE!GetTickCount:
000007fe`fd101120 8b0c250400fe7f mov ecx,dword [SharedUserData+0x004 (00000000`7ffe0004)]
000007fe`fd101127 488b04252003fe7f mov rax,qword [SharedUserData+0x320 (00000000`7ffe0320)]
000007fe`fd10112f 480fafc1 imul rax,rcx <------ перемножить 2 поля
000007fe`fd101133 48c1e818 shr rax,18h <------ поправка к 100 нано/сек блокам (см. MSDN)
000007fe`fd101137 c3 ret
;//--------------------------------- x32 ----------------------------
kd> uf GetTickCount
kernel32!GetTickCount:
7c80934a ba0000fe7f mov edx,offset SharedUserData (7ffe0000)
7c80934f 8b02 mov eax,dword ptr [edx]
7c809351 f76204 mul eax,dword ptr [edx+4]
7c809354 0facd018 shrd eax,edx,18h
7c809358 c3 ret
kd>
2.2. Системный реестр
Реестр Win – это вообще кладезь информации. Вот наиболее интересные ключи и их значения:
•
HKLM\HARDWARE\Description\System
– можно прочитать версию BIOS, которая будет отличаться на реальной и вирт.машине•
HKLM\SYSTEM\ControlSet001\Services
– службы, среди которых много указывающих на ВМ и песочницу артефактов•
HKLM\SYSTEM\CurrentControlSet\Enum\IDE
– названия харда и CDROM2.3. Файлы в папке Windows
При установки как песочницы, так и ВМ, они обязательно нагадят в системную папку Win и ProgramFiles. Так-что можно проверить их содержимое, где обнаружим библиотеки и драйвера гипервизора вирт.машины. В папке с программами хоста, VirtualBox создаёт каталог Oracle, но поскольку малварь мы будем пытать не на хосте, а на ВМ, то соответственно нужно чекать либы DLL именно в папке System32 виртуальной среды. Зоопарк там приличный, имена всех библиотек начинаются с префикса VBox***.dll. Организовать их поиск легко функцией FindFirst/NextFile(), которая способна искать файлы как-раз по маске со-звёздочкой(*).
2.4. Активные процессы и модули
Особенностью наиболее распространённой из песочниц Sandboxie является то, что все её файлы имеют префиксы Sbie_xxx. Программное ядро включает в себя три файла – это драйвер SbieDrv.sys, служба SbieSvc.exe, и внедряемая во-все запускаемые из неё процессы Inject-библиотека SbieDll.dll. Таким образом, чтобы с вероятностью 99% поймать за хвост запуск кода из песочницы, достаточно перечислить все загруженные в нашу тушку модули DLL, и проверить среди них наличие либы SbieDll.dll.
В качестве контрольного выстрела можно использовать ещё один трюк. Дело в том, что для полной изоляции среды исполнения, песочницы создают себе отдельный рабочий стол «Desktop» внутри текущей станции. Узнать имя десктопа Sandboxie можно запустив софт «ProcessHacker» или «ProcExplorer» М.Руссиновича из пакета Sysinternals. На скрине ниже видно, что он называется «Default», в то время как на реальной чистой машине система обзывает его по имени раб.станции «WinSta0». Данный факт можно использовать в качестве вещдока.
3. Практическая часть
В следующем примере я собрал всё вышеизложенное под один капот.
Для поддержки кросплатформенности, код написал специально 32-битный. Поскольку в нём просвечиваются нотки малвари, то ясное дело аверы на VirusTotal будут обкладывать нас трёх-этажным матом, хотя реально никаких вредоносных действий в нём нет, кроме как обычного скана почвы под ногами. Но попробуй это объяснить тупому аверу.. ну да ладно. В общем вот основные моменты:
1. Вендора CPU берём инструкцией
CPUID
. Для этого нужен цикл начиная с EAX=0x80000002
и до EAX=0x80000004
. На каждом шаге CPUID
будет возвращать строку в 4-х регистрах общего назначения EAX,EBX,ECX,EDX
. Просто сбрасываем их в буфер, и дампим на консоль.
2. Самый простой способ узнать кол-во ядер процессора – это прочитать их из поля «NumberOfProcessors» по смещению(64) структуры РЕВ.
Реальную (не заявленную вендором) частоту процессора на текущий момент можно вычислить запросив тики CPU инструкцией
RDTSC
, затем функцией Sleep(1000) сделать паузу на 1 сек, и повторно прочитать тики. Разница между вторым и первым запросом и будет представлять собой значение «Frequency».
3. Объём установленной физ.памяти ОЗУ возвращает API GlobalMemoryStatusEx() – здесь всё штатно.
4. Как упоминалось выше, вирт.машина хукает функцию GetTickCount(), поэтому заснув на 1 сек через Sleep(1000), можно вычислить её.
5. В некоторых случаях можно прочитать имя машины GetComputerName() – если в ответ получим что-то несуразное, то делаем выводы.
6. Строку с типом графического адаптера возвращает EnumDisplayDevices(), а разрешение дисплея GetSystemMetrics().
7. Через RegOpenKeyEx() + RegQueryValueEx() заглянем в реестр Win, чтобы получить версию BIOS.
8. Функциями из либы Setuapi.dll типа SetupDiEnumDeviceInfo() можно получить строки с именем харда и сидюка – сдают ВМ с потрохами.
9. Открыв диск чз CreateFile() с последующим
IOCTL_DISK_GET_DRIVE_GEOMETRY
узнаем ёмкость диска в гигабайтах.
10. МАС-адрес сетевой карты возвращает GetAdaptersInfo() из либы Iphlpapi.dll.
11. FindFirst/NextFile() осуществляет поиск файлов по маске Vbox*.dll – остаётся сбросить их на консоль.
12. В либе Dbghelp.dll имеется функция EnumerateLoadedModules(), которую доктор прописал для перечисления всех модулей в нашем процессе.
13. И наконец EnumDesktops() возвращает в свой колбек имена всех рабочих столов в текущей станции.
C-подобный:
format pe console
include 'win32ax.inc'
include 'equates\iphlpapi.inc'
include 'equates\setupapi.inc'
entry start
;//-----------
section '.data' data readable writeable
ai IP_ADAPTER_INFO
devInfo SP_DEVINFO_DATA
memStat MEMORYSTATUS_EX
dispDev DISPLAY_DEVICEA
align 16
struct DISK_GEOMETRY
totalCyl dd 0,0 ; - Цилиндров
mediaType dd 0 ; - Тип устройства
trackCyl dd 0 ; - Дорожек (треков) в цилиндре
secTrack dd 0 ; - Секторов в треке
byteSec dd 0 ; - Байт в секторе
ends
diskGeo DISK_GEOMETRY
IOCTL_DISK_GET_DRIVE_GEOMETRY = 0x00070000
sizePointer dd 0
hndl dd 0
type dd 0
mByte dd 1024*1024
gByte dd 1024*1024*1024
result dq 0
buff db 0
;//-----------
section '.text' code readable executable
start: invoke SetConsoleTitle,<'*** Virtual Machine & Sandbox Detect ***',0>
;//----- Инфа о процессоре -------------------------------
mov edi,buff
mov ecx,3
mov eax,0x80000002
@@: push eax ecx
cpuid
stosd
xchg eax,ebx
stosd
xchg eax,ecx
stosd
xchg eax,edx
stosd
pop ecx eax
inc eax
loop @b
cinvoke printf,<10,' CPU name string.....: %s',0>,buff
mov eax,[fs:30h]
mov eax,[eax+64h]
cinvoke printf,<10,' CPU cores...........: %d',0>,eax
rdtsc
push eax
invoke Sleep,1000
rdtsc
pop ebx
sub eax,ebx
shr eax,20
cinvoke printf,<10,' CPU frequency.......: %d.0 MHz',0>,eax
;//----- Размер памяти -----------------------------------
invoke GlobalMemoryStatusEx,memStat
push dword[memStat.dqTotalPhys+4]
push dword[memStat.dqTotalPhys]
fild qword[esp]
fidiv [mByte]
fstp [result]
add esp,8
cinvoke printf,<10,' Physical memory.....: %.1f Mb',0>,\
dword[result],dword[result+4]
;//----- Тест по таймеру ---------------------------------
cinvoke printf,<10,' Check 1 sec delay...: ',0>
invoke GetTickCount
push eax
invoke Sleep,1000
invoke GetTickCount
pop ebx
sub eax,ebx
cinvoke printf,<'%4u.0 msec',0>,eax
;//----- NetBios имя компьютера --------------------------
mov [sizePointer],128
invoke GetComputerName,buff,sizePointer
invoke CharToOem,buff,buff
cinvoke printf,<10,10,' Computer name.......: %s',0>,buff
;//----- Графический адаптер -----------------------------
invoke EnumDisplayDevices,0,0,dispDev,1
lea ebx,[dispDev.DeviceString]
cinvoke printf,<10,' Display device......: %s',0>,ebx
invoke GetSystemMetrics,SM_CXSCREEN
push eax
invoke GetSystemMetrics,SM_CYSCREEN
pop ebx
cinvoke printf,<'. %d x %d',0>,ebx,eax
;//----- Версия биос из реестра --------------------------
call ClearBuff
invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,<'Hardware\Description\System',0>,0,KEY_ALL_ACCESS,hndl
mov [sizePointer],64
invoke RegQueryValueEx,[hndl],<'SystemBiosVersion',0>,0,type,buff,sizePointer
cinvoke printf,<10,' Bios Version........: %s',10,0>,buff
;//----- Имя харда и CD через SetupApi.dll ---------------
call ClearBuff
invoke SetupDiGetClassDevs,GUID_DEVCLASS_CDROM,0,0,DIGCF_PROFILE
push eax
invoke SetupDiEnumDeviceInfo,eax,0,devInfo
pop eax
invoke SetupDiGetDeviceRegistryProperty,eax,devInfo,SPDRP_FRIENDLYNAME,0,buff,128,0
cinvoke printf,<10,' CD/DVDROM name.....: %s',0>,buff
call ClearBuff
invoke SetupDiGetClassDevs,GUID_DEVCLASS_DISKDRIVE,0,0,DIGCF_PRESENT
push eax
invoke SetupDiEnumDeviceInfo,eax,0,devInfo
pop eax
invoke SetupDiGetDeviceRegistryProperty,eax,devInfo,SPDRP_FRIENDLYNAME,0,buff,128,0
cinvoke printf,<10,' Hard drive name.....: %s',0>,buff
;//----- Размер диска ------------------------------------
call ClearBuff
invoke CreateFile,<'\\.\PhysicalDrive0',0>,0,FILE_SHARE_READ + FILE_SHARE_WRITE,\
0,OPEN_EXISTING,0,0
push eax
invoke DeviceIoControl,eax,IOCTL_DISK_GET_DRIVE_GEOMETRY,\
0,0,diskGeo,sizeof.DISK_GEOMETRY,type,0
pop eax
invoke CloseHandle,eax
mov eax,[diskGeo.byteSec]
imul eax,[diskGeo.secTrack]
imul eax,[diskGeo.trackCyl]
mov [type],eax
fild qword[diskGeo.totalCyl]
fimul [type]
fidiv [gByte]
fstp [result]
cinvoke printf, <10,' Hard drive size.....: %.1f Gb',10,0>,dword[result],dword[result+4]
;//----- МАС сетевой карты -------------------------------
invoke GetAdaptersInfo,ai,sizePointer
invoke GetAdaptersInfo,ai,sizePointer
movzx eax,[ai.Address+0]
movzx ebx,[ai.Address+1]
movzx ecx,[ai.Address+2]
movzx edx,[ai.Address+3]
movzx esi,[ai.Address+4]
movzx edi,[ai.Address+5]
cinvoke printf,<10,' NIC MAC address.....: %02x:%02x:%02x:%02x:%02x:%02x',\
10,' --------',\
10,' 08:00:27: <----- VBox v5.2',\
10,' 00:21:f6: v3.3',\
10,' 52:54:00: Vagrant or QEMU',\
10,' --------',\
10,' 00:50:56: <----- VMware Workstation',\
10,' 00:0c:29: ESXi Host ',\
10,' 00:05:69: ESXi,GSX',\
10,' 00:1c:14: VMware',10,0>,\
eax,ebx,ecx,edx,esi,edi
;//----- Библиотеки в Windows\system32 -------------------
call ClearBuff
invoke FindFirstFile,<'C:\Windows\System32\VBox*.dll',0>,buff
mov [hndl],eax
cinvoke printf,<10,' VBox \System32 dll..: %s',0>,buff+44
cmp [hndl],0
jz @f
@next: invoke FindNextFile,[hndl],buff
or eax,eax
jz @f
cinvoke printf,<10,23 dup(' '),'%s',0>,buff+44
jmp @next
@@: invoke CloseHandle,[hndl]
;//----- Sandbox - загруженные в процесс библиотеки ------
cinvoke printf,<10,10,' Sandboxie dll test..: ',0>
invoke GetCurrentProcess
invoke EnumerateLoadedModules,eax,EnumCallback,0
;//----- Перечисление рабочих столов Desktop -------------
cinvoke printf,<10,' Sandboxie Desktop...: ',0>
invoke EnumDesktops,0,DesktopCallback,0
@exit: cinvoke _getch
cinvoke exit, 0
;//********************************************************
proc ClearBuff
mov edi,buff
mov ecx,128/4
xor eax,eax
rep stosd
ret
endp
proc EnumCallback Name,Base,Size,Context
mov esi,[Name]
@@: lodsb
or al,al
jnz @b
sub esi,12
lodsd
cmp eax,'Sbie'
jnz @01
sub esi,4
cinvoke printf,<'%s <--- Found!',0>,esi
@01: mov eax,1
ret
endp
proc DesktopCallback Desktop,lParam
push esi
mov esi,[Desktop]
cmp dword[esi],'Defa'
jnz @02
cinvoke printf,<'%s <------- Found! ',0>,[Desktop]
@02: pop esi
mov eax,1
ret
endp
;//********************************************************
section '.idata' import data readable writeable
library msvcrt,'msvcrt.dll',kernel32,'kernel32.dll',\
user32,'user32.dll',iphlpapi,'iphlpapi.dll',\
advapi32,'advapi32.dll',setupapi,'setupapi.dll',dbghelp,'dbghelp.dll'
import dbghelp, EnumerateLoadedModules,'EnumerateLoadedModules'
include 'api\msvcrt.inc'
include 'api\kernel32.inc'
include 'api\user32.inc'
include 'api\iphlpapi.inc'
include 'api\setupapi.inc'
include 'api\advapi32.inc'
Теперь посмотрим на табун подстреленных зайцев..
Вот что вернул код на моей реальной машине с Win7 на борту.
Обратите внимание на значение 1 сек задержки, которая в данном случае равна 998 м/сек (погрешность таймера PIT), хотя я запрашивал ровно 1000. А в остальном ничего особенного, с реально присутствующим железом на моём экспериментальном узле:
А дальше лог кода, который я запустил уже в песочнице Sandboxie.
В принципе всё аналогично, если не считать без спроса заинжектенную в мой процесс левую библиотеку SbieDll.dll, а так-же рабочий стол «Default». Если-бы не этот нюанс, обнаружить песочницу было-бы весьма проблематично:
Зато под VirtualBox хоть к гадалке не ходи – артефактов как грибов после дождя.
Во-первых, сколько-бы раз я не запускал этот код, Sleep(1000) в шапке всегда возвращает ровно переданное мною значение 1000 м/сек, что непременно вызывает подозрение. Ну и далее всё по нарастающей: графика, биос, диски, физ.адрес сети, и либы в системной папке. Такое впечатление, что разработчики вообще не ставили перед собой задачу что-то скрыть, хотя реализовать это не так-уж сложно было. С другой стороны, у вирт.машин совсем другое предназначение, с чем они отлично справляются.
4. Выводы
Под занавес хотелось-бы сказать, что если малварь так боится виртуальных машин и песочниц, значит можно её обмануть, создав фиктивную обстановку тестовой среды. К примеру написать какую-нибудь безобидную либу обозвав её SbieDll.dll и поместить в автозагрузку, или набросать в системную папку кучу текстовых файлов переименовав их в VВox*.dll из списка выше, и далее в том-же духе. Тогда после своих тестов зловредный код может клюнуть на удочку, и добровольно отказаться от заражения системы посчитав, что попал в виртуальную среду отладки. Пусть и не на 100%, но это ещё более укрепит оборонную крепость системы.
В скрепку положил исполняемый файл для тестов. Эксперименты я гонял на вирт.машине VBox, а спец для этого дела ставить VMware было лень. Поэтому если у кого имеется варя с установленной на неё Win от XP до 10 любой разрядности, просьба показать реакцию машины на этот код. В частности интересует названия аппаратных устройств, в т.ч. диски, МАС-адрес, и да и всё остальное. Буду премного благодарен, всем удачи, пока!
Ссылки по теме:
Список малвари, и варианты её обхода вирт.машин:
Ссылка скрыта от гостей
МАС-адреса виртуальных машин:
Ссылка скрыта от гостей
Ссылка скрыта от гостей