-
-
解决WPF使用HVNC的问题-HwndHook
-
发表于: 2024-12-15 18:43 6735
-
这里就不多介绍HVNC了 因为单纯在之前的文章已经介绍过了
https://bbs.kanxue.com/thread-264956.htm
那么我们都知道 CPP中HVNC有现成的代码(github TinyNuke)可以直接抄
https://github.com/Sts0mrg0/TinyNuke
C#中也有比如
https://github.com/moom825/xeno-rat
核心代码在
他创建了一个控件来解决这个问题
其实WPF中也可以用类似的创建控件的方法来解决
但是我们这里给出第二个方案
什么是HwndHook
HwndHook 是一个委托(Delegate),在 WPF (Windows Presentation Foundation) 中用于处理 Win32 消息。它定义了 HwndSourceHook 方法的签名,该方法可以被用来拦截和处理发送到 WPF 窗口的消息。HwndHook 委托允许开发者在 WPF 应用程序中自定义和扩展对 Win32 消息的处理
在 WPF 中,HwndSource 类代表一个 Win32 窗口句柄(HWND),并且提供了一个方法 AddHook,允许你将一个 HwndSourceHook 委托(即 HwndHook)添加到窗口消息队列中。这个委托会在每个 Win32 消息被分派到相应的 WPF 窗口之前被调用,从而允许开发者在消息到达目标窗口之前对其进行拦截和处理
结构如下
HwndHook有什么用
拦截消息:在消息到达目标控件之前拦截它。
自定义消息处理:根据需要自定义消息的处理逻辑。
修改消息参数:在消息被处理之前修改 wParam 和 lParam 参数。
阻止消息传播:通过设置 handled 参数为 true 来阻止消息继续传播到默认的窗口过程。
为什么使用HwndHook
在C# WPF中,使用HwndHook(通过HwndSource.AddHook方法)来将消息转化为Window消息,是因为WPF框架本身并不直接处理Win32消息,而是通过一个叫做HwndSource的类来与Win32 API进行交互。
HwndSource提供了一个桥梁,使得WPF应用程序能够接收和处理Win32消息
另外他还可以免除自写控件的痛苦等等 总而言之就是节省了时间
如何使用HwndHook
这里只说对单个控件的HwndHook 因为全窗口的HwndHook网上教程还是比较多的
首先定义HwndSource
接下来写HOOK主体
接下来就是在Loaded写加载HwndHook的函数
这里有个小坑需要注意一下
一般来说 有人喜欢在InitializeComponent();后直接就下HwndHook
这是不可行的
因为如果这样PresentationSource.FromVisual找不到对象
所以你要先等他Loaded
也就是
本文仅供技术学习交流
public
class
CustomPictureBox : PictureBox
{
Node client;
public CustomPictureBox(Node _client)
{
client
=
_client;
}
[DllImport(
"user32.dll"
)]
public static extern short GetKeyState(
int
nVirtKey);
/
/
Constants
for
clipboard data formats
public const uint CF_TEXT
=
1
;
/
/
Text
format
public const uint CF_BITMAP
=
2
;
/
/
Bitmap
format
public const uint CF_UNICODETEXT
=
13
;
/
/
Unicode
text
format
public const uint CF_HDROP
=
15
;
/
/
File
format
/
/
Import the necessary WinAPI functions
[DllImport(
"user32.dll"
)]
[
return
: MarshalAs(UnmanagedType.
Bool
)]
public static extern
bool
IsClipboardFormatAvailable(uint
format
);
[DllImport(
"user32.dll"
)]
[
return
: MarshalAs(UnmanagedType.
Bool
)]
public static extern
bool
OpenClipboard(IntPtr hWndNewOwner);
[DllImport(
"user32.dll"
)]
public static extern IntPtr GetClipboardData(uint uFormat);
[DllImport(
"user32.dll"
)]
[
return
: MarshalAs(UnmanagedType.
Bool
)]
public static extern
bool
CloseClipboard();
[DllImport(
"user32.dll"
)]
static extern short VkKeyScan(char c);
[DllImport(
"user32.dll"
)]
public static extern
int
ToAscii(uint uVirtKey, uint uScanCode, byte[] lpKeyState, out uint lpChar, uint uFlags);
public Point TranslateCoordinates(Point originalCoords, Size originalScreenSize, PictureBox targetControl)
{
/
/
Calculate the scaling factors
float
scaleX
=
(
float
)targetControl.Image.Width
/
originalScreenSize.Width;
float
scaleY
=
(
float
)targetControl.Image.Height
/
originalScreenSize.Height;
/
/
Apply
the scaling factors
int
scaledX
=
(
int
)(originalCoords.X
*
scaleX);
int
scaledY
=
(
int
)(originalCoords.Y
*
scaleY);
/
/
Get the unzoomed
and
offset
-
adjusted coordinates
Point translatedCoords
=
UnzoomedAndAdjusted(targetControl, new Point(scaledX, scaledY));
return
translatedCoords;
}
public static void GetClipboardFormat()
{
if
(!OpenClipboard(IntPtr.Zero))
return
;
if
(IsClipboardFormatAvailable(CF_TEXT))
{
IntPtr hGlobal
=
GetClipboardData(CF_TEXT);
string clipboardText
=
Marshal.PtrToStringUni(hGlobal);
Marshal.FreeHGlobal(hGlobal);
}
else
if
(IsClipboardFormatAvailable(CF_BITMAP))
{
IntPtr hBitmap
=
GetClipboardData(CF_BITMAP);
System.Drawing.Bitmap clipboardBitmap
=
System.Drawing.Bitmap.FromHbitmap(hBitmap);
Marshal.FreeHGlobal(hBitmap);
}
else
if
(IsClipboardFormatAvailable(CF_UNICODETEXT))
{
IntPtr hGlobal
=
GetClipboardData(CF_UNICODETEXT);
string clipboardText
=
Marshal.PtrToStringUni(hGlobal);
Marshal.FreeHGlobal(hGlobal);
}
CloseClipboard();
}
private Point UnzoomedAndAdjusted(PictureBox pictureBox, Point scaledPoint)
{
/
/
Calculate the zoom factor
float
zoomFactor
=
Math.
Min
(
(
float
)pictureBox.ClientSize.Width
/
pictureBox.Image.Width,
(
float
)pictureBox.ClientSize.Height
/
pictureBox.Image.Height);
/
/
Get the displayed rectangle of the image
Rectangle displayedRect
=
GetImageDisplayRectangle(pictureBox);
/
/
Offset
and
unzoom the coordinates
int
translatedX
=
(
int
)((scaledPoint.X
-
displayedRect.X)
/
zoomFactor);
int
translatedY
=
(
int
)((scaledPoint.Y
-
displayedRect.Y)
/
zoomFactor);
return
new Point(translatedX, translatedY);
}
private Rectangle GetImageDisplayRectangle(PictureBox pictureBox)
{
if
(pictureBox.SizeMode
=
=
PictureBoxSizeMode.Normal)
{
return
new Rectangle(
0
,
0
, pictureBox.Image.Width, pictureBox.Image.Height);
}
else
if
(pictureBox.SizeMode
=
=
PictureBoxSizeMode.StretchImage)
{
return
pictureBox.ClientRectangle;
}
else
{
float
zoomFactor
=
Math.
Min
(
(
float
)pictureBox.ClientSize.Width
/
pictureBox.Image.Width,
(
float
)pictureBox.ClientSize.Height
/
pictureBox.Image.Height);
int
imageWidth
=
(
int
)(pictureBox.Image.Width
*
zoomFactor);
int
imageHeight
=
(
int
)(pictureBox.Image.Height
*
zoomFactor);
int
imageX
=
(pictureBox.ClientSize.Width
-
imageWidth)
/
2
;
int
imageY
=
(pictureBox.ClientSize.Height
-
imageHeight)
/
2
;
return
new Rectangle(imageX, imageY, imageWidth, imageHeight);
}
}
public static char GetModifiedKey(char c)
{
short vkKeyScanResult
=
VkKeyScan(c);
/
/
a result of
-
1
indicates no key translates to
input
character
if
(vkKeyScanResult
=
=
-
1
)
return
c;
/
/
vkKeyScanResult &
0xff
is
the base key, without
any
modifiers
uint code
=
(uint)vkKeyScanResult &
0xff
;
/
/
set
shift key pressed
byte[] b
=
new byte[
256
];
b[
0x10
]
=
0x80
;
uint r;
/
/
return
value of
1
expected (
1
character copied to r)
if
(
1
!
=
ToAscii(code, code, b, out r,
0
))
return
c;
return
(char)r;
}
public static
bool
IsAlphaNumeric(char c)
{
return
(c >
=
'a'
&& c <
=
'z'
) || (c >
=
'A'
&& c <
=
'Z'
) || (c >
=
'1'
&& c <
=
'9'
);
}
public void TriggerWndProc(ref Message m)
{
WndProc(ref m);
}
protected override void WndProc(ref Message m)
{
if
(this.Image
=
=
null)
{
base.WndProc(ref m);
return
;
}
byte[] payload;
switch (m.Msg)
{
case
0x0201
:
/
/
WM_LBUTTONDOWN
case
0x0202
:
/
/
WM_LBUTTONUP
case
0x0204
:
/
/
WM_RBUTTONDOWN
case
0x0205
:
/
/
WM_RBUTTONUP
case
0x0207
:
/
/
WM_MBUTTONDOWN
case
0x0208
:
/
/
WM_MBUTTONUP
case
0x0203
:
/
/
WM_LBUTTONDBLCLK
case
0x0206
:
/
/
WM_RBUTTONDBLCLK
case
0x0209
:
/
/
WM_MBUTTONDBLCLK
case
0x0200
:
/
/
WM_MOUSEMOVE
case
0x020A
:
/
/
WM_MOUSEWHEEL
int
x
=
(
int
)(m.LParam.ToInt32() &
0xFFFF
);
int
y
=
(
int
)((m.LParam.ToInt32() >>
16
) &
0xFFFF
);
Point newpoint
=
TranslateCoordinates(new Point(x, y), this.Image.Size, this);
x
=
newpoint.X;
y
=
newpoint.Y;
m.LParam
=
(IntPtr)((y <<
16
) | (x &
0xFFFF
));
uint msg
=
(uint)m.Msg;
IntPtr wParam
=
m.WParam;
IntPtr lParam
=
m.LParam;
int
Imsg
=
(
int
)msg;
int
IwParam
=
(
int
)wParam;
int
IlParam
=
(
int
)lParam;
Task.Run(async ()
=
>
{
payload
=
client.sock.Concat(new byte[] {
3
}, client.sock.IntToBytes(Imsg));
payload
=
client.sock.Concat(payload, client.sock.IntToBytes(IwParam));
payload
=
client.sock.Concat(payload, client.sock.IntToBytes(IlParam));
await client.SendAsync(payload);
}).Wait();
break
;
case
0x0302
:
/
/
WM_PASTE
break
;
case
0x0100
:
/
/
WM_KEYDOWN
case
0x0101
:
/
/
WM_KEYUP
msg
=
(uint)m.Msg;
wParam
=
m.WParam;
lParam
=
m.LParam;
/
/
Check
if
the Shift
or
Caps Lock key
is
pressed
bool
isShiftPressed
=
(GetKeyState((
int
)Keys.ShiftKey) &
0x8000
) !
=
0
;
bool
isCapsLockOn
=
Control.IsKeyLocked(Keys.CapsLock);
if
(isShiftPressed || isCapsLockOn)
{
/
/
Modify the wParam to include the SHIFT
or
CAPSLOCK flag
const
int
VK_SHIFT
=
0x10
;
const
int
VK_CAPITAL
=
0x14
;
if
(wParam.ToInt32()
=
=
VK_SHIFT || wParam.ToInt32()
=
=
VK_CAPITAL)
{
/
/
Skip processing SHIFT
or
CAPSLOCK key release
break
;
}
if
(isShiftPressed)
{
msg
=
0x0102
;
uint scanCode
=
(uint)((lParam.ToInt32() >>
16
) &
0xFF
);
byte[] keyboardState
=
new byte[
256
];
ToAscii((uint)wParam.ToInt32(), scanCode, keyboardState, out uint charCode,
0
);
wParam
=
(IntPtr)Convert.ToInt32(GetModifiedKey((char)charCode));
}
if
(isCapsLockOn)
{
uint scanCode
=
(uint)((lParam.ToInt32() >>
16
) &
0xFF
);
byte[] keyboardState
=
new byte[
256
];
ToAscii((uint)wParam.ToInt32(), scanCode, keyboardState, out uint charCode,
0
);
if
(IsAlphaNumeric((char)charCode))
{
msg
=
0x0102
;
}
}
}
Imsg
=
(
int
)msg;
IwParam
=
(
int
)wParam;
IlParam
=
(
int
)lParam;
Task.Run(async ()
=
>
{
payload
=
client.sock.Concat(new byte[] {
3
}, client.sock.IntToBytes(Imsg));
payload
=
client.sock.Concat(payload, client.sock.IntToBytes(IwParam));
payload
=
client.sock.Concat(payload, client.sock.IntToBytes(IlParam));
await client.SendAsync(payload);
}).Wait();
break
;
}
base.WndProc(ref m);
}
}
public
class
CustomPictureBox : PictureBox
{
Node client;
public CustomPictureBox(Node _client)
{
client
=
_client;
}
[DllImport(
"user32.dll"
)]
public static extern short GetKeyState(
int
nVirtKey);
/
/
Constants
for
clipboard data formats
public const uint CF_TEXT
=
1
;
/
/
Text
format
public const uint CF_BITMAP
=
2
;
/
/
Bitmap
format
public const uint CF_UNICODETEXT
=
13
;
/
/
Unicode
text
format
public const uint CF_HDROP
=
15
;
/
/
File
format
/
/
Import the necessary WinAPI functions
[DllImport(
"user32.dll"
)]
[
return
: MarshalAs(UnmanagedType.
Bool
)]
public static extern
bool
IsClipboardFormatAvailable(uint
format
);
[DllImport(
"user32.dll"
)]
[
return
: MarshalAs(UnmanagedType.
Bool
)]
public static extern
bool
OpenClipboard(IntPtr hWndNewOwner);
[DllImport(
"user32.dll"
)]
public static extern IntPtr GetClipboardData(uint uFormat);
[DllImport(
"user32.dll"
)]
[
return
: MarshalAs(UnmanagedType.
Bool
)]
public static extern
bool
CloseClipboard();
[DllImport(
"user32.dll"
)]
static extern short VkKeyScan(char c);
[DllImport(
"user32.dll"
)]
public static extern
int
ToAscii(uint uVirtKey, uint uScanCode, byte[] lpKeyState, out uint lpChar, uint uFlags);
public Point TranslateCoordinates(Point originalCoords, Size originalScreenSize, PictureBox targetControl)
{
/
/
Calculate the scaling factors
float
scaleX
=
(
float
)targetControl.Image.Width
/
originalScreenSize.Width;
float
scaleY
=
(
float
)targetControl.Image.Height
/
originalScreenSize.Height;
/
/
Apply
the scaling factors
int
scaledX
=
(
int
)(originalCoords.X
*
scaleX);
int
scaledY
=
(
int
)(originalCoords.Y
*
scaleY);
/
/
Get the unzoomed
and
offset
-
adjusted coordinates
Point translatedCoords
=
UnzoomedAndAdjusted(targetControl, new Point(scaledX, scaledY));
return
translatedCoords;
}
public static void GetClipboardFormat()
{
if
(!OpenClipboard(IntPtr.Zero))
return
;
if
(IsClipboardFormatAvailable(CF_TEXT))
{
IntPtr hGlobal
=
GetClipboardData(CF_TEXT);
string clipboardText
=
Marshal.PtrToStringUni(hGlobal);
Marshal.FreeHGlobal(hGlobal);
}
else
if
(IsClipboardFormatAvailable(CF_BITMAP))
{
IntPtr hBitmap
=
GetClipboardData(CF_BITMAP);
System.Drawing.Bitmap clipboardBitmap
=
System.Drawing.Bitmap.FromHbitmap(hBitmap);
Marshal.FreeHGlobal(hBitmap);
}
else
if
(IsClipboardFormatAvailable(CF_UNICODETEXT))
{
IntPtr hGlobal
=
GetClipboardData(CF_UNICODETEXT);
string clipboardText
=
Marshal.PtrToStringUni(hGlobal);
Marshal.FreeHGlobal(hGlobal);
}
CloseClipboard();
}
private Point UnzoomedAndAdjusted(PictureBox pictureBox, Point scaledPoint)
{
/
/
Calculate the zoom factor
float
zoomFactor
=
Math.
Min
(
(
float
)pictureBox.ClientSize.Width
/
pictureBox.Image.Width,
(
float
)pictureBox.ClientSize.Height
/
pictureBox.Image.Height);
/
/
Get the displayed rectangle of the image
Rectangle displayedRect
=
GetImageDisplayRectangle(pictureBox);
/
/
Offset
and
unzoom the coordinates
int
translatedX
=
(
int
)((scaledPoint.X
-
displayedRect.X)
/
zoomFactor);
int
translatedY
=
(
int
)((scaledPoint.Y
-
displayedRect.Y)
/
zoomFactor);
return
new Point(translatedX, translatedY);
}
private Rectangle GetImageDisplayRectangle(PictureBox pictureBox)
{
if
(pictureBox.SizeMode
=
=
PictureBoxSizeMode.Normal)
{
return
new Rectangle(
0
,
0
, pictureBox.Image.Width, pictureBox.Image.Height);
}
else
if
(pictureBox.SizeMode
=
=
PictureBoxSizeMode.StretchImage)
{
return
pictureBox.ClientRectangle;
}
else
{
float
zoomFactor
=
Math.
Min
(
(
float
)pictureBox.ClientSize.Width
/
pictureBox.Image.Width,
(
float
)pictureBox.ClientSize.Height
/
pictureBox.Image.Height);
int
imageWidth
=
(
int
)(pictureBox.Image.Width
*
zoomFactor);
int
imageHeight
=
(
int
)(pictureBox.Image.Height
*
zoomFactor);
int
imageX
=
(pictureBox.ClientSize.Width
-
imageWidth)
/
2
;
int
imageY
=
(pictureBox.ClientSize.Height
-
imageHeight)
/
2
;
return
new Rectangle(imageX, imageY, imageWidth, imageHeight);
}
}
public static char GetModifiedKey(char c)
{
short vkKeyScanResult
=
VkKeyScan(c);
/
/
a result of
-
1
indicates no key translates to
input
character
if
(vkKeyScanResult
=
=
-
1
)
return
c;
/
/
vkKeyScanResult &
0xff
is
the base key, without
any
modifiers
uint code
=
(uint)vkKeyScanResult &
0xff
;
/
/
set
shift key pressed
byte[] b
=
new byte[
256
];
b[
0x10
]
=
0x80
;
uint r;
/
/
return
value of
1
expected (
1
character copied to r)
if
(
1
!
=
ToAscii(code, code, b, out r,
0
))
return
c;
return
(char)r;
}
public static
bool
IsAlphaNumeric(char c)
{
return
(c >
=
'a'
&& c <
=
'z'
) || (c >
=
'A'
&& c <
=
'Z'
) || (c >
=
'1'
&& c <
=
'9'
);
}
public void TriggerWndProc(ref Message m)
{
WndProc(ref m);
}
protected override void WndProc(ref Message m)
{
if
(this.Image
=
=
null)
{
base.WndProc(ref m);
return
;
}
byte[] payload;
switch (m.Msg)
{
case
0x0201
:
/
/
WM_LBUTTONDOWN
case
0x0202
:
/
/
WM_LBUTTONUP
case
0x0204
:
/
/
WM_RBUTTONDOWN
case
0x0205
:
/
/
WM_RBUTTONUP
case
0x0207
:
/
/
WM_MBUTTONDOWN
case
0x0208
:
/
/
WM_MBUTTONUP
case
0x0203
:
/
/
WM_LBUTTONDBLCLK
case
0x0206
:
/
/
WM_RBUTTONDBLCLK
case
0x0209
:
/
/
WM_MBUTTONDBLCLK
case
0x0200
:
/
/
WM_MOUSEMOVE
case
0x020A
:
/
/
WM_MOUSEWHEEL
int
x
=
(
int
)(m.LParam.ToInt32() &
0xFFFF
);
int
y
=
(
int
)((m.LParam.ToInt32() >>
16
) &
0xFFFF
);
Point newpoint
=
TranslateCoordinates(new Point(x, y), this.Image.Size, this);
x
=
newpoint.X;
y
=
newpoint.Y;
m.LParam
=
(IntPtr)((y <<
16
) | (x &
0xFFFF
));
uint msg
=
(uint)m.Msg;
IntPtr wParam
=
m.WParam;
IntPtr lParam
=
m.LParam;
int
Imsg
=
(
int
)msg;
int
IwParam
=
(
int
)wParam;
int
IlParam
=
(
int
)lParam;
Task.Run(async ()
=
>
赞赏
- 解决WPF使用HVNC的问题-HwndHook 6736
- 记一次调用ETW-TI 3776
- [分享]一个MiniFilter的遍历 4135
- 最近看到自制杀软自己的一些感悟 3600
- [原创]分析一个由DCRAT二开而得的远控木马 4862