├── .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 |
--------------------------------------------------------------------------------