Skip to content

Instantly share code, notes, and snippets.

@mgeeky
Last active September 2, 2018 20:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mgeeky/8960f4fa3f9462ae7bcd6db4ce42a8d3 to your computer and use it in GitHub Desktop.
Save mgeeky/8960f4fa3f9462ae7bcd6db4ce42a8d3 to your computer and use it in GitHub Desktop.
Windows Proxy Auto-detection and debugging script crafted by Juan Caillava (https://medium.com/@br4nsh/a-meterpreter-and-windows-proxy-case-4af2b866f4a1)
import ctypes
import ctypes.wintypes
import sys
class WINHTTP_CURRENT_USER_IE_PROXY_CONFIG(ctypes.Structure):
_fields_ = [("fAutoDetect", ctypes.wintypes.BOOL),
("lpszAutoConfigUrl", ctypes.wintypes.LPWSTR),
("lpszProxy", ctypes.wintypes.LPWSTR),
("lpszProxyBypass", ctypes.wintypes.LPWSTR)]
class WINHTTP_AUTOPROXY_OPTIONS(ctypes.Structure):
_fields_ = [("dwFlags", ctypes.wintypes.DWORD),
("dwAutoDetectFlags", ctypes.wintypes.DWORD),
("lpszAutoConfigUrl", ctypes.wintypes.LPCWSTR),
("lpvReserved", ctypes.c_void_p),
("dwReserved", ctypes.wintypes.DWORD),
("fAutoLogonIfChallenged", ctypes.wintypes.BOOL)]
class WINHTTP_PROXY_INFO(ctypes.Structure):
_fields_ = [("dwAccessType", ctypes.wintypes.DWORD),
("lpszProxy", ctypes.wintypes.LPCWSTR),
("lpszProxyBypass", ctypes.wintypes.LPCWSTR)]
WINHTTP_USER_AGENT = ctypes.c_wchar_p('Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko')
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0
WINHTTP_ACCESS_TYPE_NO_PROXY = 1
WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3
WINHTTP_NO_PROXY_NAME = 0
WINHTTP_NO_PROXY_BYPASS = 0
def ShowLastError(message, alignment = 0):
error_id = ctypes.GetLastError()
print ' ' * alignment + '[-] Error on %s: %s' % (message, error_id)
if error_id == 12167:
title = 'ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT'
message = 'The PAC file cannot be downloaded. For example, the server referenced by the PAC URL may not have been reachable, or the server returned a 404 NOT FOUND response.'
elif error_id == 12007:
title = 'ERROR_WINHTTP_NAME_NOT_RESOLVED'
message = 'The server name cannot be resolved.'
elif error_id == 12029:
title = 'ERROR_WINHTTP_CANNOT_CONNECT'
message = 'Returned if connection to the server failed.'
elif error_id == 12002:
title = 'ERROR_WINHTTP_TIMEOUT'
message = 'The request has timed out.'
elif error_id == 12180:
title = 'ERROR_WINHTTP_AUTODETECTION_FAILED'
message = 'Returned by WinHttpDetectAutoProxyConfigUrl if WinHTTP was unable to discover the URL of the Proxy Auto-Configuration (PAC) file.'
else:
title = 'UNKNOWN'
message = 'unknown'
msg_max_len = 70
msg_list = [message[i:i+msg_max_len] for i in range(0, len(message), msg_max_len)]
print ' ' * alignment + ' => %s' % title
for msg in msg_list:
print ' ' * alignment + ' %s' % msg
def GetCurrentProxies():
pProxyConfig = WINHTTP_CURRENT_USER_IE_PROXY_CONFIG()
result = ctypes.windll.winhttp.WinHttpGetIEProxyConfigForCurrentUser(ctypes.byref(pProxyConfig))
if result == False:
ShowLastError('WinHttpGetIEProxyConfigForCurrentUser')
return False, None
return True, pProxyConfig
def GetProxyInfoList(pProxyConfig, target_url):
print '\n[*] Checking proxy configuration alternatives...'
proxy_list = []
hSession = ctypes.windll.winhttp.WinHttpOpen(WINHTTP_USER_AGENT, WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0)
if hSession is None:
ShowLastError('WinHttpOpen')
sys.exit()
WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001
WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001
WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002
WINHTTP_AUTOPROXY_CONFIG_URL = 0x00000002
if pProxyConfig.fAutoDetect:
print '\n (1) Automatically detect settings (enabled)'
print ' [*] Trying to get the proxy using the conventional method...'
pAutoProxyOptions = WINHTTP_AUTOPROXY_OPTIONS()
pProxyInfo = WINHTTP_PROXY_INFO()
pAutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT
pAutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A
pAutoProxyOptions.lpszAutoConfigUrl = 0
lpcwszUrl = ctypes.wintypes.LPCWSTR(target_url)
result = ctypes.windll.winhttp.WinHttpGetProxyForUrl(hSession, lpcwszUrl, ctypes.byref(pAutoProxyOptions),
ctypes.byref(pProxyInfo))
if result == False:
ShowLastError('WinHttpGetProxyForUrl', 6)
print '\n [*] Trying to get the proxy using the AutoConfigURL...'
dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A
ppwszAutoConfigUrl = ctypes.wintypes.LPWSTR()
result = ctypes.windll.winhttp.WinHttpDetectAutoProxyConfigUrl(dwAutoDetectFlags,
ctypes.byref(ppwszAutoConfigUrl))
if result == False:
ShowLastError('WinHttpDetectAutoProxyConfigUrl', 10)
else:
print ' [+] Trying to get the proxy from the obtained URL (%s)' % ppwszAutoConfigUrl.value
pAutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL
pAutoProxyOptions.dwAutoDetectFlags = 0
pAutoProxyOptions.fAutoLogonIfChallenged = True
pAutoProxyOptions.lpszAutoConfigUrl = ppwszAutoConfigUrl
result = ctypes.windll.winhttp.WinHttpGetProxyForUrl(hSession, lpcwszUrl, ctypes.byref(pAutoProxyOptions),
ctypes.byref(pProxyInfo))
if result:
print ' [+] Proxy: %s' % (pProxyInfo.lpszProxy)
proxy_list.append(pProxyInfo)
else:
ShowLastError('WinHttpGetProxyForUrl', 10)
else:
print ' [+] Proxy: %s' % (pProxyInfo.lpszProxy)
proxy_list.append(pProxyInfo)
if pProxyConfig.lpszAutoConfigUrl:
print '\n (2) Use automatic configuration script (%s)' % pProxyConfig.lpszAutoConfigUrl
pAutoProxyOptions = WINHTTP_AUTOPROXY_OPTIONS()
pProxyInfo = WINHTTP_PROXY_INFO()
pAutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL
pAutoProxyOptions.dwAutoDetectFlags = 0
pAutoProxyOptions.fAutoLogonIfChallenged = True
pAutoProxyOptions.lpszAutoConfigUrl = pProxyConfig.lpszAutoConfigUrl
lpcwszUrl = ctypes.wintypes.LPCWSTR(target_url)
result = ctypes.windll.winhttp.WinHttpGetProxyForUrl(hSession, lpcwszUrl, ctypes.byref(pAutoProxyOptions),
ctypes.byref(pProxyInfo))
if result == False:
ShowLastError('WinHttpGetProxyForUrl', 6)
else:
print ' [+] Proxy: %s' % (pProxyInfo.lpszProxy)
proxy_list.append(pProxyInfo)
if pProxyConfig.lpszProxy:
print '\n (3) Use a proxy server for your LAN'
pProxyInfo = WINHTTP_PROXY_INFO()
WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3
pProxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY
pProxyInfo.lpszProxy = pProxyConfig.lpszProxy
pProxyInfo.lpszProxyBypass = pProxyConfig.lpszProxyBypass
print ' [+] Proxy: %s' % pProxyConfig.lpszProxy
print ' [+] Proxy Bypass: %s' % pProxyConfig.lpszProxyBypass
proxy_list.append(pProxyInfo)
ctypes.windll.winhttp.WinHttpCloseHandle(hSession)
return proxy_list
def CheckProxyStatus(proxyInfo, target_server, target_port):
hSession = ctypes.windll.winhttp.WinHttpOpen(WINHTTP_USER_AGENT, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0)
if hSession is None:
ShowLastError('WinHttpOpen')
return
server_name = ctypes.c_wchar_p(target_server)
INTERNET_DEFAULT_HTTP_PORT = target_port
hInternet = ctypes.windll.winhttp.WinHttpConnect(hSession, server_name, INTERNET_DEFAULT_HTTP_PORT, 0)
if hInternet is None:
ShowLastError('WinHttpConnect', 8)
return False
WINHTTP_FLAG_BYPASS_PROXY_CACHE = 0x00000100
WINHTTP_FLAG_SECURE = 0x00800000
dwFlags = WINHTTP_FLAG_BYPASS_PROXY_CACHE
pwszVerb = ctypes.c_wchar_p('GET')
pwszObjectName = ctypes.c_wchar_p('')
hRequest = ctypes.windll.winhttp.WinHttpOpenRequest(hInternet, pwszVerb, pwszObjectName,
0, 0, 0, dwFlags)
if hRequest is None:
ShowLastError('WinHttpOpenRequest', 8)
return False
WINHTTP_OPTION_PROXY = 38
result = ctypes.windll.winhttp.WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, ctypes.byref(proxyInfo),
ctypes.sizeof(proxyInfo))
if result == False:
ShowLastError('WinHttpSetOption', 8)
return False
WINHTTP_NO_ADDITIONAL_HEADERS = 0
WINHTTP_NO_REQUEST_DATA = 0
result = ctypes.windll.winhttp.WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)
if result == False:
ShowLastError('WinHttpSendRequest', 8)
return False
else:
WINHTTP_QUERY_STATUS_CODE = 19
WINHTTP_QUERY_STATUS_TEXT = 20
WINHTTP_QUERY_RAW_HEADERS_CRLF = 22
WINHTTP_HEADER_NAME_BY_INDEX = 0
WINHTTP_NO_HEADER_INDEX = 0
dwInfoLevel = WINHTTP_QUERY_RAW_HEADERS_CRLF
lpdwBufferLength = ctypes.wintypes.DWORD()
lpdwIndex = ctypes.wintypes.DWORD()
result = ctypes.windll.winhttp.WinHttpReceiveResponse(hRequest, 0)
if result:
result = ctypes.windll.winhttp.WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX, 0,
ctypes.byref(lpdwBufferLength),
WINHTTP_NO_HEADER_INDEX)
ERROR_INSUFFICIENT_BUFFER = 122
if ctypes.GetLastError() == ERROR_INSUFFICIENT_BUFFER:
lpBuffer = ctypes.create_string_buffer(lpdwBufferLength.value)
result = ctypes.windll.winhttp.WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX, ctypes.byref(lpBuffer),
ctypes.byref(lpdwBufferLength),
WINHTTP_NO_HEADER_INDEX)
if result:
line = lpBuffer.raw.replace('\x00', '').split('\n')[0]
space_1 = line.find(' ')
space_2 = line.find(' ', space_1+1)
code = line[space_1:space_2].strip()
text = line[space_2:].strip()
print "\t[*] HTTP Query Status Code / Text: \n\t %s / %s" % (code, text)
if code != "200":
return False
else:
return True
ctypes.windll.winhttp.WinHttpCloseHandle(hRequest)
ctypes.windll.winhttp.WinHttpCloseHandle(hInternet)
ctypes.windll.winhttp.WinHttpCloseHandle(hSession)
return True
def main():
result, pProxyConfig = GetCurrentProxies()
if result == False:
sys.exit()
print '\n[*] We got the proxy configuration.'
if pProxyConfig is None:
print '[*] No proxy setting found for the current user.'
sys.exit()
target_server = 'www.google.com'
target_url = 'http://' + target_server
target_port = 80
proxy_list = GetProxyInfoList(pProxyConfig, target_url)
print '\n[*] Number of proxies: %s' % str(len(proxy_list))
print '\n[*] Testing if proxy servers actually work...'
for proxy in proxy_list:
print '\n [*] Proxy "%s" ... ' % proxy.lpszProxy
result = CheckProxyStatus(proxy, target_server, target_port)
if result:
print ' [+] Works! :)'
else:
print ' [-] Does not work :('
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment