Jump to content
Tuts 4 You

[C#] Decrypt {SmartAssembly} 3.2.3268.0 resources.


high6

Recommended Posts

@Sirp: First method is the Strings class .cctor. The 2nd one is the method to retrieve the delegates, and the 3rd one is the resource decryption. The strings class completely deobfuscated is this:


public class Strings
{
// Fields
[NonSerialized]
internal static GetString #a;
private static byte[] bytes;
private static bool cacheStrings;
private static Hashtable hashtable;
private static string MustUseCache;
private static int offset;
private static string OffsetValue; // Methods
static Strings()
{
Strings.CreateGetStringDelegate(typeof(Strings));
MustUseCache = "0";
OffsetValue = "9";
bytes = null;
hashtable = null;
cacheStrings = false;
offset = 0;
if (MustUseCache == "1")
{
cacheStrings = true;
hashtable = new Hashtable();
}
offset = Convert.ToInt32(OffsetValue);
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("{4f9e0208-fec1-4018-9c9e-6d3330c8cac8}"))
{
int count = Convert.ToInt32(stream.Length);
byte[] buffer = new byte[count];
stream.Read(buffer, 0, count);
bytes = SimpleZip.Unzip(buffer);
buffer = null;
stream.Close();
}
} public static string Get(int num1)
{
num1 -= offset;
if (cacheStrings)
{
string str = (string) hashtable[num1];
if (str != null)
{
return str;
}
}
int count = 0;
int index = num1;
int num3 = Strings.bytes[index++];
if ((num3 & 0x80) == 0)
{
count = num3;
if (count == 0)
{
return string.Empty;
}
}
else if ((num3 & 0x40) == 0)
{
count = ((num3 & 0x3f) << 8) + Strings.bytes[index++];
}
else
{
count = ((((num3 & 0x1f) << 0x18) + (Strings.bytes[index++] << 0x10)) + (Strings.bytes[index++] << 8)) + Strings.bytes[index++];
}
try
{
byte[] bytes = Convert.FromBase64String(Encoding.UTF8.GetString(Strings.bytes, index, count));
string str2 = string.Intern(Encoding.UTF8.GetString(bytes, 0, bytes.Length));
if (cacheStrings)
{
try
{
hashtable.Add(num1, str2);
}
catch
{
}
}
return str2;
}
catch
{
return null;
}
}
}
//And resources deobbed:public static byte[] Unzip(byte[] buffer)
{
Assembly callingAssembly = Assembly.GetCallingAssembly();
if (callingAssembly != Assembly.GetExecutingAssembly())
{
byte[] buffer2 = new byte[] {
0x0, 0x24, 0x0, 0x0, 0x4, 0x80, 0x0, 0x0, 0x94, 0x0, 0x0, 0x0, 0x6, 0x2, 0x0, 0x0,
0x0, 0x24, 0x0, 0x0, 0x52, 0x53, 0x41, 0x31, 0x0, 0x4, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0,
0x8f, 0xc1, 0xf, 0x45, 0x44, 0x6, 0xbf, 0x85, 0x56, 0x8f, 0x95, 0x86, 0x75, 0x56, 0x73, 0x83,
0xeb, 0x34, 0x4e, 0xf5, 0x16, 0xbe, 0xc3, 0x93, 0x7a, 0xad, 0x92, 0x39, 0xb1, 0x5e, 0xdf, 0x1e,
0xb6, 0x63, 0xe2, 0x50, 0x1c, 0xe2, 0x11, 0xab, 0x47, 0xfb, 0x6c, 0x26, 0x55, 0x46, 0x97, 0xb4,
0x87, 0xe8, 0xcd, 0xa6, 0xb2, 0xd6, 0x62, 0xb4, 0x21, 0x46, 0x41, 0x7d, 0x62, 0xaa, 0x9c, 0x74,
0xc4, 0x71, 0x9b, 0xc5, 0x91, 0xd, 0xb2, 0x65, 0x95, 0x84, 0xad, 0xc4, 0xf0, 0x7f, 0x6, 0x87,
0x74, 0x4b, 0x3, 0x80, 0x85, 0xb7, 0x6c, 0xc6, 0x33, 0x6a, 0x71, 0x8, 0x73, 0x8c, 0xcf, 0xd0,
0xaa, 0xbe, 0x44, 0x76, 0xe, 0xc9, 0x4c, 0x8d, 0xfd, 0x29, 0x0, 0x9f, 0xc2, 0xde, 0xf7, 0x84,
0x55, 0xce, 0x19, 0x20, 0xa2, 0xa5, 0x69, 0x6d, 0x10, 0x87, 0x34, 0x38, 0x6c, 0xe0, 0x4a, 0xd9
};
byte[] publicKey = callingAssembly.GetName().GetPublicKey();
if (publicKey == null)
{
return null;
}
if (publicKey.Length != 0xa0)
{
return null;
}
for (int i = 0x0; i < 0xa0; i++)
{
if (publicKey[i] != buffer2[i])
{
return null;
}
}
}
ZipStream stream = new ZipStream(buffer);
byte[] buf = new byte[0x0];
int num2 = stream.ReadInt();
if (num2 == 0x4034b50)
{
short num3 = (short) stream.ReadShort();
int num4 = stream.ReadShort();
int num5 = stream.ReadShort();
if (((num2 != 0x4034b50) || (num3 != 0x14)) || ((num4 != 0x0) || (num5 != 0x8)))
{
throw new FormatException("Wrong Header Signature");
}
stream.ReadInt();
stream.ReadInt();
stream.ReadInt();
int num6 = stream.ReadInt();
int count = stream.ReadShort();
int num8 = stream.ReadShort();
if (count > 0x0)
{
byte[] buffer5 = new byte[count];
stream.Read(buffer5, 0x0, count);
}
if (num8 > 0x0)
{
byte[] buffer6 = new byte[num8];
stream.Read(buffer6, 0x0, num8);
}
byte[] buffer7 = new byte[(uint) (stream.Length - stream.Position)];
stream.Read(buffer7, 0x0, buffer7.Length);
Inflater inflater = new Inflater(buffer7);
buf = new byte[num6];
inflater.Inflate(buf, 0x0, buf.Length);
buffer7 = null;
}
else
{
int num9 = num2 >> 0x18;
num2 -= num9 << 0x18;
if (num2 != 0x7d7a7b)
{
throw new FormatException("Unknown Header");
}
switch (num9)
{
case 0x1:
{
int num13;
int num10 = stream.ReadInt();
buf = new byte[num10];
for (int j = 0x0; j < num10; j += num13)
{
int num12 = stream.ReadInt();
num13 = stream.ReadInt();
byte[] buffer8 = new byte[num12];
stream.Read(buffer8, 0x0, buffer8.Length);
new Inflater(buffer8).Inflate(buf, j, num13);
}
break;
}
case 0x2:
{
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
provider.Key = new byte[] { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
provider.IV = new byte[] { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2 };
byte[] buffer9 = provider.CreateDecryptor().TransformFinalBlock(buffer, 0x4, buffer.Length - 0x4);
provider.Clear();
buf = Unzip(buffer9);
goto Label_0275;
}
}
}
Label_0275:
stream.Close();
stream = null;
return buf;
}

OffsetValue is (I think) where the first string begins in the resources. It's always different in each exe. Also, in your resource method, the IV and key are always different in each exe.

Edit: In the "Get" method that I posted, the param is the pointer int value that you see when decompiling any method with encrypted strings.

Edited by bball0002
Link to comment
  • 2 weeks later...

Hi guys!

I need help with a smartassembly protected .net app i'm currently trying to reverse :)

The app is communicating with an auth server to check if it has been bought or not, this is simple md5 hashed string comparison but the developer has added a salt in the md5 hashed string.. I need to find that salt!

After some searches, i found that the salt has been defined as a simple string, i just have to retrieve it then..

Here is what i did so far:

- I opened my target with reflector.

- I extracted the ressource file which contains the DES encrypted string block.

- I decrypted and inflated it and all i have now is the ressource file fully decrypted which contains all the strings, encoded in base64.

Good :) final step: i retrieved the string ID in the target which corresponds to the salt string and all i've to do now is reaching the corresponding offset in the ressource file to get my base64 encoded string, BUT, i can't get the "retrieving string" function to work!

