- Name - GUI
- Category - Reverse Engineering
- Points - 9
- Description - n/a
- Binary - Download here
- Share:1-d8effa9e8e19f7a2f17a3b55640b55295b1a327a5d8aebc832eae1a905c48b64
private void button1_Click(object sender, EventArgs e) { byte[] buf = Form1.ReadResource(<Module>.\u206F\u202C\u206B\u202E\u200F\u206E\u202E\u206B\u202D\u206D\u200F\u206F\u200F\u200F\u202B\u202C\u200E\u206B\u202C\u202A\u202E\u206D\u206C\u200E\u206C\u206E\u200B\u200F\u206F\u200E\u202A\u206F\u206C\u200B\u206B\u206A\u206B\u202C\u206B\u206E\u202E<string>(282000140u)); byte[] buffer = this.decryptBuffer(buf); byte[] rawAssembly = util.DecompressBuffer(buffer); Assembly assembly = Assembly.Load(rawAssembly); Type type = assembly.GetType(<Module>.\u202C\u200C\u200F\u202E\u202A\u200E\u202A\u206D\u206F\u200D\u206C\u202C\u200C\u206D\u200C\u206D\u206E\u200E\u200C\u202C\u200F\u206C\u206C\u200D\u200E\u206C\u200D\u202D\u206A\u206E\u200D\u202A\u200B\u206D\u206B\u200D\u206A\u206B\u206E\u206F\u202E<string>(370292149u)); MethodInfo method = type.GetMethod(<Module>.\u202A\u202C\u206D\u202C\u202A\u206C\u202C\u202B\u206D\u202B\u200F\u202C\u200B\u200F\u206E\u200D\u200C\u202C\u206B\u200E\u200D\u202E\u206C\u206A\u202C\u200F\u200D\u202A\u206C\u202A\u202D\u200B\u200E\u206F\u202B\u206D\u200F\u206E\u202A\u206E\u202E<string>(547307959u)); bool flag = (bool)method.Invoke(null, new object[] { <Module>.\u202A\u202C\u206D\u202C\u202A\u206C\u202C\u202B\u206D\u202B\u200F\u202C\u200B\u200F\u206E\u200D\u200C\u202C\u206B\u200E\u200D\u202E\u206C\u206A\u202C\u200F\u200D\u202A\u206C\u202A\u202D\u200B\u200E\u206F\u202B\u206D\u200F\u206E\u202A\u206E\u202E<string>(292816780u) }); if (flag) { MessageBox.Show(<Module>.\u202D\u202A\u202E\u206C\u202B\u200F\u206B\u202A\u206C\u200D\u200D\u200C\u202B\u206F\u206F\u202C\u206F\u206E\u206D\u206C\u206D\u206F\u206D\u202B\u202C\u200C\u200E\u206B\u200E\u200D\u202C\u206C\u206B\u206E\u200C\u202D\u202E\u200C\u200C\u200C\u202E<string>(3452886671u)); return; } MessageBox.Show(<Module>.\u206B\u206A\u200E\u202B\u200E\u202B\u202C\u200F\u202E\u202D\u202B\u200F\u206E\u202B\u206B\u202B\u202A\u206E\u206C\u202B\u202E\u206F\u202C\u200C\u200E\u206A\u202B\u202E\u202D\u200D\u202C\u206E\u202D\u206B\u206D\u206C\u202B\u202D\u206C\u206A\u202E<string>(458656109u)); }The following is the unobfuscated version:
private void button1_Click(object sender, EventArgs e) { byte[] buf = Form1.ReadResource(<Module>.smethod_4<string>(282000140u)); byte[] buffer = this.decryptBuffer(buf); byte[] rawAssembly = util.DecompressBuffer(buffer); Assembly assembly = Assembly.Load(rawAssembly); Type type = assembly.GetType(<Module>.smethod_5<string>(370292149u)); MethodInfo method = type.GetMethod(<Module>.smethod_2<string>(547307959u)); if ((bool)method.Invoke(null, new object[] { <Module>.smethod_2<string>(292816780u) })) { MessageBox.Show(<Module>.smethod_6<string>(3452886671u)); return; } MessageBox.Show(<Module>.smethod_3<string>(458656109u)); }That's much better! So let's dive into it. The button click event, displayed above, is a good place to start. The code is reading some resource, decrypting it, decompressing it, loading it, getting a method, and then invoking it. The question is: what is it loading? If we step over it, lines 14 and 15 are never reached, which means that this unknown method is returning false. We probably need to make it return true. Let's step into it and see what's happening inside. After quite a few steps we arrive at another module's constructor; the module being Layer1.dll, as can be seen from the Assembly Explorer: Once again we're back to obfuscated code. To obtain an unobfuscated version we can break at line 6 in the button click event handler displayed above, save the contents of variable rawAssembly which contains the raw bytes of the dll, deobfuscate it with Unconfuser and de4dot, and load it into dnSpy. Even though we can't run it, at least we'll have cleaner code to reference while stepping through the obfuscated one. From now on I will be displaying code extracts from the unobfuscated version even though the execution really happens in the obfuscated one. Just after the constructor we get to the Start() function:
public static bool Start(string config) { Config config2 = Config.InitConfig(config); if (config2 == null) { return false; } if (!CPUDetection.CheckCPUCount(config2.CPUCount)) { return false; } if (config2.DebugDetection && Layer1.IsDebuggerPresent()) { return false; } bool result; try { string key = Layer1.getKey(); byte[] bytesToBeDecrypted = util.ReadResource(<Module>.smethod_2<string>(2155271801u)); byte[] buffer = util.AES_Decrypt(bytesToBeDecrypted, Encoding.UTF8.GetBytes(key)); byte[] rawAssembly = util.DecompressBuffer(buffer); Assembly assembly = Assembly.Load(rawAssembly); Type type = assembly.GetType(<Module>.smethod_4<string>(1983674467u)); MethodInfo method = type.GetMethod(<Module>.smethod_2<string>(1619868913u)); result = (bool)method.Invoke(null, new object[] { <Module>.smethod_2<string>(2894386820u) }); } catch (Exception) { result = false; } return result; }Notice the contents of the local variable config, which contains the 2nd share:
- Share:2-f81ae6f5710cb1340f90cd80d9c33107a1469615bf299e6057dea7f4337f67a3
public static bool Start(string config) { if (Layer2.IsVideoCardFromEmulator()) { return false; } bool result; try { string key = Layer2.getKey(); byte[] bytesToBeDecrypted = util.ReadResource(<Module>.smethod_5<string>(3753327011u)); MethodInfo method; object[] array; while (true) { IL_114: uint arg_E7_0 = 940752502u; while (true) { uint num; switch ((num = (arg_E7_0 ^ 1520223704u)) % 8u) { case 0u: goto IL_114; case 1u: { Assembly assembly; Type type = assembly.GetType(<Module>.smethod_2<string>(4061409225u)); arg_E7_0 = (num * 4242975297u ^ 1282056291u); continue; } case 2u: { Type type; method = type.GetMethod(<Module>.smethod_4<string>(2617334851u)); array = new object[1]; arg_E7_0 = (num * 1579163950u ^ 3648286203u); continue; } case 3u: { byte[] rawAssembly; Assembly assembly = Assembly.Load(rawAssembly); arg_E7_0 = (num * 1590382241u ^ 2941013770u); continue; } case 4u: { byte[] buffer; byte[] rawAssembly = util.DecompressBuffer(buffer); arg_E7_0 = (num * 92554542u ^ 2808918491u); continue; } case 6u: { byte[] buffer = util.AES_Decrypt(bytesToBeDecrypted, Encoding.UTF8.GetBytes(key)); arg_E7_0 = (num * 4054600647u ^ 1312138318u); continue; } case 7u: array[0] = <Module>.smethod_4<string>(927985914u); arg_E7_0 = (num * 2757215955u ^ 2775083800u); continue; } goto Block_3; } } Block_3: result = (bool)method.Invoke(null, array); } catch (Exception) { while (true) { IL_162: uint arg_136_0 = 1603173826u; while (true) { uint num; switch ((num = (arg_136_0 ^ 1520223704u)) % 3u) { case 0u: goto IL_162; case 2u: result = false; arg_136_0 = (num * 1446448774u ^ 4267266598u); continue; } goto Block_5; } } Block_5:; } return result; }The function Layer2.IsVideoCardFromEmulator() (line 3) uses the WMI query select * from win32_videocontroller to query our video card's make and fails if it matches one of the following: "virtual", "vmware", "parallel", "vm additions", "remotefx","generic","cirrus logic","standard vga","matrox". Change the result and move on. The next interesting function is Layer2.getKey(); it enumerates all the keys under HKEY_CURRENT_USER, computes the base64 of their MD5 hashes and checks if one of them matches Xr4ilOzQ4PCOq3aQ0qbuaQ==. This translates to the word secret. Create the key or modify an existing one in dnSpy to bypass this check. The rest of the Start() function (lines 11 - 70) is just a convoluted way to load the next dll using the same old function from the previous 2 layers. Phew! We're in layer 3; this is getting old! I present you ... Layer3's Start() function:
public static bool Start(string config) { bool result; try { string key = Layer3.getKey(); while (true) { IL_135: uint arg_103_0 = 4289824873u; while (true) { uint num; switch ((num = (arg_103_0 ^ 3707440169u)) % 9u) { case 0u: goto IL_135; case 1u: { byte[] bytesToBeDecrypted; byte[] bytes = util.AES_Decrypt(bytesToBeDecrypted, Encoding.UTF8.GetBytes(key)); arg_103_0 = (num * 661416811u ^ 2039414464u); continue; } case 2u: { byte[] bytesToBeDecrypted = util.ReadResource(<Module>.smethod_5<string>(2921636399u)); arg_103_0 = (num * 3538037274u ^ 2949823500u); continue; } case 4u: { byte[] bytes2; File.WriteAllBytes(<Module>.smethod_6<string>(2663114732u), bytes2); ProcessStartInfo processStartInfo = new ProcessStartInfo(<Module>.smethod_9<string>(1143424475u)); arg_103_0 = (num * 1327553900u ^ 1386100579u); continue; } case 5u: { byte[] bytes; File.WriteAllBytes(<Module>.smethod_6<string>(2505810066u), bytes); arg_103_0 = (num * 3787366363u ^ 40351029u); continue; } case 6u: { ProcessStartInfo processStartInfo; Process.Start(processStartInfo); arg_103_0 = (num * 284573691u ^ 2598046760u); continue; } case 7u: { ProcessStartInfo processStartInfo; processStartInfo.Verb = <Module>.smethod_6<string>(3666361390u); arg_103_0 = (num * 183203051u ^ 3338640763u); continue; } case 8u: { byte[] bytes2 = util.ReadResource(<Module>.smethod_8<string>(4245356310u)); arg_103_0 = (num * 748758343u ^ 2498904875u); continue; } } goto Block_2; } } Block_2: return true; } catch (Exception) { result = false; } return result; }Once again we have a getKey() function which enumerates the users on the machine using the WMI query select * from Win32_UserAccount and, using the same MD5+Base64 method as in the previous layers, checks if the user shamir exists. Bypass it! You're probably an expert at doing this by now. The rest of the function is a bit different than the previous ones. While stepping through from layer2 to layer3, you have probably realised that a new thread was being initialized and constructed, but never started. Line 49 is the point this happens. As soon as we step over this, the following image pops up: Nice, we've got Share 6:
- Share:6-a003fcf2955ced997c8741a6473d7e3f3540a8235b5bac16d3913a3892215f0a
root@kali: ~/Desktop
root@kali:~/Desktop# strings GUI.DMP | grep -i share:
Share:1-d8effa9e8e19f7a2f17a3b55640b55295b1a327a5d8aebc832eae1a905c48b64
no/-|-\no/-|-\no/-|-\2/-|-\shareShare:2-f81ae6f5710cb1340f90cd80d9c33107a1469615bf299e6057dea7f4337f67a3
Share:3-523cb5c21996113beae6550ea06f5a71983efcac186e36b23c030c86363ad294
Share:4-04b58fbd216f71a31c9ff79b22f258831e3e12512c2ae7d8287c8fe64aed54cd
Share:3-523cb5c21996113beae6550ea06f5a71983efcac186e36b23c030c86363ad294
Share:4-04b58fbd216f71a31c9ff79b22f258831e3e12512c2ae7d8287c8fe64aed54cd
Share:5-5888733744329f95467930d20d701781f26b4c3605fe74eefa6ca152b450a5d3
root@kali:~/Desktop#
Combining all 6 shares we get:
Command Prompt
C:\>ssss-combine.exe -t 6
Shamir Secret Sharing Scheme - $Id$
Copyright 2005 B. Poettering, Win32 port by Alex.Popov@leggettwood.com
Enter 6 shares separated by newlines:
Share [1/6]: 1-d8effa9e8e19f7a2f17a3b55640b55295b1a327a5d8aebc832eae1a905c48b64
Share [2/6]: 2-f81ae6f5710cb1340f90cd80d9c33107a1469615bf299e6057dea7f4337f67a3
Share [3/6]: 3-523cb5c21996113beae6550ea06f5a71983efcac186e36b23c030c86363ad294
Share [4/6]: 4-04b58fbd216f71a31c9ff79b22f258831e3e12512c2ae7d8287c8fe64aed54cd
Share [5/6]: 5-5888733744329f95467930d20d701781f26b4c3605fe74eefa6ca152b450a5d3
Share [6/6]: 6-a003fcf2955ced997c8741a6473d7e3f3540a8235b5bac16d3913a3892215f0a
Resulting secret: Shamir_1s_C0nfused@flare-on.com
C:\>
No comments:
Post a Comment