Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cd73270
Initial plan
Copilot Feb 9, 2026
c51906f
Implement dynamic_chain and random_chain support with configurable ch…
Copilot Feb 9, 2026
31e4645
Fix edge case: dynamic chain with 0 proxies should not fail
Copilot Feb 9, 2026
61878e8
Add case-insensitive DNS, round-robin chain, SOCKS4 and HTTP proxy su…
Copilot Feb 9, 2026
62cd621
Update documentation and fix base64 encoding for HTTP proxy auth
Copilot Feb 9, 2026
3084c2a
Add random seed config, env variable expansion, and improved timeout …
Copilot Feb 9, 2026
2f2c455
Add CONTRIBUTING.md developer guide and update TODO.md progress tracking
Copilot Feb 9, 2026
78f18d3
Add inline documentation comments to key network proxy functions
Copilot Feb 9, 2026
90dc9ba
Add proxy health checking, automatic failover, and API documentation
Copilot Feb 9, 2026
0db920f
Expand troubleshooting guide and update README features list
Copilot Feb 9, 2026
18dddce
Enable ASLR/DEP in Release builds, add architecture diagrams
Copilot Feb 9, 2026
6ebcab2
Add IPv6 local network rules and fix link-local CIDR prefix
Copilot Feb 9, 2026
c7e126c
Add process name filtering (whitelist/blacklist) and persistent round…
Copilot Feb 9, 2026
9371568
Update documentation for process filtering and persistent round-robin
Copilot Feb 9, 2026
8e08e81
Merge changes from master branch: build fixes and embedded DLL support
Copilot Feb 9, 2026
02d8de7
Fix CI build: add Directory.Build.props to enforce v142 toolset for a…
Copilot Feb 9, 2026
81166bc
Fix x86 build: replace InetNtopA with XP-compatible IP formatting
Copilot Feb 9, 2026
a97071c
Rewrite proxychains.conf with all configuration options and demo values
Copilot Feb 9, 2026
335088a
Update proxychains.conf with recommended values and socks5 192.168.10…
Copilot Feb 9, 2026
d807167
Plan: Implement SOCKS5 UDP Associate and Enhanced DNS features
Copilot Feb 9, 2026
e7cf836
Plan: Implement DNS, IPv6, Logging, and compatibility improvements
Copilot Feb 9, 2026
74036f0
Implement SOCKS5 UDP Associate, DNS cache, custom DNS server, IPv6 du…
Copilot Feb 9, 2026
3feb48c
Fix CI build: replace HINTERNET with void*, add winsock2.h include, r…
Copilot Feb 9, 2026
0b3d370
Implement .NET/managed app proxy support with env vars, IE proxy regi…
Copilot Feb 16, 2026
618fbf8
Fix CI build: remove unused szHostA variable, fix ProxyOverride regis…
Copilot Feb 16, 2026
94710c7
Add colored console logs, optional traffic dump to files, and config …
Copilot Feb 16, 2026
e8ac4d7
Fix CI build: add missing range args to OptionGetNumberValueAfterOpti…
Copilot Feb 16, 2026
198b8cf
Apply 11 code review fixes: thread safety, buffer overflows, dangling…
Copilot Feb 16, 2026
368b660
Fix CI build: replace InitOnceExecuteOnce (Vista+) with InterlockedCo…
Copilot Feb 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .github/workflows/msvc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ jobs:
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2

- name: Build x64
run: msbuild proxychains.exe.sln /p:Configuration=Release /p:Platform=x64
shell: cmd

- name: Build x86
run: msbuild proxychains.exe.sln /p:Configuration=Release /p:Platform=x86
run: msbuild proxychains.exe.sln /p:Configuration=Release /p:Platform=x86 /p:PlatformToolset=v142 /p:WindowsTargetPlatformVersion=10.0
shell: cmd

- name: Build x64 (with embedded DLLs)
run: msbuild proxychains.exe.sln /p:Configuration=Release /p:Platform=x64 /p:PlatformToolset=v142 /p:WindowsTargetPlatformVersion=10.0 /p:EmbedDlls=true
shell: cmd

- name: Prepare release package
Expand All @@ -32,6 +32,8 @@ jobs:
copy win32_output\proxychains_win32_x64.exe release-package\proxychains.exe
copy win32_output\proxychains_hook_x64.dll release-package\
copy win32_output\proxychains_hook_x86.dll release-package\
copy win32_output\proxychains_helper_win32_x86.exe release-package\
copy win32_output\proxychains_helper_win32_x64.exe release-package\
if exist win32_output\MinHook.x64.dll copy win32_output\MinHook.x64.dll release-package\
if exist win32_output\MinHook.x86.dll copy win32_output\MinHook.x86.dll release-package\
copy proxychains.conf release-package\
Expand Down
248 changes: 248 additions & 0 deletions API_HOOKS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
# API Documentation for Hooks