I tried with the function you provided in ur previous post:

public static string Get(int num1)
{
num1 -= offset;
if (cacheStrings)
{
string str = (string) hashtable[num1];
if (str != null)
{
return str;
}
}
int count = 0;
int index = num1;
int num3 = Strings.bytes[index++];
if ((num3 & 0x80) == 0)
{
count = num3;
if (count == 0)
{
return string.Empty;
}
}
else if ((num3 & 0x40) == 0)
{
count = ((num3 & 0x3f) << 8) + Strings.bytes[index++];
}
else
{
count = ((((num3 & 0x1f) << 0x18) + (Strings.bytes[index++] << 0x10)) + (Strings.bytes[index++] << 8)) + Strings.bytes[index++];
}
try
{
byte[] bytes = Convert.FromBase64String(Encoding.UTF8.GetString(Strings.bytes, index, count));
string str2 = string.Intern(Encoding.UTF8.GetString(bytes, 0, bytes.Length));
if (cacheStrings)
{
try
{
hashtable.Add(num1, str2);
}
catch
{
}
}
return str2;
}
catch
{
return null;
}
}

But i always get an index out of bound exception, i guess that's because of that delegate thingy which i'm not really friendly with :/ or maybe i'm using it the wrong way..

The delegate thing i'm talking about is that one:

