0%

前言

这个其实是我很长一段时间之前弄的了,不过当时没有发出来(现在发出来水一下博客)

刚开学那会我在学校的某群吹水时,听说了微机室电脑有控制软件可以让老师看屏幕,于是在第一节微机课的前一天晚上连夜弄了一下这个

正文

0x01 Find

想要伪造画面,自然要用到Hook技术,可是要Hook哪里呢?

这里先贴一段截屏代码供参考
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
BOOL WriteBmp(const TSTRING &strFile, const std::vector<BYTE> &vtData, const SIZE &sizeImg);
BOOL WriteBmp(const TSTRING &strFile, HDC hdc);
BOOL WriteBmp(const TSTRING &strFile, HDC hdc, const RECT &rcDC);

BOOL WriteBmp(const TSTRING &strFile, const std::vector<BYTE> &vtData, const SIZE &sizeImg)
{

BITMAPINFOHEADER bmInfoHeader = { 0 };
bmInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bmInfoHeader.biWidth = sizeImg.cx;
bmInfoHeader.biHeight = sizeImg.cy;
bmInfoHeader.biPlanes = 1;
bmInfoHeader.biBitCount = 24;

//Bimap file header in order to write bmp file
BITMAPFILEHEADER bmFileHeader = { 0 };
bmFileHeader.bfType = 0x4d42; //bmp
bmFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmFileHeader.bfSize = bmFileHeader.bfOffBits + ((bmInfoHeader.biWidth * bmInfoHeader.biHeight) * 3); ///3=(24 / 8)

HANDLE hFile = CreateFile(strFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}

DWORD dwWrite = 0;
WriteFile(hFile, &bmFileHeader, sizeof(BITMAPFILEHEADER), &dwWrite, NULL);
WriteFile(hFile, &bmInfoHeader, sizeof(BITMAPINFOHEADER), &dwWrite, NULL);
WriteFile(hFile, &vtData[0], vtData.size(), &dwWrite, NULL);


CloseHandle(hFile);

return TRUE;
}


BOOL WriteBmp(const TSTRING &strFile, HDC hdc)
{
int iWidth = GetDeviceCaps(hdc, HORZRES);
int iHeight = GetDeviceCaps(hdc, VERTRES);
RECT rcDC = { 0,0,iWidth,iHeight };

return WriteBmp(strFile, hdc, rcDC);
}

BOOL WriteBmp(const TSTRING &strFile, HDC hdc, const RECT &rcDC)
{
BOOL bRes = FALSE;
BITMAPINFO bmpInfo = { 0 };
BYTE *pData = NULL;
SIZE sizeImg = { 0 };
HBITMAP hBmp = NULL;
std::vector<BYTE> vtData;
HGDIOBJ hOldObj = NULL;
HDC hdcMem = NULL;

//Initilaize the bitmap information
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = rcDC.right - rcDC.left;
bmpInfo.bmiHeader.biHeight = rcDC.bottom - rcDC.top;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;

//Create the compatible DC to get the data
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem == NULL)
{
goto EXIT;
}

//Get the data from the memory DC
hBmp = CreateDIBSection(hdcMem, &bmpInfo, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&pData), NULL, 0);
if (hBmp == NULL)
{
goto EXIT;
}
hOldObj = SelectObject(hdcMem, hBmp);

//Draw to the memory DC
sizeImg.cx = bmpInfo.bmiHeader.biWidth;
sizeImg.cy = bmpInfo.bmiHeader.biHeight;
StretchBlt(hdcMem,
0,
0,
sizeImg.cx,
sizeImg.cy,
hdc,
rcDC.left,
rcDC.top,
rcDC.right - rcDC.left + 1,
rcDC.bottom - rcDC.top + 1,
SRCCOPY);


vtData.resize(sizeImg.cx * sizeImg.cy * 3);
memcpy(&vtData[0], pData, vtData.size());
bRes = WriteBmp(strFile, vtData, sizeImg);

SelectObject(hdcMem, hOldObj);


EXIT:
if (hBmp != NULL)
{
DeleteObject(hBmp);
}

if (hdcMem != NULL)
{
DeleteDC(hdcMem);
}

return bRes;
}

int main()
{
HDC hdc = GetDC(0);
HDC hMemDC = CreateCompatibleDC(hdc);
SelectObject(hMemDC, CreateCompatibleBitmap(hdc, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)));
BitBlt(hMemDC, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), hdc, 0, 0, SRCCOPY);
WriteBmp(L"directWrite.bmp", hdc);
WriteBmp(L"copyWrite.bmp", hMemDC);
ReleaseDC(GetActiveWindow(), hdc);
DeleteDC(hMemDC);
return 0;
}

CreateDCA和CreateDCW?

研究截屏的实现代码,首先可以想到CreateDCA和CreateDCW两个点,把程序拿到的屏幕DC替换掉

但能够发现,GetDC(0)和GetDC(GetDesktopWindow())也能拿到截屏用的DC,这样我们又多了一个需要Hook的点,并且可能还有更多方法来获得这个DC

还有,屏幕HDC并不一定只是用来读的,如果替换掉屏幕DC,很可能影响程序的正常显示

因此,这个Hook点是不能用的

阅读全文 »