This document describes the hooked Win32 API functions and proxy protocol implementations in proxychains-windows.

## Hooked Winsock Functions

### Connection Hooks

| Function | DLL | Purpose |
|----------|-----|---------|
| `connect()` | Ws2_32.dll | Intercepts TCP connections, routes through proxy chain |
| `WSAConnect()` | Ws2_32.dll | Intercepts extended TCP connections, routes through proxy chain |
| `ConnectEx()` | Mswsock.dll | Intercepts overlapped TCP connections, routes through proxy chain |

### DNS Resolution Hooks

| Function | DLL | Purpose |
|----------|-----|---------|
| `gethostbyname()` | Ws2_32.dll | Intercepts DNS resolution, returns fake IPs for remote DNS |
| `gethostbyaddr()` | Ws2_32.dll | Intercepts reverse DNS lookups |
| `getaddrinfo()` | Ws2_32.dll | Intercepts modern DNS resolution |
| `GetAddrInfoW()` | Ws2_32.dll | Intercepts wide-string DNS resolution |
| `GetAddrInfoExA()` | Ws2_32.dll | Intercepts extended DNS resolution (ANSI) |
| `GetAddrInfoExW()` | Ws2_32.dll | Intercepts extended DNS resolution (Wide) |
| `freeaddrinfo()` | Ws2_32.dll | Intercepts address info cleanup |
| `FreeAddrInfoW()` | Ws2_32.dll | Intercepts wide address info cleanup |
| `FreeAddrInfoExA_()` | Ws2_32.dll | Intercepts extended address info cleanup (ANSI) |
| `FreeAddrInfoExW()` | Ws2_32.dll | Intercepts extended address info cleanup (Wide) |
| `getnameinfo()` | Ws2_32.dll | Intercepts name resolution from address |
| `GetNameInfoW()` | Ws2_32.dll | Intercepts wide name resolution from address |

### Process Creation Hooks

| Function | DLL | Purpose |
|----------|-----|---------|
| `CreateProcessA()` | Kernel32.dll | Intercepts ANSI process creation to inject hook DLL into child processes |
| `CreateProcessW()` | Kernel32.dll | Intercepts wide process creation to inject hook DLL into child processes |
| `CreateProcessAsUserW()` | Advapi32.dll | Intercepts elevated process creation to inject hook DLL |

All three hooks support process name filtering via `process_only`/`process_except` config directives.
The `ShouldInjectProcess()` function extracts the executable name from `lpApplicationName` or `lpCommandLine`
and performs case-insensitive matching against the configured filter list.

### WinHTTP Hooks

| Function | DLL | Purpose |
|----------|-----|---------|
| `WinHttpOpen()` | winhttp.dll | Forces proxy settings when creating WinHTTP sessions |
| `WinHttpSetOption()` | winhttp.dll | Intercepts proxy configuration changes (WINHTTP_OPTION_PROXY) |

### WinINet Hooks

| Function | DLL | Purpose |
|----------|-----|---------|
| `InternetOpenA()` | wininet.dll | Forces proxy settings when creating WinINet sessions (ANSI) |
| `InternetOpenW()` | wininet.dll | Forces proxy settings when creating WinINet sessions (Wide) |
| `InternetSetOptionA()` | wininet.dll | Intercepts proxy configuration changes (INTERNET_OPTION_PROXY, ANSI) |
| `InternetSetOptionW()` | wininet.dll | Intercepts proxy configuration changes (INTERNET_OPTION_PROXY, Wide) |

WinHTTP and WinINet hooks ensure that applications using high-level HTTP APIs (PowerShell `Invoke-WebRequest`, .NET `HttpClient`, browsers, Windows Update, etc.) are transparently proxied. The hooks override the access type to `NAMED_PROXY` and inject the configured proxy address.

## Proxy Protocol Implementations

### SOCKS5 (`socks5`)

- **Connect Function**: `Ws2_32_Socks5Connect()`
- **Handshake Function**: `Ws2_32_Socks5Handshake()`
- **Supported Address Types**: IPv4, IPv6, Hostname
- **Authentication**: Username/password (RFC 1929)
- **Protocol**: RFC 1928

**Connection Flow**:
1. Handshake: Send auth method selection → Receive server method choice
2. Authentication (if required): Send username/password → Receive auth result
3. Connect: Send CONNECT request with target address → Receive connect response

