Я пытаюсь определить, работает ли моя Windows на виртуальной машине или нет. Я нашел этот код C, который известен как Красная Таблетка Джоанны Рутковской:
int swallow_redpill ()
{
unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
*((unsigned*)&rpill[3]) = (unsigned)m;
((void(*)())&rpill)();
return (m[5]>0xd0) ? 1 : 0;
}
Но когда я запускаю его в своем проекте VC ++, он терпит неудачу на линии
((void(*)())&rpill)();
с сообщением: Нарушение прав доступа выполняется по адресу 0x003AFCE8.
Я что-то делаю не так?
Очевидно, пример кода пытается выполнить последовательность машинных инструкций, которые ведут себя по-разному внутри немного виртуальные машины, чем на * некоторых «реальных аппаратных средствах. Обратите внимание, что другие виртуальные машины могут не обнаруживаться при таком простом подходе.
Причина, по которой код не выполняется, заключается в том, что в современных ОС вы не можете выполнять разделы данных. Вам нужно было бы специально поместить этот фрагмент кода в исполняемый раздел или изменить раздел данных на исполняемый.
От Джоанна Рутковска фактический автор кода:
ПРИМЕЧАНИЕ: эта программа не будет работать в системах с защитой PAX / X ^ W / grsecurity (как было отмечено Брэдом Спенглером), поскольку переменная rpill не помечена как исполняемая. Чтобы запустить его в таких системах, следует использовать mprotect (), чтобы пометить rpill атрибутом PROT_EXEC. Другим решением было бы просто использовать ключевое слово asm () вместо буфера, похожего на шеллкод. Тем не менее, эту программу следует рассматривать скорее как каркас для встраивания в ваш собственный шелл-код, а не как автономный инструмент производственного класса;) Моя цель состояла в том, чтобы сделать его максимально простым и переносимым. Вот почему я не использовал ни asm (), ни mprotect (), поскольку они зависят от системы или компилятора.
#include <windows.h>
unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
int swallow_redpill ()
{
unsigned int old;
VirtualProtect(rpill, 8, PAGE_EXECUTE_READWRITE, &old);
*((unsigned*)&rpill[3]) = (unsigned)m;
((void(*)())&rpill)();
return (m[5]>0xd0) ? 1 : 0;
}
должен сделать трюк на Windows. Убедитесь, что вы запускаете его на Win32, если у вас машина x64.