├── .gitignore ├── README.md └── XOR Unpacker ├── CLI ├── CLI.csproj └── Program.cs ├── XOR Unpacker.sln └── XOR Unpacker ├── Debug.cs ├── StaticAnalysis ├── Parser.cs └── Simulation.cs ├── Unpacker.cs └── XOR Unpacker.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | .DS_Store 6 | CHECKLIST.md 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | .vscode/ 13 | 14 | 15 | # User-specific files (MonoDevelop/Xamarin Studio) 16 | *.userprefs 17 | 18 | # Build results 19 | [Dd]ebug/ 20 | [Dd]ebugPublic/ 21 | [Rr]elease/ 22 | [Rr]eleases/ 23 | x64/ 24 | x86/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # .NET Core 49 | project.lock.json 50 | project.fragment.lock.json 51 | artifacts/ 52 | **/Properties/launchSettings.json 53 | 54 | *_i.c 55 | *_p.c 56 | *_i.h 57 | *.ilk 58 | *.meta 59 | *.obj 60 | *.pch 61 | *.pdb 62 | *.pgc 63 | *.pgd 64 | *.rsp 65 | *.sbr 66 | *.tlb 67 | *.tli 68 | *.tlh 69 | *.tmp 70 | *.tmp_proj 71 | *.log 72 | *.vspscc 73 | *.vssscc 74 | .builds 75 | *.pidb 76 | *.svclog 77 | *.scc 78 | 79 | # Chutzpah Test files 80 | _Chutzpah* 81 | 82 | # Visual C++ cache files 83 | ipch/ 84 | *.aps 85 | *.ncb 86 | *.opendb 87 | *.opensdf 88 | *.sdf 89 | *.cachefile 90 | *.VC.db 91 | *.VC.VC.opendb 92 | 93 | # Visual Studio profiler 94 | *.psess 95 | *.vsp 96 | *.vspx 97 | *.sap 98 | 99 | # TFS 2012 Local Workspace 100 | $tf/ 101 | 102 | # Guidance Automation Toolkit 103 | *.gpState 104 | 105 | # ReSharper is a .NET coding add-in 106 | _ReSharper*/ 107 | *.[Rr]e[Ss]harper 108 | *.DotSettings.user 109 | 110 | # JustCode is a .NET coding add-in 111 | .JustCode 112 | 113 | # TeamCity is a build add-in 114 | _TeamCity* 115 | 116 | # DotCover is a Code Coverage Tool 117 | *.dotCover 118 | 119 | # Visual Studio code coverage results 120 | *.coverage 121 | *.coveragexml 122 | 123 | # NCrunch 124 | _NCrunch_* 125 | .*crunch*.local.xml 126 | nCrunchTemp_* 127 | 128 | # MightyMoose 129 | *.mm.* 130 | AutoTest.Net/ 131 | 132 | # Web workbench (sass) 133 | .sass-cache/ 134 | 135 | # Installshield output folder 136 | [Ee]xpress/ 137 | 138 | # DocProject is a documentation generator add-in 139 | DocProject/buildhelp/ 140 | DocProject/Help/*.HxT 141 | DocProject/Help/*.HxC 142 | DocProject/Help/*.hhc 143 | DocProject/Help/*.hhk 144 | DocProject/Help/*.hhp 145 | DocProject/Help/Html2 146 | DocProject/Help/html 147 | 148 | # Click-Once directory 149 | publish/ 150 | 151 | # Publish Web Output 152 | *.[Pp]ublish.xml 153 | *.azurePubxml 154 | # TODO: Comment the next line if you want to checkin your web deploy settings 155 | # but database connection strings (with potential passwords) will be unencrypted 156 | *.pubxml 157 | *.publishproj 158 | 159 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 160 | # checkin your Azure Web App publish settings, but sensitive information contained 161 | # in these scripts will be unencrypted 162 | PublishScripts/ 163 | 164 | # NuGet Packages 165 | *.nupkg 166 | # The packages folder can be ignored because of Package Restore 167 | **/packages/* 168 | # except build/, which is used as an MSBuild target. 169 | !**/packages/build/ 170 | # Uncomment if necessary however generally it will be regenerated when needed 171 | #!**/packages/repositories.config 172 | # NuGet v3's project.json files produces more ignorable files 173 | *.nuget.props 174 | *.nuget.targets 175 | 176 | # Microsoft Azure Build Output 177 | csx/ 178 | *.build.csdef 179 | 180 | # Microsoft Azure Emulator 181 | ecf/ 182 | rcf/ 183 | 184 | # Windows Store app package directories and files 185 | AppPackages/ 186 | BundleArtifacts/ 187 | Package.StoreAssociation.xml 188 | _pkginfo.txt 189 | 190 | # Visual Studio cache files 191 | # files ending in .cache can be ignored 192 | *.[Cc]ache 193 | # but keep track of directories ending in .cache 194 | !*.[Cc]ache/ 195 | 196 | # Others 197 | ClientBin/ 198 | ~$* 199 | *~ 200 | *.dbmdl 201 | *.dbproj.schemaview 202 | *.jfm 203 | *.pfx 204 | *.publishsettings 205 | orleans.codegen.cs 206 | 207 | # Since there are multiple workflows, uncomment next line to ignore bower_components 208 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 209 | #bower_components/ 210 | 211 | # RIA/Silverlight projects 212 | Generated_Code/ 213 | 214 | # Backup & report files from converting an old project file 215 | # to a newer Visual Studio version. Backup files are not needed, 216 | # because we have git ;-) 217 | _UpgradeReport_Files/ 218 | Backup*/ 219 | UpgradeLog*.XML 220 | UpgradeLog*.htm 221 | 222 | # SQL Server files 223 | *.mdf 224 | *.ldf 225 | 226 | # Business Intelligence projects 227 | *.rdl.data 228 | *.bim.layout 229 | *.bim_*.settings 230 | 231 | # Microsoft Fakes 232 | FakesAssemblies/ 233 | 234 | # GhostDoc plugin setting file 235 | *.GhostDoc.xml 236 | 237 | # Node.js Tools for Visual Studio 238 | .ntvs_analysis.dat 239 | node_modules/ 240 | 241 | # Typescript v1 declaration files 242 | typings/ 243 | 244 | # Visual Studio 6 build log 245 | *.plg 246 | 247 | # Visual Studio 6 workspace options file 248 | *.opt 249 | 250 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 251 | *.vbw 252 | 253 | # Visual Studio LightSwitch build output 254 | **/*.HTMLClient/GeneratedArtifacts 255 | **/*.DesktopClient/GeneratedArtifacts 256 | **/*.DesktopClient/ModelManifest.xml 257 | **/*.Server/GeneratedArtifacts 258 | **/*.Server/ModelManifest.xml 259 | _Pvt_Extensions 260 | 261 | # Paket dependency manager 262 | .paket/paket.exe 263 | paket-files/ 264 | 265 | # FAKE - F# Make 266 | .fake/ 267 | 268 | # JetBrains Rider 269 | .idea/ 270 | *.sln.iml 271 | 272 | # CodeRush 273 | .cr/ 274 | 275 | # Python Tools for Visual Studio (PTVS) 276 | __pycache__/ 277 | *.pyc 278 | 279 | # Cake - Uncomment if you are using it 280 | # tools/** 281 | # !tools/packages.config 282 | 283 | # Telerik's JustMock configuration file 284 | *.jmconfig 285 | 286 | # BizTalk build output 287 | *.btp.cs 288 | *.btm.cs 289 | *.odx.cs 290 | *.xsd.cs 291 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # filesecuring-xor-unpacker 2 | A static unpacker / deobfuscator for that Lua obfuscator called "filesecuring" / "xor". 3 | This obfuscator was mainly used in FiveM communities, due to the way it detects load=print, it was pretty difficult to dump it by hooking lua functions. 4 | They recently discontinued and opensourced their obfuscator, so I can publicly release my deobfuscator for it. 5 | 6 | Usage: 7 | build the project. 8 | run CLI.exe with following arguments: 9 | 10 | `CLI.exe input.lua` 11 | 12 | It will create an `input_unpacked.lua` in the same directory 13 | ⚠️ It might take a while to decode scripts bigger than 10mb, be patient 14 | This obfuscator was written by Federal#9999, feel free to skid it. thats what you do anyways 15 | -------------------------------------------------------------------------------- /XOR Unpacker/CLI/CLI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /XOR Unpacker/CLI/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using XOR_Unpacker; 4 | 5 | 6 | namespace CLI { 7 | class Program { 8 | static void Main(string[] args) { 9 | Debug.Log("XOR Deobfuscator by Federal#9999 v1.0", ConsoleColor.Cyan); 10 | Debug.Log("[1/7] Starting.."); 11 | string script = File.ReadAllText(args[0]); 12 | script = Unpacker.UnpackXORScript(script); 13 | Debug.Log("[6/7] Finalizing..", ConsoleColor.White); 14 | string @out = Path.GetFileNameWithoutExtension(args[0]) + "_unpacked.lua"; 15 | File.WriteAllText(@out, script); 16 | Debug.Log($"[7/7] Unpacked and saved into {@out}", ConsoleColor.Green); 17 | 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /XOR Unpacker/XOR Unpacker.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30907.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XOR Unpacker", "XOR Unpacker\XOR Unpacker.csproj", "{C467E186-0CCE-4C47-8D10-41151A24BF68}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLI", "CLI\CLI.csproj", "{A22E4775-8C0B-40C9-B3F9-A1584C678EA4}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {C467E186-0CCE-4C47-8D10-41151A24BF68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {C467E186-0CCE-4C47-8D10-41151A24BF68}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {C467E186-0CCE-4C47-8D10-41151A24BF68}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {C467E186-0CCE-4C47-8D10-41151A24BF68}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {A22E4775-8C0B-40C9-B3F9-A1584C678EA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {A22E4775-8C0B-40C9-B3F9-A1584C678EA4}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {A22E4775-8C0B-40C9-B3F9-A1584C678EA4}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {A22E4775-8C0B-40C9-B3F9-A1584C678EA4}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {D1721C06-4622-4B2E-8D27-36A82F7B38A9} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /XOR Unpacker/XOR Unpacker/Debug.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace XOR_Unpacker { 6 | public static class Debug { 7 | 8 | public static void Log(string msg, ConsoleColor color = ConsoleColor.Gray) { 9 | ConsoleColor old = Console.ForegroundColor; 10 | Console.ForegroundColor = color; 11 | Console.WriteLine(msg); 12 | Console.ForegroundColor = old; 13 | 14 | } 15 | 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /XOR Unpacker/XOR Unpacker/StaticAnalysis/Parser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | using System.Linq; 6 | 7 | namespace XOR_Unpacker.StaticAnalysis { 8 | public static class Parser { 9 | public static string DecodeLoader(string input) { 10 | Regex loaderData = new Regex(@"\(""(.{300,})""\)\(\)", RegexOptions.Singleline); 11 | if (loaderData.IsMatch(input)) { 12 | Debug.Log("[2/7] ---> Detected loader!", ConsoleColor.Yellow); 13 | input = loaderData.Match(input).Groups[1].Value; 14 | byte[] bytes = Array.ConvertAll(input.Substring(1).Split('\\'), b => (byte)(int.Parse(b))); 15 | return Encoding.ASCII.GetString(bytes); 16 | 17 | } else { 18 | return input; 19 | } 20 | 21 | } 22 | 23 | public static string GetMainCall(string script) { 24 | int start = script.LastIndexOf("({") + 2; 25 | return script.Substring(start); 26 | } 27 | const string realScriptSeparator = @"10'\);? ?end;? ?end\);? ?end\);? ?end\);? ?end;? ?\w+?\(\{(?:-?\d,?)+?\},""\w+?""\);? ?"; 28 | public static string GetRealScript(string script) { // analyzes the script and finds the main script between fake ones. (another funny xor mod apparently) 29 | Regex r = new Regex(realScriptSeparator, RegexOptions.Singleline); 30 | var m = r.Matches(script); 31 | int lastMaxSize = 0; 32 | string lastLargestScript = ""; 33 | 34 | foreach (Match x in m) { 35 | string match = x.Value.ToString(); 36 | if (match.Length > lastMaxSize) { 37 | lastMaxSize = match.Length; 38 | lastLargestScript = match; 39 | } 40 | } 41 | 42 | return lastLargestScript; 43 | } 44 | 45 | public class ScriptData { 46 | public int[] dataArray { get; set; } 47 | public string decryptionKey { get; set; } 48 | 49 | public ScriptData(string script) { 50 | 51 | script = DecodeLoader(script); 52 | 53 | 54 | Debug.Log("[3/7] Fetching handlers.."); 55 | 56 | bool isOriginalXOR = false; 57 | bool isUnknownXOR = false; 58 | Regex r = new Regex(@"key *?= *?""(.+?)""", RegexOptions.Singleline); 59 | Regex r2 = new Regex(realScriptSeparator, RegexOptions.Singleline); 60 | 61 | if (r.IsMatch(script)) { 62 | isOriginalXOR = true; 63 | decryptionKey = r.Match(script).Groups[1].Value; 64 | Debug.Log("[3/7] ---> Detected original XOR encryption!", ConsoleColor.Yellow); 65 | } else if (r2.Matches(script).Count > 4) { 66 | Debug.Log("[3/7] ---> Detected unknown XOR encryption! (the one that's bloated with fake scripts)", ConsoleColor.Yellow); 67 | script = GetRealScript(script); 68 | isUnknownXOR = true; 69 | } else { 70 | Debug.Log("[3/7] ---> Detected filesecuring mod XOR encryption!", ConsoleColor.Yellow); 71 | } 72 | 73 | if (isUnknownXOR) { } 74 | string main = GetMainCall(script).Replace(" ", ""); 75 | string table = main.Substring(0, main.IndexOf("}")); 76 | string[] data = table.Split(','); 77 | dataArray = Array.ConvertAll(data, s => Int32.Parse(s)); 78 | 79 | if (isOriginalXOR) return; 80 | main = main.Substring(main.IndexOf("\"") + 1); 81 | decryptionKey = main.Substring(0, main.IndexOf("\"")); 82 | 83 | 84 | 85 | } 86 | } 87 | 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /XOR Unpacker/XOR Unpacker/StaticAnalysis/Simulation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace XOR_Unpacker.StaticAnalysis { 6 | public static class Simulation { 7 | public static int L_XORDecrypt(int data, int keyByte) { 8 | int[][] XOR_l = { new int[] { 0, 1 }, new int[] { 1, 0 } }; 9 | int pow = 1; 10 | int c = 0; 11 | 12 | while (data > 0 || keyByte > 0) { 13 | c += (XOR_l[data % 2][keyByte % 2] * pow); 14 | data = (int)(data / 2); 15 | keyByte = (int)(keyByte / 2); 16 | pow *= 2; 17 | } 18 | return c; 19 | } 20 | 21 | public static int[] L_FixByteTable(int[] data) { 22 | List result = new List(); 23 | 24 | int idx = 0; 25 | int i = data[idx]; 26 | 27 | while(i >= 0) { 28 | result.Add(data[i]); 29 | idx++; 30 | i = data[idx]; 31 | } 32 | 33 | return result.ToArray(); 34 | } 35 | 36 | public static string L_DecodeTable(int[] data, string key) { 37 | StringBuilder chars = new StringBuilder(); 38 | char decChar; 39 | 40 | for (int i = 0; i < data.Length; i++) { 41 | decChar = key[i % key.Length]; 42 | chars.Append((char)L_XORDecrypt(data[i], (int)decChar)); 43 | } 44 | return chars.ToString(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /XOR Unpacker/XOR Unpacker/Unpacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using XOR_Unpacker.StaticAnalysis; 5 | 6 | namespace XOR_Unpacker { 7 | public static class Unpacker { 8 | 9 | public static string UnpackXORScript(string input) { 10 | Debug.Log("[2/7] Parsing script.."); 11 | Parser.ScriptData data = new Parser.ScriptData(input); 12 | Debug.Log("[4/7] Decrypting table data..", ConsoleColor.White); 13 | 14 | int[] fixed_1 = Simulation.L_FixByteTable(data.dataArray); 15 | Debug.Log("[5/7] Decoding table data.."); 16 | return Simulation.L_DecodeTable(fixed_1, data.decryptionKey); 17 | 18 | 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /XOR Unpacker/XOR Unpacker/XOR Unpacker.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | XOR_Unpacker 6 | 7 | 8 | 9 | --------------------------------------------------------------------------------