Log in

View Full Version : Need programming tips to achieve this effect


homersux
June 15th, 2004, 15:54
I need to write a win32 program (maybe service) that works on windows 2000 that will totally blank the screen (black) and not responding to user input (keyboard/mouse, including all the hot keys). The machine will appear dead but is actually working. (optional) Upon getting a secret passphrase from the user, the machine restores to its original state. The 2nd part is optional.

I have done a lot of research but I haven't found much useful (powerful and genreic) information on this aspect of windows. I wrote a screensaver hoping to achive this. But it has two problems,
1) it's onset is not random
2) it doesn't disable ntkrnl to wake up the scheduler when user inputs even after I tried some tricks.

So I would like to hear what you should say about this.

Clandestiny
June 15th, 2004, 17:16
I'm not sure what you mean by "random onset", but you can probably achieve the lack of user input response by writing a KMD filter driver which intercepts the keyboard and mouse IRPs. A filter driver will definately be generic and this would also be the perfect implementation for your requirement of getting a passphrase from the user. The keyboard filter could check each intercepted keyboard IRP against some passphrase very easily. The only drawback would be the necessity of doing a scan code to ascii conversion before checking it.

Cheers,
Clandestiny

homersux
June 15th, 2004, 17:27
hxxp://www.rootkit.com/board.php?thread=1172&did=edge0&disp=1172

Kayaker
June 15th, 2004, 18:05
Hi

There may be a very nice way of doing that, along the lines of a screensaver as you mentioned, or putting the monitor into a fake suspend state and disabling mouse/keyboard input except for your passphrase, but here's an idea maybe worth looking into. This code was for Win9x, I'm not sure if it would work on Win2K but you would need to program a driver to use the IN/OUT commands.

Once upon a time there was a protection which did something similar if it caught you tracing over it or something. I believe it may have been DP-tEunlock or dp-borg2, maybe someone can confirm, but I remember seeing the effect. Anyway, someone had posted a similar type code snippet on the Win32asm forum and I was interested in what it was doing so I did a bit of digging. Here's my analysis of it, which may or may not be entirely accurate.


Original question:
==============================
I have this code which is supposed to disable screen, and it worx fine on my Win98:

mov dx, 03c4h
mov al, 01h
out dx, al
inc dx
in al, dx
or al, 20h
out dx, al

The problem is that I would like to turn it back on, but I don't know how?
Also, could someone pls explain what this code does exactly?
==============================


Possible explanation:

==============================
I did a little bit of searching and came up with this. Port 3C4h Index 1 is the VGA Sequencer Clocking Mode. If bit 5 is set this turns off the screen and gives all memory cycles to the CPU interface.

--------------------------------------------

3C4h is the VGA Sequencer Index Register (SEQX).
This register is loaded with a binary value that indexes the sequencer register for read/write data. This value is referred to as the "Index Number" of the SR register.

Bits 4-0 : SEQ ADDRESS - Sequencer Register Index
A binary value indexing the register where data is to be accessed.
Bits 7-5 : Reserved

Index 0: reset register
INDEX 1: CLOCKING MODE REGISTER
Index 2: map mask register
Index 3: character map select register
Index 4: memory mode register

---------------------------------------------

3C5h is the VGA Sequencer Data Register (SEQ_DATA).
This register is the data port for the sequencer register indexed by the
Sequencer Index register (3C4h).

Bits 7-0 : SEQ DATA - Sequencer Register Data
Data to the sequencer register indexed by the sequencer address index.


3C5h Index 1: CLOCKING MODE REGISTER
.......1 8/9 dot clocks (9 bits for mda-compatibility)
.....1.. 16/8 bits shift mode (see also 3cf.5)
....1... 40/80 column mode
...1.... 32/8 bits shift mode (see also 3cf.5)
..1..... DISABLE THE DISPLAY, to give the cpu more access to video memory

---------------------------------------------

So I roughly interpret the code as:

mov dx, 03c4h ; VGA Sequencer Index Register 3C4h (SEQX)
mov al, 01h ; Index 1 (clocking mode register)
out dx, al ; write index to 3C4h register
inc dx ; point to Data Register 3C5h (SEQ_DATA)
in al, dx ; read indexed Data Register into accumulator
or al, 20h ; set bit 5 (20h = 100000)
out dx, al ; output to Data Register

I would assume to reverse it you would just need to unset bit 5 again with xor 20h.

==============================
EOF


