Files
djhackersdev_bemanitools/src/main/iidxhook-util/eamuse.c
T
2019-09-27 22:36:50 +02:00

190 lines
5.6 KiB
C

#define LOG_MODULE "eamuse-hook"
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "hook/table.h"
#include "iidxhook-util/eamuse.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
/* ------------------------------------------------------------------------- */
static unsigned long STDCALL my_inet_addr(const char *cp);
static int STDCALL my_connect(SOCKET s, const struct sockaddr* addr,
int addrlen);
static struct hostent FAR* STDCALL my_gethostbyname(const char *nameB);
static unsigned long (STDCALL *real_inet_addr)(const char *cp);
static int (STDCALL *real_connect)(SOCKET s, const struct sockaddr* addr,
int addrlen);
static struct hostent FAR* (STDCALL *real_gethostbyname)(const char *nameB);
/* ------------------------------------------------------------------------- */
static const struct hook_symbol eamuse_hook_syms[] = {
/* WS2_32.DLL's SDK import lib generates ordinal imports, so these ordinals
are a frozen aspect of the Win32 ABI. */
{
.name = "inet_addr",
.ordinal = 11,
.patch = my_inet_addr,
.link = (void **) &real_inet_addr
},
{
.name = "connect",
.ordinal = 4,
.patch = my_connect,
.link = (void **) &real_connect
},
{
.name = "gethostbyname",
.ordinal = 52,
.patch = my_gethostbyname,
.link = (void **) &real_gethostbyname
},
};
/* ------------------------------------------------------------------------- */
static struct net_addr eamuse_server_addr;
static struct net_addr eamuse_server_addr_resolved;
/* ------------------------------------------------------------------------- */
static unsigned long STDCALL my_inet_addr(const char *cp)
{
char* tmp;
/* for a stock machine connected to the eamuse router,
the game wants to connect to the standard domain
services.konami.eamuse.fun
depending on the router you got, it will be services.hostname.my.router
so we catch that and turn it into any ip we want */
/* bugfix win10: don't just catch services.konami... because
win10 is doing some weird stuff and this call also contains
various IP addresses. Always return the server address */
tmp = net_addr_to_str(&eamuse_server_addr_resolved);
log_misc("my_inet_addr: '%s' -> %s", cp, tmp);
free(tmp);
return eamuse_server_addr_resolved.ipv4.addr;
}
static int STDCALL my_connect(SOCKET s, const struct sockaddr* addr, int addrlen)
{
char* tmp;
if (addr->sa_family == AF_INET) {
/* check if we got our server's address */
struct sockaddr_in* addr_in = (struct sockaddr_in*) addr;
if (addr_in->sin_addr.S_un.S_addr ==
eamuse_server_addr_resolved.ipv4.addr) {
tmp = net_addr_to_str(&eamuse_server_addr_resolved);
log_misc("Patching port '%d' of %s to %d", ntohs(addr_in->sin_port),
tmp, eamuse_server_addr_resolved.ipv4.port);
free(tmp);
addr_in->sin_port = htons(eamuse_server_addr_resolved.ipv4.port);
}
}
return real_connect(s, addr, addrlen);
}
static struct hostent FAR* STDCALL my_gethostbyname(const char* name)
{
char* tmp;
/* for doc, checkout the other detour of inetaddr above
this call is used starting GOLD (not used on pre GOLD) */
/* bugfix win10: don't just catch services.konami... because
win10 is doing some weird stuff and this call also contains
various IP addresses. Always return the server address */
tmp = net_addr_to_str(&eamuse_server_addr_resolved);
log_misc("my_gethostbyname: '%s' to ip %s", name, tmp);
free(tmp);
/* very ugly hack to get this working.
don't bother with dynamic allocations and have stuff staticly alloc'd
just populate what's touched by the game */
static struct hostent ret;
static uint32_t addr;
static char* arr[2];
static bool first = true;
if (first) {
ret.h_length = 4;
ret.h_addr_list = (char**) &arr;
ret.h_addr_list[0] = (char*) &addr;
ret.h_addr_list[1] = NULL;
ret.h_aliases = NULL;
ret.h_name = NULL;
}
addr = eamuse_server_addr_resolved.ipv4.addr;
return &ret;
}
/* ------------------------------------------------------------------------- */
void eamuse_hook_init(void)
{
hook_table_apply(
NULL,
"ws2_32.dll",
eamuse_hook_syms,
lengthof(eamuse_hook_syms));
log_info("Inserted eamuse hooks");
}
void eamuse_set_addr(const struct net_addr* addr)
{
char* tmp_str;
char* tmp_str2;
log_assert(addr);
memcpy(&eamuse_server_addr, addr, sizeof(struct net_addr));
tmp_str = net_addr_to_str(&eamuse_server_addr);
eamuse_server_addr_resolved.type = NET_ADDR_TYPE_IPV4;
if (!net_resolve_hostname_net_addr(&eamuse_server_addr,
&eamuse_server_addr_resolved.ipv4)) {
log_fatal("Failed to resolve eamuse server address: %s", tmp_str);
free(tmp_str);
return;
}
tmp_str2 = net_addr_to_str(&eamuse_server_addr_resolved);
log_info("Target eamuse server %s resolved to %s", tmp_str, tmp_str2);
free(tmp_str);
free(tmp_str2);
}
void eamuse_check_connection()
{
if (!net_check_remote_connection(&eamuse_server_addr_resolved, 5000)) {
log_info("Target eamuse server reachable.");
} else {
log_warning("Target eamuse server is not reachable. Game might throw "
"network errors/warnings if eamuse is enabled.");
}
}