public void setConnection(SessionEventArgs e) { if (this.InvokeRequired) { this.Invoke(new setInfo(setConnection), new object[] { e }); } else { label1.Text = "Hostname: " + e.RequestHostname; label2.Text = "URL: " + e.RequestURL; label3.Text = "Useragent: " + e.ProxyRequest.UserAgent; label4.Text = "Status Code: " + ((e.ServerResponse!=null)?e.ServerResponse.StatusDescription:"-1"); label5.Text = "Referer: " + e.ProxyRequest.Referer; label6.Text = "Keep alive: " + e.ProxyRequest.KeepAlive; label7.Text = "Request URI: " + e.ProxyRequest.RequestUri; try { textBox1.Text = e.GetResponseHtmlBody(); } catch(Exception exception) { textBox1.Text = "Could not read response! ["+exception.Message+"]"; } } }
public void OnRequest(object sender, SessionEventArgs e) { flag = true; addConnection(i, e); if (connections.Count > 250) { connections.RemoveAt(0); } connections.Add(new Tuple<int, SessionEventArgs>(i,e)); i++; flag = false; }
//Test On Request, intecept requests //Read browser URL send back to proxy by the injection script in OnResponse event public void OnRequest(object sender, SessionEventArgs e) { Console.WriteLine(e.RequestURL); //To cancel a request with a custom HTML content //Filter URL //if (e.RequestURL.Contains("somewebsite.com")) //{ // e.Ok("<!DOCTYPE html><html><body><h1>Blocked</h1><p>website blocked.</p></body></html>"); //} }
public void modifyFrom(int i, SessionEventArgs e) { if (this.InvokeRequired) { this.Invoke(new modifyFromList(modifyFrom), new object[] { i, e }); } else { if (e.ServerResponse != null) { dataGridView1.Rows[i].Cells[2].Value = e.ServerResponse.StatusCode.ToString(); dataGridView1.Rows[i].Cells[5].Value = e.ServerResponse.ContentLength; } } }
//Test script injection //Insert script to read the Browser URL and send it back to proxy public void OnResponse(object sender, SessionEventArgs e) { //To modify a response //if (e.ServerResponse.StatusCode == HttpStatusCode.OK) //{ // if (e.ServerResponse.ContentType.Trim().ToLower().Contains("text/html")) // { // //Get response body // string responseHtmlBody = e.GetResponseHtmlBody(); // //Modify e.ServerResponse // responseHtmlBody = "<html><head></head><body>Response is modified!</body></html>"; // //Set modifed response Html Body // e.SetResponseHtmlBody(responseHtmlBody); // } //} }
//Test On Request, intecept requests //Read browser URL send back to proxy by the injection script in OnResponse event public void OnRequest(object sender, SessionEventArgs e) { string Random = e.RequestURL.Substring(e.RequestURL.LastIndexOf(@"/") + 1); int index = _URLList.IndexOf(Random); if (index >= 0) { string URL = e.Decode(); if (_lastURL != URL) { OnChanged(new VisitedEventArgs() { hostname = e.Hostname, URL = URL, remoteIP = e.ipAddress, remotePort = e.Port }); } e.Ok(null); _lastURL = URL; } }
public int addConnection(int i,SessionEventArgs e) { if (this.InvokeRequired) { this.Invoke(new addToList(addConnection),new object[] { i, e }); } else { if (e.ServerResponse == null) { String url = e.RequestURL; if (e.RequestURL.IndexOf(e.RequestHostname) != -1) { String s = (e.RequestURL.Substring(e.RequestURL.IndexOf(e.RequestHostname) + e.RequestHostname.Length)); url = s.Substring(s.IndexOf("/")); } dataGridView1.Rows.Add(e.ProxyRequest.Method,i, "Waiting...", e.RequestHostname, url, "-1"); return dataGridView1.Rows.Count-1; } } return -1; }
private static void HandleClientRequest(TcpClient Client) { string connectionGroup = null; Stream clientStream = null; CustomBinaryReader clientStreamReader = null; StreamWriter connectStreamWriter = null; string tunnelHostName = null; int tunnelPort = 0; try { connectionGroup = Dns.GetHostEntry(((IPEndPoint)Client.Client.RemoteEndPoint).Address).HostName; clientStream = Client.GetStream(); clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII); string securehost = null; List<string> requestLines = new List<string>(); string tmpLine; while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) { requestLines.Add(tmpLine); } //read the first line HTTP command String httpCmd = requestLines.Count > 0 ? requestLines[0] : null; if (String.IsNullOrEmpty(httpCmd)) { throw new EndOfStreamException(); } //break up the line into three components String[] splitBuffer = httpCmd.Split(spaceSplit, 3); String method = splitBuffer[0]; String remoteUri = splitBuffer[1]; Version version; string RequestVersion; if (splitBuffer[2] == "HTTP/1.1") { version = new Version(1, 1); RequestVersion = "HTTP/1.1"; } else { version = new Version(1, 0); RequestVersion = "HTTP/1.0"; } if (splitBuffer[0].ToUpper() == "CONNECT") { //Browser wants to create a secure tunnel //instead = we are going to perform a man in the middle "attack" //the user's browser should warn them of the certification errors, //so we need to install our root certficate in users machine as Certificate Authority. remoteUri = "https://" + splitBuffer[1]; tunnelHostName = splitBuffer[1].Split(':')[0]; int.TryParse(splitBuffer[1].Split(':')[1], out tunnelPort); if (tunnelPort == 0) tunnelPort = 80; var isSecure = true; for (int i = 1; i < requestLines.Count; i++) { var rawHeader = requestLines[i]; String[] header = rawHeader.ToLower().Trim().Split(colonSpaceSplit, 2, StringSplitOptions.None); if ((header[0] == "host")) { var hostDetails = header[1].ToLower().Trim().Split(':'); if (hostDetails.Length > 1) { isSecure = false; } } } requestLines.Clear(); connectStreamWriter = new StreamWriter(clientStream); connectStreamWriter.WriteLine(RequestVersion + " 200 Connection established"); connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString())); connectStreamWriter.WriteLine(String.Format("connection:close")); connectStreamWriter.WriteLine(); connectStreamWriter.Flush(); if (tunnelPort != 443) { TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream); if (clientStream != null) clientStream.Close(); return; } Monitor.Enter(certificateAccessLock); var _certificate = CertificateHelper.GetCertificate(RootCertificateName, tunnelHostName); Monitor.Exit(certificateAccessLock); SslStream sslStream = null; if (!pinnedCertificateClients.Contains(tunnelHostName) && isSecure) { sslStream = new SslStream(clientStream, true); try { sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false); } catch (AuthenticationException ex) { if (pinnedCertificateClients.Contains(tunnelHostName) == false) { pinnedCertificateClients.Add(tunnelHostName); } throw ex; } } else { TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream); if (clientStream != null) clientStream.Close(); return; } clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII); //HTTPS server created - we can now decrypt the client's traffic clientStream = sslStream; while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) { requestLines.Add(tmpLine); } //read the new http command. httpCmd = requestLines.Count > 0 ? requestLines[0] : null; if (String.IsNullOrEmpty(httpCmd)) { throw new EndOfStreamException(); } securehost = remoteUri; } int count = 0; SessionEventArgs args = new SessionEventArgs(BUFFER_SIZE); while (!String.IsNullOrEmpty(httpCmd)) { count++; MemoryStream mw = null; StreamWriter sw = null; args = new SessionEventArgs(BUFFER_SIZE); try { splitBuffer = httpCmd.Split(spaceSplit, 3); if (splitBuffer.Length != 3) { TcpHelper.SendRaw(httpCmd, tunnelHostName, ref requestLines, args.IsSecure, clientStreamReader.BaseStream); if (clientStream != null) clientStream.Close(); return; } method = splitBuffer[0]; remoteUri = splitBuffer[1]; if (splitBuffer[2] == "HTTP/1.1") { version = new Version(1, 1); } else { version = new Version(1, 0); } if (securehost != null) { remoteUri = securehost + remoteUri; args.IsSecure = true; } //construct the web request that we are going to issue on behalf of the client. args.ProxyRequest = (HttpWebRequest)HttpWebRequest.Create(remoteUri.Trim()); args.ProxyRequest.Proxy = null; args.ProxyRequest.UseDefaultCredentials = true; args.ProxyRequest.Method = method; args.ProxyRequest.ProtocolVersion = version; args.ClientStream = clientStream; args.ClientStreamReader = clientStreamReader; for (int i = 1; i < requestLines.Count; i++) { var rawHeader = requestLines[i]; String[] header = rawHeader.ToLower().Trim().Split(colonSpaceSplit, 2, StringSplitOptions.None); if ((header[0] == "upgrade") && (header[1] == "websocket")) { TcpHelper.SendRaw(httpCmd, tunnelHostName, ref requestLines, args.IsSecure, clientStreamReader.BaseStream); if (clientStream != null) clientStream.Close(); return; } } ReadRequestHeaders(ref requestLines, args.ProxyRequest); int contentLen = (int)args.ProxyRequest.ContentLength; args.ProxyRequest.AllowAutoRedirect = false; args.ProxyRequest.AutomaticDecompression = DecompressionMethods.None; if (BeforeRequest != null) { args.Hostname = args.ProxyRequest.RequestUri.Host; args.RequestURL = args.ProxyRequest.RequestUri.OriginalString; args.RequestLength = contentLen; args.HttpVersion = version; args.Port = ((IPEndPoint)Client.Client.RemoteEndPoint).Port; args.ipAddress = ((IPEndPoint)Client.Client.RemoteEndPoint).Address; args.IsAlive = args.ProxyRequest.KeepAlive; BeforeRequest(null, args); } if (args.Cancel) { if (args.IsAlive) { requestLines.Clear(); while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) { requestLines.Add(tmpLine); } httpCmd = requestLines.Count > 0 ? requestLines[0] : null; continue; } else break; } args.ProxyRequest.ConnectionGroupName = connectionGroup; args.ProxyRequest.AllowWriteStreamBuffering = true; args.FinishedRequestEvent = new ManualResetEvent(false); if (method.ToUpper() == "POST" || method.ToUpper() == "PUT") { args.ProxyRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), args); } else { args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleServerResponse), args); } if (args.IsSecure) { if (args.ProxyRequest.Method == "POST" || args.ProxyRequest.Method == "PUT") args.FinishedRequestEvent.WaitOne(); else args.FinishedRequestEvent.Set(); } else args.FinishedRequestEvent.WaitOne(); httpCmd = null; if (args.ProxyRequest.KeepAlive) { requestLines.Clear(); while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) { requestLines.Add(tmpLine); } httpCmd = requestLines.Count() > 0 ? requestLines[0] : null; } if (args.ServerResponse != null) args.ServerResponse.Close(); } catch (IOException ex) { throw ex; } catch (UriFormatException ex) { throw ex; } catch (WebException ex) { throw ex; } finally { if (sw != null) sw.Close(); if (mw != null) mw.Close(); if (args.ProxyRequest != null) args.ProxyRequest.Abort(); if (args.ServerResponseStream != null) args.ServerResponseStream.Close(); } } } catch (AuthenticationException ex) { Debug.WriteLine(ex.Message); } catch (EndOfStreamException ex) { Debug.WriteLine(ex.Message); } catch (IOException ex) { Debug.WriteLine(ex.Message); } catch (UriFormatException ex) { Debug.WriteLine(ex.Message); } catch (WebException ex) { Debug.WriteLine(ex.Message); } finally { if (connectStreamWriter != null) connectStreamWriter.Close(); if (clientStreamReader != null) clientStreamReader.Close(); if (clientStream != null) clientStream.Close(); } }
public void OnResponse(object sender, SessionEventArgs e) { foreach (Tuple<int, SessionEventArgs> request in connections) { if (e.ProxyRequest.Equals(request.Item2.ProxyRequest)) { modifyFrom(request.Item1, e); break; } } if (e.ServerResponse.StatusCode == HttpStatusCode.OK) { if (e.ServerResponse.ContentType.Trim().ToLower().Contains("text/html")) { if (e.GetResponseHtmlBody() != null) { try { String body = e.GetResponseHtmlBody(); try { foreach (DataGridViewRow row in dataGridView2.Rows) { if (row == null) continue; bool check = true; foreach (DataGridViewCell cell in row.Cells) { if (cell.Value == null) { check = false; continue; } String val = (String)cell.Value; if (val.Trim().Length <= 1) { check = false; } } if (check) { HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); doc.LoadHtml(body); Console.WriteLine("//" + row.Cells[0].Value + "[@" + row.Cells[1].Value + "]"); foreach (HtmlNode img in doc.DocumentNode.SelectNodes("//" + row.Cells[0].Value + "[@" + row.Cells[1].Value + "]")) { if (img == null) continue; if (img.Attributes[(String)row.Cells[1].Value] != null) { img.SetAttributeValue((String)row.Cells[1].Value, (String)row.Cells[2].Value); } } body = doc.DocumentNode.OuterHtml; } } } catch { } e.Ok("<!-- Processed by RequestBuilder -->\n" + body); } catch(Exception exception) { Console.WriteLine("EXCEPTION: " + exception.Message); } } } } }
public ConnectionView(SessionEventArgs e) { this.Name = e.RequestHostname; this.SubItems.Add(e.RequestHostname); }
//Test script injection //Insert script to read the Browser URL and send it back to proxy public void OnResponse(object sender, SessionEventArgs e) { try { if (e.ProxyRequest.Method == "GET" || e.ProxyRequest.Method == "POST") { if (e.ServerResponse.StatusCode == HttpStatusCode.OK) { if (e.ServerResponse.ContentType.Trim().ToLower().Contains("text/html")) { string c = e.ServerResponse.GetResponseHeader("X-Requested-With"); if (e.ServerResponse.GetResponseHeader("X-Requested-With") == "") { e.GetResponseBody(); string functioname = "fr" + RandomString(10); string VisitedURL = RandomString(5); string RequestVariable = "c" + RandomString(5); string RandomURLEnding = RandomString(25); string RandomLastRequest = RandomString(10); string LocalRequest; if (e.IsSecure) LocalRequest = "https://" + e.Hostname + "/" + RandomURLEnding; else LocalRequest = "http://" + e.Hostname + "/" + RandomURLEnding; string script = "var " + RandomLastRequest + " = null;" + "if(window.top==self) { " + "\n" + " " + functioname + "();" + "setInterval(" + functioname + ",500); " + "\n" + "}" + "function " + functioname + "(){ " + "\n" + "var " + RequestVariable + " = new XMLHttpRequest(); " + "\n" + "var " + VisitedURL + " = null;" + "\n" + "if(window.top.location.href!=null) " + "\n" + "" + VisitedURL + " = window.top.location.href; else " + "\n" + "" + VisitedURL + " = document.referrer; " + "if(" + RandomLastRequest + "!= " + VisitedURL + ") {" + RequestVariable + ".open(\"POST\",\"" + LocalRequest + "\", true); " + "\n" + RequestVariable + ".send(" + VisitedURL + ");} " + RandomLastRequest + " = " + VisitedURL + "}"; string response = e.ResponseString; Regex RE = new Regex("</body>", RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.Multiline); string replaced = RE.Replace(response, "<script type =\"text/javascript\">" + script + "</script></body>", 1); if (replaced.Length != response.Length) { e.ResponseString = replaced; _URLList.Add(RandomURLEnding); } } } } } } catch { } }
private static void HandleHttpSessionRequest(TcpClient Client, string httpCmd, Stream clientStream, string tunnelHostName, List<string> requestLines, CustomBinaryReader clientStreamReader, string securehost) { if (httpCmd == null) return; var args = new SessionEventArgs(BUFFER_SIZE); args.Client = Client; args.tunnelHostName = tunnelHostName; args.securehost = securehost; try { //break up the line into three components (method, remote URL & Http Version) var splitBuffer = httpCmd.Split(spaceSplit, 3); if (splitBuffer.Length != 3) { TcpHelper.SendRaw(httpCmd, tunnelHostName, ref requestLines, args.IsSSLRequest, clientStreamReader.BaseStream); if (clientStream != null) clientStream.Close(); return; } var method = splitBuffer[0]; var remoteUri = splitBuffer[1]; Version version; if (splitBuffer[2] == "HTTP/1.1") { version = new Version(1, 1); } else { version = new Version(1, 0); } if (securehost != null) { remoteUri = securehost + remoteUri; args.IsSSLRequest = true; } //construct the web request that we are going to issue on behalf of the client. args.ProxyRequest = (HttpWebRequest)HttpWebRequest.Create(remoteUri.Trim()); args.ProxyRequest.Proxy = null; args.ProxyRequest.UseDefaultCredentials = true; args.ProxyRequest.Method = method; args.ProxyRequest.ProtocolVersion = version; args.ClientStream = clientStream; args.ClientStreamReader = clientStreamReader; for (int i = 1; i < requestLines.Count; i++) { var rawHeader = requestLines[i]; String[] header = rawHeader.ToLower().Trim().Split(colonSpaceSplit, 2, StringSplitOptions.None); //if request was upgrade to web-socket protocol then relay the request without proxying if ((header[0] == "upgrade") && (header[1] == "websocket")) { TcpHelper.SendRaw(httpCmd, tunnelHostName, ref requestLines, args.IsSSLRequest, clientStreamReader.BaseStream); if (clientStream != null) clientStream.Close(); return; } } ReadRequestHeaders(ref requestLines, args.ProxyRequest); int contentLen = (int)args.ProxyRequest.ContentLength; args.ProxyRequest.AllowAutoRedirect = false; args.ProxyRequest.AutomaticDecompression = DecompressionMethods.None; //If requested interception if (BeforeRequest != null) { args.RequestHostname = args.ProxyRequest.RequestUri.Host; args.RequestURL = args.ProxyRequest.RequestUri.OriginalString; args.RequestLength = contentLen; args.RequestHttpVersion = version; args.ClientPort = ((IPEndPoint)Client.Client.RemoteEndPoint).Port; args.ClientIpAddress = ((IPEndPoint)Client.Client.RemoteEndPoint).Address; args.RequestIsAlive = args.ProxyRequest.KeepAlive; BeforeRequest(null, args); } string tmpLine; if (args.CancelRequest) { if (args.RequestIsAlive) { requestLines.Clear(); while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) { requestLines.Add(tmpLine); } httpCmd = requestLines.Count > 0 ? requestLines[0] : null; return; } else return; } args.ProxyRequest.ConnectionGroupName = args.RequestHostname; args.ProxyRequest.AllowWriteStreamBuffering = true; //If request was modified by user if (args.RequestWasModified) { ASCIIEncoding encoding = new ASCIIEncoding(); byte[] requestBytes = encoding.GetBytes(args.RequestHtmlBody); args.ProxyRequest.ContentLength = requestBytes.Length; Stream newStream = args.ProxyRequest.GetRequestStream(); newStream.Write(requestBytes, 0, requestBytes.Length); args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args); } else { //If its a post/put request, then read the client html body and send it to server if (method.ToUpper() == "POST" || method.ToUpper() == "PUT") { args.ProxyRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), args); } else { //otherwise wait for response asynchronously args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args); //Now read the next request (if keep-Alive is enabled, otherwise exit thus thread) //If client is pipeling the request, this will be immediately hit before response for previous request was made if (args.ProxyRequest.KeepAlive) { requestLines = new List<string>(); requestLines.Clear(); while (!String.IsNullOrEmpty(tmpLine = args.ClientStreamReader.ReadLine())) { requestLines.Add(tmpLine); } httpCmd = requestLines.Count() > 0 ? requestLines[0] : null; HandleHttpSessionRequest(Client, httpCmd, args.ClientStream, args.tunnelHostName, requestLines, args.ClientStreamReader, args.securehost); } } } } catch (IOException) { return; } catch (UriFormatException) { return; } catch (WebException) { return; } finally { } }
//This is called when the request is PUT/POST to read the body private static void SendClientRequestBody(SessionEventArgs args) { // End the operation Stream postStream = args.ProxyRequest.GetRequestStream(); if (args.ProxyRequest.ContentLength > 0) { args.ProxyRequest.AllowWriteStreamBuffering = true; try { int totalbytesRead = 0; int bytesToRead; if (args.ProxyRequest.ContentLength < BUFFER_SIZE) { bytesToRead = (int)args.ProxyRequest.ContentLength; } else bytesToRead = BUFFER_SIZE; while (totalbytesRead < (int)args.ProxyRequest.ContentLength) { var buffer = args.ClientStreamReader.ReadBytes(bytesToRead); totalbytesRead += buffer.Length; int RemainingBytes = (int)args.ProxyRequest.ContentLength - totalbytesRead; if (RemainingBytes < bytesToRead) { bytesToRead = RemainingBytes; } postStream.Write(buffer, 0, buffer.Length); } postStream.Close(); } catch { if (postStream != null) postStream.Close(); throw; } } //Need to revist, find any potential bugs else if (args.ProxyRequest.SendChunked) { args.ProxyRequest.AllowWriteStreamBuffering = true; try { StringBuilder sb = new StringBuilder(); byte[] byteRead = new byte[1]; while (true) { args.ClientStream.Read(byteRead, 0, 1); sb.Append(Encoding.ASCII.GetString(byteRead)); if (sb.ToString().EndsWith(Environment.NewLine)) { var chunkSizeInHex = sb.ToString().Replace(Environment.NewLine, String.Empty); var chunckSize = int.Parse(chunkSizeInHex, System.Globalization.NumberStyles.HexNumber); if (chunckSize == 0) { for (int i = 0; i < Encoding.ASCII.GetByteCount(Environment.NewLine); i++) { args.ClientStream.ReadByte(); } break; } var totalbytesRead = 0; int bytesToRead; if (chunckSize < BUFFER_SIZE) { bytesToRead = chunckSize; } else bytesToRead = BUFFER_SIZE; while (totalbytesRead < chunckSize) { var buffer = args.ClientStreamReader.ReadBytes(bytesToRead); totalbytesRead += buffer.Length; int RemainingBytes = chunckSize - totalbytesRead; if (RemainingBytes < bytesToRead) { bytesToRead = RemainingBytes; } postStream.Write(buffer, 0, buffer.Length); } for (int i = 0; i < Encoding.ASCII.GetByteCount(Environment.NewLine); i++) { args.ClientStream.ReadByte(); } sb.Clear(); } } postStream.Close(); } catch { if (postStream != null) postStream.Close(); throw; } } }
//Test script injection //Insert script to read the Browser URL and send it back to proxy public void OnResponse(object sender, SessionEventArgs e) { }
//Test On Request, intecept requests //Read browser URL send back to proxy by the injection script in OnResponse event public void OnRequest(object sender, SessionEventArgs e) { Console.WriteLine(e.RequestURL); }