Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Peacoor Zomboss
miscellaneous
提交
2a71e0a8
M
miscellaneous
项目概览
Peacoor Zomboss
/
miscellaneous
通知
151
Star
9
Fork
18
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
2
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
miscellaneous
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
2
Issue
2
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
2a71e0a8
编写于
1月 31, 2023
作者:
Peacoor Zomboss
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
First step to implement x86 and x64 sendto hook
上级
382b1d66
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
386 addition
and
0 deletion
+386
-0
230130-hookgamesendto/inc/fksendto.h
230130-hookgamesendto/inc/fksendto.h
+7
-0
230130-hookgamesendto/inc/inlinehook.h
230130-hookgamesendto/inc/inlinehook.h
+19
-0
230130-hookgamesendto/inc/platform.h
230130-hookgamesendto/inc/platform.h
+9
-0
230130-hookgamesendto/inc/sockqueue.h
230130-hookgamesendto/inc/sockqueue.h
+17
-0
230130-hookgamesendto/src/fksendto.cpp
230130-hookgamesendto/src/fksendto.cpp
+91
-0
230130-hookgamesendto/src/hookdll.cpp
230130-hookgamesendto/src/hookdll.cpp
+20
-0
230130-hookgamesendto/src/inlinehook.cpp
230130-hookgamesendto/src/inlinehook.cpp
+116
-0
230130-hookgamesendto/src/sockqueue.cpp
230130-hookgamesendto/src/sockqueue.cpp
+23
-0
230130-hookgamesendto/test/testhook/Makefile
230130-hookgamesendto/test/testhook/Makefile
+50
-0
230130-hookgamesendto/test/testhook/testhook.cpp
230130-hookgamesendto/test/testhook/testhook.cpp
+34
-0
未找到文件。
230130-hookgamesendto/inc/fksendto.h
0 → 100644
浏览文件 @
2a71e0a8
#pragma once
#include <winsock2.h>
#include "inlinehook.h"
void
hook_sendto
();
void
unhook_sendto
();
230130-hookgamesendto/inc/inlinehook.h
0 → 100644
浏览文件 @
2a71e0a8
#pragma once
#include <windows.h>
#define HOOK_JUMP_LEN 5
class
InlineHook
{
private:
void
*
old_entry
;
// 存放原来的代码和跳转回去的代码
char
hook_entry
[
HOOK_JUMP_LEN
];
// hook跳转的代码
void
*
func_ptr
;
// 被hook函数的地址
public:
InlineHook
(
HMODULE
hmodule
,
const
char
*
name
,
void
*
fake_func
,
int
entry_len
);
~
InlineHook
();
void
hook
();
void
unhook
();
void
*
get_old_entry
();
};
230130-hookgamesendto/inc/platform.h
0 → 100644
浏览文件 @
2a71e0a8
#pragma once
#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || defined(_M_AMD64)
#define _CPU_X64
#elif defined(__i386__) || defined(_M_IX86)
#define _CPU_X86
#else
#error "Unsupported CPU"
#endif
230130-hookgamesendto/inc/sockqueue.h
0 → 100644
浏览文件 @
2a71e0a8
#pragma once
#include <winsock2.h>
#define MAX_SOCK_QUEUE 64
// Socket循环队列,使socket排队关闭而不是立即关闭
class
SockQueue
{
private:
SOCKET
socks
[
MAX_SOCK_QUEUE
];
int
current
;
public:
SockQueue
();
~
SockQueue
();
void
add
(
SOCKET
s
);
};
230130-hookgamesendto/src/fksendto.cpp
0 → 100644
浏览文件 @
2a71e0a8
#include "fksendto.h"
#include "sockqueue.h"
#include "platform.h"
#include <vector>
#ifdef _CPU_X86
#define SENDTO_ENTRY_LEN 5
#endif
#ifdef _CPU_X64
#define SENDTO_ENTRY_LEN 7
#endif
typedef
int
WINAPI
(
*
sendto_func
)
(
SOCKET
,
const
char
*
,
int
,
int
,
const
sockaddr
*
,
int
);
static
InlineHook
*
sendto_hook
=
NULL
;
static
sendto_func
_sendto
=
NULL
;
// 枚举当前所有可用网卡的IPv4地址
static
const
std
::
vector
<
in_addr
>
&
enum_addr
()
{
static
std
::
vector
<
in_addr
>
list
;
hostent
*
phost
=
gethostbyname
(
""
);
// 获取本机网卡
if
(
phost
)
{
if
(
phost
->
h_length
==
list
.
size
())
// 数量相同直接返回
return
list
;
char
**
ppc
=
phost
->
h_addr_list
;
// 获取地址列表
if
(
ppc
)
{
list
.
clear
();
// 遍历列表添加到容器
while
(
*
ppc
)
{
in_addr
addr
;
memcpy
(
&
addr
,
*
ppc
,
sizeof
(
in_addr
));
list
.
push_back
(
addr
);
ppc
++
;
}
}
}
return
list
;
}
// hook后替换的函数
static
int
WINAPI
fake_sendto
(
SOCKET
s
,
const
char
*
buf
,
int
len
,
int
flags
,
const
sockaddr
*
to
,
int
tolen
)
{
static
SockQueue
sockqueue
;
int
result
=
-
1
;
sockaddr_in
*
toaddr
=
(
sockaddr_in
*
)
to
;
if
(
toaddr
->
sin_addr
.
S_un
.
S_addr
!=
INADDR_BROADCAST
)
{
result
=
_sendto
(
s
,
buf
,
len
,
flags
,
to
,
tolen
);
// 非广播直接原样发送
}
else
{
sockaddr_in
addr_self
;
int
namelen
=
sizeof
(
sockaddr_in
);
getsockname
(
s
,
(
sockaddr
*
)
&
addr_self
,
&
namelen
);
// 获取原sockaddr
if
(
addr_self
.
sin_port
==
0
)
{
// 如果没有端口号,先原样发送,这样系统才会分配一个端口号
result
=
_sendto
(
s
,
buf
,
len
,
flags
,
to
,
tolen
);
getsockname
(
s
,
(
sockaddr
*
)
&
addr_self
,
&
namelen
);
// 重新获取
}
const
std
::
vector
<
in_addr
>
&
list
=
enum_addr
();
// 向列表中的每一个地址转发广播
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++
)
{
addr_self
.
sin_addr
=
list
[
i
];
// 把新的地址换上去,然后发送
SOCKET
sock
=
socket
(
AF_INET
,
SOCK_DGRAM
,
0
);
BOOL
opt
=
TRUE
;
setsockopt
(
sock
,
SOL_SOCKET
,
SO_BROADCAST
,
(
char
*
)
&
opt
,
sizeof
(
BOOL
));
// 广播
setsockopt
(
sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
char
*
)
&
opt
,
sizeof
(
BOOL
));
// 重用地址端口
bind
(
sock
,
(
sockaddr
*
)
&
addr_self
,
sizeof
(
sockaddr
));
// 绑定到地址端口
result
=
_sendto
(
sock
,
buf
,
len
,
flags
,
to
,
tolen
);
sockqueue
.
add
(
sock
);
// 加到socket队列里
}
}
return
result
;
}
void
hook_sendto
()
{
if
(
!
sendto_hook
)
{
sendto_hook
=
new
InlineHook
(
GetModuleHandleA
(
"ws2_32.dll"
),
"sendto"
,
(
void
*
)
fake_sendto
,
SENDTO_ENTRY_LEN
);
_sendto
=
(
sendto_func
)
sendto_hook
->
get_old_entry
();
sendto_hook
->
hook
();
}
}
void
unhook_sendto
()
{
if
(
sendto_hook
)
{
sendto_hook
->
unhook
();
delete
sendto_hook
;
sendto_hook
=
NULL
;
}
}
230130-hookgamesendto/src/hookdll.cpp
0 → 100644
浏览文件 @
2a71e0a8
#include <winsock2.h>
#include <windows.h>
#include <vector>
#include "inlinehook.h"
#include "fksendto.h"
#ifdef _MSC_VER
#pragma comment (lib, "ws2_32.lib") // 比较坑啊,在项目设置里加没用
#endif
BOOL
APIENTRY
DllMain
(
HINSTANCE
hinstdll
,
DWORD
reason
,
LPVOID
reserved
)
{
if
(
reason
==
DLL_PROCESS_ATTACH
)
{
hook_sendto
();
}
else
if
(
reason
==
DLL_PROCESS_DETACH
)
{
unhook_sendto
();
}
return
TRUE
;
}
230130-hookgamesendto/src/inlinehook.cpp
0 → 100644
浏览文件 @
2a71e0a8
#include <windows.h>
#include "inlinehook.h"
#include "platform.h"
#ifdef _CPU_X64
static
void
*
FindModuleTextBlankAlign
(
HMODULE
hmodule
)
{
BYTE
*
p
=
(
BYTE
*
)
hmodule
;
IMAGE_DOS_HEADER
dosh
;
ReadProcessMemory
(
GetCurrentProcess
(),
p
,
&
dosh
,
sizeof
(
dosh
),
NULL
);
// 读取dos头
p
+=
dosh
.
e_lfanew
+
4
;
// PE信息偏移量
IMAGE_FILE_HEADER
exeh
;
ReadProcessMemory
(
GetCurrentProcess
(),
p
,
&
exeh
,
sizeof
(
exeh
),
NULL
);
// 读取PE信息
p
+=
sizeof
(
exeh
)
+
exeh
.
SizeOfOptionalHeader
;
// 跳过可选头
for
(
int
i
=
0
;
i
<
exeh
.
NumberOfSections
;
i
++
)
{
IMAGE_SECTION_HEADER
sech
;
ReadProcessMemory
(
GetCurrentProcess
(),
p
,
&
sech
,
sizeof
(
sech
),
NULL
);
// 读取区段头
if
(
memcmp
(
sech
.
Name
,
".text"
,
5
)
==
0
)
{
// 是否.text段
BYTE
*
offset
=
(
BYTE
*
)
hmodule
+
sech
.
VirtualAddress
+
sech
.
Misc
.
VirtualSize
;
// 计算空白区域偏移量
offset
+=
16
-
(
INT_PTR
)
offset
%
16
;
// 对齐16字节
long
long
buf
[
2
];
ReadProcessMemory
(
GetCurrentProcess
(),
offset
,
&
buf
,
16
,
NULL
);
while
(
buf
[
0
]
!=
0
||
buf
[
1
]
!=
0
)
{
offset
+=
16
;
ReadProcessMemory
(
GetCurrentProcess
(),
offset
,
&
buf
,
16
,
NULL
);
}
return
offset
;
}
}
return
0
;
}
#endif
InlineHook
::
InlineHook
(
HMODULE
hmodule
,
const
char
*
name
,
void
*
fake_func
,
int
entry_len
)
{
func_ptr
=
(
void
*
)
GetProcAddress
(
hmodule
,
name
);
// 范围检查
if
(
entry_len
<
HOOK_JUMP_LEN
)
entry_len
=
HOOK_JUMP_LEN
;
if
(
entry_len
>
27
)
entry_len
=
27
;
// 允许func_ptr处最前面的5字节内存可读可写可执行
VirtualProtect
(
func_ptr
,
HOOK_JUMP_LEN
,
PAGE_EXECUTE_READWRITE
,
NULL
);
// 使用VirtualAlloc申请内存,使其可读可写可执行
old_entry
=
VirtualAlloc
(
NULL
,
32
,
MEM_COMMIT
,
PAGE_EXECUTE_READWRITE
);
#ifdef _CPU_X64
union
{
void
*
ptr
;
struct
{
long
lo
;
long
hi
;
};
}
ptr64
;
void
*
blank
=
FindModuleTextBlankAlign
(
hmodule
);
// 找到第一处空白区域
VirtualProtect
(
blank
,
14
,
PAGE_EXECUTE_READWRITE
,
NULL
);
// 可读写
hook_entry
[
0
]
=
0xE9
;
// 跳转代码
*
(
long
*
)
&
hook_entry
[
1
]
=
(
BYTE
*
)
blank
-
(
BYTE
*
)
func_ptr
-
5
;
// 跳转到空白区域
ptr64
.
ptr
=
fake_func
;
BYTE
blank_jump
[
14
];
blank_jump
[
0
]
=
0x68
;
// push xxx
*
(
long
*
)
&
blank_jump
[
1
]
=
ptr64
.
lo
;
// xxx,即地址的低4位
blank_jump
[
5
]
=
0xC7
;
blank_jump
[
6
]
=
0x44
;
blank_jump
[
7
]
=
0x24
;
blank_jump
[
8
]
=
0x04
;
// mov dword [rsp+4], yyy
*
(
long
*
)
&
blank_jump
[
9
]
=
ptr64
.
hi
;
// yyy,即地址的高4位
blank_jump
[
13
]
=
0xC3
;
// ret
// 写入真正的跳转代码到空白区域
WriteProcessMemory
(
GetCurrentProcess
(),
blank
,
&
blank_jump
,
14
,
NULL
);
// 保存原来的入口代码
ReadProcessMemory
(
GetCurrentProcess
(),
func_ptr
,
old_entry
,
entry_len
,
NULL
);
ptr64
.
ptr
=
(
BYTE
*
)
func_ptr
+
entry_len
;
// 设置新的跳转代码
BYTE
*
new_jump
=
(
BYTE
*
)
old_entry
+
entry_len
;
new_jump
[
0
]
=
0x68
;
*
(
long
*
)(
new_jump
+
1
)
=
ptr64
.
lo
;
new_jump
[
5
]
=
0xC7
;
new_jump
[
6
]
=
0x44
;
new_jump
[
7
]
=
0x24
;
new_jump
[
8
]
=
0x04
;
*
(
long
*
)(
new_jump
+
9
)
=
ptr64
.
hi
;
new_jump
[
13
]
=
0xC3
;
#endif
#ifdef _CPU_X86
hook_entry
[
0
]
=
0xE9
;
// 跳转代码
*
(
long
*
)
&
hook_entry
[
1
]
=
(
BYTE
*
)
fake_func
-
(
BYTE
*
)
func_ptr
-
5
;
// 直接到hook的代码
ReadProcessMemory
(
GetCurrentProcess
(),
func_ptr
,
old_entry
,
entry_len
,
NULL
);
// 保存入口
BYTE
*
new_jump
=
(
BYTE
*
)
old_entry
+
entry_len
;
*
new_jump
=
0xE9
;
// 跳回去的代码
*
(
long
*
)(
new_jump
+
1
)
=
(
BYTE
*
)
func_ptr
+
entry_len
-
new_jump
-
5
;
#endif
}
InlineHook
::~
InlineHook
()
{
if
(
old_entry
)
VirtualFree
(
old_entry
,
0
,
MEM_RELEASE
);
}
void
InlineHook
::
hook
()
{
WriteProcessMemory
(
GetCurrentProcess
(),
func_ptr
,
&
hook_entry
,
HOOK_JUMP_LEN
,
NULL
);
}
void
InlineHook
::
unhook
()
{
WriteProcessMemory
(
GetCurrentProcess
(),
func_ptr
,
old_entry
,
HOOK_JUMP_LEN
,
NULL
);
}
void
*
InlineHook
::
get_old_entry
()
{
return
old_entry
;
}
230130-hookgamesendto/src/sockqueue.cpp
0 → 100644
浏览文件 @
2a71e0a8
#include "sockqueue.h"
SockQueue
::
SockQueue
()
{
memset
(
&
socks
,
0
,
MAX_SOCK_QUEUE
*
sizeof
(
SOCKET
));
current
=
0
;
}
SockQueue
::~
SockQueue
()
{
for
(
int
i
=
0
;
i
<
MAX_SOCK_QUEUE
;
i
++
)
if
(
socks
[
i
]
!=
0
)
closesocket
(
socks
[
i
]);
}
void
SockQueue
::
add
(
SOCKET
s
)
{
if
(
socks
[
current
]
!=
0
)
closesocket
(
socks
[
current
]);
socks
[
current
++
]
=
s
;
if
(
current
==
MAX_SOCK_QUEUE
)
current
=
0
;
}
230130-hookgamesendto/test/testhook/Makefile
0 → 100644
浏览文件 @
2a71e0a8
cxx
=
g++
cxxflags
=
-c
-I
../../inc
cxx32prefix
=
i686-w64-mingw32-
cxx64prefix
=
x86_64-w64-mingw32-
target
=
testhook.exe
target32
=
testhook32.exe
target64
=
testhook64.exe
src
=
testhook.cpp inlinehook.cpp
objdir
=
./obj/
obj
=
$(
patsubst
%.cpp,
$(objdir)
%.o,
$(src)
)
obj32
=
$(
patsubst
%.cpp,
$(objdir)
%_32.o,
$(src)
)
obj64
=
$(
patsubst
%.cpp,
$(objdir)
%_64.o,
$(src)
)
targets
=
$(target)
vpath
%.cpp
../../src
ifeq
($(cpu32),1)
targets
+=
$(target32)
endif
ifeq
($(cpu64),1)
targets
+=
$(target64)
endif
all
:
check $(targets)
$(target)
:
$(obj)
$(cxx)
-o
$@
$^
$(target32)
:
$(obj32)
$(cxx32prefix)$(cxx)
-o
$@
$^
$(target64)
:
$(obj64)
$(cxx64prefix)$(cxx)
-o
$@
$^
$(objdir)%.o
:
%.cpp
$(cxx)
$(cxxflags)
-o
$@
$<
$(objdir)%_32.o
:
%.cpp
$(cxx32prefix)$(cxx)
$(cxxflags)
-o
$@
$<
$(objdir)%_64.o
:
%.cpp
$(cxx64prefix)$(cxx)
$(cxxflags)
-o
$@
$<
.PHONY
:
check clean
check
:
@
if
not exist obj md obj
clean
:
@
if
exist obj del obj
\*
.o
@
del
*
.exe
230130-hookgamesendto/test/testhook/testhook.cpp
0 → 100644
浏览文件 @
2a71e0a8
#include <windows.h>
#include <stdio.h>
#include "inlinehook.h"
#include "platform.h"
#ifdef _CPU_X64
#define MESSAGEBOXA_ENTRYLEN 7 // 64位的一般需要反汇编得出
#endif
#ifdef _CPU_X86
#define MESSAGEBOXA_ENTRYLEN 5
#endif
typedef
int
WINAPI
(
*
MessageBoxA_func
)(
HWND
,
LPCSTR
,
LPCSTR
,
UINT
);
static
InlineHook
*
hook
;
static
MessageBoxA_func
_MessageBoxA
;
int
WINAPI
fk_MessageBoxA
(
HWND
hWnd
,
LPCSTR
lpText
,
LPCSTR
lpCaption
,
UINT
uType
)
{
printf
(
"original caption: %s
\n
original text: %s
\n
"
,
lpCaption
,
lpText
);
return
_MessageBoxA
(
hWnd
,
"Hook MessageBoxA"
,
"test"
,
MB_ICONERROR
);
}
int
main
()
{
hook
=
new
InlineHook
(
GetModuleHandleA
(
"user32.dll"
),
"MessageBoxA"
,
(
void
*
)
fk_MessageBoxA
,
MESSAGEBOXA_ENTRYLEN
);
_MessageBoxA
=
(
MessageBoxA_func
)
hook
->
get_old_entry
();
hook
->
hook
();
MessageBoxA
(
0
,
"testhook"
,
"test"
,
0
);
// 被hook
_MessageBoxA
(
0
,
"never hook"
,
"test"
,
0
);
// 不被hook
hook
->
unhook
();
delete
hook
;
MessageBoxA
(
0
,
"nohook"
,
"test"
,
0
);
// 不被hook
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录