Авторские статьи Цветной экран смерти

Discussion in 'Статьи' started by _Great_, 13 Feb 2007.

  1. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    Article: Цветной экран смерти
    Author: Great
    Date: 13.02.2007
    Lang: C/C++ kernel mode
    Note: Ко всем приелось уже знакомое сокращение - BSoD (Blue Screen of Death, Синий Экран Смерти). А что если... сделать его не синим. А, например, серым. Или зеленым?

    UPD: прежде чем прочитать, рекомендую в конце статьи найти ссылки на скриншоты и посмотреть :)

    Если ты кодил под Ring 0, то знаешь, что за показ экрана смерти ответственны функции ядра KeBugCheck и KeBugCheckEx.
    Правда, это реализовано немного по-разному в Windows 2000 и ниже и в Windows XP и выше.
    В Windows 2000 всю работу делает KeBugCheckEx, а KeBugCheck - обертка.
    В Windows XP KeBugCheckEx и KeBugCheck - обертки, всю работу делает внутренняя неэкспортируемая функция ядра KeBugCheck2.
    Где-то в теле функции происходит задание фона для экрана смерти. Мы попробуем его найти и пропатчить прямо в памяти. Для простоты мы будем писать для Windows XP, а отчасти и из-за того, что сейчас она установлена на большем числе компьютеров, чем Windows 2000.
    Поскольку все смещения и т.п. сильно зависят от билда, тут есть два пути - прописать смещения жестко для каждого билда или искать нужные данные динамически. Чтобы не усложнять себе жизнь, мы выберем первый вариант и пропишем смещения только для системы "Windows XP build 2600".
    Посмотрим на код функции KeBugCheck2:
    Code:
    //
    // Enable InbvDisplayString calls to make it through to bootvid driver.
    //
    
    if (InbvIsBootDriverInstalled()) {
    
        InbvAcquireDisplayOwnership();
    
        InbvResetDisplay();
        [b]InbvSolidColorFill(0,0,639,479,4); // make the screen blue[/b]
        InbvSetTextColor(15);
        InbvInstallDisplayStringFilter((INBV_DISPLAY_STRING_FILTER)NULL);
        InbvEnableDisplayString(TRUE);     // enable display string
        InbvSetScrollRegion(0,0,639,479);  // set to use entire screen
    }
    
    интересующую нас строчку я выделил. тут происходит задание цвета фона.
    Нам надо только лишь его поменять. Поехали!

    Итак, мы пишем под Windows XP 2600. Откроем в IDA Pro код KeBugCheckEx:
    Code:
    .text:0045C303 _KeBugCheckEx@20 proc near
    .text:0045C303 BugCheckCode    = dword ptr  8
    .text:0045C303 BugCheckParameter1= dword ptr  0Ch
    .text:0045C303 BugCheckParameter2= dword ptr  10h
    .text:0045C303 BugCheckParameter3= dword ptr  14h
    .text:0045C303 BugCheckParameter4= dword ptr  18h
    .text:0045C303
    .text:0045C303                 mov     edi, edi
    .text:0045C305                 push    ebp
    .text:0045C306                 mov     ebp, esp
    .text:0045C308                 push    0               ; int
    .text:0045C30A                 push    [ebp+BugCheckParameter4] ; int
    .text:0045C30D                 push    [ebp+BugCheckParameter3] ; int
    .text:0045C310                 push    [ebp+BugCheckParameter2] ; int
    .text:0045C313                 push    [ebp+BugCheckParameter1] ; int
    .text:0045C316                 push    [ebp+BugCheckCode] ; int
    .text:0045C319                 call    _KeBugCheck2@24 ; KeBugCheck2(x,x,x,x,x,x)
    
    Вот тут как раз и вызывается внутренняя функция KeBugCheck2. Опкод этой команды CALL выглядит так: E8 9CF4FFFF. E8 - код команды call, 9CF4FFFF - смещение KeBugCheck2 относительно следующей команды. Адрес команды call равен 0045C319, + 1 байт, мы получим 0045C31A - адрес смещения.
    0045C31Ah - 0045C303h (адрес KeBugCheckEx) = 17h - то есть адрес смещения функции KeBugCheck2 лежит через 17h байт после начала KeBugCheckEx.
    Что ж.. нам это пригодится. Глянем внутрь KeBugCheck2 и найдем вызов InbvSolidColorFill, устанавливающей цвет фона экрана:
    Code:
    .text:0045BDA3                 push    4
    .text:0045BDA5                 push    1DFh
    .text:0045BDAA                 mov     ebx, 27Fh
    .text:0045BDAF                 push    ebx
    .text:0045BDB0                 push    esi
    .text:0045BDB1                 push    esi
    .text:0045BDB2                 call    _InbvSolidColorFill@20 ; InbvSolidColorFill(x,x,x,x,x)
    Так-так. PUSH 4 - как раз заталкивание в стек цвета фона (4 - синий). Опкод команды PUSH 4 выглядит так: 6A 04 PUSH 4. Нам нужно изменить операнд команды PUSH. Адрес начала KeBugCheck2 - 0045B7BA, адрес операнда команды PUSH - 0045BDA4. Не нужно быть гением, чтобы посчитать разницу - 5EA.

    Вот мы и собрали все нужные нам данные. Приступим к кодерской части.
    Реализация будет такова - мы напишем драйвер ядра, у которого по DeviceIoControl можно вызвать 2 функции - прочитать текущий цвет и записать новый.
    С учетом всего вышенаписнаного, вот вспомогательная функция для получения адреса байта, где лежит цвет фона:
    Code:
    PUCHAR GetBugcheckColorAddress()
    {
    	DWORD addr = (DWORD) &KeBugCheckEx;
    	addr += 0x17;
    	addr = addr + 4 + *(DWORD*)addr;
    	addr += 0x5EA;
    	return (PUCHAR) addr;
    }
    Определим следующие два кода для DeviceIoControl:
    Code:
    #define IOCTL_FAULTDRIVER_GET_BUGCHECK_COLOR 0x0014
    #define IOCTL_FAULTDRIVER_SET_BUGCHECK_COLOR 0x0024
    
    Проследим, чтобы младшие 2 бита были сброшены - они показывают тип ввода-вывода при DeviceIoControl. 00 означает буферизированный ввод-вывод, он нам и нужен. Диспетчер ввода-вывода выделит системный буфер, скопирует пользовательский буфер в системный, мы его будем изменять как хотим, а потом системный буфер скопируется обратно в выходной.

    Напишем вот такую функцию для обработки IRP_MJ_DEVICE_CONTROL:

    Code:
    NTSTATUS DriverIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
    {
        PIO_STACK_LOCATION pisl     = IoGetCurrentIrpStackLocation(Irp);
    	NTSTATUS           status   = STATUS_UNSUCCESSFUL;
    	ULONG              BuffSize = pisl->Parameters.DeviceIoControl.InputBufferLength;
    	PUCHAR             pBuff    = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
    
    	Irp->IoStatus.Information = 0;
    
    	switch(pisl->Parameters.DeviceIoControl.IoControlCode)
    	{
    		case IOCTL_FAULTDRIVER_GET_BUGCHECK_COLOR: 
    			if (pBuff && pisl->Parameters.DeviceIoControl.OutputBufferLength >= 1)
    			{
    				DPRINT("[~] DeviceIoControl : IOCTL_FAULTDRIVER_GET_BUGCHECK_COLOR");
    
    				__try
    				{
    					if(*NtBuildNumber != 2600)
    					{
    						DPRINT("[!] This driver supports only Windows XP build 2600, current build is %d", *NtBuildNumber);
    						status = STATUS_ILLEGAL_FUNCTION;
    						break;
    					}
    					
    					PUCHAR lpBugcheckColor = GetBugcheckColorAddress();
    					*pBuff = *lpBugcheckColor;
    
    					DPRINT("[+] Search completed. Address is 0x%08x, bugcheck color is %02x", lpBugcheckColor, *pBuff);
    
    					Irp->IoStatus.Information = 1;
    					status = STATUS_SUCCESS;
    				}
    				__except(EXCEPTION_EXECUTE_HANDLER)
    				{
    					Irp->IoStatus.Status = status = GetExceptionCode();
    					Irp->IoStatus.Information = 0;
    
    					DPRINT("[!] Unhandled exception %.x", status);
    					break;
    				}
    			}
    			break;
    
    		case IOCTL_FAULTDRIVER_SET_BUGCHECK_COLOR: 
    			DPRINT("Buffer size = %d", BuffSize);
    
    			if (pBuff && BuffSize >= 1 && pisl->Parameters.DeviceIoControl.OutputBufferLength >= 1)
    			{
    				DPRINT("[~] DeviceIoControl : IOCTL_FAULTDRIVER_SET_BUGCHECK_COLOR");
    
    				__try
    				{
    					if(*NtBuildNumber != 2600)
    					{
    						DPRINT("[!] This driver supports only Windows XP build 2600, current build is %d", *NtBuildNumber);
    						status = STATUS_ILLEGAL_FUNCTION;
    						break;
    					}
    					
    					PUCHAR lpBugcheckColor = GetBugcheckColorAddress();
    					BYTE oldcolor = *lpBugcheckColor;
    
    					DPRINT("[+] Search completed. Address is 0x%08x, bugcheck color is %02x", lpBugcheckColor, oldcolor);
    					DPRINT("[~] Requested color is %02x", *pBuff);
    
    					*lpBugcheckColor = *pBuff;
    					*pBuff = oldcolor;
    
    					DPRINT("[+] New color set: %02x, color returned: %02x", *lpBugcheckColor, *pBuff);
    
    					Irp->IoStatus.Information = 1;
    					status = STATUS_SUCCESS;
    				}
    				__except(EXCEPTION_EXECUTE_HANDLER)
    				{
    					Irp->IoStatus.Status = status = GetExceptionCode();
    					Irp->IoStatus.Information = 0;
    
    					DPRINT("[!] Unhandled exception %.x", status);
    					break;
    				}
    			}		
    			break;
    	}   
    
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }
    Я думаю, стоит кое-что пояснить. Сначала мы получаем текущий стек ввода-вывода, адрес системного буфера и размеры входного и выходного буферов.
    Дальше смотрим, что же от нас хотят - прочитать или установить новый цвет. Основной код обернут в __try/__except, чтобы, не дай Бог, случайно не уронить систему, если что.
    Мы проверяем NtBuildNumber - номер билда ОС и ругаемся, если он не 2600. Дальше мы получаем адрес байта с цветом фона и химичим с ним. Выставляем в Irp->IoStatus.Information число байт, которое нужно скопировать в пользовательский буфер из системного.

    Остальной код драйвера комментировать, думаю, не стоит:

    Code:
    #define _X86_
    #include <ntddk.h>
    
    #define DPRINT DbgPrint
    
    UNICODE_STRING DeviceName;
    UNICODE_STRING SymbolicLinkName;
    PDEVICE_OBJECT deviceObject;
    
    void DriverUnload(IN PDRIVER_OBJECT DriverObject)
    {
    	IoDeleteSymbolicLink (&SymbolicLinkName);
    	if(deviceObject)
    		IoDeleteDevice (deviceObject);
    
    	DPRINT ("[+] Driver unloaded");
    }
    
    extern "C" PUSHORT NtBuildNumber;
    
    NTSTATUS DriverIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
    
    NTSTATUS DriverCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
    {
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }
    
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
    {
    	NTSTATUS status;
    
    	DPRINT("[~] Driver loading");
    
    	RtlInitUnicodeString(&DeviceName, L"\\Device\\faultdriver");
        RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\faultdriver");
    
    	status = IoCreateDevice(DriverObject, 
    		                    0, 
    							&DeviceName, 
    							FILE_DEVICE_UNKNOWN, 
    							0, 
    							TRUE, 
    							&deviceObject);
    	
    	if (!NT_SUCCESS(status))
    	{
    		DPRINT("[-] Failed to create device. IoCreateDevice returned %x", status);
    		return STATUS_UNSUCCESSFUL;
    	}
    	
    	deviceObject->Flags |= DO_BUFFERED_IO;
    	status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
    	if (!NT_SUCCESS(status))
    	{
    		DPRINT("[-] Failed to create symbolic link. IoCreateSymbolicLink returned %x", status);
    		IoDeleteDevice(deviceObject);
    		return STATUS_UNSUCCESSFUL;
    	}
    
    	// Set dispath routines
    		
    	DriverObject->DriverUnload = DriverUnload;
    
    	DriverObject->MajorFunction [IRP_MJ_CREATE] =
        DriverObject->MajorFunction [IRP_MJ_CLOSE ] = DriverCreateClose;
        DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL ] = DriverIoControl;
    
    	DPRINT("[+] Driver initialization successful");
    
    	return STATUS_SUCCESS;
    }
    
    Теперь у нас готов работающий драйвер, который умеет оперировать с цветом фона для экрана смерти.
    Напишем несложное GUI для этого. Я приведу только код юзермодных функций для работы с цветом:

    Code:
    // User mode API
    
    #define IOCTL_FAULTDRIVER_GET_BUGCHECK_COLOR 0x0014
    #define IOCTL_FAULTDRIVER_SET_BUGCHECK_COLOR 0x0024
    
    UCHAR GetCurrentBugcheckColor()
    {
    	HANDLE hDevice = CreateFile("\\\\.\\faultdriver", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
    	if(hDevice == INVALID_HANDLE_VALUE)
    		return -1;
    
    	DWORD ret;
    	char buffer;
    	if(!DeviceIoControl(
    		hDevice,
    		IOCTL_FAULTDRIVER_GET_BUGCHECK_COLOR,
    		&buffer, sizeof(buffer),
    		&buffer, sizeof(buffer),
    		&ret,
    		0
    		))
    	{
    		CloseHandle(hDevice);
    		return -1;
    	}
    	else
    	{
    		CloseHandle(hDevice);
    		return buffer;
    	}
    }
    
    UCHAR SetCurrentBugcheckColor(UCHAR cNew)
    {
    	HANDLE hDevice = CreateFile("\\\\.\\faultdriver", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
    	if(hDevice == INVALID_HANDLE_VALUE)
    		return -1;
    
    	DWORD ret;
    	char buffer = cNew;
    	if(!DeviceIoControl(
    		hDevice,
    		IOCTL_FAULTDRIVER_SET_BUGCHECK_COLOR,
    		&buffer, sizeof(buffer),
    		&buffer, sizeof(buffer),
    		&ret,
    		0
    		))
    	{
    		CloseHandle(hDevice);
    		return -1;
    	}
    	else
    	{
    		CloseHandle(hDevice);
    		return buffer;
    	}
    }
    Вот и все :) Бинарники и сорсы можно найти тут: http://cribble.by.ru/bugcheck.rar
    Для запуска нужно распаковать GUI-программку и бинарник драйвера в одну директорию и запустить EXEшник (он сам загрузит драйвер и выгрузит по окончании работы).
    В соотв. каталогах в rar'e находятся проекты с сорцами для компилера Microsoft Visual C++ 6.0
    Для тестирования пригодится программка М.Руссиновича "NotMyFault", которую можно скачать тут: http://www.sysinternals.com/Files/Notmyfault.zip

    Удачи, пока!


    ЗЫ. Посмотреть, как это выглядит, можно на скриншотах:
    http://img255.imageshack.us/img255/1978/deathob9.png
    http://img503.imageshack.us/img503/6316/xexe2zs3.png
    http://img520.imageshack.us/img520/6940/xexe3if0.png
    Зеленый симпотичный, правда? :)
     
    #1 _Great_, 13 Feb 2007
    Last edited: 13 Feb 2007
    14 people like this.
  2. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    Мда. Совсем забыл сказать про цвета :)
    Придется экспериментально проверять. По дефолту стоит 4 (синий).
    Из экспериментов могу сказат, что
    15 - белый
    3 - болотный
    7 - серый
     
  3. AHTOLLlKA

    AHTOLLlKA Member

    Joined:
    1 Feb 2005
    Messages:
    225
    Likes Received:
    35
    Reputations:
    22
    перекрасим бсод в эниСОД =)
     
  4. ice1k

    ice1k Banned

    Joined:
    1 Jan 2007
    Messages:
    462
    Likes Received:
    382
    Reputations:
    490
    Неплохо, Great! ;)
    ога =))
     
  5. Deem3n®

    Deem3n® RTFMSDN

    Joined:
    19 Sep 2005
    Messages:
    378
    Likes Received:
    153
    Reputations:
    164
    Вот еще ссылка по теме:
    http://fanpotai.wordpress.com/2006/03/12/change-the-blue-screen-of-death-bsod-color-to-something-other-than-blue/
     
  6. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    как и обещал. вот красный:
    [​IMG]
    Код красного цвета - 9.

    Кто желает - вот фрагмент BOOTVID.DLL, функция установки палитры:

    Code:
    .text:800115B3                 xor     esi, esi
    .text:800115B5                 mov     [ebp+var_40], esi
    .text:800115B8                 mov     [ebp+var_3C], 20h
    .text:800115BF                 mov     [ebp+var_38], 2000h
    .text:800115C6                 mov     [ebp+var_34], 2020h
    .text:800115CD                 mov     [ebp+var_30], 200000h
    .text:800115D4                 mov     [ebp+var_2C], 200020h
    .text:800115DB                 mov     [ebp+var_28], 202000h
    .text:800115E2                 mov     [ebp+var_24], 202020h
    .text:800115E9                 mov     [ebp+var_20], 303030h
    .text:800115F0                 mov     [ebp+var_1C], 3Fh
    .text:800115F7                 mov     [ebp+var_18], 3F00h
    .text:800115FE                 mov     [ebp+var_14], 3F3Fh
    .text:80011605                 mov     [ebp+var_10], 3F0000h
    .text:8001160C                 mov     [ebp+var_C], 3F003Fh
    .text:80011613                 mov     [ebp+var_8], 3F3F00h
    .text:8001161A                 mov     [ebp+var_4], 3F3F3Fh
    .text:80011621
    .text:80011621 loc_80011621:                           ; CODE XREF: InitializePalette()+83j
    .text:80011621                 push    [ebp+esi*4+var_40] ; int
    .text:80011625                 push    esi             ; Value
    .text:80011626                 call    _SetPaletteEntry@8 ; SetPaletteEntry(x,x)
    .text:8001162B                 inc     esi
    .text:8001162C                 cmp     esi, 10h
    .text:8001162F                 jb      short loc_80011621
    
    Выводы делайте сами, какой цвет какому номеру соответствует. Правда, тут не совсем RGB.
     
    #6 _Great_, 13 Feb 2007
    Last edited: 13 Feb 2007
    1 person likes this.
  7. Masad

    Masad New Member

    Joined:
    13 Feb 2007
    Messages:
    1
    Likes Received:
    0
    Reputations:
    0
    мд-ааа.мой ламерский мозг умрёт если я начну такое творить. сайт с бесплатной регистрацией сайтов не подскажите? ещё нужно какую нибудь фигню,которую можно прилепить к Exe и чтоб она мне прислала на мыло инфу с компа жертвы.
     
  8. ice1k

    ice1k Banned

    Joined:
    1 Jan 2007
    Messages:
    462
    Likes Received:
    382
    Reputations:
    490
    Удали свой пост, чувак... =\
     
  9. Ksander

    Ksander Elder - Старейшина

    Joined:
    21 Jun 2006
    Messages:
    526
    Likes Received:
    260
    Reputations:
    138
    Надеюсь что никогда его не увижу, а если и увижу, то сомневаюсь что зеленый поднимет мне настроение =)
     
    1 person likes this.
  10. Cr4sh

    Cr4sh net maniac

    Joined:
    25 Aug 2005
    Messages:
    30
    Likes Received:
    22
    Reputations:
    27
    гг))) грейт, не перестаю удивляться твоему коду, неужели так трудно заюзать небольшой дизассемблер длинн и на его основе написать анализатор кода??!!!
    думаю что те, кто запустят твой рантайм-патчер на ядре, немного отличном от твоего будут в ахуе)
     
  11. DRON-ANARCHY

    DRON-ANARCHY Отец порядка

    Joined:
    4 Mar 2005
    Messages:
    713
    Likes Received:
    142
    Reputations:
    50
    А мне интересно, зачем его перекрашивать?
    чтобы поставить вот такой же красный и в случае краха, чтобы п*здец еще и тебе самому настал?))
     
    1 person likes this.
  12. xismyname

    xismyname Elder - Старейшина

    Joined:
    7 Sep 2008
    Messages:
    77
    Likes Received:
    7
    Reputations:
    -5
    Эхх виндовс юзеры :D вы еще гордитесь BSOD,оффиииигеть