### SOCKS5 UDP Associate (DNS)

- **Function**: `Socks5UdpAssociateDnsQuery()`
- **Helper Functions**: `BuildDnsQuery()`, `ParseDnsResponse()`, `ResolveDnsViaSocks5UdpAssociate()`
- **Config**: `proxy_dns_udp_associate`
- **Protocol**: RFC 1928 (command 0x03)

**DNS Resolution Flow**:
1. Connect TCP to SOCKS5 proxy (control channel)
2. Perform SOCKS5 handshake (auth if configured)
3. Send UDP ASSOCIATE request (cmd=0x03, DST.ADDR=0.0.0.0:0)
4. Receive relay address (BND.ADDR, BND.PORT) from proxy
5. Create UDP socket, build SOCKS5 UDP header + DNS query
6. Send to relay address, receive DNS response
7. Parse A/AAAA records from response
8. Cache result if `dns_cache_ttl > 0`

### SOCKS4/SOCKS4a (`socks4`)

- **Connect Function**: `Ws2_32_Socks4Connect()`
- **Handshake Function**: `Ws2_32_Socks4Handshake()` (no-op)
- **Supported Address Types**: IPv4, Hostname (SOCKS4a)
- **Authentication**: Userid (ident-based)

**Connection Flow**:
1. Send CONNECT request with VN=4, CD=1, DSTPORT, DSTIP, USERID, NULL
2. For SOCKS4a hostnames: set DSTIP to 0.0.0.x, append hostname after userid
3. Receive 8-byte response, check CD=0x5A for success

### HTTP CONNECT (`http`)

- **Connect Function**: `Ws2_32_HttpConnect()`
- **Handshake Function**: `Ws2_32_HttpHandshake()` (no-op)
- **Supported Address Types**: IPv4, IPv6, Hostname
- **Authentication**: Basic (username:password base64-encoded)

**Connection Flow**:
1. Send `CONNECT host:port HTTP/1.1\r\nHost: host:port\r\n`
2. If auth: Add `Proxy-Authorization: Basic <base64>\r\n`
3. Send `\r\n` (end of headers)
4. Receive response, check for `HTTP/1.x 200`
5. Drain remaining headers until `\r\n\r\n`

## Chain Modes

### Strict Chain (`strict_chain`)
All proxies in order. Any failure aborts the entire chain.
Health tracking: failure counters incremented on failure, reset on success.

### Dynamic Chain (`dynamic_chain`)
All proxies in order, dead ones are skipped. At least one must succeed.
Health tracking: proxies with ≥3 consecutive failures are auto-skipped.
When all proxies fail, counters are reset for retry.

### Random Chain (`random_chain`)
Randomly selects `chain_len` unique proxies from the list.
Supports `random_seed` for reproducible selection.

### Round-Robin Chain (`round_robin_chain`)
Cycles through proxies using a thread-safe `InterlockedIncrement` counter.
Uses `chain_len` proxies starting from current rotation position.

## Health Checking

Per-proxy health tracking is implemented using thread-safe counters:

```c
// In hook_connect_win32.c
static volatile LONG g_proxyFailureCount[PXCH_MAX_PROXY_NUM]; // Consecutive failures
static volatile LONG g_proxySuccessCount[PXCH_MAX_PROXY_NUM]; // Total successes
```

**Behavior**:
- On proxy failure: `InterlockedIncrement(&g_proxyFailureCount[index])`
- On proxy success: `InterlockedExchange(&g_proxyFailureCount[index], 0)` (reset)
- In dynamic mode: proxies with `g_proxyFailureCount[i] >= 3` are skipped
- When all proxies are dead: all failure counters are reset to allow retry

## Internal Helper Functions

| Function | Purpose |
|----------|---------|
| `Ws2_32_BlockConnect()` | Connect with timeout using select() for non-blocking sockets |
| `Ws2_32_LoopSend()` | Send all bytes, retrying until complete or error |
| `Ws2_32_LoopRecv()` | Receive exact byte count, with timeout via select() |
| `Ws2_32_OriginalConnect()` | Direct call to original connect() without blocking |
| `Ws2_32_DirectConnect()` | Connect directly (used when chain is empty) |
| `Ws2_32_GenericConnectTo()` | Connect through current chain to a target host |
| `Ws2_32_GenericTunnelTo()` | Tunnel to a specific proxy (connect + handshake) |
| `TunnelThroughProxyChain()` | Route connection through chain based on mode |

## Configuration Structure

The `PROXYCHAINS_CONFIG` structure (defined in `defines_generic.h`) is shared between the launcher executable and injected DLL via memory-mapped files. Key fields:

