修复10年前游戏的BUG
原创 huoji 2026-05-28 08:00 北京

前言
这几天在跟朋友玩《异形:殖民军》这款游戏,这款游戏于2013年发售,制作完后制作组就跑路了。可以简单理解为这是一款太空版支持联机过剧情的使命召唤like游戏。我们两个下的都是FLT修改版本,本来想以前走hamachi局域网联机。
但是意外发生了,我们死活联机不上。提示找不到游戏。随后我们试了一下tun方案/对战平台方案,完全没办法联机。

可是我记得十年前玩的时候是可以正常联机的。问题出在哪?
联机流程
由于游戏早就死了,steam买不值得,我们用的是盗版,盗版走的是局域网联机方案,所谓局域网联机方案,一般指的是用hamachi或者对战平台或者各种联机工具 建立一个虚拟局域网,大家都有一样的虚拟局域网ip

这个虚拟机的网卡就是假的局域网,从而让大家走“局域网联机”

理论上我们应该连的上,所以对这个网卡进行抓包,发现完全没游戏的数据包进来(游戏数据包是UPD,这里只有ICMP,是测延迟用的)

传统游戏的局域网联机逻辑是,游戏对所有网卡的0.0.0.0 发一个UDP广播包,255.255.255.255 这个包会在整个局域网进行广播,然后如果有客户端就会 回包。
这个游戏确实监听了UDP端口,并且等待广播包

所以 问题很明显,游戏并没有对这个网卡发包。打开procmon,我们看看游戏发了什么包:

我们可以看到,这个是第一个问题,这个游戏广播的包是我的物理网卡地址,并不是TUN的卡的地址。那肯定是没有人回复的。
这个问题很好解决,根据我多年的零信任开发经验,游戏应该是通过一个叫做 越点 的机制去判断当前可用网卡的,我们只需要把虚拟网卡的越点设置为1就行

这样游戏就会优先考虑虚拟网卡的IP发包。但是依然连不上
再次抓包,发现:

