/// <summary> /// Dummy logic loop, for test purposes /// </summary> override public bool LogicLoop() { uint r = SocketBP.ReadBinary(); if (r == 0) { // Connection closed return(false); } string s = System.Text.ASCIIEncoding.ASCII.GetString( SocketBP.Buffer, 0, (int)r); if (bPrintEchoPrefix) { SocketBP.WriteBinary(System.Text.ASCIIEncoding. ASCII.GetBytes("Echo: ")); } SocketBP.WriteBinary(SocketBP.Buffer, r); if (s.StartsWith("x")) { return(false); } return(true); }
protected override void OnReceiveRequest() { if (InternetReports.BlockSites) { for (int i = 0; i < InternetReports.WebBlock.Count; i++) { if (RequestLine.URI.Contains(InternetReports.WebBlock[i])) { SocketBP.Send403(); State.NextStep = AbortRequest; } } } if (InternetReports.BlockSocialSites) { if (RequestLine.URI.Contains("facebook.com") || RequestLine.URI.Contains("twitter.com") || RequestLine.URI.Contains("instagram.com") || RequestLine.URI.Contains("myspace.com") || RequestLine.URI.Contains("plus.google.com")) { SocketBP.Send403(); State.NextStep = AbortRequest; } } if (!string.IsNullOrWhiteSpace(RequestHeaders.Referer)) { txt = RequestHeaders.Referer; } else { //myUri = new Uri(RequestLine.URI); //txt = myUri.Host; txt = RequestLine.URI; if (txt.Contains("localhost")) { txt = ""; } } if (!string.IsNullOrWhiteSpace(txt)) { //Debug.WriteLine("txt: "+txt+" Last: "+InternetReports.Last); if (!txt.Equals(InternetReports.Last) && !txt.Equals(InternetReports.Last2) && !txt.Equals(InternetReports.Last3) && !txt.Equals("localhost")) { InternetReports.save.WriteLine(DateTime.Now.Hour.ToString("00") + ":" + DateTime.Now.Minute.ToString("00") + " : " + txt); InternetReports.Last3 = InternetReports.Last2; InternetReports.Last2 = InternetReports.Last; InternetReports.Last = txt; InternetReports.save.Flush(); } } }
protected override void OnReceiveRequest(HttpRequestLine e) { #if DEBUG Console.ForegroundColor = ConsoleColor.DarkBlue; Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + " -> " + RequestLine + (RequestHeaders.Referer != null ? ", Referer: " + RequestHeaders.Referer : "") ); Console.ForegroundColor = ConsoleColor.Gray; #endif requestUri = RequestLine.Uri; // NOTE: used by ReceiveResponse if (blacklistHosts.Contains(requestUri?.Host)) { SocketBP.CloseSocket(); } var method = e.Method.ToUpper(); if (method != "CONNECT") { timer = new System.Threading.Timer(new System.Threading.TimerCallback(OnExpire), null, 300 * 1000, System.Threading.Timeout.Infinite); } if ((method == "POST" || method == "PUT" || method == "PATCH")) { if (skipHosts.Contains(e.Uri.Host)) { return; } // Typical requests endpoint: //http://summonerswar-gb.qpyou.cn/api/gateway_c2.php if (e.Uri.AbsoluteUri.Contains("summonerswar") && e.Uri.AbsoluteUri.Contains("/api/gateway")) { string bodyString = Encoding.ASCII.GetString(SocketBP.Buffer, 0, Array.IndexOf(SocketBP.Buffer, (byte)0)); bodyString = bodyString.Substring(bodyString.IndexOf("\r\n\r\n")); // TODO: FIXME: this needs to match first \r?\n\r?\n decRequest = decryptRequest(bodyString, e.Uri.AbsolutePath.Contains("_c2.php") ? 2 : 1); try { req = JsonConvert.DeserializeObject <JObject>(decRequest); if (!Directory.Exists("Json")) { Directory.CreateDirectory("Json"); } File.WriteAllText($"Json\\{req["command"]}" + #if DEBUG $"_{DateTime.Now.ToString("yyyyMMddHHmmssfff")}" + #endif ".req.json", JsonConvert.SerializeObject(req, Formatting.Indented)); Console.ForegroundColor = ConsoleColor.DarkGray; Console.WriteLine($">{req["command"]}"); Console.ForegroundColor = ConsoleColor.Gray; } catch { }; } } }
protected override void OnReceiveResponse() { if (ResponseStatusLine.StatusCode != HttpStatus.OK || !ResponseHeaders.Headers.ContainsKey("content-type")) { return; } if (RequestLine.Method != "POST" || !_requestUri.AbsoluteUri.Contains("api/gateway_c2")) { return; } var response = GetContent(); State.NextStep = null; string content; using (var sr = new StreamReader(GetResponseMessageStream(response))) { content = sr.ReadToEnd(); } SendResponseStatusAndHeaders(); SocketBP.TunnelDataTo(TunnelBP, response); if (SocketBP != null) { SocketBP.CloseSocket(); SocketBP = null; } if (SocketPS != null) { SocketPS.CloseSocket(); SocketPS = null; } State.bPersistConnectionBP = false; State.bPersistConnectionPS = false; var stringResponse = Decrypt.DecryptResponse(content); var json = JObject.Parse(stringResponse); MainWindow.Instance.HandleNewPacket(json); // Temp. saving all commands content to file using (var file = new StreamWriter($@"D:/SW-Commands/{json["command"].ToString()}.txt")) { file.WriteLine(json); file.Close(); } Debug.WriteLine($"Proxy Command: {json["command"].ToString()}"); Debug.WriteLine($"ts: {json["ts_val"].ToString()} / {Ut3()}"); }
protected override void OnReceiveRequest() { // Make your thesis more interesting by upgrading // your primary source of information int i = RequestLine.URI.IndexOf("wikipedia.org"); if (i > -1) { ChangeRequestURI("http://uncyclopedia.org/" + RequestLine.URI.Substring(i + 14)); return; } // Make yourself more productive if (RequestLine.URI.Contains("facebook.com")) { SocketBP.Send403(); State.NextStep = AbortRequest; } }
private void OnExpire(object state) { #if DEBUG Console.ForegroundColor = ConsoleColor.DarkBlue; Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + " -- " + this.requestUri.Host + " Expired"); Console.ForegroundColor = ConsoleColor.Gray; #endif if (SocketBP != null) { SocketBP.CloseSocket(); SocketBP = null; } if (SocketPS != null) { SocketPS.CloseSocket(); SocketPS = null; } State.bPersistConnectionBP = false; State.bPersistConnectionPS = false; State.NextStep = null; }
protected override void OnReceiveRequest() { //store complete request uri first, it will parsed and the host will be removed later FullRequestUri = RequestLine.URI; DomainName = GetDomain.GetDomainFromUrl(RequestLine.URI); DomainType = PornDB.GetDomainType(DomainName); _autoDomainStatus = PornDB.GetAutoDomainStatus(DomainName); log.Debug(GetDomain.GetDomainFromUrl(RequestLine.URI)); //DomainType == PornDatabase.DomainType.Black || if (DomainType != PornDatabase.DomainType.White && _autoDomainStatus == PornDatabase.ForbiddenItemStatus.Normal && Properties.Settings.Default.IsPornWebsiteProtectionTurnOn) { PornDB.InsertBlockedPage(FullRequestUri); //SocketBP.Send403(); //SocketBP.SendMasaHttpForbidden("I Love You!"); SocketBP.SendMasaHttpForbidden(Properties.Settings.Default.forbiddenRedirectUrl, "<h1>该网页包含不良信息,已被" + Properties.Resources.ProductionName + "屏蔽!</h1>"); //SocketBP.SendHttpError(); State.NextStep = AbortRequest; log.Info("Block request in tmp black list: " + RequestLine.URI); } }
protected override void OnReceiveResponse() { // Use the content-type field of the response headers to // Determine which HTTP content we want to modify. bool bModifyContent = false; if (ResponseHeaders.Headers.ContainsKey("content-type")) { bModifyContent = ResponseHeaders.Headers["content-type"]. Contains("text/html"); } // Rewriting may also depend on the user agent. #if false if (RequestHeaders.Headers.ContainsKey("user-agent")) { if (RequestHeaders.Headers["user-agent"].ToLower().Contains("msie")) { // ... } } #endif // Do not rewrite anything unless we got a 200 status code. if (ResponseStatusLine.StatusCode != 200) { bModifyContent = false; } if (!bModifyContent) { // Propagate the content without modifying it. return; } // Let's assume we need to retrieve the entire file before // we can do the rewriting. This is usually the case if the // content has been compressed by the remote server, or if we // want to build a DOM tree. byte[] response = GetContent(); // From now on, the default State.NextStep ( == SendResponse() // at this point) must not be called, since we already read // the response. State.NextStep = null; // Decompress the message stream, if necessary Stream stream = GetResponseMessageStream(response); byte[] content = ReadEverything(stream); Encoding fileEncoding = GetFileEncoding(content); if (fileEncoding == null) { // We could not guess the file encoding, so it's better not // to modify anything. SendResponseStatusAndHeaders(); SocketBP.TunnelDataTo(TunnelBP, response); return; } string text; using (stream = new MemoryStream(content)) using (var sr = new StreamReader(stream, fileEncoding)) text = sr.ReadToEnd(); // We are now in a position to rewrite stuff. text = ModifyHTML(text); // Tell the browser not to cache our modified version. ResponseHeaders.CacheControl = "no-cache, no-store, must-revalidate"; ResponseHeaders.Expires = "Fri, 01 Jan 1990 00:00:00 GMT"; ResponseHeaders.Pragma = "no-cache"; // Even if the response was originally transferred // by chunks, we are going to send it unchunked. // (We could send it chunked, though, by calling // TunnelChunkedDataTo, instead of TunnelDataTo.) ResponseHeaders.TransferEncoding = null; // Encode the modified content, and recompress it, as necessary. byte[] output = EncodeStringResponse(text, fileEncoding); ResponseHeaders.ContentLength = (uint)output.Length; // Finally, send the result. SendResponseStatusAndHeaders(); SocketBP.TunnelDataTo(TunnelBP, output); // We are done with the request. // Note that State.NextStep has been set to null earlier. }
protected override void OnReceiveResponse() { #if DEBUG Console.ForegroundColor = ConsoleColor.DarkBlue; Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + " <- " + ResponseStatusLine + ", " + requestUri.AbsoluteUri + (ResponseHeaders.ContentLength != null ? " Content-Length: " + ResponseHeaders.ContentLength.ToString() : "") ); Console.ForegroundColor = ConsoleColor.Gray; #endif if (ResponseStatusLine.StatusCode == HttpStatus.OK && ResponseHeaders.Headers.ContainsKey("content-type")) { if (skipHosts.Contains(requestUri.Host)) { return; } if (requestUri.AbsoluteUri.Contains("summonerswar") && requestUri.AbsoluteUri.Contains("/api/gateway")) { if (RequestLine.Method == "GET" || RequestLine.Method == "POST") { byte[] response = GetContent(); // From now on, the default State.NextStep ( == SendResponse() // at this point) must not be called, since we already read // the response. State.NextStep = null; // Decompress the message stream, if necessary Stream stream = GetResponseMessageStream(response); string body; using (var sr = new StreamReader(stream)) { body = sr.ReadToEnd(); } SendResponseStatusAndHeaders(); SocketBP.TunnelDataTo(TunnelBP, response); var decResponse = decryptResponse(body, requestUri.AbsolutePath.Contains("_c2.php") ? 2 : 1); try { var resp = JsonConvert.DeserializeObject <JObject>(decResponse); if (!Directory.Exists("Json")) { Directory.CreateDirectory("Json"); } File.WriteAllText($"Json\\{resp["command"]}" + #if DEBUG $"_{DateTime.Now.ToString("yyyyMMddHHmmssfff")}" + #endif ".resp.json", JsonConvert.SerializeObject(resp, Formatting.Indented)); Console.ForegroundColor = ConsoleColor.DarkGray; Console.WriteLine($"<{resp["command"]}"); Console.ForegroundColor = ConsoleColor.Gray; // only mangle my wizards who want it, don't crash others. if (resp["command"].ToString() == "GetNoticeChat" && whitelistDebugWizards.Contains((ulong)req["wizard_id"])) { var version = Assembly.GetExecutingAssembly().GetName().Version; var jobj = new JObject(); // Add the proxy version number to chat notices to remind people. jobj["message"] = "Proxy version: " + version; ///(json["notice_list"] as JArray).Add(jobj); resp["tzone"] = resp["tzone"].ToString().Replace("/", @"\/"); var ver = requestUri.AbsolutePath.Contains("_c2.php") ? 2 : 1; var inMsg = Convert.FromBase64String(body); var outMsg = decryptMessage(inMsg, ver); var decData = zlibDecompressData(outMsg); var fix = JsonConvert.SerializeObject(resp); fix = fix.Replace(@"\\", "\\"); var bytes = zlibCompressData(fix); var str = encryptMessage(bytes, ver); var send = Convert.ToBase64String(str); Console.WriteLine("str:" + (fix == decData)); Console.WriteLine("b64:" + (inMsg.SequenceEqual(str))); Console.WriteLine("cry:" + (outMsg.SequenceEqual(bytes))); Console.WriteLine("bytes:" + (body.SequenceEqual(send))); //encryptResponse(fix, ver); //if (body.SequenceEqual(send)) // await e.SetResponseBodyString(send); } } catch { }; if (decRequest != null) { System.Threading.Thread thr = new System.Threading.Thread(() => { SWEventArgs args = null; try { args = new SWEventArgs(decRequest, decResponse); Plugins?.Invoke(this, args); } catch (Exception ex) { Console.WriteLine($"Failed triggering plugin {ex.Source} with {ex.GetType().Name}: {ex.Message}"); #if DEBUG Console.WriteLine(ex.StackTrace); #endif } }); thr.Start(); } } } else if (RequestHeaders.Headers.ContainsKey("accept-encoding")) { if (!ResponseHeaders.Headers.ContainsKey("content-encoding") && !ResponseHeaders.Headers.ContainsKey("transfer-encoding")) { // read response data // compress // add content-encoding header // add Vary: Accept-Encoding // (re)set content-length header } } } }
protected void ProcessHtml() { log.Info("Process HTML: " + RequestLine.URI); // Let's assume we need to retrieve the entire file before // we can do the rewriting. This is usually the case if the // content has been compressed by the remote server, or if we // want to build a DOM tree. byte[] response = GetContent(); // From now on, the default State.NextStep ( == SendResponse() // at this point) must not be called, since we already read // the response. State.NextStep = null; // Decompress the message stream, if necessary //byte[] content = ReadEverything(stream); Encoding fileEncoding = GetFileEncoding(); bool bNoFileEncoding = false; if (fileEncoding == null) { bNoFileEncoding = true; fileEncoding = Encoding.UTF8; // We could not guess the file encoding, so it's better not // to modify anything. //ResponseHeaders.TransferEncoding = null; //ResponseHeaders.ContentLength = (uint)response.Length; //SendResponseStatusAndHeaders(); //SocketBP.TunnelDataTo(TunnelBP, response); //return; } //load html document Stream stream = GetResponseMessageStream(response); HtmlDocument htmlDoc = new HtmlDocument(); htmlDoc.Load(stream, fileEncoding); // We are now in a position to get image src // if the white list does not contain the domain name if (DomainType != PornDatabase.DomainType.White) { HtmlNodeCollection nc = htmlDoc.DocumentNode.SelectNodes("//img[@src]"); if (nc != null) { log.Info("Images of page url: " + FullRequestUri); lock (SyncObject) { HashSet <String> currentSet = GetPornSet(FullRequestUri); foreach (HtmlNode imgsrc in nc) { HtmlAttribute src = imgsrc.Attributes["src"]; String asrc = ToAbsoluteUrl(src.Value); currentSet.Add(asrc.ToLower()); log.Info("items: " + asrc.ToLower()); } } } } //add p to body if (!bNoFileEncoding) { //var head = htmlDoc.DocumentNode.SelectSingleNode("//head"); //var body = htmlDoc.DocumentNode.SelectSingleNode("//body"); //if (head != null && body != null) //{ // HtmlNode pcss = htmlDoc.CreateElement("style"); // pcss.SetAttributeValue("type", "text/css"); // pcss.InnerHtml = HtmlDocument.HtmlEncode("#masatek-tag{color:green; background-color: gray; padding:5px; text-align:center; font-size: 150%;}"); // head.PrependChild(pcss); // HtmlNode pMasaTag = htmlDoc.CreateElement("p"); // pMasaTag.SetAttributeValue("id", "masatek-tag"); // pMasaTag.InnerHtml = HtmlDocument.HtmlEncode("Powered by Masatek"); // body.PrependChild(pMasaTag); //} } // Even if the response was originally transferred // by chunks, we are going to send it unchunked. // (We could send it chunked, though, by calling // TunnelChunkedDataTo, instead of TunnelDataTo.) ResponseHeaders.TransferEncoding = null; // Encode the modified content, and recompress it, as necessary. //String text = htmlDoc.Save() //htmlDoc.Save(HttpUtility.UrlEncode(RequestLine.URI)); if (!bNoFileEncoding) { //MemoryStream mstr = new MemoryStream(); //htmlDoc.Save(mstr, fileEncoding); //response = CompressResponse(mstr.GetBuffer()); } ResponseHeaders.ContentLength = (uint)response.Length; // Finally, send the result. SendResponseStatusAndHeaders(); SocketBP.TunnelDataTo(TunnelBP, response); // We are done with the request. // Note that State.NextStep has been set to null earlier. }
protected void ProcessImage() { log.Info("Process Image: " + RequestLine.URI); byte[] response = GetContent(); // From now on, the default State.NextStep ( == SendResponse() // at this point) must not be called, since we already read // the response. State.NextStep = null; // Decompress the message stream, if necessary using (Stream stream = GetResponseMessageStream(response)) { using (Bitmap bm = new Bitmap(stream)) { PornClassifier.ImageType imgType = PornClassifier.Instance.Classify(bm); IProgress <PornDatabase.PornItemType> ip = MainForm.Instance.TargetProcessedProgress as IProgress <PornDatabase.PornItemType>; bool isImageBad = false; if (imgType == PornClassifier.ImageType.P**n) { isImageBad = true; //添加到不良网页中,以进行不良网站检查,只针对色情图片进行处理 //只在启用了色情网站侦测时才处理,但实际上由于未启用色情网站侦测时 //html不处理,这里其实即使处理也无法hit if (Properties.Settings.Default.IsPornWebsiteProtectionTurnOn) { AddPorn(); } } else if (imgType == PornClassifier.ImageType.Disguise && Properties.Settings.Default.IsStrongNetworkImageFilter) { isImageBad = true; } else { ip.Report(PornDatabase.PornItemType.Undefined); } //if (p != null) //只在图片过滤功能开启时才将色情图片加入数据库,并替换图片 Bitmap nbm = null; if (isImageBad && Properties.Settings.Default.IsNetworkImageTurnOn) { //只有色情图片才加入数据库,防止将性感图片加入以后带来不好的感觉 if (imgType == PornClassifier.ImageType.P**n) { //先保存图片,在插入数据库,否则第一项会导致没有图片可以显示 bm.Save(Program.AppLocalDir + Properties.Settings.Default.imagesDir + "\\" + HttpUtility.UrlEncode(FullRequestUri)); PornDB.InsertPornPic(FullRequestUri, PornClassifier.ImageType.P**n); log.Debug("After PornPicInserted"); ip.Report(PornDatabase.PornItemType.NetworkImage); } //此处如果图像为带索引格式,则会引发异常,无法创建graphics对象 //这使得网页上一个图片总是无法加载 nbm = new Bitmap(bm.Width, bm.Height); //using (Graphics g = Graphics.FromImage(bm)) using (Graphics g = Graphics.FromImage(nbm)) { //SolidBrush solidBrush = new SolidBrush(Color.Red); SolidBrush solidBrush = new SolidBrush(Color.Azure); g.FillRectangle(solidBrush, 0, 0, bm.Width, bm.Height); SolidBrush stringBrush = new SolidBrush(Color.CadetBlue); g.DrawString(Properties.Resources.ProductionName, new Font("微软雅黑", bm.Width / 10, GraphicsUnit.Pixel), stringBrush, new Point(0, 0)); g.Flush(); } } // Even if the response was originally transferred // by chunks, we are going to send it unchunked. // (We could send it chunked, though, by calling // TunnelChunkedDataTo, instead of TunnelDataTo.) ResponseHeaders.TransferEncoding = null; // Encode the modified content, and recompress it, as necessary. //String text = htmlDoc.Save() //htmlDoc.Save(HttpUtility.UrlEncode(RequestLine.URI)); MemoryStream mstr = new MemoryStream(); if (nbm != null) { nbm.Save(mstr, bm.RawFormat); //这里使用toArray就可以得到和实际内容长度相同的数据 byte[] output = CompressResponse(mstr.ToArray()); //这里必须使用mstr.Length,而不能使用output.Length //因为前者表示真实长度,后者表示总缓存长度,比实际长度要长 //如果前面是使用ToArray,而不是GetBuffer则没问题 ResponseHeaders.ContentLength = (uint)output.Length; SendResponseStatusAndHeaders(); SocketBP.TunnelDataTo(TunnelBP, output); nbm.Dispose(); } else { //用于测试,即使图片不替换,也重新保存 //bm.Save(mstr, bm.RawFormat); //byte[] output = CompressResponse(mstr.ToArray()); //ResponseHeaders.ContentLength = (uint)output.Length; SendResponseStatusAndHeaders(); SocketBP.TunnelDataTo(TunnelBP, response); } //debug code //bm.Save(mstr, bm.RawFormat); //这里使用toArray就可以得到和实际内容长度相同的数据 //byte[] output = CompressResponse(mstr.ToArray()); //byte[] output = CompressResponse(mstr.GetBuffer()); //这里必须使用mstr.Length,而不能使用output.Length //因为前者表示真实长度,后者表示总缓存长度,比实际长度要长 //如果前面是使用ToArray,而不是GetBuffer则没问题 //ResponseHeaders.ContentLength = (uint)output.Length; //SendResponseStatusAndHeaders(); //SocketBP.TunnelDataTo(TunnelBP, output); //byte[] output = CompressResponse(mstr.GetBuffer()); //ResponseHeaders.ContentLength = (uint)output.Length; // Finally, send the result. //SendResponseStatusAndHeaders(); //SocketBP.TunnelDataTo(TunnelBP, output); // We are done with the request. // Note that State.NextStep has been set to null earlier. } } }