Files
BadBuilder/BadBuilder/Program.cs

319 lines
15 KiB
C#

global using DownloadItem = (string name, string url);
global using ArchiveItem = (string name, string path);
global using HomebrewApp = (string name, string folder, string entryPoint);
using System.Linq;
using Spectre.Console;
using BadBuilder.Models;
using BadBuilder.Helpers;
using BadBuilder.Utilities;
using static BadBuilder.Utilities.Constants;
namespace BadBuilder
{
internal partial class Program
{
static readonly Style OrangeStyle = new(new Color(255, 114, 0));
static readonly Style LightOrangeStyle = new(new Color(255, 172, 77));
static readonly Style PeachStyle = new(new Color(255, 216, 153));
static readonly Style GreenStyle = new(new Color(118, 185, 0));
static readonly Style GrayStyle = new(new Color(132, 133, 137));
static string XexToolPath = string.Empty;
static string TargetDriveLetter = string.Empty;
static ActionQueue actionQueue = new();
static DiskInfo targetDisk = new("Z:\\", "Fixed", 0, "", 0, int.MaxValue); // Default values just incase.
static void Main(string[] args)
{
ShowWelcomeMessage();
while (true)
{
Console.WriteLine();
string action = PromptForAction();
if (action == "Exit") Environment.Exit(0);
List<DiskInfo> disks = DiskHelper.GetDisks();
string selectedDisk = PromptDiskSelection(disks);
TargetDriveLetter = selectedDisk[..3];
int diskIndex = disks.FindIndex(disk => $"{disk.DriveLetter} ({disk.SizeFormatted}) - {disk.Type}" == selectedDisk);
targetDisk = disks[diskIndex];
bool confirmation = PromptFormatConfirmation(selectedDisk);
if (confirmation)
{
if (!FormatDisk(targetDisk)) continue;
break;
}
}
List<ArchiveItem> downloadedFiles = DownloadRequiredFiles().Result;
ExtractFiles(downloadedFiles).Wait();
ClearConsole();
string selectedDefaultApp = "XeUnshackle";
AnsiConsole.MarkupLine("[#76B900]{0}[/] Default payload set to [bold]XeUnshackle[/].", Markup.Escape("[*]"));
AnsiConsole.MarkupLine("[#76B900]{0}[/] Copying requried files and folders.", Markup.Escape("[*]"));
foreach (var folder in Directory.GetDirectories($@"{EXTRACTED_DIR}"))
{
switch (folder.Split("\\").Last())
{
case "ABadAvatar":
string avatarPayloadPath = Path.Combine(folder, "BadUpdatePayload");
if (Directory.Exists(avatarPayloadPath))
{
EnqueueMirrorDirectory(
avatarPayloadPath,
Path.Combine(TargetDriveLetter, "BadUpdatePayload"),
5
);
}
string avatarContentPath = Path.Combine(folder, "Content");
if (Directory.Exists(avatarContentPath))
{
EnqueueMirrorDirectory(
avatarContentPath,
Path.Combine(TargetDriveLetter, "Content"),
5
);
}
break;
case "Aurora Dashboard":
string auroraDestination = Path.Combine(TargetDriveLetter, "Apps", "Aurora");
Directory.CreateDirectory(auroraDestination);
bool auroraRootHasXex = Directory.GetFiles(folder, "*.xex", SearchOption.TopDirectoryOnly).Any();
if (auroraRootHasXex)
{
EnqueueMirrorDirectory(
folder,
auroraDestination,
4
);
break;
}
string[] auroraSubDirs = Directory.GetDirectories(folder);
string[] auroraRootFiles = Directory.GetFiles(folder);
string? primaryAuroraDir = auroraSubDirs.FirstOrDefault(dir =>
Directory.GetFiles(dir, "*.xex", SearchOption.TopDirectoryOnly).Any());
if (primaryAuroraDir == null)
{
EnqueueMirrorDirectory(
folder,
auroraDestination,
4
);
break;
}
EnqueueMirrorDirectory(
primaryAuroraDir,
auroraDestination,
4
);
foreach (string subDir in auroraSubDirs.Where(dir => dir != primaryAuroraDir))
{
EnqueueMirrorDirectory(
subDir,
Path.Combine(auroraDestination, Path.GetFileName(subDir)),
4
);
}
foreach (string file in auroraRootFiles)
{
EnqueueFileCopy(
file,
Path.Combine(auroraDestination, Path.GetFileName(file)),
4
);
}
break;
case "XeXmenu":
EnqueueMirrorDirectory(
Path.Combine(folder, $"{ContentFolder}C0DE9999"),
Path.Combine(TargetDriveLetter, $"{ContentFolder}C0DE9999"),
7
);
break;
case "XeUnshackle":
string readmePath = Path.Combine(folder, "README - IMPORTANT.txt");
if (File.Exists(readmePath))
{
File.Delete(readmePath);
}
foreach (string subDirectory in Directory.GetDirectories(folder))
{
EnqueueMirrorDirectory(
subDirectory,
Path.Combine(TargetDriveLetter, Path.GetFileName(subDirectory)),
9
);
}
foreach (string file in Directory.GetFiles(folder))
{
EnqueueFileCopy(
file,
Path.Combine(TargetDriveLetter, Path.GetFileName(file)),
9
);
}
break;
case "BadUpdate":
actionQueue.EnqueueAction(async () =>
{
using (StreamWriter writer = new(Path.Combine(TargetDriveLetter, "name.txt")))
writer.WriteLine("USB Storage Device");
using (StreamWriter writer = new(Path.Combine(TargetDriveLetter, "info.txt")))
writer.WriteLine($"This drive was created with BadBuilder by Pdawg.\nFind more info here: https://github.com/Pdawg-bytes/BadBuilder\nConfiguration: \n- BadUpdate target binary: {selectedDefaultApp}");
Directory.CreateDirectory(Path.Combine(TargetDriveLetter, "Apps"));
await FileSystemHelper.MirrorDirectoryAsync(Path.Combine(folder, "Rock Band Blitz"), TargetDriveLetter);
}, 10);
break;
case "BadUpdate Tools":
XexToolPath = Path.Combine(folder, "XePatcher", "XexTool.exe");
break;
case "Rock Band Blitz":
EnqueueMirrorDirectory(
Path.Combine(folder, $"{ContentFolder}5841122D\\000D0000"),
Path.Combine(TargetDriveLetter, $"{ContentFolder}5841122D\\000D0000"),
8
);
break;
case "Simple 360 NAND Flasher":
actionQueue.EnqueueAction(async () =>
{
await PatchHelper.PatchXexAsync(Path.Combine(folder, "Simple 360 NAND Flasher", "Default.xex"), XexToolPath);
await FileSystemHelper.MirrorDirectoryAsync(Path.Combine(folder, "Simple 360 NAND Flasher"), Path.Combine(TargetDriveLetter, "Apps", "Simple 360 NAND Flasher"));
}, 6);
break;
default: throw new Exception($"[-] Unexpected directory in working folder: {folder}");
}
}
actionQueue.ExecuteActionsAsync().Wait();
string launchIniPath = Path.Combine(TargetDriveLetter, "launch.ini");
if (File.Exists(launchIniPath))
{
List<string> launchIniLines = File.ReadAllLines(launchIniPath).ToList();
for (int i = 0; i < launchIniLines.Count; i++)
{
if (launchIniLines[i].TrimStart().StartsWith("Default =", StringComparison.OrdinalIgnoreCase))
{
launchIniLines[i] = @"Default = Usb:\Apps\Aurora\Aurora.xex";
break;
}
}
const string commentText = "; Hallo von NiklasCFW :D";
int autoContIndex = launchIniLines.FindIndex(line =>
line.Trim().Equals("autocont = false", StringComparison.OrdinalIgnoreCase));
if (autoContIndex >= 0)
{
bool commentAlreadyPresent = autoContIndex > 0 &&
launchIniLines[autoContIndex - 1].Trim().Equals(commentText, StringComparison.OrdinalIgnoreCase);
if (!commentAlreadyPresent)
{
launchIniLines.Insert(autoContIndex, commentText);
}
}
File.WriteAllLines(launchIniPath, launchIniLines);
}
File.AppendAllText(Path.Combine(TargetDriveLetter, "info.txt"), $"- Disk formatted using {(targetDisk.TotalSize < 31 * GB ? "Windows \"format.com\"" : "BadBuilder Large FAT32 formatter")}\n");
File.AppendAllText(Path.Combine(TargetDriveLetter, "info.txt"), $"- Disk total size: {targetDisk.TotalSize} bytes\n");
ClearConsole();
WriteHomebrewLog(1);
AnsiConsole.MarkupLine("\n[#76B900]{0}[/] Your USB drive is ready to go.", Markup.Escape("[+]"));
Console.Write("\nPress any key to exit...");
Console.ReadKey();
}
static void EnqueueMirrorDirectory(string sourcePath, string destinationPath, int priority)
{
actionQueue.EnqueueAction(async () =>
{
await FileSystemHelper.MirrorDirectoryAsync(sourcePath, destinationPath);
}, priority);
}
static void EnqueueFileCopy(string sourceFile, string destinationFile, int priority)
{
actionQueue.EnqueueAction(async () =>
{
await FileSystemHelper.CopyFileAsync(sourceFile, destinationFile);
}, priority);
}
static void WriteHomebrewLog(int count)
{
string logPath = Path.Combine(TargetDriveLetter, "info.txt");
string logEntry = $"- {count} homebrew app(s) added (including Simple 360 NAND Flasher)\n";
File.AppendAllText(logPath, logEntry);
}
static void ShowWelcomeMessage() => AnsiConsole.Markup(
"""
[#4D8C00] [/]
[#65A800] [/]
[#76B900] [/]
[#A1CF3E] [/]
[#CCE388] [/]
[#CCE388] [/]
[#76B900]v0.31[/]
Xbox 360 [#FF7200]BadUpdate[/] USB Builder
[#848589]Created by Pdawg | Forked by NiklasCFW[/]
[#76B900][/]
""");
static string PromptForAction() => AnsiConsole.Prompt(
new SelectionPrompt<string>()
.HighlightStyle(GreenStyle)
.AddChoices(
"Build exploit USB",
"Exit"
)
);
static void ClearConsole()
{
AnsiConsole.Clear();
ShowWelcomeMessage();
Console.WriteLine();
}
}
}