Skip to content

Commit

Permalink
Add source after decompiling and fixing
Browse files Browse the repository at this point in the history
  • Loading branch information
holly-hacker committed Oct 29, 2017
1 parent 270d379 commit 3d15ab5
Show file tree
Hide file tree
Showing 11 changed files with 821 additions and 0 deletions.
22 changes: 22 additions & 0 deletions osu!decoder.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu!decoder", "osu!decoder\osu!decoder.csproj", "{7CDE3892-D6ED-4784-AC5C-560649D75F9A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7CDE3892-D6ED-4784-AC5C-560649D75F9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CDE3892-D6ED-4784-AC5C-560649D75F9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CDE3892-D6ED-4784-AC5C-560649D75F9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CDE3892-D6ED-4784-AC5C-560649D75F9A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
72 changes: 72 additions & 0 deletions osu!decoder/BinaryPatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using dnlib.DotNet;
using dnlib.DotNet.Emit;

namespace osu_decoder_dnlib
{
// Token: 0x02000002 RID: 2
internal class BinaryPatch
{
// Token: 0x06000002 RID: 2 RVA: 0x00002058 File Offset: 0x00000258
public static void PatchSignatureCheck(ModuleDefMD module)
{
bool flag = false;
foreach (TypeDef typeDef in from a in module.Types
where a.Methods.Any((MethodDef b) => b.IsPinvokeImpl && b.ImplMap.Name == "WinVerifyTrust")
select a)
{
foreach (MethodDef methodDef in typeDef.Methods.Where((MethodDef a) => a.ReturnType.TypeName == "Boolean"))
{
Program.Verbose("Writing ret true to " + methodDef.FullName);
methodDef.Body.Instructions.Insert(0, new Instruction(OpCodes.Ldc_I4_1));
methodDef.Body.Instructions.Insert(1, new Instruction(OpCodes.Ret));
flag = true;
}
}
if (!flag)
{
Console.WriteLine("WARNING: did not write any changes.");
}
}

// Token: 0x06000003 RID: 3 RVA: 0x0000217C File Offset: 0x0000037C
public static void PatchExecutableName(ModuleDefMD module)
{
try
{
MethodDef methodDef = (MethodDef)module.EntryPoint.Body.Instructions[0].Operand;
Program.Verbose("Patching name check in " + methodDef.FullName);
IList<Instruction> instructions = methodDef.Body.Instructions;
Instruction item = instructions.Last((Instruction a) => a.OpCode == OpCodes.Brfalse_S);
int num = instructions.IndexOf(item);
for (int i = -4; i < 10; i++)
{
instructions[i + num].OpCode = OpCodes.Nop;
}
}
catch (Exception ex)
{
Console.WriteLine("Could not patch: " + ex.Message);
}
}

// Token: 0x06000004 RID: 4 RVA: 0x0000224C File Offset: 0x0000044C
public static MethodDef FindEazStringMethod(ModuleDefMD module)
{
MethodDef methodDef = (MethodDef)module.EntryPoint.Body.Instructions[0].Operand;
IList<Instruction> instructions = methodDef.Body.Instructions;
for (int i = 0; i < methodDef.Body.Instructions.Count; i++)
{
Instruction instruction = instructions[i];
MemberRef memberRef;
if (instruction.OpCode == OpCodes.Newobj && (memberRef = (instruction.Operand as MemberRef)) != null && memberRef.Class.Name == "Exception")
{
return (MethodDef)instructions[i - 1].Operand;
}
}
return null;
}
}
}
98 changes: 98 additions & 0 deletions osu!decoder/CliOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using CommandLine;
using CommandLine.Text;

namespace osu_decoder_dnlib
{
// Token: 0x02000004 RID: 4
internal class CliOptions
{
// Token: 0x17000001 RID: 1
// (get) Token: 0x0600000C RID: 12 RVA: 0x00002388 File Offset: 0x00000588
// (set) Token: 0x0600000D RID: 13 RVA: 0x00002390 File Offset: 0x00000590
[ValueOption(0)]
public string Input { get; set; }

// Token: 0x17000002 RID: 2
// (get) Token: 0x0600000E RID: 14 RVA: 0x0000239C File Offset: 0x0000059C
// (set) Token: 0x0600000F RID: 15 RVA: 0x000023A4 File Offset: 0x000005A4
[ValueOption(1)]
public string Input2 { get; set; }

// Token: 0x17000003 RID: 3
// (get) Token: 0x06000010 RID: 16 RVA: 0x000023B0 File Offset: 0x000005B0
// (set) Token: 0x06000011 RID: 17 RVA: 0x000023B8 File Offset: 0x000005B8
[Option('o', "output", HelpText = "Path of the output file")]
public string Output { get; set; }

// Token: 0x17000004 RID: 4
// (get) Token: 0x06000012 RID: 18 RVA: 0x000023C4 File Offset: 0x000005C4
// (set) Token: 0x06000013 RID: 19 RVA: 0x000023CC File Offset: 0x000005CC
[Option('v', "verbose", HelpText = "Prints more output.")]
public bool Verbose { get; set; }

// Token: 0x17000005 RID: 5
// (get) Token: 0x06000014 RID: 20 RVA: 0x000023D8 File Offset: 0x000005D8
// (set) Token: 0x06000015 RID: 21 RVA: 0x000023E0 File Offset: 0x000005E0
[Option('d', "debug", HelpText = "Prints a lot more output, you should pipe this to a file.")]
public bool Debug { get; set; }

// Token: 0x17000006 RID: 6
// (get) Token: 0x06000016 RID: 22 RVA: 0x000023EC File Offset: 0x000005EC
// (set) Token: 0x06000017 RID: 23 RVA: 0x000023F4 File Offset: 0x000005F4
[Option('s', "sourcemap", HelpText = "Writes a file containing an original:decoded source map.")]
public bool Sourcemap { get; set; }

// Token: 0x17000007 RID: 7
// (get) Token: 0x06000018 RID: 24 RVA: 0x00002400 File Offset: 0x00000600
// (set) Token: 0x06000019 RID: 25 RVA: 0x00002408 File Offset: 0x00000608
[Option('r', "dry-run", HelpText = "Do not write decoded executable to disk.")]
public bool DryRun { get; set; }

// Token: 0x17000008 RID: 8
// (get) Token: 0x0600001A RID: 26 RVA: 0x00002414 File Offset: 0x00000614
public string Password { get; } = "recorderinthesandybridge";

// Token: 0x17000009 RID: 9
// (get) Token: 0x0600001B RID: 27 RVA: 0x0000241C File Offset: 0x0000061C
// (set) Token: 0x0600001C RID: 28 RVA: 0x00002424 File Offset: 0x00000624
[Option("exp-eagerdecode", HelpText = "EXPERIMENTAL: decode from reference in method bodies", DefaultValue = false)]
public bool ExperimentEagerDecoding { get; set; }

// Token: 0x1700000A RID: 10
// (get) Token: 0x0600001D RID: 29 RVA: 0x00002430 File Offset: 0x00000630
// (set) Token: 0x0600001E RID: 30 RVA: 0x00002438 File Offset: 0x00000638
[Option("exp-secondpass", HelpText = "EXPERIMENTAL: do a second pass to check if everything is decoded", DefaultValue = false)]
public bool ExperimentSecondPass { get; set; }

// Token: 0x1700000B RID: 11
// (get) Token: 0x0600001F RID: 31 RVA: 0x00002444 File Offset: 0x00000644
// (set) Token: 0x06000020 RID: 32 RVA: 0x0000244C File Offset: 0x0000064C
[Option("exp-patch", HelpText = "Apply patch to remove signature and filename check", DefaultValue = false)]
public bool ExperimentPatch { get; set; }

// Token: 0x1700000C RID: 12
// (get) Token: 0x06000021 RID: 33 RVA: 0x00002458 File Offset: 0x00000658
// (set) Token: 0x06000022 RID: 34 RVA: 0x00002460 File Offset: 0x00000660
[Option("exp-full", HelpText = "Decode everything, resulting in unrunnable executable", DefaultValue = false)]
public bool ExperimentFullDecrypt { get; set; }

// Token: 0x06000023 RID: 35 RVA: 0x0000246C File Offset: 0x0000066C
[HelpOption]
public string GetHelp()
{
HelpText helpText = new HelpText();
helpText.Heading = new HeadingInfo("osu!decoder", "v1.2");
helpText.Copyright = new CopyrightInfo("HoLLy/JustM3", 2017);
helpText.AdditionalNewLineAfterOption = false;
helpText.AddDashesToOption = true;
helpText.MaximumDisplayWidth = Console.BufferWidth;
helpText.AddPreOptionsLine("\nExample usage:");
helpText.AddPreOptionsLine("\t- osu!decoder osu!.exe");
helpText.AddPreOptionsLine("\t- osu!decoder osu!.exe -v -p updated_password -o c:/newosu!.exe");
helpText.AddOptions(this);
helpText.AddPostOptionsLine("Please do not distribute. If you have this, it means I trust you :)");
return helpText;
}
}
}
137 changes: 137 additions & 0 deletions osu!decoder/CryptoHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace osu_decoder_dnlib
{
// Token: 0x02000005 RID: 5
internal class CryptoHelper
{
// Token: 0x04000012 RID: 18
private readonly SymmetricAlgorithm _symmetricAlgorithm;

// Token: 0x06000025 RID: 37 RVA: 0x00002518 File Offset: 0x00000718
public CryptoHelper(string password)
{
Program.Verbose("Creating new decoder with password " + password);
this._symmetricAlgorithm = new RijndaelManaged
{
KeySize = 256,
BlockSize = 128,
IV = new Rfc2898DeriveBytes(password, new byte[]
{
28,
136,
27,
216,
83,
147,
140,
207,
60,
153,
41,
107,
117,
164,
37,
157,
94,
233,
51,
48,
146,
108,
127,
191,
30,
226,
250,
88,
109,
7,
132,
15
}).GetBytes(16),
Key = new Rfc2898DeriveBytes(password, new byte[]
{
167,
126,
112,
16,
4,
244,
15,
120,
135,
116,
123,
212,
157,
48,
5,
194,
12,
179,
153,
201,
204,
249,
248,
212,
86,
20,
215,
55,
105,
157,
111,
11
}).GetBytes(32)
};
}

// Token: 0x06000026 RID: 38 RVA: 0x000025A8 File Offset: 0x000007A8
internal string Decrypt(string input)
{
if (!input.StartsWith("#="))
{
throw new NotImplementedException("I don't support this encryption type");
}
string text = input.Substring(2);
if (text.StartsWith("q"))
{
text = text.Substring(1);
text = text.Replace('_', '+').Replace('$', '/');
string text2 = this.DecryptWithXor(Convert.FromBase64String(text));
Program.Debug(string.Format("Decrypted {0} to {1}", input, text2));
return text2;
}
throw new NotImplementedException("I don't support this encryption type (yet), poke me about it");
}

// Token: 0x06000027 RID: 39 RVA: 0x0000262C File Offset: 0x0000082C
private string DecryptWithXor(byte[] toDecrypt)
{
MemoryStream memoryStream = new MemoryStream();
using (ICryptoTransform cryptoTransform = this._symmetricAlgorithm.CreateDecryptor())
{
CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write);
cryptoStream.Write(toDecrypt, 0, toDecrypt.Length);
cryptoStream.FlushFinalBlock();
cryptoStream.Close();
}
toDecrypt = memoryStream.ToArray();
byte b = toDecrypt[toDecrypt.Length - 1];
Array.Resize<byte>(ref toDecrypt, toDecrypt.Length - 1);
for (int i = 0; i < toDecrypt.Length; i++)
{
byte[] array = toDecrypt;
int num = i;
array[num] ^= b;
}
return Encoding.UTF8.GetString(toDecrypt);
}
}
}
Loading

0 comments on commit 3d15ab5

Please sign in to comment.