Confuser Metadata-Confusion explained
Dieser Artikel wurde auf Englisch geschrieben da dieses Writeup auch an nicht deutschsprachige Reverser gerichtet ist.
Der Artikel beschreibt die Vorgehensweise des Confusers beim Anwenden der sog. Metadata-Confusion. Diese Confusion schafft es die Assembly weiterhin lauffähig zu halten, allerdings die Metadata so zu manipulieren dass jegliche Decompiler und sogar Mono.Cecil versagen die Datei zu lesen.
Dieses Writeup ist nur mit dem Source des Confusers nachzuvollziehen und ist an Experten gerichtet, solltet ihr dennoch Interesse am Verstehen des Artikels haben so lest euch zunächst den Artikel zum .NET Fileformat durch.
Introduction:
I’ll try to give sense to the quite confusing source of the InvaildMetadata-Confusion and point out how the confusion works.Confuser makes use of the Mono.Cecil.Metadata-namespace to edit/add the .NET metadata tables in the #~ stream. Many aspects of this MD-confusion is based on replacing, adding and randomizing table-entries.
All the metadata tables with detailed information can be found in this great article, this is really helpfull to get the nessessary information and to eventually write a deobfuscator!Phase 1:
In the beginning this phase adds a invaild DeclSecurity to the DeclSecurityTable. The Flags (2 bytes), the index to a Type/Method/Assembly (4 bytes) and the PermissionSet (4 bytes) are set to 0xffffffff, therefore no index can be found.Next random characters are added to the #String-stream, 0×10000 in total.
If no reflection is used in the assembly a new row in the ManifestResourceTable is added:
The Offset to the ressource points to -1 (0xffffffff), the ressource is set to private (0×02) and the ressource name points to the generated random stuff in the #String-stream.This is basicly what the first phase does, this probably wouldn’t mess up the file although the ressource is quite a nesty thing…
Phase 2:
All the hard confusion is done in this phase, its hard to follow this phase without the source. Therefore grab the confuser source and check out InvaildMDConfusion.cs!!!11111!The phase begins with setting Col1 (I assume this is Column1 = Name) in the TypeDefTable to 0xffff. This invaild index points to nothing, no name for this type can be found.
If there is no reflection used and the target runtime is < 4 (Runtime =< 3.5) serveral things are done:
A list<uint> (named nss) with all the referenced namespaces of each TypeDef is filled (Row.Col3 = Namespaceindex in #String). Next a nested type in TypeDef is created (Flags = 0, Name = 0x7fffffff, Namespace = 0×00, Extends index in TypeDef/TypeRef = 0x3FFFD, FieldList and MethodList = Last Entry of Field/Method table).
Next this created nested class is added to the NestedClassTable.
Finally Confuser loops trough all the namespaces and adds a new type (same values as above), links it with a nested type and also adds this type to the NestedTypeTable:
foreach (uint i in nss) { uint type = (uint)accessor.TableHeap.GetTable<TypeDefTable>(Table.TypeDef).AddRow(new Row<TypeAttributes, uint, uint, uint, uint, uint>(0, 0x7fffffff, i, 0x3FFFD, fldLen, mtdLen)); accessor.TableHeap.GetTable<NestedClassTable>(Table.NestedClass).AddRow(new Row<uint, uint>(nested, type)); }Next the names of all Parameters in the Param Table are set to an invaild value, Col3 = 0x7fffffff;
This phase so far destroyed all the names of types and paramters by setting them to Int32.Max …A invaild module with a random string is added to the ModuleTable, also an invaild assembly with a random name is added to the Assembly Table.
10 Entities are added to the ENCLogTable and ENCMapTable with random values (never heard about ENCMapTable before o.O).An invaild AssemblyReference is added to the AssemblyRefTable (invaild name and values).
Between 5 and 10 invaild types are added, as already descripted above.
Between 10 and 20 invaild Params are added to the GenericParamTable, a nonexistend Metadata-Token is generated, the Name is set to Index 42 (= answer to anything) LOOOL
The same happens to the GenericParamConstraintTable, take a look at the source…Finally the tables NestedClass, ManifestRessource and GenericParamConstraintTable are randomized, also pretty effective for obfsucation.
If you read so far, well done, you got my respect
Phase 3:
This phase does some things with the PE-file, it acctually doesn’t harm ILSpy or Reflector.
The attribute-flags of the last 2 bytes of each section is set to 0×20 instead of 0×00, no idea what the sense is.
The #~ stream is renamed to #- , doesn’t makes a big diffence. I think its even allowed by the .NET Framework to use #- instead of #~.Finally two sections of the PE-file are changed, although this didn’t happen when I implemented the third phase.
How to break Confuser Invaild MD:
Confuser is awesome and hard to deobfuscate, Mono.Cecil can’t even handle with these obfuscated files.You have to change and recompile the Mono.Cecil, especially the ressources and the nested types makes Mono.Cecil hard to deal with the assembly.
OR you have to implement an own metadata-writer / manipulator, all the information are given in the link posted above. You would have to rebuild the whole assembly, therefore rewriting / fixxing Mono.Cecil is probably the better way…Conclusion:
The third Phase (Phase 4) is easy to fix, the other other two phases are quite hard. Give it a try, I’d like to see any attempts to break the MD-ConfusionAny questions so far?
Greez Easy
Noch keine Kommentare vorhanden.