Modify host header in HTTP requests to bypass domain censorship in China. (#34)

Co-authored-by: Sanheiii <35133371+Sanheiii@users.noreply.github.com>
Reviewed-on: Dniel97/segatools#34
Co-authored-by: Sanhei <sanhei@noreply.gitea.tendokyu.moe>
Co-committed-by: Sanhei <sanhei@noreply.gitea.tendokyu.moe>
This commit is contained in:
2024-11-11 16:24:33 +00:00
committed by Dniel97
parent 83840e0a87
commit ceb2b63e8b
10 changed files with 138 additions and 3 deletions

View File

@ -14,6 +14,7 @@
#include "hook/table.h"
#include "util/dprintf.h"
#include "util/get_function_ordinal.h"
#include "hooklib/dns.h"
@ -81,6 +82,12 @@ static bool WINAPI hook_WinHttpCrackUrl(
DWORD dwFlags,
LPURL_COMPONENTS lpUrlComponents);
static DWORD WINAPI hook_send(
SOCKET s,
const char* buf,
int len,
int flags);
/* Link pointers */
static DNS_STATUS (WINAPI *next_DnsQuery_A)(
@ -122,6 +129,12 @@ static bool (WINAPI *next_WinHttpCrackUrl)(
DWORD dwFlags,
LPURL_COMPONENTS lpUrlComponents);
static DWORD (WINAPI *next_send)(
SOCKET s,
const char* buf,
int len,
int flags);
static const struct hook_symbol dns_hook_syms_dnsapi[] = {
{
.name = "DnsQuery_A",
@ -144,7 +157,7 @@ static const struct hook_symbol dns_hook_syms_ws2[] = {
.ordinal = 176,
.patch = hook_getaddrinfo,
.link = (void **) &next_getaddrinfo,
}
},
};
static const struct hook_symbol dns_hook_syms_winhttp[] = {
@ -157,7 +170,14 @@ static const struct hook_symbol dns_hook_syms_winhttp[] = {
.patch = hook_WinHttpCrackUrl,
.link = (void **) &next_WinHttpCrackUrl,
}
};
static struct hook_symbol http_hook_syms_ws2[] = {
{
.name = "send",
.patch = hook_send,
.link = (void **) &next_send
},
};
static bool dns_hook_initted;
@ -186,7 +206,7 @@ static void dns_hook_init(void)
"ws2_32.dll",
dns_hook_syms_ws2,
_countof(dns_hook_syms_ws2));
hook_table_apply(
NULL,
"winhttp.dll",
@ -194,6 +214,18 @@ static void dns_hook_init(void)
_countof(dns_hook_syms_winhttp));
}
void http_hook_init(){
for (size_t i = 0; i < _countof(http_hook_syms_ws2); ++i) {
http_hook_syms_ws2[i].ordinal = get_function_ordinal("ws2_32.dll", http_hook_syms_ws2[i].name);
}
hook_table_apply(
NULL,
"ws2_32.dll",
http_hook_syms_ws2,
_countof(http_hook_syms_ws2));
}
// This function match domain and subdomains like *.naominet.jp.
bool match_domain(const wchar_t* target, const wchar_t* pattern) {
if (_wcsicmp(pattern, target) == 0) {
@ -618,3 +650,49 @@ static bool WINAPI hook_WinHttpCrackUrl(
lpUrlComponents
);
}
DWORD WINAPI hook_send(SOCKET s, const char* buf, int len, int flags) {
if (strstr(buf, "HTTP/") != NULL) {
char *new_buf = malloc(len + 1);
if (new_buf == NULL) return SOCKET_ERROR;
memcpy(new_buf, buf, len);
new_buf[len] = '\0';
char *host_start = strstr(new_buf, "Host: ");
if (host_start != NULL) {
char *host_end = strstr(host_start, "\r\n");
if (host_end != NULL) {
host_end += 2;
int host_len = host_end - host_start;
char *host_value_start = host_start + 6;
char *host_value_end = strstr(host_value_start, "\r\n");
if (host_value_end != NULL) {
int value_len = host_value_end - host_value_start;
char host_value[value_len + 1];
strncpy(host_value, host_value_start, value_len);
host_value[value_len] = '\0';
for (struct dns_hook_entry *entry = dns_hook_entries; entry && entry->from; entry++) {
char from_value[256];
wcstombs(from_value, entry->from, sizeof(from_value));
if (strcmp(host_value, from_value) == 0) {
char to_value[256];
wcstombs(to_value, entry->to, sizeof(to_value));
snprintf(host_start, len - (host_start - new_buf), "Host: %s\r\n", to_value);
break;
}
}
}
len = (int)strlen(new_buf);
}
}
DWORD result = next_send(s, new_buf, len, flags);
free(new_buf);
return result;
}
return next_send(s, buf, len, flags);
}