internal static GetString #a;
Strings.CreateGetStringDelegate(typeof(Strings));
int num3 = Strings.bytes[index++];

Visual studio tells me that he can't find CreateGetStringDelegate etc etc..

Hope you guys can help me :)

Thanks!

Link to comment

Delegates Tutorial
/>http://msdn.microsoft.com/en-us/library/aa288459%28VS.71%29.aspx

Understanding Delegates in C#
/>http://www.codeproject.com/KB/cs/Delegates_in_C_.aspx

C# - Delegates 101 - A Practical Example
/>http://www.codeproject.com/KB/cs/Cs_delegates101_practical.aspx

Edited by sirp
Link to comment

Thank you sirp, i already searched docs about delegates in C# but i'll check yours!

But i still got an error with this line:

internal static GetString #a;

I don't understand what this #a is made for.

Link to comment
  • 4 months later...

SmartAssembly 6.0

add aes

switch (type)

{

case 1:

int num11;

int num8 = stream.ReadInt32();

buffer = new byte[num8];

for (int i = 0x0; i < num8; i += num11)

{

int num10 = stream.ReadInt32();

num11 = stream.ReadInt32();

byte[] buffer5 = new byte[num10];

stream.Read(buffer5, 0x0, buffer5.Length);

new Class_72_Object(buffer5).Method_2(buffer, i, num11);

}

break;

case 2:

DESCryptoServiceProvider provider = new DESCryptoServiceProvider();

provider.Key = new byte[] { 14, 0x4f, 70, 0xf1, 0xfe, 210, 0xb1, 60 };

//{ 0xea, 0xd0, 0xe0, 0x71, 0xed, 0x13, 0xac, 0x58 };

provider.IV = new byte[] { 0x99, 0x6b, 0x86, 0x63, 200, 0x44, 0x72, 0xcd };

//{ 0xa1, 0x47, 1, 0x7c, 0x26, 0x1b, 0xfd, 0x57 };

buffer8 = provider.CreateDecryptor().TransformFinalBlock(buffer1, 4, buffer1.Length - 4);

provider.Clear();

buffer = Decrypt(buffer8);

break;

case 3:

RijndaelManaged provideraes = new RijndaelManaged();

provideraes.Key = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };

provideraes.IV = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };

buffer8 = provideraes.CreateDecryptor().TransformFinalBlock(buffer1, 4, buffer1.Length - 4);

provideraes.Clear();

buffer = Decrypt(buffer8);

break;

}

but i can't build high6 's code

error:"can't find "GetManifestResource;

EmbeddedResource er = GetManifestResource(Assembly); reporter error line

Link to comment
  • 3 weeks later...
  • 2 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...