提交 7b58f839 编写于 作者: Peacoor Zomboss's avatar Peacoor Zomboss

Fix bugs, hook select and recvfrom

上级 3ac69fe1
......@@ -6,7 +6,7 @@ cxx32prefix = i686-w64-mingw32-
cxx64prefix = x86_64-w64-mingw32-
objdir = ./obj/
bindir = ../bin/
src = hookdll.cpp fksendto.cpp inlinehook.cpp sockqueue.cpp
src = hookdll.cpp fkhook.cpp inlinehook.cpp sockqueue.cpp
obj32 = $(patsubst %.cpp, $(objdir)%_32.o, $(src))
obj64 = $(patsubst %.cpp, $(objdir)%_64.o, $(src))
target32 = $(bindir)hookdll32.dll
......
#include <windows.h>
#include "inlinehook.h"
#include "fksendto.h"
#include "fkhook.h"
#ifdef _MSC_VER
#pragma comment (lib, "ws2_32.lib")
......@@ -9,10 +9,10 @@
BOOL APIENTRY DllMain(HINSTANCE hinstdll, DWORD reason, LPVOID reserved)
{
if (reason == DLL_PROCESS_ATTACH) {
hook_sendto();
hook();
}
else if (reason == DLL_PROCESS_DETACH) {
unhook_sendto();
unhook();
}
return TRUE;
}
......@@ -2,5 +2,5 @@
#include "inlinehook.h"
void hook_sendto();
void unhook_sendto();
void hook();
void unhook();
#include <winsock2.h>
#include "fksendto.h"
#include "fkhook.h"
#include "sockqueue.h"
#include "platform.h"
#include <vector>
#ifdef _CPU_X86
#define SENDTO_ENTRY_LEN 5
#define SELECT_ENTRY_LEN 7
#define RECVFROM_ENTRY_LEN 5
#endif
#ifdef _CPU_X64
#define SENDTO_ENTRY_LEN 7
#define SELECT_ENTRY_LEN 7
#define RECVFROM_ENTRY_LEN 7
#endif
typedef int WINAPI(*sendto_func) (SOCKET, const char *, int, int, const sockaddr *, int);
typedef int WINAPI(*select_func) (int, fd_set *, fd_set *, fd_set *, const TIMEVAL *);
typedef int WINAPI(*recvfrom_func) (SOCKET, char *, int, int, sockaddr *, int *);
static InlineHook *sendto_hook = NULL;
static InlineHook *select_hook = NULL;
static InlineHook *recvfrom_hook = NULL;
static sendto_func _sendto = NULL;
static select_func _select = NULL;
static recvfrom_func _recvfrom = NULL;
static SOCKET origin_sock = 0, fake_sock = 0;
static std::vector<SOCKET> socks;
// 枚举当前所有可用网卡的IPv4地址
static const std::vector<in_addr> &enum_addr()
......@@ -44,35 +56,73 @@ static const std::vector<in_addr> &enum_addr()
// 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;
// static SockQueue sockqueue;
sockaddr_in *toaddr = (sockaddr_in *)to;
if (toaddr->sin_addr.S_un.S_addr != INADDR_BROADCAST) {
result = _sendto(s, buf, len, flags, to, tolen); // 非广播直接原样发送
return _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); // 重新获取
}
int result = -1;
origin_sock = s; // 暂存这个socket
const std::vector<in_addr> &list = enum_addr();
if (socks.size() != list.size()) {
sockaddr_in addr_self;
addr_self.sin_family = AF_INET;
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); // 重新获取
}
for (int i = 0; i < socks.size(); i++)
closesocket(socks[i]);
socks.clear();
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)); // 绑定到地址端口
socks.push_back(sock);
}
}
// 向列表中的每一个地址转发广播
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队列里
for (int i = 0; i < socks.size(); i++) {
result = _sendto(socks[i], buf, len, flags, to, tolen);
}
return result;
}
return -1;
}
static int WINAPI fake_select(int n, fd_set *rd, fd_set *wr, fd_set *ex, const TIMEVAL *timeout)
{
if (rd && rd->fd_count == 1 && origin_sock == rd->fd_array[0]) {
fd_set fds;
FD_ZERO(&fds);
for (int i = 0; i < socks.size(); i++)
FD_SET(socks[i], &fds);
int r = _select(0, &fds, NULL, NULL, timeout);
if (r > 0) {
fake_sock = fds.fd_array[0];
return fds.fd_count;
}
fake_sock = 0;
return _select(n, rd, wr, ex, timeout);
}
else
return _select(n, rd, wr, ex, timeout);
}
static int WINAPI fake_recvfrom(SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen)
{
if (s == origin_sock && fake_sock != 0) {
return _recvfrom(fake_sock, buf, len, flags, from, fromlen);
}
return result;
else
return _recvfrom(s, buf, len, flags, from, fromlen);
}
void hook_sendto()
......@@ -92,3 +142,55 @@ void unhook_sendto()
sendto_hook = NULL;
}
}
void hook_select()
{
if (!select_hook) {
select_hook = new InlineHook(GetModuleHandleA("ws2_32.dll"), "select", (void *)fake_select, SELECT_ENTRY_LEN);
_select = (select_func)select_hook->get_old_entry();
select_hook->hook();
}
}
void unhook_select()
{
if (select_hook) {
select_hook->unhook();
delete select_hook;
select_hook = NULL;
}
}
void hook_recvfrom()
{
if (!recvfrom_hook) {
recvfrom_hook = new InlineHook(GetModuleHandleA("ws2_32.dll"), "recvfrom", (void *)fake_recvfrom, RECVFROM_ENTRY_LEN);
_recvfrom = (recvfrom_func)recvfrom_hook->get_old_entry();
recvfrom_hook->hook();
}
}
void unhook_recvfrom()
{
if (recvfrom_hook) {
recvfrom_hook->unhook();
delete recvfrom_hook;
recvfrom_hook = NULL;
}
}
void hook()
{
hook_sendto();
hook_select();
hook_recvfrom();
}
void unhook()
{
unhook_sendto();
unhook_select();
unhook_recvfrom();
for (int i = 0; i < socks.size(); i++)
closesocket(socks[i]);
socks.clear();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册