Интернет-казино Grand Casino произвело фурор в игорном мире.
Одно из самых важных нововведений - наличие системы контроля честности всех азартных игр казино. Наличие контроля честности дает возможность полностью уйти в игру, не задумываясь о подтасовке или обмане. В Grand Casino можно пополнить счет и вывести выигрыш большим количеством способов:(SMS, E-gold, Rupay, Яндекс.Деньги, Webmoney,Кредитные карты,...). Теперь азартные игры на деньги стали доступнее.
Предоставлены игры: Рулетка, Покер, Блэкджек, Видео Покер, Игровые автоматы, Кено.
Если ты кодил под 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:
//
// Enable InbvDisplayString calls to make it through to bootvid driver.
//
if (InbvIsBootDriverInstalled()) {
InbvAcquireDisplayOwnership();
InbvResetDisplay();
InbvSolidColorFill(0,0,639,479,4); // make the screen blue
InbvSetScrollRegion(0,0,639,479); // set to use entire screen
}
интересующую нас строчку я выделил. тут происходит задание цвета фона. Нам надо только лишь его поменять. Поехали!
Итак, мы пишем под Windows XP 2600. Откроем в IDA Pro код KeBugCheckEx:
.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, устанавливающей цвет фона экрана:
Так-так. PUSH 4 - как раз заталкивание в стек цвета фона (4 - синий). Опкод команды PUSH 4 выглядит так: 6A 04 PUSH 4. Нам нужно изменить операнд команды PUSH. Адрес начала KeBugCheck2 - 0045B7BA, адрес операнда команды PUSH - 0045BDA4. Не нужно быть гением, чтобы посчитать разницу - 5EA.
Вот мы и собрали все нужные нам данные. Приступим к кодерской части. Реализация будет такова - мы напишем драйвер ядра, у которого по DeviceIoControl можно вызвать 2 функции - прочитать текущий цвет и записать новый. С учетом всего вышенаписнаного, вот вспомогательная функция для получения адреса байта, где лежит цвет фона:
Проследим, чтобы младшие 2 бита были сброшены - они показывают тип ввода-вывода при DeviceIoControl. 00 означает буферизированный ввод-вывод, он нам и нужен. Диспетчер ввода-вывода выделит системный буфер, скопирует пользовательский буфер в системный, мы его будем изменять как хотим, а потом системный буфер скопируется обратно в выходной.
Напишем вот такую функцию для обработки IRP_MJ_DEVICE_CONTROL:
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;
__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;
Я думаю, стоит кое-что пояснить. Сначала мы получаем текущий стек ввода-вывода, адрес системного буфера и размеры входного и выходного буферов. Дальше смотрим, что же от нас хотят - прочитать или установить новый цвет. Основной код обернут в __try/__except, чтобы, не дай Бог, случайно не уронить систему, если что. Мы проверяем NtBuildNumber - номер билда ОС и ругаемся, если он не 2600. Дальше мы получаем адрес байта с цветом фона и химичим с ним. Выставляем в Irp->IoStatus.Information число байт, которое нужно скопировать в пользовательский буфер из системного.
Остальной код драйвера комментировать, думаю, не стоит:
Теперь у нас готов работающий драйвер, который умеет оперировать с цветом фона для экрана смерти. Напишем несложное GUI для этого. Я приведу только код юзермодных функций для работы с цветом:
Вот и все Бинарники и сорсы можно найти тут: http://cribble.by.ru/bugcheck.rar Для запуска нужно распаковать GUI-программку и бинарник драйвера в одну директорию и запустить EXEшник (он сам загрузит драйвер и выгрузит по окончании работы). В соотв. каталогах в rar'e находятся проекты с сорцами для компилера Microsoft Visual C++ 6.0 Для тестирования пригодится программка М.Руссиновича "NotMyFault", которую можно скачать тут: http://www.sysinternals.com/Files/Notmyfault.zip
Удачи, пока!
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо зайти на сайт под своим именем.