解读一下,游戏的广播包服务端确实返回了回复了,我的客户端也即将链接,但是我的客户端莫名其妙的链到了25.16.24.136这个完全摸不着头脑的国外地址! 按理说应该直接链接10.100.239.2这个我的朋友的虚拟网卡IP的
经过一段时间的摸索,我发现,这个25.16.245.136是我朋友的一个虚拟网卡的IP地址,说明: 游戏服务端收到信息了,但是回复的网卡IP错误!理论上,应该回复他的当前包过来的绑定的IP但是为什么会回复这个,不知道。
临时解决方法是,禁用这个虚拟网卡,祈祷游戏能找到真的地址
禁用虚拟网卡后,我们发现更完蛋了,游戏服务端返回的是电脑的物理网卡地址
这个是不可能通的,除非开零信任。零信任这个时候确实派上用场了。但是肯定不能为了一个游戏装这玩意。
因此有必要去代码层看看了
深入代码层
让我们直接逆向这个游戏,看看为什么会这样吧拖入IDA,对sento打断点,连接游戏看看:
构造255.255.255.255的包
发送:
可以看到,发送的socket是一个socket,而不是枚举网卡逐个发送
这就导致了第一个问题,广播包没广播对网卡
对于第二个问题,我们抓一个包看看:
游戏服务器会返回一个包里面带了游戏服务端的IP地址
这一段是服务端的IP地址:
这个IP地址很明显也是错误的
根据服务端代码,问题出在得到网卡地址的这里,服务端收到包是能知道哪个socket的,但是他的网络和引擎层不是一个socket,他的网络层是获取不到的,所以他就只能,取一个本机 IP 发出去….毕竟,2013年的时候哪有那么复杂的网卡局域网联机环境?
而这个IP就是纯随机的来源。
修复这个bug
我们有几个修复方案,比如改包把IP改成自己的,起一个假的转发代理服务器等。但是最直接的办法是hook,我跟朋友写了两个方案,我的方案是客户端的方案,朋友的是服务端方案
客户端方案:
通过hook sockets,进行改包,我用的是minihook:
#include "pch.h"
#include <cstdio>
#include <cstdarg>
#include <cstdint>
#include <cstring>
#include <vector>
#include <string>
#include "MinHook/include/MinHook.h"
namespace {
using sendto_t = int(WINAPI*)(SOCKET, const char*, int, int, const sockaddr*,
int);
using recvfrom_t = int(WINAPI*)(SOCKET, char*, int, int, sockaddr*, int*);
using bind_t = int(WINAPI*)(SOCKET, const sockaddr*, int);
using getsockname_t = int(WINAPI*)(SOCKET, sockaddr*, int*);
using gethostname_t = int(WINAPI*)(char*, int);
using gethostbyname_t = hostent*(WINAPI*)(const char*);
sendto_t RealSendTo = nullptr;
recvfrom_t RealRecvFrom = nullptr;
bind_t RealBind = nullptr;
getsockname_t RealGetSockName = nullptr;
gethostname_t RealGetHostName = nullptr;
gethostbyname_t RealGetHostByName = nullptr;
HMODULE g_Module = nullptr;
HANDLE g_WorkerThread = nullptr;
volatile bool g_Running = true;
bool g_LogPackets = true;
bool g_FixPayload = false;
uint32_t g_ForcedIp = 0;
std::vector<uint32_t> g_LocalIps;
CRITICAL_SECTION g_LogLock;
uint32_t ReadBe32(const char* p) {
return (uint32_t(uint8_t(p[0])) << 24) | (uint32_t(uint8_t(p[1])) << 16) |
(uint32_t(uint8_t(p[2])) << 8) | uint32_t(uint8_t(p[3]));
}
void WriteBe32(char* p, uint32_t ip) {
p[0] = char((ip >> 24) & 0xff);
p[1] = char((ip >> 16) & 0xff);
p[2] = char((ip >> 8) & 0xff);
p[3] = char(ip & 0xff);
}
std::string IpToString(uint32_t ip) {
char buf[32];
std::snprintf(buf, sizeof(buf), "%u.%u.%u.%u", (ip >> 24) & 0xff,
(ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
return buf;
}
uint32_t SockAddrIp(const sockaddr* addr) {
if (!addr || addr->sa_family != AF_INET) {
return 0;
}
const sockaddr_in* in = reinterpret_cast<const sockaddr_in*>(addr);
return ntohl(in->sin_addr.s_addr);
}
uint16_t SockAddrPort(const sockaddr* addr) {
if (!addr || addr->sa_family != AF_INET) {
return 0;
}
const sockaddr_in* in = reinterpret_cast<const sockaddr_in*>(addr);
return ntohs(in->sin_port);
}
void Log(const char* fmt, ...) {
EnterCriticalSection(&g_LogLock);
va_list args;
va_start(args, fmt);
std::vprintf(fmt, args);
va_end(args);
std::printf("\n");
std::fflush(stdout);
LeaveCriticalSection(&g_LogLock);
}
bool IsInterestingPacket(const char* buf, int len) {
if (!buf || len <= 0) {
return false;
}
if (len >= 2 && buf[0] == 'U' &&
(buf[1] == 'D' || buf[1] == 'C' || buf[1] == 'F')) {
return true;
}
if (len >= 2 && buf[0] == 'N' && buf[1] == 'F') {
return true;
}
if (len > 200) {
return true;
}
return false;
}
bool LooksLikeUsefulIp(uint32_t ip) {
const uint8_t a = uint8_t((ip >> 24) & 0xff);
const uint8_t b = uint8_t((ip >> 16) & 0xff);
if (ip == 0 || ip == 0xffffffff || a == 0 || a == 127 || a >= 224) {
return false;
}
if (a == 10 || a == 25 || (a == 172 && b >= 16 && b <= 31) ||
(a == 192 && b == 168)) {
return true;
}
return false;
}
void ScanPayloadIps(const char* tag, const char* buf, int len) {
if (!buf || len < 4) {
return;
}
int shown = 0;
for (int i = 0; i <= len - 4; ++i) {
const uint32_t be = ReadBe32(buf + i);
if (LooksLikeUsefulIp(be)) {
if (shown == 0) {
std::printf("%s candidate IPs:", tag);
}
std::printf(" +0x%X=%s", i, IpToString(be).c_str());
++shown;
if (shown >= 12) {
std::printf(" ...");
break;
}
}
}
if (shown > 0) {
std::printf("\n");
}
}
void DumpPacketPrefix(const char* tag, const char* buf, int len) {
if (!buf || len <= 0) {
return;
}
const int count = len < 64 ? len : 64;
std::printf("%s first %d:", tag, count);
for (int i = 0; i < count; ++i) {
std::printf(" %02X", uint8_t(buf[i]));
}
std::printf("\n");
}
void AddLocalIp(uint32_t ip) {
if (ip == 0 || ip == 0x7f000001) {
return;
}
for (uint32_t existing : g_LocalIps) {
if (existing == ip) {
return;
}
}
g_LocalIps.push_back(ip);
}
void RefreshLocalIps() {
g_LocalIps.clear();
HMODULE wsock32 = GetModuleHandleW(L"WSOCK32.dll");
if (!wsock32) {
wsock32 = LoadLibraryW(L"WSOCK32.dll");
}
auto realGetHostName =
reinterpret_cast<gethostname_t>(GetProcAddress(wsock32, "gethostname"));
auto realGetHostByName = reinterpret_cast<gethostbyname_t>(
GetProcAddress(wsock32, "gethostbyname"));
char name[256] = {};
if (realGetHostName && realGetHostByName &&
realGetHostName(name, sizeof(name)) == 0) {
hostent* host = realGetHostByName(name);
if (host && host->h_addrtype == AF_INET) {
for (char** addr = host->h_addr_list; addr && *addr; ++addr) {
AddLocalIp(ntohl(*reinterpret_cast<uint32_t*>(*addr)));
}
}
}
}
int ReplaceIpsInPayload(char* buf, int len, uint32_t replacement) {
if (!buf || len < 4 || replacement == 0) {
return 0;
}
int replaced = 0;
for (int i = 0; i <= len - 4; ++i) {
const uint32_t value = ReadBe32(buf + i);
for (uint32_t localIp : g_LocalIps) {
if (value == localIp && value != replacement) {
WriteBe32(buf + i, replacement);
++replaced;
}
}
}
return replaced;
}
int WINAPI HookSendTo(SOCKET s, const char* buf, int len, int flags,
const sockaddr* to, int tolen) {
const uint32_t toIp = SockAddrIp(to);
const uint16_t toPort = SockAddrPort(to);
if (g_LogPackets && IsInterestingPacket(buf, len)) {
Log("sendto s=%p to=%s:%u len=%d", reinterpret_cast<void*>(s),
IpToString(toIp).c_str(), toPort, len);
DumpPacketPrefix(" send", buf, len);
ScanPayloadIps(" send", buf, len);
}
if (g_FixPayload && g_ForcedIp && buf && len > 0) {
std::vector<char> copy(buf, buf + len);
const int changed = ReplaceIpsInPayload(copy.data(), len, g_ForcedIp);
if (changed > 0) {
Log("sendto fixed %d payload IP(s) -> %s", changed,
IpToString(g_ForcedIp).c_str());
return RealSendTo(s, copy.data(), len, flags, to, tolen);
}
}
return RealSendTo(s, buf, len, flags, to, tolen);
}
int WINAPI HookRecvFrom(SOCKET s, char* buf, int len, int flags, sockaddr* from,
int* fromlen) {
const int ret = RealRecvFrom(s, buf, len, flags, from, fromlen);
if (ret <= 0) {
return ret;
}
const uint32_t fromIp = SockAddrIp(from);
const uint16_t fromPort = SockAddrPort(from);
if (g_FixPayload && fromIp) {
const int changed = ReplaceIpsInPayload(buf, ret, fromIp);
if (changed > 0) {
Log("recvfrom fixed %d payload IP(s) -> packet source %s", changed,
IpToString(fromIp).c_str());
}
}
if (g_LogPackets && IsInterestingPacket(buf, ret)) {
Log("recvfrom s=%p from=%s:%u len=%d", reinterpret_cast<void*>(s),
IpToString(fromIp).c_str(), fromPort, ret);
DumpPacketPrefix(" recv", buf, ret);
ScanPayloadIps(" recv", buf, ret);
}
return ret;
}
int WINAPI HookBind(SOCKET s, const sockaddr* name, int namelen) {
const uint32_t ip = SockAddrIp(name);
AddLocalIp(ip);
Log("bind s=%p local=%s:%u", reinterpret_cast<void*>(s),
IpToString(ip).c_str(), SockAddrPort(name));
return RealBind(s, name, namelen);
}
int WINAPI HookGetSockName(SOCKET s, sockaddr* name, int* namelen) {
const int ret = RealGetSockName(s, name, namelen);
if (ret == 0) {
const uint32_t ip = SockAddrIp(name);
AddLocalIp(ip);
Log("getsockname s=%p local=%s:%u", reinterpret_cast<void*>(s),
IpToString(ip).c_str(), SockAddrPort(name));
}
return ret;
}
int WINAPI HookGetHostName(char* name, int namelen) {
const int ret = RealGetHostName(name, namelen);
if (ret == 0) {
Log("gethostname -> %s", name);
}
return ret;
}
hostent* WINAPI HookGetHostByName(const char* name) {
hostent* ret = RealGetHostByName(name);
if (ret) {
std::printf("gethostbyname %s ->", name ? name : "<null>");
if (ret->h_addrtype == AF_INET) {
for (char** addr = ret->h_addr_list; addr && *addr; ++addr) {
const uint32_t ip = ntohl(*reinterpret_cast<uint32_t*>(*addr));
AddLocalIp(ip);
std::printf(" %s", IpToString(ip).c_str());
}
}
std::printf("\n");
}
return ret;
}
bool HookExport(HMODULE module, const char* name, void* hook, void** original) {
void* target = reinterpret_cast<void*>(GetProcAddress(module, name));
if (!target) {
Log("missing export: %s", name);
return false;
}
MH_STATUS status = MH_CreateHook(target, hook, original);
if (status != MH_OK && status != MH_ERROR_ALREADY_CREATED) {
Log("MH_CreateHook(%s) failed: %d", name, status);
return false;
}
status = MH_EnableHook(target);
if (status != MH_OK && status != MH_ERROR_ENABLED) {
Log("MH_EnableHook(%s) failed: %d", name, status);
return false;
}
Log("hooked %s at %p", name, target);
return true;
}
uint32_t ParseIp(const char* text) {
unsigned int a = 0, b = 0, c = 0, d = 0;
if (sscanf_s(text, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) {
return 0;
}
if (a > 255 || b > 255 || c > 255 || d > 255) {
return 0;
}
return (a << 24) | (b << 16) | (c << 8) | d;
}
void PrintHelp() {
Log("commands:");
Log(" help show commands");
Log(" log on|off enable or disable packet logs");
Log(" fix on|off replace payload local IPs, default off");
Log(" ip a.b.c.d force replacement IP for outgoing sendto");
Log(" local a.b.c.d add an IP that should be replaced");
Log(" ips show local IPs detected by gethostbyname");
Log(" refresh refresh local IP list");
Log(" quit unhook and unload DLL");
}
void CommandLoop() {
PrintHelp();
char line[256] = {};
while (g_Running && std::fgets(line, sizeof(line), stdin)) {
line[strcspn(line, "\r\n")] = 0;
if (_stricmp(line, "help") == 0) {
PrintHelp();
} else if (_stricmp(line, "log on") == 0) {
g_LogPackets = true;
Log("log on");
} else if (_stricmp(line, "log off") == 0) {
g_LogPackets = false;
Log("log off");
} else if (_stricmp(line, "fix on") == 0) {
g_FixPayload = true;
Log("fix on");
} else if (_stricmp(line, "fix off") == 0) {
g_FixPayload = false;
Log("fix off");
} else if (_strnicmp(line, "ip ", 3) == 0) {
const uint32_t ip = ParseIp(line + 3);
if (ip) {
g_ForcedIp = ip;
Log("forced IP = %s", IpToString(g_ForcedIp).c_str());
} else {
Log("bad ip");
}
} else if (_strnicmp(line, "local ", 6) == 0) {
const uint32_t ip = ParseIp(line + 6);
if (ip) {
AddLocalIp(ip);
Log("added local/replace source IP = %s",
IpToString(ip).c_str());
} else {
Log("bad ip");
}
} else if (_stricmp(line, "ips") == 0) {
for (uint32_t ip : g_LocalIps) {
Log("local %s", IpToString(ip).c_str());
}
} else if (_stricmp(line, "refresh") == 0) {
RefreshLocalIps();
Log("refreshed %u local IP(s)", unsigned(g_LocalIps.size()));
} else if (_stricmp(line, "quit") == 0) {
g_Running = false;
break;
} else if (line[0]) {
Log("unknown command: %s", line);
}
}
}
DWORD WINAPI WorkerThread(LPVOID) {
AllocConsole();
FILE* file = nullptr;
freopen_s(&file, "CONOUT$", "w", stdout);
freopen_s(&file, "CONOUT$", "w", stderr);
freopen_s(&file, "CONIN$", "r", stdin);
SetConsoleTitleW(L"ACM LAN hook");
Log("ACM LAN hook loaded");
RefreshLocalIps();
Log("local IP count: %u", unsigned(g_LocalIps.size()));
for (uint32_t ip : g_LocalIps) {
Log("local %s", IpToString(ip).c_str());
}
HMODULE wsock32 = GetModuleHandleW(L"WSOCK32.dll");
if (!wsock32) {
wsock32 = LoadLibraryW(L"WSOCK32.dll");
}
if (!wsock32) {
Log("failed to load WSOCK32.dll");
CommandLoop();
} else if (MH_Initialize() == MH_OK) {
HookExport(wsock32, "sendto", HookSendTo,
reinterpret_cast<void**>(&RealSendTo));
HookExport(wsock32, "recvfrom", HookRecvFrom,
reinterpret_cast<void**>(&RealRecvFrom));
HookExport(wsock32, "bind", HookBind,
reinterpret_cast<void**>(&RealBind));
HookExport(wsock32, "getsockname", HookGetSockName,
reinterpret_cast<void**>(&RealGetSockName));
HookExport(wsock32, "gethostname", HookGetHostName,
reinterpret_cast<void**>(&RealGetHostName));
HookExport(wsock32, "gethostbyname", HookGetHostByName,
reinterpret_cast<void**>(&RealGetHostByName));
CommandLoop();
MH_DisableHook(MH_ALL_HOOKS);
MH_Uninitialize();
} else {
Log("MH_Initialize failed");
CommandLoop();
}
Log("unloading");
FreeConsole();
FreeLibraryAndExitThread(g_Module, 0);
return 0;
}
} // namespace
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
g_Module = hModule;
DisableThreadLibraryCalls(hModule);
InitializeCriticalSection(&g_LogLock);
g_WorkerThread =
CreateThread(nullptr, 0, WorkerThread, nullptr, 0, nullptr);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
if (lpReserved == nullptr) {
g_Running = false;
}
DeleteCriticalSection(&g_LogLock);
break;
}
return TRUE;
}关键点在这,把朋友广播过来的错误包改成正确的IP包
if (g_FixPayload && g_ForcedIp && buf && len > 0) {
std::vector<char> copy(buf, buf + len);
const int changed = ReplaceIpsInPayload(copy.data(), len, g_ForcedIp);
if (changed > 0) {
Log("sendto fixed %d payload IP(s) -> %s", changed,
IpToString(g_ForcedIp).c_str());
return RealSendTo(s, copy.data(), len, flags, to, tolen);
}
}朋友的服务端的代码更粗暴,直接白加黑劫持游戏,把他的gethostbyname给hook了,从而发真的包给我
//
// created by AheadLib
// github:https://github.com/strivexjun/AheadLib-x86-x64
//
#include <windows.h>
#include <Shlwapi.h>
#pragma comment( lib, "Shlwapi.lib")
#pragma comment(linker, "/EXPORT:accept=_AheadLib_accept,@1")
#pragma comment(linker, "/EXPORT:bind=_AheadLib_bind,@2")
#pragma comment(linker, "/EXPORT:closesocket=_AheadLib_closesocket,@3")
#pragma comment(linker, "/EXPORT:connect=_AheadLib_connect,@4")
#pragma comment(linker, "/EXPORT:getpeername=_AheadLib_getpeername,@5")
#pragma comment(linker, "/EXPORT:getsockname=_AheadLib_getsockname,@6")
#pragma comment(linker, "/EXPORT:getsockopt=_AheadLib_getsockopt,@7")
#pragma comment(linker, "/EXPORT:htonl=_AheadLib_htonl,@8")
#pragma comment(linker, "/EXPORT:htons=_AheadLib_htons,@9")
#pragma comment(linker, "/EXPORT:inet_addr=_AheadLib_inet_addr,@10")
#pragma comment(linker, "/EXPORT:inet_ntoa=_AheadLib_inet_ntoa,@11")
#pragma comment(linker, "/EXPORT:ioctlsocket=_AheadLib_ioctlsocket,@12")
#pragma comment(linker, "/EXPORT:listen=_AheadLib_listen,@13")
#pragma comment(linker, "/EXPORT:ntohl=_AheadLib_ntohl,@14")
#pragma comment(linker, "/EXPORT:ntohs=_AheadLib_ntohs,@15")
#pragma comment(linker, "/EXPORT:recv=_AheadLib_recv,@16")
#pragma comment(linker, "/EXPORT:recvfrom=_AheadLib_recvfrom,@17")
#pragma comment(linker, "/EXPORT:select=_AheadLib_select,@18")
#pragma comment(linker, "/EXPORT:send=_AheadLib_send,@19")
#pragma comment(linker, "/EXPORT:sendto=_AheadLib_sendto,@20")
#pragma comment(linker, "/EXPORT:setsockopt=_AheadLib_setsockopt,@21")
#pragma comment(linker, "/EXPORT:shutdown=_AheadLib_shutdown,@22")
#pragma comment(linker, "/EXPORT:socket=_AheadLib_socket,@23")
#pragma comment(linker, "/EXPORT:MigrateWinsockConfiguration=_AheadLib_MigrateWinsockConfiguration,@24")
#pragma comment(linker, "/EXPORT:gethostbyaddr=_AheadLib_gethostbyaddr,@51")
#pragma comment(linker, "/EXPORT:gethostbyname=_AheadLib_gethostbyname,@52")
#pragma comment(linker, "/EXPORT:getprotobyname=_AheadLib_getprotobyname,@53")
#pragma comment(linker, "/EXPORT:getprotobynumber=_AheadLib_getprotobynumber,@54")
#pragma comment(linker, "/EXPORT:getservbyname=_AheadLib_getservbyname,@55")
#pragma comment(linker, "/EXPORT:getservbyport=_AheadLib_getservbyport,@56")
#pragma comment(linker, "/EXPORT:gethostname=_AheadLib_gethostname,@57")
#pragma comment(linker, "/EXPORT:WSAAsyncSelect=_AheadLib_WSAAsyncSelect,@101")
#pragma comment(linker, "/EXPORT:WSAAsyncGetHostByAddr=_AheadLib_WSAAsyncGetHostByAddr,@102")
#pragma comment(linker, "/EXPORT:WSAAsyncGetHostByName=_AheadLib_WSAAsyncGetHostByName,@103")
#pragma comment(linker, "/EXPORT:WSAAsyncGetProtoByNumber=_AheadLib_WSAAsyncGetProtoByNumber,@104")
#pragma comment(linker, "/EXPORT:WSAAsyncGetProtoByName=_AheadLib_WSAAsyncGetProtoByName,@105")
#pragma comment(linker, "/EXPORT:WSAAsyncGetServByPort=_AheadLib_WSAAsyncGetServByPort,@106")
#pragma comment(linker, "/EXPORT:WSAAsyncGetServByName=_AheadLib_WSAAsyncGetServByName,@107")
#pragma comment(linker, "/EXPORT:WSACancelAsyncRequest=_AheadLib_WSACancelAsyncRequest,@108")
#pragma comment(linker, "/EXPORT:WSASetBlockingHook=_AheadLib_WSASetBlockingHook,@109")
#pragma comment(linker, "/EXPORT:WSAUnhookBlockingHook=_AheadLib_WSAUnhookBlockingHook,@110")
#pragma comment(linker, "/EXPORT:WSAGetLastError=_AheadLib_WSAGetLastError,@111")
#pragma comment(linker, "/EXPORT:WSASetLastError=_AheadLib_WSASetLastError,@112")
#pragma comment(linker, "/EXPORT:WSACancelBlockingCall=_AheadLib_WSACancelBlockingCall,@113")
#pragma comment(linker, "/EXPORT:WSAIsBlocking=_AheadLib_WSAIsBlocking,@114")
#pragma comment(linker, "/EXPORT:WSAStartup=_AheadLib_WSAStartup,@115")
#pragma comment(linker, "/EXPORT:WSACleanup=_AheadLib_WSACleanup,@116")
#pragma comment(linker, "/EXPORT:__WSAFDIsSet=_AheadLib___WSAFDIsSet,@151")
#pragma comment(linker, "/EXPORT:WEP=_AheadLib_WEP,@500")
#pragma comment(linker, "/EXPORT:WSApSetPostRoutine=_AheadLib_WSApSetPostRoutine,@1000")
#pragma comment(linker, "/EXPORT:inet_network=_AheadLib_inet_network,@1100")
#pragma comment(linker, "/EXPORT:getnetbyname=_AheadLib_getnetbyname,@1101")
#pragma comment(linker, "/EXPORT:rcmd=_AheadLib_rcmd,@1102")
#pragma comment(linker, "/EXPORT:rexec=_AheadLib_rexec,@1103")
#pragma comment(linker, "/EXPORT:rresvport=_AheadLib_rresvport,@1104")
#pragma comment(linker, "/EXPORT:sethostname=_AheadLib_sethostname,@1105")
#pragma comment(linker, "/EXPORT:dn_expand=_AheadLib_dn_expand,@1106")
#pragma comment(linker, "/EXPORT:WSARecvEx=_AheadLib_WSARecvEx,@1107")
#pragma comment(linker, "/EXPORT:s_perror=_AheadLib_s_perror,@1108")
#pragma comment(linker, "/EXPORT:GetAddressByNameA=_AheadLib_GetAddressByNameA,@1109")
#pragma comment(linker, "/EXPORT:GetAddressByNameW=_AheadLib_GetAddressByNameW,@1110")
#pragma comment(linker, "/EXPORT:EnumProtocolsA=_AheadLib_EnumProtocolsA,@1111")
#pragma comment(linker, "/EXPORT:EnumProtocolsW=_AheadLib_EnumProtocolsW,@1112")
#pragma comment(linker, "/EXPORT:GetTypeByNameA=_AheadLib_GetTypeByNameA,@1113")
#pragma comment(linker, "/EXPORT:GetTypeByNameW=_AheadLib_GetTypeByNameW,@1114")
#pragma comment(linker, "/EXPORT:GetNameByTypeA=_AheadLib_GetNameByTypeA,@1115")
#pragma comment(linker, "/EXPORT:GetNameByTypeW=_AheadLib_GetNameByTypeW,@1116")
#pragma comment(linker, "/EXPORT:SetServiceA=_AheadLib_SetServiceA,@1117")
#pragma comment(linker, "/EXPORT:SetServiceW=_AheadLib_SetServiceW,@1118")
#pragma comment(linker, "/EXPORT:GetServiceA=_AheadLib_GetServiceA,@1119")
#pragma comment(linker, "/EXPORT:GetServiceW=_AheadLib_GetServiceW,@1120")
#pragma comment(linker, "/EXPORT:NPLoadNameSpaces=_AheadLib_NPLoadNameSpaces,@1130")
#pragma comment(linker, "/EXPORT:TransmitFile=_AheadLib_TransmitFile,@1140")
#pragma comment(linker, "/EXPORT:AcceptEx=_AheadLib_AcceptEx,@1141")
#pragma comment(linker, "/EXPORT:GetAcceptExSockaddrs=_AheadLib_GetAcceptExSockaddrs,@1142")
#include <string>
// --- ??核心 ---
std::string GetTargetIPFromConfig() {
char szPath[MAX_PATH];
GetModuleFileNameA(NULL, szPath, MAX_PATH);
// 配置路?:与 exe 同目?的 hostip.config
std::string configPath = std::string(szPath).substr(0, std::string(szPath).find_last_of("\\/")) + "\\hostip.config";
char szIP[64] = { 0 };
GetPrivateProfileStringA("Network", "TargetIP", "", szIP, sizeof(szIP), configPath.c_str());
return std::string(szIP);
}
extern PVOID pfnAheadLib_gethostbyname;
// 核心 Hook 函?,使用 __stdcall 保??平衡
extern "C" struct hostent* __stdcall My_gethostbyname_Hook(const char* name) {
// ?制?型??,使用全局?量 pfnAheadLib_gethostbyname
typedef struct hostent* (__stdcall *pfn_orig)(const char*);
pfn_orig pOrig = (pfn_orig)pfnAheadLib_gethostbyname;
struct hostent* pResult = pOrig(name);
std::string targetIP = GetTargetIPFromConfig();
if (!targetIP.empty()) {
unsigned long ip = inet_addr(targetIP.c_str());
if (ip != INADDR_NONE) {
if (pResult && pResult->h_addrtype == AF_INET) {
// 原始请求成功,直接修改其缓存的 IP
*(unsigned long*)pResult->h_addr_list[0] = ip;
} else {
// 原始请求失败(如域名已失效),构造一个假的 hostent 结构体返回
static struct hostent fake_hostent;
static char* fake_aliases[] = { NULL };
static unsigned long fake_ip;
static char* fake_addr_list[] = { (char*)&fake_ip, NULL };
static char fake_name[256];
fake_ip = ip;
if (name) {
strncpy(fake_name, name, sizeof(fake_name) - 1);
fake_name[sizeof(fake_name) - 1] = '\0';
} else {
fake_name[0] = '\0';
}
fake_hostent.h_name = fake_name;
fake_hostent.h_aliases = fake_aliases;
fake_hostent.h_addrtype = AF_INET;
fake_hostent.h_length = 4;
fake_hostent.h_addr_list = fake_addr_list;
pResult = &fake_hostent;
}
}
}
return pResult;
}
PVOID pfnAheadLib_accept;
PVOID pfnAheadLib_bind;
PVOID pfnAheadLib_closesocket;
PVOID pfnAheadLib_connect;
PVOID pfnAheadLib_getpeername;
PVOID pfnAheadLib_getsockname;
PVOID pfnAheadLib_getsockopt;
PVOID pfnAheadLib_htonl;
PVOID pfnAheadLib_htons;
PVOID pfnAheadLib_inet_addr;
PVOID pfnAheadLib_inet_ntoa;
PVOID pfnAheadLib_ioctlsocket;
PVOID pfnAheadLib_listen;
PVOID pfnAheadLib_ntohl;
PVOID pfnAheadLib_ntohs;
PVOID pfnAheadLib_recv;
PVOID pfnAheadLib_recvfrom;
PVOID pfnAheadLib_select;
PVOID pfnAheadLib_send;
PVOID pfnAheadLib_sendto;
PVOID pfnAheadLib_setsockopt;
PVOID pfnAheadLib_shutdown;
PVOID pfnAheadLib_socket;
PVOID pfnAheadLib_MigrateWinsockConfiguration;
PVOID pfnAheadLib_gethostbyaddr;
PVOID pfnAheadLib_gethostbyname;
PVOID pfnAheadLib_getprotobyname;
PVOID pfnAheadLib_getprotobynumber;
PVOID pfnAheadLib_getservbyname;
PVOID pfnAheadLib_getservbyport;
PVOID pfnAheadLib_gethostname;
PVOID pfnAheadLib_WSAAsyncSelect;
PVOID pfnAheadLib_WSAAsyncGetHostByAddr;
PVOID pfnAheadLib_WSAAsyncGetHostByName;
PVOID pfnAheadLib_WSAAsyncGetProtoByNumber;
PVOID pfnAheadLib_WSAAsyncGetProtoByName;
PVOID pfnAheadLib_WSAAsyncGetServByPort;
PVOID pfnAheadLib_WSAAsyncGetServByName;
PVOID pfnAheadLib_WSACancelAsyncRequest;
PVOID pfnAheadLib_WSASetBlockingHook;
PVOID pfnAheadLib_WSAUnhookBlockingHook;
PVOID pfnAheadLib_WSAGetLastError;
PVOID pfnAheadLib_WSASetLastError;
PVOID pfnAheadLib_WSACancelBlockingCall;
PVOID pfnAheadLib_WSAIsBlocking;
PVOID pfnAheadLib_WSAStartup;
PVOID pfnAheadLib_WSACleanup;
PVOID pfnAheadLib___WSAFDIsSet;
PVOID pfnAheadLib_WEP;
PVOID pfnAheadLib_WSApSetPostRoutine;
PVOID pfnAheadLib_inet_network;
PVOID pfnAheadLib_getnetbyname;
PVOID pfnAheadLib_rcmd;
PVOID pfnAheadLib_rexec;
PVOID pfnAheadLib_rresvport;
PVOID pfnAheadLib_sethostname;
PVOID pfnAheadLib_dn_expand;
PVOID pfnAheadLib_WSARecvEx;
PVOID pfnAheadLib_s_perror;
PVOID pfnAheadLib_GetAddressByNameA;
PVOID pfnAheadLib_GetAddressByNameW;
PVOID pfnAheadLib_EnumProtocolsA;
PVOID pfnAheadLib_EnumProtocolsW;
PVOID pfnAheadLib_GetTypeByNameA;
PVOID pfnAheadLib_GetTypeByNameW;
PVOID pfnAheadLib_GetNameByTypeA;
PVOID pfnAheadLib_GetNameByTypeW;
PVOID pfnAheadLib_SetServiceA;
PVOID pfnAheadLib_SetServiceW;
PVOID pfnAheadLib_GetServiceA;
PVOID pfnAheadLib_GetServiceW;
PVOID pfnAheadLib_NPLoadNameSpaces;
PVOID pfnAheadLib_TransmitFile;
PVOID pfnAheadLib_AcceptEx;
PVOID pfnAheadLib_GetAcceptExSockaddrs;
static
HMODULE g_OldModule = NULL;
VOID WINAPI Free()
{
if (g_OldModule)
{
FreeLibrary(g_OldModule);
}
}
BOOL WINAPI Load()
{
TCHAR tzPath[MAX_PATH];
TCHAR tzTemp[MAX_PATH * 2];
//
// ?里是否?系?目?或?前目?加?原始DLL
//
//GetModuleFileName(NULL,tzPath,MAX_PATH); //?取本目?下的
//PathRemoveFileSpec(tzPath);
GetSystemDirectory(tzPath, MAX_PATH); //默??取系?目?的
lstrcat(tzPath, TEXT("\\wsock32.dll"));
g_OldModule = LoadLibrary(tzPath);
if (g_OldModule == NULL)
{
wsprintf(tzTemp, TEXT("?法找到模? %s,程序?法正常?行"), tzPath);
MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
}
return (g_OldModule != NULL);
}
FARPROC WINAPI GetAddress(PCSTR pszProcName)
{
FARPROC fpAddress;
CHAR szProcName[64];
TCHAR tzTemp[MAX_PATH];
fpAddress = GetProcAddress(g_OldModule, pszProcName);
if (fpAddress == NULL)
{
if (HIWORD(pszProcName) == 0)
{
wsprintfA(szProcName, "#%d", pszProcName);
pszProcName = szProcName;
}
wsprintf(tzTemp, TEXT("?法找到函? %hs,程序?法正常?行"), pszProcName);
MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
ExitProcess(-2);
}
return fpAddress;
}
BOOL WINAPI Init()
{
pfnAheadLib_accept = GetAddress("accept");
pfnAheadLib_bind = GetAddress("bind");
pfnAheadLib_closesocket = GetAddress("closesocket");
pfnAheadLib_connect = GetAddress("connect");
pfnAheadLib_getpeername = GetAddress("getpeername");
pfnAheadLib_getsockname = GetAddress("getsockname");
pfnAheadLib_getsockopt = GetAddress("getsockopt");
pfnAheadLib_htonl = GetAddress("htonl");
pfnAheadLib_htons = GetAddress("htons");
pfnAheadLib_inet_addr = GetAddress("inet_addr");
pfnAheadLib_inet_ntoa = GetAddress("inet_ntoa");
pfnAheadLib_ioctlsocket = GetAddress("ioctlsocket");
pfnAheadLib_listen = GetAddress("listen");
pfnAheadLib_ntohl = GetAddress("ntohl");
pfnAheadLib_ntohs = GetAddress("ntohs");
pfnAheadLib_recv = GetAddress("recv");
pfnAheadLib_recvfrom = GetAddress("recvfrom");
pfnAheadLib_select = GetAddress("select");
pfnAheadLib_send = GetAddress("send");
pfnAheadLib_sendto = GetAddress("sendto");
pfnAheadLib_setsockopt = GetAddress("setsockopt");
pfnAheadLib_shutdown = GetAddress("shutdown");
pfnAheadLib_socket = GetAddress("socket");
pfnAheadLib_MigrateWinsockConfiguration = GetAddress("MigrateWinsockConfiguration");
pfnAheadLib_gethostbyaddr = GetAddress("gethostbyaddr");
pfnAheadLib_gethostbyname = GetAddress("gethostbyname");
pfnAheadLib_getprotobyname = GetAddress("getprotobyname");
pfnAheadLib_getprotobynumber = GetAddress("getprotobynumber");
pfnAheadLib_getservbyname = GetAddress("getservbyname");
pfnAheadLib_getservbyport = GetAddress("getservbyport");
pfnAheadLib_gethostname = GetAddress("gethostname");
pfnAheadLib_WSAAsyncSelect = GetAddress("WSAAsyncSelect");
pfnAheadLib_WSAAsyncGetHostByAddr = GetAddress("WSAAsyncGetHostByAddr");
pfnAheadLib_WSAAsyncGetHostByName = GetAddress("WSAAsyncGetHostByName");
pfnAheadLib_WSAAsyncGetProtoByNumber = GetAddress("WSAAsyncGetProtoByNumber");
pfnAheadLib_WSAAsyncGetProtoByName = GetAddress("WSAAsyncGetProtoByName");
pfnAheadLib_WSAAsyncGetServByPort = GetAddress("WSAAsyncGetServByPort");
pfnAheadLib_WSAAsyncGetServByName = GetAddress("WSAAsyncGetServByName");
pfnAheadLib_WSACancelAsyncRequest = GetAddress("WSACancelAsyncRequest");
pfnAheadLib_WSASetBlockingHook = GetAddress("WSASetBlockingHook");
pfnAheadLib_WSAUnhookBlockingHook = GetAddress("WSAUnhookBlockingHook");
pfnAheadLib_WSAGetLastError = GetAddress("WSAGetLastError");
pfnAheadLib_WSASetLastError = GetAddress("WSASetLastError");
pfnAheadLib_WSACancelBlockingCall = GetAddress("WSACancelBlockingCall");
pfnAheadLib_WSAIsBlocking = GetAddress("WSAIsBlocking");
pfnAheadLib_WSAStartup = GetAddress("WSAStartup");
pfnAheadLib_WSACleanup = GetAddress("WSACleanup");
pfnAheadLib___WSAFDIsSet = GetAddress("__WSAFDIsSet");
pfnAheadLib_WEP = GetAddress("WEP");
pfnAheadLib_WSApSetPostRoutine = GetAddress("WSApSetPostRoutine");
pfnAheadLib_inet_network = GetAddress("inet_network");
pfnAheadLib_getnetbyname = GetAddress("getnetbyname");
pfnAheadLib_rcmd = GetAddress("rcmd");
pfnAheadLib_rexec = GetAddress("rexec");
pfnAheadLib_rresvport = GetAddress("rresvport");
pfnAheadLib_sethostname = GetAddress("sethostname");
pfnAheadLib_dn_expand = GetAddress("dn_expand");
pfnAheadLib_WSARecvEx = GetAddress("WSARecvEx");
pfnAheadLib_s_perror = GetAddress("s_perror");
pfnAheadLib_GetAddressByNameA = GetAddress("GetAddressByNameA");
pfnAheadLib_GetAddressByNameW = GetAddress("GetAddressByNameW");
pfnAheadLib_EnumProtocolsA = GetAddress("EnumProtocolsA");
pfnAheadLib_EnumProtocolsW = GetAddress("EnumProtocolsW");
pfnAheadLib_GetTypeByNameA = GetAddress("GetTypeByNameA");
pfnAheadLib_GetTypeByNameW = GetAddress("GetTypeByNameW");
pfnAheadLib_GetNameByTypeA = GetAddress("GetNameByTypeA");
pfnAheadLib_GetNameByTypeW = GetAddress("GetNameByTypeW");
pfnAheadLib_SetServiceA = GetAddress("SetServiceA");
pfnAheadLib_SetServiceW = GetAddress("SetServiceW");
pfnAheadLib_GetServiceA = GetAddress("GetServiceA");
pfnAheadLib_GetServiceW = GetAddress("GetServiceW");
pfnAheadLib_NPLoadNameSpaces = GetAddress("NPLoadNameSpaces");
pfnAheadLib_TransmitFile = GetAddress("TransmitFile");
pfnAheadLib_AcceptEx = GetAddress("AcceptEx");
pfnAheadLib_GetAcceptExSockaddrs = GetAddress("GetAcceptExSockaddrs");
return TRUE;
}
DWORD WINAPI ThreadProc(LPVOID lpThreadParameter)
{
HANDLE hProcess;
PVOID addr1 = reinterpret_cast<PVOID>(0x00401000);
BYTE data1[] = { 0x90, 0x90, 0x90, 0x90 };
//
// ??VMP3.x 的?存保?
//
hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, GetCurrentProcessId());
if (hProcess)
{
WriteProcessMemory(hProcess, addr1, data1, sizeof(data1), NULL);
CloseHandle(hProcess);
}
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
if (Load() && Init())
{
TCHAR szAppName[MAX_PATH] = TEXT("MyApp.exe");//?修改宿主?程名
TCHAR szCurName[MAX_PATH];
GetModuleFileName(NULL, szCurName, MAX_PATH);
PathStripPath(szCurName);
//是否判?宿主?程名
if (StrCmpI(szCurName, szAppName) == 0)
{
//???丁?程或者其他操作
HANDLE hThread = CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
if (hThread)
{
CloseHandle(hThread);
}
}
}
}
else if (dwReason == DLL_PROCESS_DETACH)
{
Free();
}
return TRUE;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_accept(void)
{
__asm jmp pfnAheadLib_accept;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_bind(void)
{
__asm jmp pfnAheadLib_bind;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_closesocket(void)
{
__asm jmp pfnAheadLib_closesocket;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_connect(void)
{
__asm jmp pfnAheadLib_connect;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_getpeername(void)
{
__asm jmp pfnAheadLib_getpeername;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_getsockname(void)
{
__asm jmp pfnAheadLib_getsockname;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_getsockopt(void)
{
__asm jmp pfnAheadLib_getsockopt;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_htonl(void)
{
__asm jmp pfnAheadLib_htonl;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_htons(void)
{
__asm jmp pfnAheadLib_htons;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_inet_addr(void)
{
__asm jmp pfnAheadLib_inet_addr;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_inet_ntoa(void)
{
__asm jmp pfnAheadLib_inet_ntoa;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_ioctlsocket(void)
{
__asm jmp pfnAheadLib_ioctlsocket;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_listen(void)
{
__asm jmp pfnAheadLib_listen;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_ntohl(void)
{
__asm jmp pfnAheadLib_ntohl;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_ntohs(void)
{
__asm jmp pfnAheadLib_ntohs;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_recv(void)
{
__asm jmp pfnAheadLib_recv;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_recvfrom(void)
{
__asm jmp pfnAheadLib_recvfrom;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_select(void)
{
__asm jmp pfnAheadLib_select;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_send(void)
{
__asm jmp pfnAheadLib_send;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_sendto(void)
{
__asm jmp pfnAheadLib_sendto;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_setsockopt(void)
{
__asm jmp pfnAheadLib_setsockopt;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_shutdown(void)
{
__asm jmp pfnAheadLib_shutdown;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_socket(void)
{
__asm jmp pfnAheadLib_socket;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_MigrateWinsockConfiguration(void)
{
__asm jmp pfnAheadLib_MigrateWinsockConfiguration;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_gethostbyaddr(void)
{
__asm jmp pfnAheadLib_gethostbyaddr;
}
/*
EXTERN_C __declspec(naked) void __cdecl AheadLib_gethostbyname(void)
{
__asm jmp pfnAheadLib_gethostbyname;
}
*/
EXTERN_C __declspec(naked) void __cdecl AheadLib_getprotobyname(void)
{
__asm jmp pfnAheadLib_getprotobyname;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_getprotobynumber(void)
{
__asm jmp pfnAheadLib_getprotobynumber;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_getservbyname(void)
{
__asm jmp pfnAheadLib_getservbyname;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_getservbyport(void)
{
__asm jmp pfnAheadLib_getservbyport;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_gethostname(void)
{
__asm jmp pfnAheadLib_gethostname;
}
// 修改原本的 naked ??
EXTERN_C __declspec(naked) void __cdecl AheadLib_gethostbyname(void)
{
__asm {
push [esp+4] // ?入??
call My_gethostbyname_Hook
ret 4 // 恢复?平衡
}
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAAsyncSelect(void)
{
__asm jmp pfnAheadLib_WSAAsyncSelect;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAAsyncGetHostByAddr(void)
{
__asm jmp pfnAheadLib_WSAAsyncGetHostByAddr;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAAsyncGetHostByName(void)
{
__asm jmp pfnAheadLib_WSAAsyncGetHostByName;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAAsyncGetProtoByNumber(void)
{
__asm jmp pfnAheadLib_WSAAsyncGetProtoByNumber;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAAsyncGetProtoByName(void)
{
__asm jmp pfnAheadLib_WSAAsyncGetProtoByName;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAAsyncGetServByPort(void)
{
__asm jmp pfnAheadLib_WSAAsyncGetServByPort;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAAsyncGetServByName(void)
{
__asm jmp pfnAheadLib_WSAAsyncGetServByName;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSACancelAsyncRequest(void)
{
__asm jmp pfnAheadLib_WSACancelAsyncRequest;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSASetBlockingHook(void)
{
__asm jmp pfnAheadLib_WSASetBlockingHook;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAUnhookBlockingHook(void)
{
__asm jmp pfnAheadLib_WSAUnhookBlockingHook;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAGetLastError(void)
{
__asm jmp pfnAheadLib_WSAGetLastError;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSASetLastError(void)
{
__asm jmp pfnAheadLib_WSASetLastError;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSACancelBlockingCall(void)
{
__asm jmp pfnAheadLib_WSACancelBlockingCall;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAIsBlocking(void)
{
__asm jmp pfnAheadLib_WSAIsBlocking;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSAStartup(void)
{
__asm jmp pfnAheadLib_WSAStartup;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSACleanup(void)
{
__asm jmp pfnAheadLib_WSACleanup;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib___WSAFDIsSet(void)
{
__asm jmp pfnAheadLib___WSAFDIsSet;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WEP(void)
{
__asm jmp pfnAheadLib_WEP;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSApSetPostRoutine(void)
{
__asm jmp pfnAheadLib_WSApSetPostRoutine;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_inet_network(void)
{
__asm jmp pfnAheadLib_inet_network;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_getnetbyname(void)
{
__asm jmp pfnAheadLib_getnetbyname;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_rcmd(void)
{
__asm jmp pfnAheadLib_rcmd;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_rexec(void)
{
__asm jmp pfnAheadLib_rexec;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_rresvport(void)
{
__asm jmp pfnAheadLib_rresvport;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_sethostname(void)
{
__asm jmp pfnAheadLib_sethostname;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_dn_expand(void)
{
__asm jmp pfnAheadLib_dn_expand;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_WSARecvEx(void)
{
__asm jmp pfnAheadLib_WSARecvEx;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_s_perror(void)
{
__asm jmp pfnAheadLib_s_perror;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetAddressByNameA(void)
{
__asm jmp pfnAheadLib_GetAddressByNameA;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetAddressByNameW(void)
{
__asm jmp pfnAheadLib_GetAddressByNameW;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_EnumProtocolsA(void)
{
__asm jmp pfnAheadLib_EnumProtocolsA;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_EnumProtocolsW(void)
{
__asm jmp pfnAheadLib_EnumProtocolsW;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetTypeByNameA(void)
{
__asm jmp pfnAheadLib_GetTypeByNameA;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetTypeByNameW(void)
{
__asm jmp pfnAheadLib_GetTypeByNameW;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetNameByTypeA(void)
{
__asm jmp pfnAheadLib_GetNameByTypeA;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetNameByTypeW(void)
{
__asm jmp pfnAheadLib_GetNameByTypeW;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_SetServiceA(void)
{
__asm jmp pfnAheadLib_SetServiceA;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_SetServiceW(void)
{
__asm jmp pfnAheadLib_SetServiceW;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetServiceA(void)
{
__asm jmp pfnAheadLib_GetServiceA;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetServiceW(void)
{
__asm jmp pfnAheadLib_GetServiceW;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_NPLoadNameSpaces(void)
{
__asm jmp pfnAheadLib_NPLoadNameSpaces;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_TransmitFile(void)
{
__asm jmp pfnAheadLib_TransmitFile;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_AcceptEx(void)
{
__asm jmp pfnAheadLib_AcceptEx;
}
EXTERN_C __declspec(naked) void __cdecl AheadLib_GetAcceptExSockaddrs(void)
{
__asm jmp pfnAheadLib_GetAcceptExSockaddrs;
}关键点:
// 核心 Hook 函?,使用 __stdcall 保??平衡
extern "C" struct hostent* __stdcall My_gethostbyname_Hook(const char* name) {
// ?制?型??,使用全局?量 pfnAheadLib_gethostbyname
typedef struct hostent* (__stdcall *pfn_orig)(const char*);
pfn_orig pOrig = (pfn_orig)pfnAheadLib_gethostbyname;
struct hostent* pResult = pOrig(name);
std::string targetIP = GetTargetIPFromConfig();
if (!targetIP.empty()) {
unsigned long ip = inet_addr(targetIP.c_str());
if (ip != INADDR_NONE) {
if (pResult && pResult->h_addrtype == AF_INET) {
// 原始请求成功,直接修改其缓存的 IP
*(unsigned long*)pResult->h_addr_list[0] = ip;
} else {
// 原始请求失败(如域名已失效),构造一个假的 hostent 结构体返回
static struct hostent fake_hostent;
static char* fake_aliases[] = { NULL };
static unsigned long fake_ip;
static char* fake_addr_list[] = { (char*)&fake_ip, NULL };
static char fake_name[256];
fake_ip = ip;
if (name) {
strncpy(fake_name, name, sizeof(fake_name) - 1);
fake_name[sizeof(fake_name) - 1] = '\0';
} else {
fake_name[0] = '\0';
}
fake_hostent.h_name = fake_name;
fake_hostent.h_aliases = fake_aliases;
fake_hostent.h_addrtype = AF_INET;
fake_hostent.h_length = 4;
fake_hostent.h_addr_list = fake_addr_list;
pResult = &fake_hostent;
}
}
}
return pResult;
}结论
通过这样修改后,我们终于可以愉快联机了
要是以后有人玩《Aliens: Colonial Marines》出现一样的问题,可以看看这个咋修。