Skip to content
This repository has been archived by the owner on Jul 26, 2019. It is now read-only.

Commit

Permalink
Submit files
Browse files Browse the repository at this point in the history
  • Loading branch information
Igoorx committed Jul 25, 2019
1 parent 71ef5a9 commit 6ec8347
Show file tree
Hide file tree
Showing 7 changed files with 432 additions and 0 deletions.
292 changes: 292 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using Mono.Cecil;
using Mono.Cecil.Cil;

namespace osuPatcher
{
internal class Program
{
/// <summary>
/// osu! assembly.
/// </summary>
private static AssemblyDefinition Assembly;

/// <summary>
/// A bool to tell to patcher if it will mantain the https connection.
/// </summary>
private static bool KeepHttps;

/// <summary>
/// A list of <seealso cref="Tuple{T1, T2}"/> storing the replaces that the patcher will force osu to do in its requests.
/// </summary>
private static List<Tuple<string, string>> Replaces;

/// <summary>
/// The entry point of Patcher
/// </summary>
private static void Main()
{
if (!File.Exists("osu!.exe"))
{
Console.WriteLine("osu!.exe not found.");
Environment.Exit(-1);
}

KeepHttps = false;
Replaces = new List<Tuple<string, string>> // <oldString, newString>
{
Tuple.Create("osu.ppy.sh", "localhost"),
Tuple.Create("a.ppy.sh", "localhost"),
Tuple.Create("c.ppy.sh", "localhost:890"),
Tuple.Create("c1.ppy.sh", "localhost:890")
};

Console.WriteLine("Trying to patch osu..");

if (PatcherV2() || PatcherV1())
{
Console.WriteLine("Success! Saving the patched osu..");
try
{
Assembly.Write("osu!_patched.exe");
Console.WriteLine("Saved.");
}
catch (Exception e)
{
Console.WriteLine("Error: "+e.Message);
}
}
else Console.WriteLine("Failed, none of the patch processes were completed successfully.");

Console.WriteLine();
Console.WriteLine("Press any key to exit");
Console.ReadKey(true);
}

/// <summary>
/// First version of patcher, working in all versions newer than fallback and older than 08042016.
/// </summary>
/// <returns>Patched sucessfully?</returns>
private static bool PatcherV1()
{
Assembly = AssemblyDefinition.ReadAssembly("osu!.exe");

string[] signature =
{
"ldarg.0",
"call",
"ldc.i4",
"call",
"callvirt",
"brtrue.s",
"ldarg.0",
"ldc.i4",
"call",
"ldarg.0"
};

foreach (TypeDefinition type in Assembly.MainModule.Types.Where(type => type.Name != "<Module>"))
{
foreach (MethodDefinition method in type.Methods.Where(method => method.Body != null && method.Body.Instructions.Count > 10))
{
for (int i = 0; i != 10; i++) //Search by signature in current method
{
if (method.Body.Instructions[i].OpCode.ToString() != signature[i])
goto cont;
}
//If found, start the patch process

ILProcessor worker = method.Body.GetILProcessor();

Instruction curi = worker.Body.Instructions[1];
curi = curi.Next; //ldc.i4

ReplaceProtectionWith("http://", ref curi, worker);

curi = curi.Next; //brtrue
if (curi.OpCode.ToString() != "brtrue.s")
{
Console.WriteLine("Semething is very wrong..");
return false;
}

if (!KeepHttps)
{
curi = curi.Next.Next; //ldc.i4
ReplaceProtectionWith("http://", ref curi, worker); //ldarg.0
curi = curi.Next.Next; //ldc.i4
ReplaceProtectionWith("https://", ref curi, worker);
}
else
curi = worker.Body.Instructions[worker.Body.Instructions.IndexOf(curi) + 8];


curi = curi.Next; //reference of Method Replace
MethodReference methodRC = curi.Operand as MethodReference;
foreach (Tuple<string, string> pair in Replaces)
{
InsertReplace(pair.Item1, pair.Item2, ref curi, worker, methodRC);
}

return true;
cont:;
}
}
return false;
}

/// <summary>
/// Second version of patcher, currently working in versions newer than 08042016.
/// </summary>
/// <returns>Patched sucessfully?</returns>
private static bool PatcherV2()
{
Assembly = AssemblyDefinition.ReadAssembly("osu!.exe");

bool P1 = false;

string[] signatureP2 =
{
"ldarg.0",
"call",
"leave.s",
"stloc.0",
"ldarg.0",
"ldloc.0",
"ldc.i4.0",
"call"
};
int P2 = 0; //P2 has two matchs

string[] signatureP3 =
{
"ldarg.1",
"ldc.i4",
"call",
"callvirt",
"brtrue.s",
"ldc.i4",
"call",
"ldarg.1"
};
bool P3 = false;

foreach (TypeDefinition type in Assembly.MainModule.Types.Where(type => type.Name != "<Module>"))
{
foreach (MethodDefinition method in type.Methods.Where(method => method.Body != null && method.Body.Instructions.Count > 8))
{
if (!P1 && method.Body.Instructions[3].OpCode.ToString() == "call" &&
method.Body.Instructions[3].Operand.ToString().Contains("Guid:"))
{
//Disable the "unsigned executable" error.
ILProcessor _worker = method.Body.GetILProcessor();

_worker.Replace(method.Body.Instructions.Last().Previous, _worker.Create(OpCodes.Ldc_I4_1));

P1 = true;
continue;
}

if (P2<2)
{
for (int i = 0; i != 8; i++) //Search by signature2 in current method
{
if (method.Body.Instructions[i].OpCode.ToString() != signatureP2[i])
goto exitP2;
}
//If found, remove method content

ILProcessor _worker = method.Body.GetILProcessor();
foreach (Instruction ins in _worker.Body.Instructions.ToList())
_worker.Remove(ins);
_worker.Body.ExceptionHandlers.Clear();

_worker.Emit(OpCodes.Ret);

++P2;
continue;
}
exitP2:;

if (!P3)
{
for (int i = 0; i != 8; i++) //Search by signature in current method
{
if (method.Body.Instructions[i].OpCode.ToString() != signatureP3[i])
goto exitP3;
}
//If found, start the patch process

ILProcessor worker = method.Body.GetILProcessor();
Instruction curi = worker.Body.Instructions[1];

ReplaceProtectionWith("http://", ref curi, worker);

curi = curi.Next; //brtrue
if (curi.OpCode.ToString() != "brtrue.s")
{
Console.WriteLine("Semething is very wrong..");
return false;
}

if (!KeepHttps)
{
curi = curi.Next; //ldc.i4
ReplaceProtectionWith("http://", ref curi, worker); //ldarg.0
curi = curi.Next; //ldc.i4
ReplaceProtectionWith("https://", ref curi, worker);
}
else
curi = worker.Body.Instructions[worker.Body.Instructions.IndexOf(curi) + 8];


curi = curi.Next; //reference of Method Replace
MethodReference methodRC = curi.Operand as MethodReference;
foreach (Tuple<string, string> pair in Replaces)
{
InsertReplace(pair.Item1, pair.Item2, ref curi, worker, methodRC);
}

P3 = true;
}
exitP3:;
}

if (P1 && P2==2 && P3) break;
}
return P1 && P2==2 && P3;
}

/// <summary>
/// Insert an replace method after the current IL instruction.
/// </summary>
/// <param name="from"></param>
/// <param name="to">Replace all occurencies of <seealso cref="from"/> by it</param>
/// <param name="curi">Current IL instruction</param>
/// <param name="worker">Current IL worker</param>
/// <param name="methodRC">An reference to replace method to use as base</param>
private static void InsertReplace(string from, string to, ref Instruction curi, ILProcessor worker, MethodReference methodRC)
{
worker.InsertAfter(curi, curi = worker.Create(OpCodes.Ldstr, from));
worker.InsertAfter(curi, curi = worker.Create(OpCodes.Ldstr, to));
worker.InsertAfter(curi, curi = worker.Create(OpCodes.Callvirt, methodRC));
}

/// <summary>
/// Replace an Eazfuscator protected string with an unprotected string.
/// </summary>
/// <param name="str"></param>
/// <param name="curi">Current IL instruction</param>
/// <param name="worker">Current IL worker</param>
private static void ReplaceProtectionWith(string str, ref Instruction curi, ILProcessor worker)
{
worker.Replace(curi, curi = worker.Create(OpCodes.Ldstr, str));
worker.Remove(curi.Next);
curi = curi.Next;
}
}
}
36 changes: 36 additions & 0 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu!Patcher")]
[assembly: AssemblyDescription("Patcher for the osu! bancho")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Igoor")]
[assembly: AssemblyProduct("osu!Patcher")]
[assembly: AssemblyCopyright("Igoor 2016")]
[assembly: AssemblyTrademark("Igoor")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4b77791f-1993-4e64-8afa-2e7fe5639cc0")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# osuPatcher
A old project to patch osu! executable

<b>This project is old (last update: 2016) and so may not work with newer osu! versions.</b>
7 changes: 7 additions & 0 deletions app.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>

<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
</configuration>
Loading

0 comments on commit 6ec8347

Please sign in to comment.