Last active
October 28, 2025 00:03
-
-
Save dev-zzo/2e9f89742311f37916317adb86fcfda9 to your computer and use it in GitHub Desktop.
A libcurl.dll proxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers | |
| // Windows Header Files | |
| #include <windows.h> | |
| #include <stdio.h> | |
| #include <malloc.h> | |
| #include <string.h> | |
| HMODULE hRealCurl; | |
| HANDLE ghMutex; | |
| char gszLogPath[1024]; | |
| #define DEFINE_THUNK(name) \ | |
| PVOID (*name##_p)(); \ | |
| PVOID __declspec(dllexport) name() { return name##_p(); } | |
| #define LOAD_THUNK(name) name##_p = GetProcAddress(hRealCurl, #name); | |
| DEFINE_THUNK(curl_easy_cleanup); | |
| DEFINE_THUNK(curl_easy_duphandle); | |
| DEFINE_THUNK(curl_easy_escape); | |
| DEFINE_THUNK(curl_easy_getinfo); | |
| DEFINE_THUNK(curl_easy_header); | |
| DEFINE_THUNK(curl_easy_init); | |
| DEFINE_THUNK(curl_easy_nextheader); | |
| DEFINE_THUNK(curl_easy_option_by_id); | |
| DEFINE_THUNK(curl_easy_option_by_name); | |
| DEFINE_THUNK(curl_easy_option_next); | |
| DEFINE_THUNK(curl_easy_pause); | |
| //DEFINE_THUNK(curl_easy_perform); | |
| DEFINE_THUNK(curl_easy_recv); | |
| DEFINE_THUNK(curl_easy_reset); | |
| DEFINE_THUNK(curl_easy_send); | |
| DEFINE_THUNK(curl_easy_setopt); | |
| DEFINE_THUNK(curl_easy_ssls_export); | |
| DEFINE_THUNK(curl_easy_ssls_import); | |
| DEFINE_THUNK(curl_easy_strerror); | |
| DEFINE_THUNK(curl_easy_unescape); | |
| DEFINE_THUNK(curl_easy_upkeep); | |
| DEFINE_THUNK(curl_escape); | |
| DEFINE_THUNK(curl_formadd); | |
| DEFINE_THUNK(curl_formfree); | |
| DEFINE_THUNK(curl_formget); | |
| DEFINE_THUNK(curl_free); | |
| DEFINE_THUNK(curl_getdate); | |
| DEFINE_THUNK(curl_getenv); | |
| DEFINE_THUNK(curl_global_cleanup); | |
| DEFINE_THUNK(curl_global_init); | |
| DEFINE_THUNK(curl_global_init_mem); | |
| DEFINE_THUNK(curl_global_sslset); | |
| DEFINE_THUNK(curl_global_trace); | |
| DEFINE_THUNK(curl_maprintf); | |
| DEFINE_THUNK(curl_mfprintf); | |
| DEFINE_THUNK(curl_mime_addpart); | |
| DEFINE_THUNK(curl_mime_data); | |
| DEFINE_THUNK(curl_mime_data_cb); | |
| DEFINE_THUNK(curl_mime_encoder); | |
| DEFINE_THUNK(curl_mime_filedata); | |
| DEFINE_THUNK(curl_mime_filename); | |
| DEFINE_THUNK(curl_mime_free); | |
| DEFINE_THUNK(curl_mime_headers); | |
| DEFINE_THUNK(curl_mime_init); | |
| DEFINE_THUNK(curl_mime_name); | |
| DEFINE_THUNK(curl_mime_subparts); | |
| DEFINE_THUNK(curl_mime_type); | |
| DEFINE_THUNK(curl_mprintf); | |
| DEFINE_THUNK(curl_msnprintf); | |
| DEFINE_THUNK(curl_msprintf); | |
| DEFINE_THUNK(curl_multi_add_handle); | |
| DEFINE_THUNK(curl_multi_assign); | |
| DEFINE_THUNK(curl_multi_cleanup); | |
| DEFINE_THUNK(curl_multi_fdset); | |
| DEFINE_THUNK(curl_multi_get_handles); | |
| DEFINE_THUNK(curl_multi_info_read); | |
| DEFINE_THUNK(curl_multi_init); | |
| DEFINE_THUNK(curl_multi_perform); | |
| DEFINE_THUNK(curl_multi_poll); | |
| DEFINE_THUNK(curl_multi_remove_handle); | |
| DEFINE_THUNK(curl_multi_setopt); | |
| DEFINE_THUNK(curl_multi_socket); | |
| DEFINE_THUNK(curl_multi_socket_action); | |
| DEFINE_THUNK(curl_multi_socket_all); | |
| DEFINE_THUNK(curl_multi_strerror); | |
| DEFINE_THUNK(curl_multi_timeout); | |
| DEFINE_THUNK(curl_multi_wait); | |
| DEFINE_THUNK(curl_multi_waitfds); | |
| DEFINE_THUNK(curl_multi_wakeup); | |
| DEFINE_THUNK(curl_mvaprintf); | |
| DEFINE_THUNK(curl_mvfprintf); | |
| DEFINE_THUNK(curl_mvprintf); | |
| DEFINE_THUNK(curl_mvsnprintf); | |
| DEFINE_THUNK(curl_mvsprintf); | |
| DEFINE_THUNK(curl_pushheader_byname); | |
| DEFINE_THUNK(curl_pushheader_bynum); | |
| DEFINE_THUNK(curl_share_cleanup); | |
| DEFINE_THUNK(curl_share_init); | |
| DEFINE_THUNK(curl_share_setopt); | |
| DEFINE_THUNK(curl_share_strerror); | |
| DEFINE_THUNK(curl_slist_append); | |
| DEFINE_THUNK(curl_slist_free_all); | |
| DEFINE_THUNK(curl_strequal); | |
| DEFINE_THUNK(curl_strnequal); | |
| DEFINE_THUNK(curl_unescape); | |
| DEFINE_THUNK(curl_url); | |
| DEFINE_THUNK(curl_url_cleanup); | |
| DEFINE_THUNK(curl_url_dup); | |
| DEFINE_THUNK(curl_url_get); | |
| DEFINE_THUNK(curl_url_set); | |
| DEFINE_THUNK(curl_url_strerror); | |
| DEFINE_THUNK(curl_version); | |
| DEFINE_THUNK(curl_version_info); | |
| DEFINE_THUNK(curl_ws_meta); | |
| DEFINE_THUNK(curl_ws_recv); | |
| DEFINE_THUNK(curl_ws_send); | |
| typedef struct | |
| { | |
| LPBYTE buffer_out; | |
| ULONGLONG buffer_out_length; | |
| ULONGLONG buffer_out_capacity; | |
| LPBYTE buffer_in; | |
| ULONGLONG buffer_in_length; | |
| ULONGLONG buffer_in_capacity; | |
| } DEBUG_LOG_DATA, *PDEBUG_LOG_DATA; | |
| int debug_callback(PVOID handle, int type, char* data, size_t size, void* clientp) | |
| { | |
| PDEBUG_LOG_DATA log_data = (PDEBUG_LOG_DATA)clientp; | |
| switch (type) | |
| { | |
| case 1: // HEADER_IN | |
| case 3: // DATA_IN | |
| if (log_data->buffer_in_capacity < log_data->buffer_in_length + size) | |
| { | |
| log_data->buffer_in = realloc(log_data->buffer_in, log_data->buffer_in_capacity + size * 2); | |
| log_data->buffer_in_capacity = log_data->buffer_in_capacity + size * 2; | |
| } | |
| memcpy(&log_data->buffer_in[log_data->buffer_in_length], data, size); | |
| log_data->buffer_in_length += size; | |
| break; | |
| case 2: // HEADER_OUT | |
| case 4: // DATA_OUT | |
| if (log_data->buffer_out_capacity < log_data->buffer_out_length + size) | |
| { | |
| log_data->buffer_out = realloc(log_data->buffer_out, log_data->buffer_out_capacity + size * 2); | |
| log_data->buffer_out_capacity = log_data->buffer_out_capacity + size * 2; | |
| } | |
| memcpy(&log_data->buffer_out[log_data->buffer_out_length], data, size); | |
| log_data->buffer_out_length += size; | |
| break; | |
| } | |
| return 0; | |
| } | |
| INT(*curl_easy_perform_p)(PVOID handle); | |
| INT __declspec(dllexport) curl_easy_perform(PVOID handle) | |
| { | |
| INT result; | |
| HANDLE hFile; | |
| char buffer[256]; | |
| curl_easy_setopt_p(handle, 20094, debug_callback); // CURLOPT_DEBUGFUNCTION | |
| curl_easy_setopt_p(handle, 41, 1L); // CURLOPT_VERBOSE | |
| PDEBUG_LOG_DATA log_data = calloc(1, sizeof(*log_data)); | |
| curl_easy_setopt_p(handle, 10095, log_data); // CURLOPT_DEBUGDATA | |
| result = curl_easy_perform_p(handle); | |
| WaitForSingleObject(ghMutex, INFINITE); | |
| hFile = CreateFileA(gszLogPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
| if (hFile == INVALID_HANDLE_VALUE) | |
| { | |
| hFile = CreateFileA(gszLogPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); | |
| if (hFile == INVALID_HANDLE_VALUE) | |
| MessageBoxA(NULL, "Welp, can't create/open the log file.", "Welp!", MB_OK); | |
| } | |
| SetFilePointer(hFile, 0, 0, FILE_END); | |
| WriteFile(hFile, "================================================================\r\n", 66, NULL, NULL); | |
| sprintf_s(buffer, 256, ">>> PID: %d TID: %d Handle: %p\r\n", GetCurrentProcessId(), GetCurrentThreadId(), handle); | |
| WriteFile(hFile, buffer, lstrlenA(buffer), NULL, NULL); | |
| WriteFile(hFile, "================================================================\r\n", 66, NULL, NULL); | |
| WriteFile(hFile, log_data->buffer_out, log_data->buffer_out_length, NULL, NULL); | |
| WriteFile(hFile, "\r\n----------------------------------------------------------------\r\n", 68, NULL, NULL); | |
| WriteFile(hFile, log_data->buffer_in, log_data->buffer_in_length, NULL, NULL); | |
| WriteFile(hFile, "\r\n----------------------------------------------------------------\r\n\r\n", 70, NULL, NULL); | |
| CloseHandle(hFile); | |
| ReleaseMutex(ghMutex); | |
| curl_easy_setopt_p(handle, 10095, NULL); | |
| free(log_data->buffer_out); | |
| free(log_data->buffer_in); | |
| free(log_data); | |
| curl_easy_setopt_p(handle, 41, 0L); | |
| curl_easy_setopt_p(handle, 20094, NULL); | |
| return result; | |
| } | |
| BOOL APIENTRY DllMain( HMODULE hModule, | |
| DWORD ul_reason_for_call, | |
| LPVOID lpReserved | |
| ) | |
| { | |
| switch (ul_reason_for_call) | |
| { | |
| case DLL_PROCESS_ATTACH: | |
| hRealCurl = LoadLibraryA("libcurw.dll"); | |
| if (hRealCurl == INVALID_HANDLE_VALUE) | |
| { | |
| MessageBoxA(NULL, "Welp, LoadLibrary failed.", "Welp!", MB_OK); | |
| return FALSE; | |
| } | |
| LOAD_THUNK(curl_easy_cleanup); | |
| LOAD_THUNK(curl_easy_duphandle); | |
| LOAD_THUNK(curl_easy_escape); | |
| LOAD_THUNK(curl_easy_getinfo); | |
| LOAD_THUNK(curl_easy_header); | |
| LOAD_THUNK(curl_easy_init); | |
| LOAD_THUNK(curl_easy_nextheader); | |
| LOAD_THUNK(curl_easy_option_by_id); | |
| LOAD_THUNK(curl_easy_option_by_name); | |
| LOAD_THUNK(curl_easy_option_next); | |
| LOAD_THUNK(curl_easy_pause); | |
| LOAD_THUNK(curl_easy_perform); | |
| LOAD_THUNK(curl_easy_recv); | |
| LOAD_THUNK(curl_easy_reset); | |
| LOAD_THUNK(curl_easy_send); | |
| LOAD_THUNK(curl_easy_setopt); | |
| LOAD_THUNK(curl_easy_ssls_export); | |
| LOAD_THUNK(curl_easy_ssls_import); | |
| LOAD_THUNK(curl_easy_strerror); | |
| LOAD_THUNK(curl_easy_unescape); | |
| LOAD_THUNK(curl_easy_upkeep); | |
| LOAD_THUNK(curl_escape); | |
| LOAD_THUNK(curl_formadd); | |
| LOAD_THUNK(curl_formfree); | |
| LOAD_THUNK(curl_formget); | |
| LOAD_THUNK(curl_free); | |
| LOAD_THUNK(curl_getdate); | |
| LOAD_THUNK(curl_getenv); | |
| LOAD_THUNK(curl_global_cleanup); | |
| LOAD_THUNK(curl_global_init); | |
| LOAD_THUNK(curl_global_init_mem); | |
| LOAD_THUNK(curl_global_sslset); | |
| LOAD_THUNK(curl_global_trace); | |
| LOAD_THUNK(curl_maprintf); | |
| LOAD_THUNK(curl_mfprintf); | |
| LOAD_THUNK(curl_mime_addpart); | |
| LOAD_THUNK(curl_mime_data); | |
| LOAD_THUNK(curl_mime_data_cb); | |
| LOAD_THUNK(curl_mime_encoder); | |
| LOAD_THUNK(curl_mime_filedata); | |
| LOAD_THUNK(curl_mime_filename); | |
| LOAD_THUNK(curl_mime_free); | |
| LOAD_THUNK(curl_mime_headers); | |
| LOAD_THUNK(curl_mime_init); | |
| LOAD_THUNK(curl_mime_name); | |
| LOAD_THUNK(curl_mime_subparts); | |
| LOAD_THUNK(curl_mime_type); | |
| LOAD_THUNK(curl_mprintf); | |
| LOAD_THUNK(curl_msnprintf); | |
| LOAD_THUNK(curl_msprintf); | |
| LOAD_THUNK(curl_multi_add_handle); | |
| LOAD_THUNK(curl_multi_assign); | |
| LOAD_THUNK(curl_multi_cleanup); | |
| LOAD_THUNK(curl_multi_fdset); | |
| LOAD_THUNK(curl_multi_get_handles); | |
| LOAD_THUNK(curl_multi_info_read); | |
| LOAD_THUNK(curl_multi_init); | |
| LOAD_THUNK(curl_multi_perform); | |
| LOAD_THUNK(curl_multi_poll); | |
| LOAD_THUNK(curl_multi_remove_handle); | |
| LOAD_THUNK(curl_multi_setopt); | |
| LOAD_THUNK(curl_multi_socket); | |
| LOAD_THUNK(curl_multi_socket_action); | |
| LOAD_THUNK(curl_multi_socket_all); | |
| LOAD_THUNK(curl_multi_strerror); | |
| LOAD_THUNK(curl_multi_timeout); | |
| LOAD_THUNK(curl_multi_wait); | |
| LOAD_THUNK(curl_multi_waitfds); | |
| LOAD_THUNK(curl_multi_wakeup); | |
| LOAD_THUNK(curl_mvaprintf); | |
| LOAD_THUNK(curl_mvfprintf); | |
| LOAD_THUNK(curl_mvprintf); | |
| LOAD_THUNK(curl_mvsnprintf); | |
| LOAD_THUNK(curl_mvsprintf); | |
| LOAD_THUNK(curl_pushheader_byname); | |
| LOAD_THUNK(curl_pushheader_bynum); | |
| LOAD_THUNK(curl_share_cleanup); | |
| LOAD_THUNK(curl_share_init); | |
| LOAD_THUNK(curl_share_setopt); | |
| LOAD_THUNK(curl_share_strerror); | |
| LOAD_THUNK(curl_slist_append); | |
| LOAD_THUNK(curl_slist_free_all); | |
| LOAD_THUNK(curl_strequal); | |
| LOAD_THUNK(curl_strnequal); | |
| LOAD_THUNK(curl_unescape); | |
| LOAD_THUNK(curl_url); | |
| LOAD_THUNK(curl_url_cleanup); | |
| LOAD_THUNK(curl_url_dup); | |
| LOAD_THUNK(curl_url_get); | |
| LOAD_THUNK(curl_url_set); | |
| LOAD_THUNK(curl_url_strerror); | |
| LOAD_THUNK(curl_version); | |
| LOAD_THUNK(curl_version_info); | |
| LOAD_THUNK(curl_ws_meta); | |
| LOAD_THUNK(curl_ws_recv); | |
| LOAD_THUNK(curl_ws_send); | |
| ghMutex = CreateMutex(NULL, FALSE, NULL); | |
| ExpandEnvironmentStringsA("%USERPROFILE%\\CurlLog.txt", gszLogPath, sizeof(gszLogPath)); | |
| break; | |
| case DLL_THREAD_ATTACH: | |
| case DLL_THREAD_DETACH: | |
| break; | |
| case DLL_PROCESS_DETACH: | |
| CloseHandle(ghMutex); | |
| ghMutex = INVALID_HANDLE_VALUE; | |
| FreeLibrary(hRealCurl); | |
| break; | |
| } | |
| return TRUE; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment