print screen hook?
-
Hi, I need a global print screen hook, not based on keyboard hooks, but based on the actual process of getting the bitmap of the print screen. Does anybody know a place to start? Ive worked with keyboard hooks, but i dont know WHAT to hook for this specific thing!!! Thanks in Advance!!!
-
Hi, I need a global print screen hook, not based on keyboard hooks, but based on the actual process of getting the bitmap of the print screen. Does anybody know a place to start? Ive worked with keyboard hooks, but i dont know WHAT to hook for this specific thing!!! Thanks in Advance!!!
The first thing you do is figure out where and when the printscreen key is processed. For example, the shell does a lot of processing, so if you open a paint program and kill the shell (explorer) then hit printscreen, does it still work? Yes it does. So, it would seem that it may happen in the kernel. There are two ends you could attempt to start watching for PRINT SCREEN. The starting end, where the keys are sent from or the other end, where the bitmap ends up. The bitmap ends up in the clipboard. So, my guess would be WIN32K.SYS in the kernel may have something to do with it. So, you get out your kernel debugger and you load up Microsoft's symbols and you start to look for anything you think may occur at that time. For example, print screen functions in the kernel, key strokes or clipboard functions. We want to find out who puts the image in the clipboard, usermode or kernel mode and see where you want to hook. So, I did this for you. I searched WIN32K.SYS for symbols. Found nothing on print screen. So, as I said, we know that paint programs get the bitmap from the clipboard. So, what I did was searched for *clip*board* symbols and set some breakpoints on ones related to setting data. kd> bl 0 e a00b0cc8 0001 (0001) win32k!InternalSetClipboardData 1 e a00b0c35 0001 (0001) win32k!NtUserSetClipboardData 2 e a0046c43 0001 (0001) win32k!NtUserOpenClipboard Then, I pressed "Print Screen" and I get a break point! kd> kb ChildEBP RetAddr Args to Child fb676b30 a00b0e72 fcdb8bf8 00000002 18050144 win32k!InternalSetClipboardData fb676b54 a01038ea 00000002 18050144 00000000 win32k!_SetClipboardData+0x2f fb676bac a00c3a34 0185000f 00000201 e1ccf948 win32k!xxxSnapWindow+0x212 fb676c8c a00152e2 00000100 fb676d10 00000000 win32k!xxxScanSysQueue+0x1056 fb676ce0 a001612e fb676d10 000021ff 00000000 win32k!xxxInternalGetMessage+0x280 fb676d4c 80461691 0103fd70 00000000 00000000 win32k!NtUserGetMessage+0x43 fb676d4c 77e1414f 0103fd70 00000000 00000000 nt!KiSystemService+0xc4 0103fd1c 766d16d3 0103fd70 00000000 00000000 USER32!NtUserGetMessage+0xb 0103fd90 766d15bd 00020070 00000000 766d2610 stobject!SysTrayMain+0x124 0103ffb4 77e92ca8 00000000 00ccfaa0 77fb80db stobject!CSysTray::SysTrayThreadProc+0x45 0103ffec 00000000 766d1578 00000000 00000000 KERNEL32!BaseThreadStart+0x52 kd> !process -1 0 PROCESS fcc88020 SessionId: 0 Cid: 0324 Peb: 7ffdf000 ParentCid: 0318 DirBase: 0684b000 ObjectTable: fcc7db68 TableSize: 200. Image: ex
-
The first thing you do is figure out where and when the printscreen key is processed. For example, the shell does a lot of processing, so if you open a paint program and kill the shell (explorer) then hit printscreen, does it still work? Yes it does. So, it would seem that it may happen in the kernel. There are two ends you could attempt to start watching for PRINT SCREEN. The starting end, where the keys are sent from or the other end, where the bitmap ends up. The bitmap ends up in the clipboard. So, my guess would be WIN32K.SYS in the kernel may have something to do with it. So, you get out your kernel debugger and you load up Microsoft's symbols and you start to look for anything you think may occur at that time. For example, print screen functions in the kernel, key strokes or clipboard functions. We want to find out who puts the image in the clipboard, usermode or kernel mode and see where you want to hook. So, I did this for you. I searched WIN32K.SYS for symbols. Found nothing on print screen. So, as I said, we know that paint programs get the bitmap from the clipboard. So, what I did was searched for *clip*board* symbols and set some breakpoints on ones related to setting data. kd> bl 0 e a00b0cc8 0001 (0001) win32k!InternalSetClipboardData 1 e a00b0c35 0001 (0001) win32k!NtUserSetClipboardData 2 e a0046c43 0001 (0001) win32k!NtUserOpenClipboard Then, I pressed "Print Screen" and I get a break point! kd> kb ChildEBP RetAddr Args to Child fb676b30 a00b0e72 fcdb8bf8 00000002 18050144 win32k!InternalSetClipboardData fb676b54 a01038ea 00000002 18050144 00000000 win32k!_SetClipboardData+0x2f fb676bac a00c3a34 0185000f 00000201 e1ccf948 win32k!xxxSnapWindow+0x212 fb676c8c a00152e2 00000100 fb676d10 00000000 win32k!xxxScanSysQueue+0x1056 fb676ce0 a001612e fb676d10 000021ff 00000000 win32k!xxxInternalGetMessage+0x280 fb676d4c 80461691 0103fd70 00000000 00000000 win32k!NtUserGetMessage+0x43 fb676d4c 77e1414f 0103fd70 00000000 00000000 nt!KiSystemService+0xc4 0103fd1c 766d16d3 0103fd70 00000000 00000000 USER32!NtUserGetMessage+0xb 0103fd90 766d15bd 00020070 00000000 766d2610 stobject!SysTrayMain+0x124 0103ffb4 77e92ca8 00000000 00ccfaa0 77fb80db stobject!CSysTray::SysTrayThreadProc+0x45 0103ffec 00000000 766d1578 00000000 00000000 KERNEL32!BaseThreadStart+0x52 kd> !process -1 0 PROCESS fcc88020 SessionId: 0 Cid: 0324 Peb: 7ffdf000 ParentCid: 0318 DirBase: 0684b000 ObjectTable: fcc7db68 TableSize: 200. Image: ex
I took a quick look again here in a little more detail and here's what I think is happening. The keyboard generates the keydown event and it's most likely passed and filtered by the WH_KEYBOARD_LL hooks first. Eventually, it makes it way as a WM_KEYDOWN message into the active window. In the case where I saw it in CSRSS's message queue, was since I had the command window debugger active. So, then the ScanQueue is called and there's a call to get the next message. Then, it's checked if it's a keydown. If it is, it then checks specific scan codes and performs certain system actions. kd> r eax=e1ba81e8 ebx=e1cb0a48 ecx=00000001 edx=00005d6e esi=00000000 edi=00000001 eip=a0025769 esp=f766fbac ebp=f766fc8c iopl=3 nv up ei pl zr na po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003246 win32k!xxxScanSysQueue+0xa2: a0025769 e80d0f0000 call win32k!xxxGetNextSysMsg (a002667b) kd> p;r ... kd> eax=00000000 ebx=e1cb0a48 ecx=f766fc20 edx=00000000 esi=00000000 edi=00000001 eip=a00257bf esp=f766fbb8 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+0x10c: a00257bf 8b4dac mov ecx,[ebp-0x54] ss:0010:f766fc38=00000100 kd> eax=00000000 ebx=e1cb0a48 ecx=00000100 edx=00000000 esi=00000000 edi=00000001 eip=a00257c2 esp=f766fbb8 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+0x10f: a00257c2 6a23 push 0x23 kd> eax=00000000 ebx=e1cb0a48 ecx=00000100 edx=00000000 esi=00000000 edi=00000001 eip=a00257c4 esp=f766fbb4 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+0x111: a00257c4 5a pop edx kd> eax=00000000 ebx=e1cb0a48 ecx=00000100 edx=00000023 esi=00000000 edi=00000001 eip=a00257c5 esp=f766fbb8 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+0x112: a00257c5 894d08 mov [ebp+0x8],ecx ss:0010:f766fc94=e1cb0a48 kd> eax=00000000 ebx=e1cb0a48 ecx=00000100 edx=00000023 esi=00000000 edi=00000001 eip=a00257c8 esp=f766fbb8 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+
-
I took a quick look again here in a little more detail and here's what I think is happening. The keyboard generates the keydown event and it's most likely passed and filtered by the WH_KEYBOARD_LL hooks first. Eventually, it makes it way as a WM_KEYDOWN message into the active window. In the case where I saw it in CSRSS's message queue, was since I had the command window debugger active. So, then the ScanQueue is called and there's a call to get the next message. Then, it's checked if it's a keydown. If it is, it then checks specific scan codes and performs certain system actions. kd> r eax=e1ba81e8 ebx=e1cb0a48 ecx=00000001 edx=00005d6e esi=00000000 edi=00000001 eip=a0025769 esp=f766fbac ebp=f766fc8c iopl=3 nv up ei pl zr na po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003246 win32k!xxxScanSysQueue+0xa2: a0025769 e80d0f0000 call win32k!xxxGetNextSysMsg (a002667b) kd> p;r ... kd> eax=00000000 ebx=e1cb0a48 ecx=f766fc20 edx=00000000 esi=00000000 edi=00000001 eip=a00257bf esp=f766fbb8 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+0x10c: a00257bf 8b4dac mov ecx,[ebp-0x54] ss:0010:f766fc38=00000100 kd> eax=00000000 ebx=e1cb0a48 ecx=00000100 edx=00000000 esi=00000000 edi=00000001 eip=a00257c2 esp=f766fbb8 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+0x10f: a00257c2 6a23 push 0x23 kd> eax=00000000 ebx=e1cb0a48 ecx=00000100 edx=00000000 esi=00000000 edi=00000001 eip=a00257c4 esp=f766fbb4 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+0x111: a00257c4 5a pop edx kd> eax=00000000 ebx=e1cb0a48 ecx=00000100 edx=00000023 esi=00000000 edi=00000001 eip=a00257c5 esp=f766fbb8 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+0x112: a00257c5 894d08 mov [ebp+0x8],ecx ss:0010:f766fc94=e1cb0a48 kd> eax=00000000 ebx=e1cb0a48 ecx=00000100 edx=00000023 esi=00000000 edi=00000001 eip=a00257c8 esp=f766fbb8 ebp=f766fc8c iopl=3 nv up ei ng nz na pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00003283 win32k!xxxScanSysQueue+
Hi. Thank you for the help so far!!! It has been of great help! It seems ill have to make, as you say, a kernel hook on SnapWindow... Ill start working on it, although im relativly new to global hooks. Any extra help would be appreciated!!
-
Hi. Thank you for the help so far!!! It has been of great help! It seems ill have to make, as you say, a kernel hook on SnapWindow... Ill start working on it, although im relativly new to global hooks. Any extra help would be appreciated!!
xxxSnapWindow isn't an exported function, so it's going to be hard to find since it's offset would be specific to any version of win32k.sys My suggestion would be WH_KEYBOARD_LL, but I don't know what you're trying to accomplish. BTW, I hope this is for NT?
-
xxxSnapWindow isn't an exported function, so it's going to be hard to find since it's offset would be specific to any version of win32k.sys My suggestion would be WH_KEYBOARD_LL, but I don't know what you're trying to accomplish. BTW, I hope this is for NT?
Well, first, its only supposed to work on win2000+, so no legacy problem. Ive checked win32k.sys with PEView application and i didnt found, as you said, xxxSnapWindow as an exported function. Keyboard hook is no good, cause the printscreen message might not come from the keyboard, but might come by a call from a 3rd party capture application, which i want to avoid. Basically, i require an almost fail-proof mechanism to avoid screen capture in a specific window of my application. I have it all figured out when it's copied to clipboard, but when the capturing application saves it to file, i havent been able to stop it from happening. Other options could include a hook to a file write to disk, but that could have disasterouses consequences!!!
-
Well, first, its only supposed to work on win2000+, so no legacy problem. Ive checked win32k.sys with PEView application and i didnt found, as you said, xxxSnapWindow as an exported function. Keyboard hook is no good, cause the printscreen message might not come from the keyboard, but might come by a call from a 3rd party capture application, which i want to avoid. Basically, i require an almost fail-proof mechanism to avoid screen capture in a specific window of my application. I have it all figured out when it's copied to clipboard, but when the capturing application saves it to file, i havent been able to stop it from happening. Other options could include a hook to a file write to disk, but that could have disasterouses consequences!!!
Ok, so you also want to stop screen captures from anyone taking a picture of your application. This will be tough, because an application could do this: GetDC(NULL); and get a screen shot of the desktop without going through the code I showed. (Or get your window handle and do a copy). Then, they just do: BitBlt(); to their HDC and write it to disk or whatever they want. So, there's more than one way to take a screen shot without having to push "print screen" button or emulate they are taking a snapshot with the function I showed. SnapShot is also a kernel function, you planed to write a driver to fix this? :)
-
Ok, so you also want to stop screen captures from anyone taking a picture of your application. This will be tough, because an application could do this: GetDC(NULL); and get a screen shot of the desktop without going through the code I showed. (Or get your window handle and do a copy). Then, they just do: BitBlt(); to their HDC and write it to disk or whatever they want. So, there's more than one way to take a screen shot without having to push "print screen" button or emulate they are taking a snapshot with the function I showed. SnapShot is also a kernel function, you planed to write a driver to fix this? :)
Yeah, ive checked a few things and there are a lot of ways that this can fail. Regarding BitBlt(), i guess i could make a hook just for that, as it is a windows GDI function. Reguarding SnapShot, i've been reading an article here on codeproject on how to make a kernel-mode spying driver. Ill eventually have to make it, as it will be essential in the following months to my app. Combining a lot of these protection, i might then be able to completly protect the system from screenshots, and, who knows, even sell the overall protection system :)