I'm not sure how you're thinking of adding a "random" onset of the screen blanking. Perhaps using an APC callback (slight random factor there since the OS decides when to call your APC), then a small random sleep/timer function within the callback itself before calling the screen blanking code. Couple of ideas anyway (to go along with Clandestiny's covert filter driver of course )

Cheers,
Kayaker

nikolatesla20
June 15th, 2004, 18:25
U guys are all just pure evil :P

-nt20

Clandestiny
June 15th, 2004, 20:57
Quote:
[Originally Posted by homersux]hxxp://www.rootkit.com/board.php?thread=1172&did=edge0&disp=1172


Heh, heh, yeah... I have some experience with the filter driver approach as you can see

Hi Kayaker Nice idea for the screen part.

Clandestiny

bilbo
June 16th, 2004, 02:51
Nice snippet, Kayaker!
Just three notes:

(1) not all the non-VGA graphic boards will support the bit you refer at. I tried it on an Intel 82845G, and it did not worked. Worked well on Matrox MGA G100.

(2) As far as I've tried, if you read the Clocking Mode Register you will always obtain a 0 value. So, just two out's are necessary: the first, with value 0x20,
to blank the screen; the second, with value 0, to unblank it!

(3) on XP platforms a driver is no more required to do port I/O! Try the following code...
Code:

/*
* Written by Bilbo - 16jun04 - for XP platform
* NOTE: it does not work on ALL video boards! (e.g. Intel 82845G)
*/

#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "advapi32"

typedef DWORD (NTAPI *PZwSystemDebugControl)(DWORD ControlCode,
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer,
ULONG OutputBufferLength, PULONG ReturnLength);
PZwSystemDebugControl ZwSystemDebugControl;

typedef struct {
DWORD low_io_addr;
DWORD high_io_addr;
PVOID user_addr;
DWORD len;
DWORD reserved0; // must be 1
DWORD reserved1; // must be 0
DWORD reserved2; // must be 1
DWORD unused; // never accessed by the kernel
} IO_STRUCT_OP;

#define FCHK(a) if (!(a)) { printf(#a " failed\n"; exit(0); }

void
get_api_address(void)
{
HMODULE hModule;

FCHK(hModule = GetModuleHandle("ntdll.dll");

FCHK((ZwSystemDebugControl = (PZwSystemDebugControl)
GetProcAddress(hModule, "ZwSystemDebugControl"));
}

void
debug_privileges(BOOL on)
{
HANDLE hToken;
TOKEN_PRIVILEGES tok;

FCHK(OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken));

tok.PrivilegeCount = 1;
tok.Privileges[0].Attributes = on ? SE_PRIVILEGE_ENABLED : 0;

FCHK(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tok.Privileges[0].Luid));
FCHK(AdjustTokenPrivileges(hToken, FALSE, &tok, sizeof(tok), NULL, NULL));
}

void
out(WORD port, BYTE val)
{
IO_STRUCT_OP io = { port, 0, &val, 1/*len*/, 1, 0, 1, 0 };

FCHK(ZwSystemDebugControl(15, &io, sizeof(io), 0, 0, 0) == 0);
}

BYTE
in(WORD port)
{
BYTE val;
IO_STRUCT_OP io = { port, 0, &val, 1/*len*/, 1, 0, 1, 0 };

FCHK(ZwSystemDebugControl(14, &io, sizeof(io), 0, 0, 0) == 0);
return val;
}

void
main(void)
{
get_api_address();
debug_privileges(TRUE);

out(0x3C4, 1); // force next I/O from Clocking Mode Register
printf("%x\n", (BYTE)in(0x3C5)); // 0

out(0x3C5, 0x20);
Sleep(3000);
out(0x3C5, 0x00);

debug_privileges(FALSE);
}


Cheers, Bilbo

Forgot to say: you need to be Administrator to grant debug privileges...

Kayaker
June 16th, 2004, 11:38
Wow. That's interesting Bilbo, nice code. I'm glad Windows is getting so much more secure from 9x->2K->XP, heheh


==============================
Multiple Windows XP Kernel Vulnerability Allow User Mode Programs To Gain Kernel Privileges

Summary:
There exist several vulnerabilities in one of Windows XP kernel's native API functions which allow any user with the SeDebugPrivilege privilege to execute arbitrary code in kernel mode, and read from and write to any memory address, including kernel memory.

Details:
ZwSystemDebugControl(), exported from ntdll.dll, calls a Windows operating system function

NtSystemDebugControl(). This function is executed in ring 0 (kernel mode) and is meant to be used by user mode debuggers having the SeDebugPrivilege privilege.

Impact:
Any user with the SeDebugPrivilege privilege could execute arbitrary code as the kernel, and read from and write to any address the kernel can. The program can do anything to the computer the kernel can, e.g. reprogram any computer hardware, such as the BIOS flash memory or patch the kernel in memory.

Since the user needs the SeDebugPrivilege, a privilege normally only given to administrators, to exploit these vulnerabilities, these are not serious vulnerabilities. The user is also normally an admin so he or she could easily install a device driver to become part of the kernel instead of exploiting these vulnerabilities.

Microsoft says it's OK for user mode programs to write to the kernel so long as you have the SeDebugPrivilege privilege, and will not fix anything.
===========================

Silver
June 16th, 2004, 11:46
I'll throw this one in there. How about writing a hook for the gdi? I looked into something similar a long time ago (I wanted to code an app that could pull text from any part of the screen), and got deeply involved in gdi mirror drivers. That will allow you to make sure nothing is displayed on-screen, and it's all win32 user-mode legit AFAIR. This book is more than helpful & includes example code:

Windows Graphics Programming Win32 GDI and DirectDrawŽ
Feng Yuan
Publisher: Prentice Hall PTR
First Edition December 01, 2000
ISBN: 0-13-086985-6, 1234

It's around in .chm format.

homersux
June 16th, 2004, 14:07
Looks like I opened a can of worms...
//Cheers

dELTA
June 16th, 2004, 18:31
In my view, the clearly most simple way of doing this, involving only ring 3 code, would seem to be just a program that puts a black window over the entire screen, and then hooks the mouse and all function keys that would normally be used to manipulate windows (like alt-tab, the windows key combinations, and such), using simple usermode hooks. The only thing that might then be a problem is the ctrl-alt-delete sequence, but it can be quite easily circumvented too, with e.g. a simple GINA dll...

TQN
June 16th, 2004, 22:14
I think this article on CodeProject can help you:
hxxp://www.codeproject.com/w2k/AntonioWinLock.asp
Regards

homersux
June 17th, 2004, 08:17
I am having trouble getting my hands on w2k ddk, it seems they no longer offer free downloads at M$.

bilbo
June 17th, 2004, 11:34
Just another chance:

write your kernel drivers in Assembly Language, using KdmKit
(www.freewebs.com/four-f/) and MASM32 (www.masm32.com)

both are updated frequently, they are free, they come with very good samples and documentation... what else?

Good luck! Bilbo.

Silver
June 17th, 2004, 13:23
dELTA, if you're replacing the gina then there's not much point sticking to usermode only... As minor changes go, that one isn't

How about this, code a DirectX app that uses fullscreen mode, then use DirectInput in exclusive mode to trap the keyboard and mouse. DInput has functions built in to disable windows hotkeys. Not sure about Ctl-Alt-Del, but I do know if you create a fullscreen app with a wierd displaymode then hit Ctl-Alt-Del, the security box doesn't appear properly...

evilbit
June 18th, 2004, 07:43
Install a global hook on the system (using SetWindowsHookEx), and do not pass mouse/keyboard messages.

ZaiRoN
June 18th, 2004, 08:17
evilbit, this is exactly what Delta suggested

homersux
June 18th, 2004, 09:59
The KDM approach worked. But the screen isn't restored after out 3c5h, 0

I haven't tried the SetWindowsHookEx approach, but I doubt it will disable keyboard (of course there are tricks to disable the hot keys...), imo the kdm approach is better.

homersux
June 18th, 2004, 10:17
Ok, I found out the reason:

blank_screen
invoke Sleep, 3000
restore_screen

The problem is with "invoke Sleep, 3000", it calls the scheduler and there is some task switch. Upon waking up, my task IO map is not restored properly by windows (I updated my task IO map so I can do port IO directly through my device driver) and then restore_screen doesn't work. So if I don't call sleep and immediately restore screen, it works. Task switch is the evil.

Ok, now a new problem, if the user press power down or blindly use ctl+esc, up, enter, select "restart", and go ahead, there is a split second of window screen showing up (I imagine during g_exit_window, the WEP calls the video driver to restore screen anyhow). This is kinda bad because the user now knows there is something that's messing with software and the hardware is actually ok. I don't want the user to see anything after the monitor goes blank.

ZaiRoN
June 18th, 2004, 17:13
Hi homersux,
Quote:
haven't tried the SetWindowsHookEx approach, but I doubt it will disable keyboard... imo the kdm approach is better.
I agree with you about the kdm approach but I think that it's also possible using SetWindowsHookEx approach.
You can easily avoid special combos, like ctrl-esc. The main problem is ctrl-alt-del combination but you can follow Delta's suggestion... maybe it's also possible to avoid this kind of combination with a runtime patch that doesn't run the task manager (re-enabling the feature when the program is closed, of course).

regards,
ZaiRoN

evilbit
June 19th, 2004, 08:38
Quote:
evilbit, this is exactly what Delta suggested

well.. didn't read the whole thread, stupid me

anyway,
a WH_DEBUG hook should solve this problem.

From the MSDN:
Quote:

The DebugProc hook procedure is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function before calling the hook procedures associated with any type of hook. The system passes information about the hook to be called to the DebugProc hook procedure, which examines the information and determines whether to allow the hook to be called.

0rp
June 21st, 2004, 16:11
you could also try to create a Direct3DDEvice or DirectDrawSurface with exclusive and fullscreen flags set.

with a directinput device, you could also block keyb and mouse inputs

Silver
June 22nd, 2004, 06:25
Didn't I already say that?

Oh also, homer, if you code a gdi mirror driver you can prevent anything from being drawn IIRC, so it may be worth looking into that.

SynApsus
June 27th, 2004, 16:28
Exactly Silver, you can use the SetCooperativeLevel () function of the DirectX SDK with the flag (DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN), which will draw your window in the entire screen and disables all the hotkeys you don't define, even CTRL+ALT+DEL.