Задача, - найти окно, получить размеры этого окна, и сделать скрин по ним. Реализовал следующим образом: Код (Text): .586 .model flat, stdcall option casemap :none include \masm32\include\w2k\ntdll.inc includelib \masm32\lib\w2k\ntdll.lib include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib include \masm32\include\user32.inc include \masm32\include\gdi32.inc includelib \masm32\lib\gdi32.lib include \masm32\macros\strings.mac include \masm32\include\masm32.inc includelib \masm32\lib\masm32.lib .code Screen proc hWnd:DWORD,lParam:DWORD local hdc:HDC local memdc:HDC local hBitmap:dword local dwWidth:dword local dwHeight:dword local hSize:dword local hSize2:dword local buffer[1024]:byte local rc:RECT local lpBMPImage:dword invoke GetWindowText,hWnd,addr buffer,sizeof buffer .if eax > 0 invoke lstrcmp,addr buffer,$CTA0("Calculator");$CTA0("Калькулятор"); .if eax == 0 invoke GetWindowRect,hWnd,addr rc mov eax,rc.right sub eax,rc.left sub eax,6 mov dwWidth,eax mov ecx,rc.bottom sub ecx,rc.top sub ecx,25 mov dwHeight,ecx mul ecx mov ecx,24 mul ecx shr eax,3 add eax,sizeof BITMAPFILEHEADER add eax,sizeof BITMAPINFOHEADER mov hSize,eax mov hSize2,eax mov lpBMPImage,0 invoke ZwAllocateVirtualMemory,-1,addr lpBMPImage,0,addr hSize2,MEM_COMMIT,PAGE_EXECUTE_READWRITE .if eax == 0 mov edi,lpBMPImage mov (BITMAPFILEHEADER ptr [edi]).bfType,4D42h mov eax,hSize mov (BITMAPFILEHEADER ptr [edi]).bfSize,eax mov (BITMAPFILEHEADER ptr [edi]).bfOffBits,sizeof BITMAPFILEHEADER + sizeof BITMAPINFOHEADER add edi,sizeof BITMAPFILEHEADER mov (BITMAPINFOHEADER ptr [edi]).biSize,sizeof BITMAPINFOHEADER mov eax,dwWidth mov (BITMAPINFOHEADER ptr [edi]).biWidth,eax mov eax,dwHeight mov (BITMAPINFOHEADER ptr [edi]).biHeight,eax mov (BITMAPINFOHEADER ptr [edi]).biPlanes,1 mov (BITMAPINFOHEADER ptr [edi]).biBitCount,24 mov (BITMAPINFOHEADER ptr [edi]).biCompression,BI_RGB invoke GetDCEx,hWnd,0,0 mov hdc,eax invoke CreateCompatibleDC,hdc mov memdc,eax invoke CreateCompatibleBitmap,hdc,dwWidth,dwHeight mov hBitmap,eax invoke SelectObject,memdc,hBitmap invoke BitBlt,memdc,0,0,dwWidth,dwHeight,hdc,0,0,SRCCOPY invoke ReleaseDC,0,hdc mov esi,edi add edi,sizeof BITMAPINFOHEADER invoke GetDIBits,memdc,hBitmap,0,dwHeight,edi,esi,0 invoke DeleteObject,hBitmap invoke DeleteDC,memdc invoke DeleteFileA,lParam invoke _lcreat,lParam,OF_WRITE mov esi,eax invoke _lwrite,esi,lpBMPImage,hSize invoke _lclose,esi invoke ZwFreeVirtualMemory,-1,addr lpBMPImage,addr hSize2,MEM_RELEASE .endif xor eax,eax ret .endif .endif mov eax,1 ret Screen endp start proc invoke EnumWindows,offset Screen,$CTA0("sample.bmp") invoke ExitProcess,0 start endp end start Хотел узнать: 1) Насколько это корявая реализация ? 2) Будет ли работать на все Vista и Seven ? 3) Можно-ли еще пооптимальнее? Мне просто потом весь этот код надо будет перенести на уровен ниже, т.е. на функции ZwUser* и ZwGdi*. Спасибо За мнимание.
Flasher 1. На уровень шадов сервисов бессмысленно переносить это, обёртка вокруг них очень большая и в версиях сильно отличается. Ядерными указателями вам не нужно ведь манипулировать из юзермода(ога, на уровне сервисов именно ядерные адреса передаются), выщитывать дельты между пользовательской и ядерной проекциями, искать кучу не экспортируемых функций(ValidateHwnd() etc.).. незачем это делать. Вашу защиту это не улучшит. 2. Скрин таким образом не получится снять. Если окно закрыто другим или скрыто, то нужную картинку вы не получите. Следует использовать чтото типа PrintWindow(), при запросе на перерисовку шадов доставляет некоторые калбэки, которые вызывают оконные функции и инициируют перересовку, логично принять решение о захвате этих сообщений(только удалённо) и подмене контекста.
Clerk, почти для всех функций нашел прототипы в ядре. Код (Text): .586 .model flat, stdcall option casemap :none include \masm32\include\w2k\ntdll.inc includelib \masm32\lib\w2k\ntdll.lib include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib include \masm32\include\user32.inc include \masm32\include\gdi32.inc includelib \masm32\lib\gdi32.lib include \masm32\macros\strings.mac include \masm32\include\masm32.inc includelib \masm32\lib\masm32.lib .code Screen proc hWnd:DWORD,lParam:DWORD local hdc:HDC local memdc:HDC local hBitmap:dword local dwWidth:dword local dwHeight:dword local hSize:dword local hSize2:dword local buffer[1024]:byte local rc:RECT local lpBMPImage:dword local po:POINT invoke GetWindowText,hWnd,addr buffer,sizeof buffer .if eax > 0 invoke lstrcmp,addr buffer,$CTA0("Calculator");$CTA0("Калькулятор"); .if eax == 0 ;invoke GetWindowRect,hWnd,addr rc lea eax,po push eax lea eax,rc push eax push hWnd mov eax,119Bh ;ZwUserGetInternalWindowPos mov edx,esp int 2Eh lea esp,[esp+3*4] mov eax,rc.right sub eax,rc.left sub eax,6 mov dwWidth,eax mov ecx,rc.bottom sub ecx,rc.top sub ecx,25 mov dwHeight,ecx mul ecx mov ecx,24 mul ecx shr eax,3 add eax,sizeof BITMAPFILEHEADER add eax,sizeof BITMAPINFOHEADER mov hSize,eax mov hSize2,eax mov lpBMPImage,0 invoke ZwAllocateVirtualMemory,-1,addr lpBMPImage,0,addr hSize2,MEM_COMMIT,PAGE_EXECUTE_READWRITE .if eax == 0 mov edi,lpBMPImage mov (BITMAPFILEHEADER ptr [edi]).bfType,4D42h mov eax,hSize mov (BITMAPFILEHEADER ptr [edi]).bfSize,eax mov (BITMAPFILEHEADER ptr [edi]).bfOffBits,sizeof BITMAPFILEHEADER + sizeof BITMAPINFOHEADER add edi,sizeof BITMAPFILEHEADER mov (BITMAPINFOHEADER ptr [edi]).biSize,sizeof BITMAPINFOHEADER mov eax,dwWidth mov (BITMAPINFOHEADER ptr [edi]).biWidth,eax mov eax,dwHeight mov (BITMAPINFOHEADER ptr [edi]).biHeight,eax mov (BITMAPINFOHEADER ptr [edi]).biPlanes,1 mov (BITMAPINFOHEADER ptr [edi]).biBitCount,24 mov (BITMAPINFOHEADER ptr [edi]).biCompression,BI_RGB ;invoke GetDCEx,hWnd,0,0 push 0 push 0 push hWnd mov eax,1192h ;ZwUserGetDCEx mov edx,esp int 2Eh lea esp,[esp+3*4] mov hdc,eax ;invoke CreateCompatibleDC,hdc push hdc mov eax,101Eh ;ZwGdiCreateCompatibleDC mov edx,esp int 2Eh lea esp,[esp+1*4] mov memdc,eax ;invoke CreateCompatibleBitmap,hdc,dwWidth,dwHeight push dwHeight push dwWidth push hdc mov eax,101Dh ;ZwGdiCreateCompatibleBitmap mov edx,esp int 2Eh lea esp,[esp+3*4] mov hBitmap,eax ;invoke SelectObject,memdc,hBitmap push hBitmap push memdc mov eax,1101h ;ZwGdiSelectBitmap mov edx,esp int 2Eh lea esp,[esp+2*4] ;invoke PrintWindow,hWnd,memdc,0 push 0 push memdc push hWnd mov eax,11DDh ;ZwUserPrintWindow mov edx,esp int 2Eh lea esp,[esp+3*4] ;invoke BitBlt,memdc,0,0,dwWidth,dwHeight,hdc,0,0,SRCCOPY push 0 push 0 push SRCCOPY push 0 push 0 push hdc push dwHeight push dwWidth push 0 push 0 push memdc mov eax,100Dh ;ZwGdiBitBlt mov edx,esp int 2Eh lea esp,[esp+11*4] ;invoke ReleaseDC,0,hdc push hdc mov eax,100Eh ;ZwGdiCancelDC mov edx,esp int 2Eh lea esp,[esp+1*4] push 39h push hdc mov eax,1143h ;ZwUserCallOneParam mov edx,esp int 2Eh lea esp,[esp+2*4] mov esi,edi add edi,sizeof BITMAPINFOHEADER invoke GetDIBits,memdc,hBitmap,0,dwHeight,edi,esi,0 ;invoke DeleteObject,hBitmap push hBitmap mov eax,107Ah ;ZwGdiDeleteObjectApp mov edx,esp int 2Eh lea esp,[esp+1*4] invoke DeleteDC,memdc invoke DeleteFileA,lParam invoke _lcreat,lParam,OF_WRITE mov esi,eax invoke _lwrite,esi,lpBMPImage,hSize invoke _lclose,esi invoke ZwFreeVirtualMemory,-1,addr lpBMPImage,addr hSize2,MEM_RELEASE .endif xor eax,eax ret .endif .endif mov eax,1 ret Screen endp start proc invoke EnumWindows,offset Screen,$CTA0("sample.bmp") invoke ExitProcess,0 start endp end start Номера сервисов из XP. У меня норм снимает. А от функции PrintWindow вроди никакого толка, если поверх другое окно, снимает это окно.
Только для DeleteDC не нашел, и столкнулся с проблемами при юзании ZwGdiGetDIBitsInternal вместо GetDIBits.
Flasher Наоборот, PrintWindow(NtUserPrintWindow) выполняет замену коннтекста, доставляет сообщение для обновления его и копирует изображение, тоесть на внутренний контекст отрисовка происходит, смотрим: Но всятаки я бы выполнил код как и сказал, вручную подменив контекст. Касательно сервисов. На сколько понимаю вам они нужны чтобы код был самодостаточным, тоесть сокрыть от юзермодного отладчика. Это бесполезно, элементарно условный останов на прерывание, тутже обнаружит вызов, на это секунды уйдут, под сисером выполнить > proc, bpint 2e (pid == #), F9. Более того это инициирует ядерный калбэк в чужём процессе, там можно выполнить проверку состояния обьектов.
А, т.е. в верхнем коде отпадает юзание ZwGdiBitBlt и все да ? А хочу юзать прямиком из ядря чтобы хотябы юзермодных антискринов не написали, т.е. перехватить и подменить.