Decrypt CS 5.0 encrypted methods
This commit is contained in:
parent
d3f1a2fd8e
commit
c9fa7caf91
|
@ -158,6 +158,8 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hasPinvokeMethod(TypeDefinition type, string methodName) {
|
static bool hasPinvokeMethod(TypeDefinition type, string methodName) {
|
||||||
|
if (type == null)
|
||||||
|
return false;
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (method.PInvokeInfo == null)
|
if (method.PInvokeInfo == null)
|
||||||
continue;
|
continue;
|
||||||
|
@ -166,5 +168,9 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool isAtLeastVersion50() {
|
||||||
|
return hasPinvokeMethod(cliSecureRtType, "LoadLibraryA");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
}
|
}
|
||||||
|
|
||||||
PeImage peImage;
|
PeImage peImage;
|
||||||
|
CliSecureRtType csRtType;
|
||||||
CodeHeader codeHeader = new CodeHeader();
|
CodeHeader codeHeader = new CodeHeader();
|
||||||
IDecrypter decrypter;
|
IDecrypter decrypter;
|
||||||
|
|
||||||
|
@ -115,16 +116,19 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
}
|
}
|
||||||
|
|
||||||
class NormalDecrypter : DecrypterBase {
|
class NormalDecrypter : DecrypterBase {
|
||||||
public NormalDecrypter(PeImage peImage, CodeHeader codeHeader)
|
uint codeHeaderSize;
|
||||||
|
|
||||||
|
public NormalDecrypter(PeImage peImage, CodeHeader codeHeader, uint codeHeaderSize)
|
||||||
: base(peImage, codeHeader) {
|
: base(peImage, codeHeader) {
|
||||||
|
this.codeHeaderSize = codeHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
|
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
|
||||||
byte[] data = peImage.offsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize);
|
byte[] data = peImage.offsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize);
|
||||||
for (int i = 0; i < data.Length; i++) {
|
for (int i = 0; i < data.Length; i++) {
|
||||||
byte b = data[i];
|
byte b = data[i];
|
||||||
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - 0x30 + i) % 16];
|
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - codeHeaderSize + i) % 16];
|
||||||
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - 0x30 + i + 7) % 16];
|
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - codeHeaderSize + i + 7) % 16];
|
||||||
data[i] = b;
|
data[i] = b;
|
||||||
}
|
}
|
||||||
return getCodeBytes(data, out code, out extraSections);
|
return getCodeBytes(data, out code, out extraSections);
|
||||||
|
@ -186,20 +190,24 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos);
|
void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CS 4.0
|
abstract class CsHeaderBase : ICsHeader {
|
||||||
class CsHeader40 : ICsHeader {
|
protected readonly MethodsDecrypter methodsDecrypter;
|
||||||
MethodsDecrypter methodsDecrypter;
|
protected readonly uint codeHeaderSize;
|
||||||
|
|
||||||
public CsHeader40(MethodsDecrypter methodsDecrypter) {
|
public CsHeaderBase(MethodsDecrypter methodsDecrypter, uint codeHeaderSize) {
|
||||||
this.methodsDecrypter = methodsDecrypter;
|
this.methodsDecrypter = methodsDecrypter;
|
||||||
|
this.codeHeaderSize = codeHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDecrypter createDecrypter() {
|
public abstract IDecrypter createDecrypter();
|
||||||
return new Decrypter40(methodsDecrypter.peImage);
|
|
||||||
|
public virtual void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MethodInfo> getMethodInfos(uint codeHeaderOffset) {
|
public abstract List<MethodInfo> getMethodInfos(uint codeHeaderOffset);
|
||||||
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + 0x28;
|
|
||||||
|
protected List<MethodInfo> getMethodInfos1(uint codeHeaderOffset) {
|
||||||
|
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize;
|
||||||
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
|
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
|
||||||
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 4) {
|
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 4) {
|
||||||
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset);
|
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset);
|
||||||
|
@ -210,24 +218,8 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
return methodInfos;
|
return methodInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos) {
|
protected List<MethodInfo> getMethodInfos2(uint codeHeaderOffset) {
|
||||||
}
|
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize;
|
||||||
}
|
|
||||||
|
|
||||||
// CS 4.5
|
|
||||||
class CsHeader45 : ICsHeader {
|
|
||||||
MethodsDecrypter methodsDecrypter;
|
|
||||||
|
|
||||||
public CsHeader45(MethodsDecrypter methodsDecrypter) {
|
|
||||||
this.methodsDecrypter = methodsDecrypter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDecrypter createDecrypter() {
|
|
||||||
return new Decrypter45(methodsDecrypter.peImage, methodsDecrypter.codeHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MethodInfo> getMethodInfos(uint codeHeaderOffset) {
|
|
||||||
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + 0x28;
|
|
||||||
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
|
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
|
||||||
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 8) {
|
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 8) {
|
||||||
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset);
|
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset);
|
||||||
|
@ -237,34 +229,8 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
return methodInfos;
|
return methodInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos) {
|
protected List<MethodInfo> getMethodInfos4(uint codeHeaderOffset) {
|
||||||
}
|
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize;
|
||||||
}
|
|
||||||
|
|
||||||
// CS 5.2+
|
|
||||||
class CsHeader5 : ICsHeader {
|
|
||||||
MethodsDecrypter methodsDecrypter;
|
|
||||||
|
|
||||||
public CsHeader5(MethodsDecrypter methodsDecrypter) {
|
|
||||||
this.methodsDecrypter = methodsDecrypter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDecrypter createDecrypter() {
|
|
||||||
switch (getSigType(methodsDecrypter.codeHeader.signature)) {
|
|
||||||
case SigType.Normal:
|
|
||||||
return new NormalDecrypter(methodsDecrypter.peImage, methodsDecrypter.codeHeader);
|
|
||||||
|
|
||||||
case SigType.Pro:
|
|
||||||
return new ProDecrypter(methodsDecrypter.peImage, methodsDecrypter.codeHeader);
|
|
||||||
|
|
||||||
case SigType.Unknown:
|
|
||||||
default:
|
|
||||||
throw new ArgumentException("sig");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MethodInfo> getMethodInfos(uint codeHeaderOffset) {
|
|
||||||
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + 0x30;
|
|
||||||
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
|
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
|
||||||
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 16) {
|
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 16) {
|
||||||
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset);
|
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset);
|
||||||
|
@ -275,8 +241,65 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
}
|
}
|
||||||
return methodInfos;
|
return methodInfos;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos) {
|
// CS 4.0
|
||||||
|
class CsHeader40 : CsHeaderBase {
|
||||||
|
public CsHeader40(MethodsDecrypter methodsDecrypter)
|
||||||
|
: base(methodsDecrypter, 0x28) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IDecrypter createDecrypter() {
|
||||||
|
return new Decrypter40(methodsDecrypter.peImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<MethodInfo> getMethodInfos(uint codeHeaderOffset) {
|
||||||
|
return getMethodInfos1(codeHeaderOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CS 4.5
|
||||||
|
class CsHeader45 : CsHeaderBase {
|
||||||
|
public CsHeader45(MethodsDecrypter methodsDecrypter)
|
||||||
|
: base(methodsDecrypter, 0x28) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IDecrypter createDecrypter() {
|
||||||
|
return new Decrypter45(methodsDecrypter.peImage, methodsDecrypter.codeHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<MethodInfo> getMethodInfos(uint codeHeaderOffset) {
|
||||||
|
return getMethodInfos2(codeHeaderOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CS 5.0+
|
||||||
|
class CsHeader5 : CsHeaderBase {
|
||||||
|
public CsHeader5(MethodsDecrypter methodsDecrypter, uint codeHeaderSize)
|
||||||
|
: base(methodsDecrypter, codeHeaderSize) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IDecrypter createDecrypter() {
|
||||||
|
switch (getSigType(methodsDecrypter.codeHeader.signature)) {
|
||||||
|
case SigType.Normal:
|
||||||
|
return new NormalDecrypter(methodsDecrypter.peImage, methodsDecrypter.codeHeader, codeHeaderSize);
|
||||||
|
|
||||||
|
case SigType.Pro:
|
||||||
|
return new ProDecrypter(methodsDecrypter.peImage, methodsDecrypter.codeHeader);
|
||||||
|
|
||||||
|
case SigType.Unknown:
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("sig");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<MethodInfo> getMethodInfos(uint codeHeaderOffset) {
|
||||||
|
if (codeHeaderSize == 0x28)
|
||||||
|
return getMethodInfos2(codeHeaderOffset);
|
||||||
|
return getMethodInfos4(codeHeaderOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos) {
|
||||||
uint offset = methodDefTable.fileOffset - methodDefTable.totalSize;
|
uint offset = methodDefTable.fileOffset - methodDefTable.totalSize;
|
||||||
foreach (var methodInfo in methodInfos) {
|
foreach (var methodInfo in methodInfos) {
|
||||||
offset += methodDefTable.totalSize;
|
offset += methodDefTable.totalSize;
|
||||||
|
@ -291,6 +314,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
|
|
||||||
public bool decrypt(PeImage peImage, string filename, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
|
public bool decrypt(PeImage peImage, string filename, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
|
||||||
this.peImage = peImage;
|
this.peImage = peImage;
|
||||||
|
this.csRtType = csRtType;
|
||||||
try {
|
try {
|
||||||
return decrypt2(ref dumpedMethods);
|
return decrypt2(ref dumpedMethods);
|
||||||
}
|
}
|
||||||
|
@ -321,12 +345,15 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
Unknown,
|
Unknown,
|
||||||
V40,
|
V40,
|
||||||
V45,
|
V45,
|
||||||
V52,
|
V50, // 5.0, possibly also 5.1
|
||||||
|
V52, // 5.2+ (or maybe 5.1+)
|
||||||
}
|
}
|
||||||
|
|
||||||
CsHeaderVersion getCsHeaderVersion(uint codeHeaderOffset, MetadataType methodDefTable) {
|
CsHeaderVersion getCsHeaderVersion(uint codeHeaderOffset, MetadataType methodDefTable) {
|
||||||
if (!isOldHeader(methodDefTable))
|
if (!isOldHeader(methodDefTable))
|
||||||
return CsHeaderVersion.V52;
|
return CsHeaderVersion.V52;
|
||||||
|
if (csRtType.isAtLeastVersion50())
|
||||||
|
return CsHeaderVersion.V50;
|
||||||
if (isCsHeader40(codeHeaderOffset))
|
if (isCsHeader40(codeHeaderOffset))
|
||||||
return CsHeaderVersion.V40;
|
return CsHeaderVersion.V40;
|
||||||
return CsHeaderVersion.V45;
|
return CsHeaderVersion.V45;
|
||||||
|
@ -364,7 +391,8 @@ namespace de4dot.code.deobfuscators.CliSecure {
|
||||||
switch (getCsHeaderVersion(codeHeaderOffset, methodDefTable)) {
|
switch (getCsHeaderVersion(codeHeaderOffset, methodDefTable)) {
|
||||||
case CsHeaderVersion.V40: return new CsHeader40(this);
|
case CsHeaderVersion.V40: return new CsHeader40(this);
|
||||||
case CsHeaderVersion.V45: return new CsHeader45(this);
|
case CsHeaderVersion.V45: return new CsHeader45(this);
|
||||||
case CsHeaderVersion.V52: return new CsHeader5(this);
|
case CsHeaderVersion.V50: return new CsHeader5(this, 0x28);
|
||||||
|
case CsHeaderVersion.V52: return new CsHeader5(this, 0x30);
|
||||||
default: throw new ApplicationException("Unknown CS header");
|
default: throw new ApplicationException("Unknown CS header");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user