| Field | Type | Description |
|-------|------|-------------|
| `dwChainType` | UINT32 | Chain mode (STRICT/DYNAMIC/RANDOM/ROUND_ROBIN) |
| `dwChainLen` | UINT32 | Number of proxies per connection (random/round-robin) |
| `dwRandomSeed` | UINT32 | Fixed seed for random chain mode |
| `dwRandomSeedSet` | UINT32 | Whether random_seed was explicitly set |
| `dwProxyConnectionTimeoutMillisecond` | UINT32 | TCP connect timeout (default: 3000ms) |
| `dwProxyHandshakeTimeoutMillisecond` | UINT32 | Handshake read timeout (default: 5000ms) |
| `dwProxyNum` | UINT32 | Number of proxies in ProxyList |
| `dwRuleNum` | UINT32 | Number of routing rules |
| `dwProcessFilterMode` | UINT32 | Process filter mode: 0=none, 1=whitelist, 2=blacklist |
| `dwProcessFilterCount` | UINT32 | Number of process name filter entries |
| `szProcessFilterNames` | WCHAR[8][256] | Process name patterns for filtering |

## Process Name Filtering

Process name filtering allows controlling which child processes get injected with the hook DLL.

### Configuration

```ini
# Whitelist mode: only inject into these processes
process_only = curl.exe
process_only = git.exe

# OR blacklist mode: inject into all EXCEPT these
process_except = explorer.exe
process_except = svchost.exe
```

### Behavior

- **Whitelist** (`process_only`): Only matching processes are injected. All others run without proxying.
- **Blacklist** (`process_except`): All processes are injected EXCEPT matching ones.
- **No filter** (default): All child processes are injected.
- Matching is case-insensitive on the executable filename (not the full path).
- Maximum 8 filter entries. Cannot mix `process_only` and `process_except`.

## .NET / Managed Application Support

### Problem

Pure .NET applications (like LMSA Software Fix, LmsaWindowsService) don't import Winsock or WinHTTP directly. They use .NET's managed `System.Net.Http.HttpClient` or `System.Net.WebRequest` which go through the CLR runtime. DLL injection via EntryDetour fails because these apps have a CLR runtime header, and CreateRemoteThread often fails because the CLR hasn't initialized when injection occurs.

### Solution: Multi-Layer Proxy

proxychains now uses three complementary approaches to proxy .NET apps:

1. **Environment Variables** (`set_proxy_env`): Sets `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` (both upper and lowercase) in the injected process. .NET HttpClient (Framework 4.7+ / .NET Core 3.0+) reads these automatically.

2. **Windows Internet Settings Registry**: Sets `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings` proxy values (`ProxyEnable`, `ProxyServer`, `ProxyOverride`). This is read by .NET `WebRequest.DefaultWebProxy` which uses the IE/system proxy settings.

3. **CLR Injection Retry**: When a .NET CLR binary is detected, the main thread is resumed first to allow the CLR to initialize, then CreateRemoteThread is retried up to 3 times with progressive delay (500ms, 1000ms, 1500ms).

### Configuration

```ini
# Enable/disable proxy environment variables and registry proxy (default: 1)
set_proxy_env 1
```

### Supported .NET Networking APIs

| .NET API | Proxy Method | Status |
|----------|-------------|--------|
| `HttpClient` (.NET 4.7+) | `HTTP_PROXY`/`HTTPS_PROXY` env vars | ✅ Working |
| `WebRequest`/`HttpWebRequest` | IE proxy registry (`DefaultWebProxy`) | ✅ Working |
| `WebClient` | IE proxy registry (`DefaultWebProxy`) | ✅ Working |
| `Socket`/`TcpClient` | Winsock hooks (if DLL injection succeeds) | ✅ Working |
| WebView2 (Chromium) | IE proxy settings / `--proxy-server` | ✅ Working |

### Analyzed Applications

- **Software Fix.exe**: .NET 4.7.2, WPF GUI, x64. Pure CLR (zero native imports). Uses `HttpClient` and `WebRequest` for downloads. WebView2 for web content.
- **LmsaWindowsService.exe**: .NET Framework, Windows Service, x86. Uses `HttpClient`, named pipes. Only native import: `mscoree.dll!_CorExeMain`.
- **lenovo.mbg.service.framework.download.dll**: .NET, uses `HttpWebRequest` with HTTP and FTP download modes, `WebProxy` support.
- **lenovo.mbg.service.common.webservices.dll**: .NET, uses `HttpClient` and `WebClient` for REST API calls.
Loading