private void ReplaceResources(object sender, ResponseInterceptedEventArgs e) { string absoluteUri = e.Response.ResponseUri.AbsoluteUri; if (ResourceReplacements.ContainsKey(absoluteUri)) { var httpResponse = (HttpWebResponse)e.Response; string replacementUrl = ResourceReplacements[absoluteUri]; if (httpResponse.StatusCode == HttpStatusCode.TemporaryRedirect) { ResourceReplacements.Remove(absoluteUri); absoluteUri = httpResponse.Headers[HttpResponseHeader.Location]; ResourceReplacements[absoluteUri] = replacementUrl; return; } if (replacementUrl.StartsWith("http")) { using (var webClient = new WebClient()) e.Payload = webClient.DownloadData(replacementUrl); } else { e.Payload = File.ReadAllBytes(replacementUrl); } ResourceReplacements.Remove(absoluteUri); if (ResourceReplacements.Count < 1) { Halt(); SetStatus(TanjiState.StandingBy); } } }
private async Task InterceptClientPageAsync(object sender, ResponseInterceptedEventArgs e) { if (e.Content == null) { return; } string contentType = e.ContentType.ToLower(); if (!contentType.Contains("text") && !contentType.Contains("javascript")) { return; } string body = await e.Content.ReadAsStringAsync().ConfigureAwait(false); if (!body.Contains("info.host") && !body.Contains("info.port")) { return; } Eavesdropper.ResponseInterceptedAsync -= InterceptClientPageAsync; Master.GameData.Source = body; body = body.Replace(".swf", $".swf?{_randomQuery = Guid.NewGuid()}"); e.Content = new StringContent(body); _ui.SetStatusMessage(Constants.INJECTING_CLIENT); Eavesdropper.RequestInterceptedAsync += InjectGameClientAsync; }
private void ReplaceClient(object sender, ResponseInterceptedEventArgs e) { if (e.Response.ContentType != "application/x-shockwave-flash" && !File.Exists(e.Response.ResponseUri.LocalPath)) { return; } Eavesdropper.ResponseIntercepted -= ReplaceClient; ushort infoPort = ushort.Parse(UI.GameData.InfoPort.Split(',')[0]); if (UI.Game == null) { VerifyGameClientAsync(e.Payload).Wait(); SetState(TanjiState.ModifyingClient); UI.Game.BypassOriginCheck(); UI.Game.BypassRemoteHostCheck(); UI.Game.ReplaceRSAKeys(HandshakeManager.FAKE_EXPONENT, HandshakeManager.FAKE_MODULUS); UI.ModulesPg.ModifyGame(UI.Game); SetState(TanjiState.AssemblingClient); UI.Game.Assemble(); SetState(TanjiState.CompressingClient); e.Payload = UI.Game.Compress(); string clientPath = Path.Combine( _modifiedClientsDir.FullName, UI.Game.GetClientRevision()); Directory.CreateDirectory(clientPath); File.WriteAllBytes(clientPath + "\\Habbo.swf", e.Payload); } else { if (UI.ModulesPg.ModifyGame(UI.Game)) { UI.Game.Assemble(); } e.Payload = UI.Game.ToByteArray(); } if (ResourceReplacements.Count > 0) { Eavesdropper.ResponseIntercepted += ReplaceResources; } else { Halt(); } SetState(TanjiState.InterceptingConnection); UI.Connection.ConnectAsync(UI.GameData.InfoHost, infoPort).ContinueWith(ConnectTaskCompleted); }
private void ReplaceClient(object sender, ResponseInterceptedEventArgs e) { if (e.Response.ContentType != "application/x-shockwave-flash" && !File.Exists(e.Response.ResponseUri.LocalPath)) { return; } Eavesdropper.ResponseIntercepted -= ReplaceClient; ushort infoPort = ushort.Parse(Master.GameData.InfoPort.Split(',')[0]); if (Master.Game == null) { VerifyGameClientAsync(e.Payload).Wait(); State = MODIFYING_CLIENT; Master.Game.BypassOriginCheck(); Master.Game.BypassRemoteHostCheck(); Master.Game.ReplaceRSAKeys(FAKE_EXPONENT, FAKE_MODULUS); // TODO: Master.ModulesPg.ModifyGame(Master.Game); State = ASSEMBLING_CLIENT; Master.Game.Assemble(); State = COMPRESSING_CLIENT; e.Payload = Master.Game.Compress(); string clientPath = Path.Combine( _modifiedClientsDir.FullName, Master.Game.GetClientRevision()); Directory.CreateDirectory(clientPath); File.WriteAllBytes(clientPath + "\\Habbo.swf", e.Payload); } else { // TODO: if (Master.ModulesPg.ModifyGame(Master.Game)) // Master.Game.Assemble(); e.Payload = Master.Game.ToByteArray(); } if (_replacedVars.Count > 0) { Eavesdropper.ResponseIntercepted += ReplaceResources; } else { Halt(); } State = INTERCEPTING_CONNECTING; Master.Connection.ConnectAsync(Master.GameData.InfoHost, infoPort).ContinueWith(ConnectTaskCompleted); }
private void ReplaceClient(object sender, ResponseInterceptedEventArgs e) { if (e.Response.ContentType != "application/x-shockwave-flash" && !File.Exists(e.Response.ResponseUri.LocalPath)) { return; } Eavesdropper.ResponseIntercepted -= ReplaceClient; ushort[] ports = GameData.Port.Split(',') .Select(s => ushort.Parse(s)).ToArray(); if (Game == null) { VerifyGameClientAsync(e.Payload).Wait(); SetStatus(TanjiState.ModifyingClient); Game.BypassRemoteHostCheck(); Game.RemoveLocalUseRestrictions(); Game.DisableExpirationDateCheck(); Game.ReplaceRSA(HandshakeManager.FAKE_EXPONENT, HandshakeManager.FAKE_MODULUS); SetStatus(TanjiState.ReconstructingClient); Game.Reconstruct(); File.WriteAllBytes( $"{_modifiedClientsDir.FullName}\\{GameData.MovieName}.swf", Game.ToByteArray()); } e.Payload = Game.ToByteArray(); if (ResourceReplacements.Count > 0) { Eavesdropper.ResponseIntercepted += ReplaceResources; } else { Halt(); } SetStatus(TanjiState.InterceptingConnection); UI.Connection.ConnectAsync(GameData.Host, ports) .ContinueWith(ConnectTaskCompleted); }
private void InterceptClientPage(object sender, ResponseInterceptedEventArgs e) { if (!e.Response.ContentType.Contains("text/html")) { return; } string body = Encoding.UTF8.GetString(e.Payload); if (!body.Contains("info.host") && !body.Contains("info.port")) { return; } Eavesdropper.ResponseIntercepted -= InterceptClientPage; App.Master.GameData.Source = body; if (IsAutomaticServerExtraction) { string[] ports = App.Master.GameData.InfoPort.Split(','); if (ports.Length == 0 || !ushort.TryParse(ports[0], out ushort port) || !HotelEndPoint.TryParse(App.Master.GameData.InfoHost, port, out HotelEndPoint endpoint)) { Cancel(null); return; } HotelServer = endpoint; } if (App.Master.GameData.Hotel != HHotel.Unknown) { body = body.Replace(App.Master.GameData.InfoHost, "127.0.0.1"); } body = body.Replace(".swf", $".swf?Tanji-{DateTime.Now.Ticks}"); Status = SYNCHRONIZING_GAME_DATA; App.Master.Synchronize(App.Master.GameData); e.Payload = Encoding.UTF8.GetBytes(body); Status = INJECTING_CLIENT; Eavesdropper.RequestIntercepted += InjectGameClient; }
private void ExtractGameData(object sender, ResponseInterceptedEventArgs e) { if (e.Response.ContentType != "text/html") { return; } if (GameData != null) { return; } string responseBody = Encoding.UTF8.GetString(e.Payload); if (responseBody.Contains("swfobject.embedSWF") && responseBody.Contains("connection.info.host")) { Eavesdropper.ResponseIntercepted -= ExtractGameData; try { GameData = new HGameData(responseBody); Hotel = SKore.ToHotel(GameData.InfoHost); var clientUri = new Uri(GameData["flash.client.url"]); string clientPath = clientUri.Segments[2].TrimEnd('/'); Task <bool> gameClientVerifierTask = VerifyGameClientAsync($"{_modifiedClientsDir.FullName}\\{clientPath}\\Habbo.swf"); if (e.Response.ResponseUri.Segments.Length > 2) { // TODO: Set uniqueId somewhere. //GameData.UniqueId = // e.Response.ResponseUri.Segments[2].TrimEnd('/'); } string embeddedSwf = responseBody.GetChild("embedSWF(", ','); string nonCachedSwf = $"{embeddedSwf} + \"?{DateTime.Now.Ticks}-Tanji\""; responseBody = responseBody.Replace( "embedSWF(" + embeddedSwf, "embedSWF(" + nonCachedSwf); e.Payload = Encoding.UTF8.GetBytes(responseBody); var resourceKeys = ResourceReplacements.Keys.ToArray(); foreach (string resourceKey in resourceKeys) { string realValue = GameData[resourceKey] .Replace("\\/", "/"); string fakeValue = ResourceReplacements[resourceKey]; ResourceReplacements.Remove(resourceKey); ResourceReplacements[realValue] = fakeValue; } if (gameClientVerifierTask.Result) { SetStatus(TanjiState.InjectingClient); Eavesdropper.RequestIntercepted += InjectClient; } else { SetStatus(TanjiState.InterceptingClient); Eavesdropper.ResponseIntercepted += ReplaceClient; } } catch (Exception ex) { WriteLog(ex); } finally { if (GameData == null) { Eavesdropper.ResponseIntercepted += ExtractGameData; } } } }
private static Task Eavesdropper_ResponseInterceptedAsync(object sender, ResponseInterceptedEventArgs e) { return(Task.CompletedTask); }
private void ExtractGameData(object sender, ResponseInterceptedEventArgs e) { if (e.Response.ContentType != "text/html") { return; } if (State != TanjiState.ExtractingGameData) { return; } string responseBody = Encoding.UTF8.GetString(e.Payload); if (responseBody.Contains("swfobject.embedSWF") && responseBody.Contains("connection.info.host")) { byte[] replacementData = e.Payload; Eavesdropper.ResponseIntercepted -= ExtractGameData; try { UI.GameData.Update(responseBody); UI.Hotel = SKore.ToHotel(UI.GameData.InfoHost); UI.ModulesPg.ModifyGameData(UI.GameData); responseBody = UI.GameData.Source; var clientUri = new Uri(UI.GameData["flash.client.url"]); string clientPath = clientUri.Segments[2].TrimEnd('/'); Task <bool> verifyGameClientTask = null; if (!string.IsNullOrWhiteSpace(CustomClientPath)) { verifyGameClientTask = VerifyGameClientAsync(CustomClientPath); } if (verifyGameClientTask == null || !verifyGameClientTask.Result) { verifyGameClientTask = VerifyGameClientAsync($"{_modifiedClientsDir.FullName}\\{clientPath}\\Habbo.swf"); } string embeddedSwf = responseBody.GetChild("embedSWF(", ','); string nonCachedSwf = $"{embeddedSwf} + \"?{DateTime.Now.Ticks}-Tanji\""; responseBody = responseBody.Replace( "embedSWF(" + embeddedSwf, "embedSWF(" + nonCachedSwf); responseBody = responseBody.Replace(UI.GameData.InfoHost, "127.0.0.1"); replacementData = Encoding.UTF8.GetBytes(responseBody); string[] resourceKeys = ResourceReplacements.Keys.ToArray(); foreach (string resourceKey in resourceKeys) { string realValue = UI.GameData[resourceKey] .Replace("\\/", "/"); string fakeValue = ResourceReplacements[resourceKey]; ResourceReplacements.Remove(resourceKey); ResourceReplacements[realValue] = fakeValue; } if (verifyGameClientTask.Result) { SetState(TanjiState.InjectingClient); Eavesdropper.RequestIntercepted += InjectClient; } else { SetState(TanjiState.InterceptingClient); Eavesdropper.ResponseIntercepted += ReplaceClient; } } catch (Exception ex) { MessageBox.Show("Intercepted game data is not recognized as coming from a valid Habbo Hotel site.", "Tanji ~ Alert!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); WriteLog(ex); } finally { if (State == TanjiState.ExtractingGameData) { Eavesdropper.ResponseIntercepted += ExtractGameData; } else { e.Payload = replacementData; } } } }
private async Task InterceptGameClientAsync(object sender, ResponseInterceptedEventArgs e) { if (e.ContentType != "application/x-shockwave-flash") { return; } if (!e.Uri.Query.StartsWith("?" + _randomQuery)) { return; } Eavesdropper.ResponseInterceptedAsync -= InterceptGameClientAsync; string clientPath = Path.Combine(Master.DataDirectory.FullName, $@"Modified Clients\{e.Uri.Host}\{e.Uri.LocalPath}");; string clientDirectory = Path.GetDirectoryName(clientPath); Directory.CreateDirectory(clientDirectory); _ui.SetStatusMessage(Constants.DISASSEMBLING_CLIENT); using var game = new HGame(await e.Content.ReadAsStreamAsync().ConfigureAwait(false)) { Location = clientPath }; game.Disassemble(); _ui.SetStatusMessage(Constants.GENERATING_MESSAGE_HASHES); game.GenerateMessageHashes(Path.Combine(Master.ProgramDirectory.FullName, "Hashes.ini")); //We don't need this stuff in HabboGallery foreach (HMessage message in game.Out.Concat(game.In)) { message.Class = null; message.Parser = null; message.Structure = null; message.References.Clear(); } Master.In = game.In; Master.Out = game.Out; _ui.SetStatusMessage(Constants.MODIFYING_CLIENT); game.DisableHostChecks(); game.InjectKeyShouter(4001); game.InjectEndPointShouter(4000); game.InjectEndPoint("127.0.0.1", Connection.ListenPort); CompressionKind compression = CompressionKind.ZLIB; #if DEBUG compression = CompressionKind.None; #endif _ui.SetStatusMessage(Constants.ASSEMBLING_CLIENT); byte[] payload = game.ToArray(compression); e.Headers[HttpResponseHeader.ContentLength] = payload.Length.ToString(); e.Content = new ByteArrayContent(payload); using (FileStream clientStream = File.Open(clientPath, FileMode.Create, FileAccess.Write)) { clientStream.Write(payload); } TerminateProxy(); Task interceptConnectionTask = InterceptConnectionAsync(); }
private Task ResponseInterceptedAsync(object sender, ResponseInterceptedEventArgs e) { Console.WriteLine($"Intercepted Response: " + e.Uri); return(null); }
private void InterceptGameClient(object sender, ResponseInterceptedEventArgs e) { if (!e.Response.ResponseUri.Query.StartsWith("?Tanji-")) { return; } if (e.Response.ContentType != "application/x-shockwave-flash") { return; } Eavesdropper.ResponseIntercepted -= InterceptGameClient; Uri remoteUrl = e.Response.ResponseUri; string clientPath = Path.GetFullPath($"Modified Clients/{remoteUrl.Host}/{remoteUrl.LocalPath}"); string clientDirectory = Path.GetDirectoryName(clientPath); Directory.CreateDirectory(clientDirectory); Status = DISASSEMBLING_CLIENT; App.Master.Game = new HGame(e.Payload); App.Master.Game.Location = clientPath; App.Master.Game.Disassemble(); if (App.Master.Game.IsPostShuffle) { Status = GENERATING_MESSAGE_HASHES; App.Master.Game.GenerateMessageHashes(); Status = MODIFYING_CLIENT; App.Master.Game.DisableHostChecks(); App.Master.Game.InjectKeyShouter(4001); } if (App.Master.GameData.Hotel == HHotel.Unknown) { if (IsAutomaticServerExtraction) { Tuple <string, int?> endPoint = App.Master.Game.ExtractEndPoint(); if (!string.IsNullOrWhiteSpace(endPoint.Item1) || endPoint.Item2 != null) { string host = (!string.IsNullOrWhiteSpace(endPoint.Item1) ? endPoint.Item1 : HotelServer.Host); HotelServer = HotelEndPoint.Parse(host, endPoint.Item2 ?? HotelServer.Port); } } Status = MODIFYING_CLIENT; App.Master.Game.InjectEndPoint("127.0.0.1", HotelServer.Port); } Status = SYNCHRONIZING_GAME; App.Master.Synchronize(App.Master.Game); CompressionKind compression = CompressionKind.ZLIB; #if DEBUG compression = CompressionKind.None; #endif Status = ASSEMBLING_CLIENT; e.Payload = App.Master.Game.ToArray(compression); using (var clientStream = File.Open(clientPath, FileMode.Create, FileAccess.Write)) { clientStream.Write(e.Payload, 0, e.Payload.Length); } TerminateProxy(); InterceptConnection(); }