代码改变世界

[.NET逆向] [入门级]de4dot参数详解

2019-07-07 22:19  狼人:-)  阅读(8202)  评论(0编辑  收藏  举报

为了避免被0xd4d(de4dot作者)认为是"N00bUser"
为了认识到Some of the advanced options may be incompatible, causing a nice exception.
With great power comes great responsibility.(de4dot开头2句话,可google翻译)
务必要了解如何带参数运行de4dot!!!



“de4dot弹出的用法都是英文,我看不懂怎么办?”
所以我写了一篇入门级教程,只要能认真看此贴,多用de4dot脱复杂些的壳,你一定能掌握de4dot的高级用法



在此之前,你需要准备好:
1. dnSpy(勾好这个选项)
<ignore_js_op> 
2. de4dot(最新版请点击https://ci.appveyor.com/project/0xd4d/de4dot/branch/master/artifacts下载)


 

正文


直接运行de4dot,看看de4dot告诉我们如何使用它。
这里我直接把英文以及翻译附上。会提到的参数标记为红色,这些比较常用

de4dot v3.1.41592.3405 Copyright (C) 2011-2015 de4dot@gmail.com
Latest version and source code: https://github.com/0xd4d/de4dot

Some of the advanced options may be incompatible, causing a nice exception.
With great power comes great responsibility.

de4dot.exe <options> <file options>
Options:
  //全局参数
  -r DIR           Scan for .NET files in all subdirs
  //搜索当前目录以及子目录中所有程序集并去混淆
  -ro DIR          Output base dir for recursively found files
  //同-r参数,但是并不搜索子目录,仅限当前目录
  -ru              Skip recursively found files with unsupported obfuscator
  //跳过查找到带有de4dot不支持的混淆器的程序集
  -d               Detect obfuscators and exit
  //查明混淆器名称,然后退出de4dot
  --asm-path PATH  Add an assembly search path
  //增加一个被搜索的目录
  --dont-rename    Don't rename classes, methods, etc.
  //禁止所有重命名(比如类,方法,字段,属性,资源......)

  --keep-names FLAGS
                   Don't rename n(amespaces), t(ypes), p(rops), e(vents), f(ields), m(ethods), a(rgs), g(enericparams), d(elegate fields). Can be combined, eg. efm
  //禁止对指定内容重命名。比如我不想重命名命名空间、类名和方法名,那么我可以添加这样一个参数"--keep-names ntm",这里的n代表namespaces,t代表types,m代表methods
  --dont-create-params
                   Don't create method params when renaming
  //在重命名时不创建方法参数(?我也看不太懂)
  --dont-restore-props
                   Don't restore properties/events
  //不还原属性和事件
  --default-strtyp TYPE
                   Default string decrypter type
  //与--strtyp类似
  --default-strtok METHOD
                   Default string decrypter method token or [type::][name][(args,...)]
  //与--strtok类似
  --no-cflow-deob  No control flow deobfuscation (NOT recommended)
  //不还原控制流混淆(举个例子,ConfuserEx的恐怖的switch,几乎只能让程序来还原)
  --only-cflow-deob
                   Only control flow deobfuscation
  //仅还原控制流混淆
  --load-new-process
                   Load executed assemblies into a new process
  //将程序集放在新进程中进行脱壳处理
  --keep-types     Keep obfuscator types, fields, methods
  //保留混淆器类、字段和方法
  --preserve-tokens
                   Preserve important tokens, #US, #Blob, extra sig data
  //保持tokens不变,包括#US, #Blob, extra sig data。比如有个方法的token是0x06000008,不使用这个选项,去混淆之后某方法的token可能会变成0x06000004(比如这之前有4个无效方法被de4dot移除了),使用这个选项之后,无论怎样,方法的token始终是0x06000008

  --preserve-table FLAGS
                   Preserve rids in table: tr (TypeRef), td (TypeDef), fd (Field), md (Method), pd (Param), mr (MemberRef), s (StandAloneSig), ed (Event), pr (Property), ts (TypeSpec), ms (MethodSpec), all (all previous tables). Use - to disable (eg. all,-pd). Can be combined: ed,fd,md
  //保持表中指定种类的tokens不变。比如"--preserve-table ed,fd,md","--preserve-table all"

  --preserve-strings
                   Preserve #Strings heap offsets
  //保持#Strings堆偏移不变
  --preserve-us    Preserve #US heap offsets
  //保持#US堆偏移不变
  --preserve-blob  Preserve #Blob heap offsets
  //保持#Blob堆偏移不变
  --preserve-sig-data
                   Preserve extra data at the end of signatures
  //保持额外的签名数据偏移不变

  --one-file       Deobfuscate one file at a time
  //一次只对一个程序集去混淆
  -v               Verbose
  //显示详细信息
  -vv              Very verbose
  //显示更多详细信息(?应该是,反正和-v一样都会显示信息)

  -h               Show this help message
  //显示帮助,就是我翻译的这些内容
  --help           Same as -h
  //同-h

File options:
  //局部参数
  -f FILE          Name of .NET file
  //指定被去混淆的程序集的路径(可以是相对路径或者绝对路径)
  -o FILE          Name of output file
  //指定输出去混淆后的程序集的路径(可以是相对路径或者绝对路径)
  -p TYPE          Obfuscator type (see below)
  //指定混淆器类型(下面写了)

  --strtyp TYPE    String decrypter type
  //指定如何使用字符串解密器(字符串解密器指的是被混淆程序集中的一个方法)
  --strtok METHOD  String decrypter method token or [type::][name][(args,...)]
  //指定哪一个方法作为字符串解密器


Deobfuscator options:
//混淆器参数(我就不翻译了,因为有些没用过,不是很常用)
//比如"--un-name REGEX  Valid name regex pattern (^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$)"
//全大写单词代表一个参数,最尾处有一个括号,里面代表默认参数,如果你不填这个参数,那么de4dot认为你输入了--un-name "^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$",因为这是默认的
//这里有个地方要注意,REGEX的内容一定要用""包起来,比如--un-name ^就是无效的,--un-name "^
"是有效的
//而BOOL只要直接输入True/False,比如--an-methods True
Type un (Unknown)
  --un-name REGEX  Valid name regex pattern (^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$)

Type an (Agile.NET)
  --an-name REGEX  Valid name regex pattern (^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --an-methods BOOL
                   Decrypt methods (True)
  --an-rsrc BOOL   Decrypt resources (True)
  --an-stack BOOL  Remove all StackFrameHelper code (True)
  --an-vm BOOL     Restore VM code (True)
  --an-initlocals BOOL
                   Set initlocals in method header (True)

Type bl (Babel .NET)
  --bl-name REGEX  Valid name regex pattern (^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --bl-inline BOOL Inline short methods (True)
  --bl-remove-inlined BOOL
                   Remove inlined methods (True)
  --bl-methods BOOL
                   Decrypt methods (True)
  --bl-rsrc BOOL   Decrypt resources (True)
  --bl-consts BOOL Decrypt constants and arrays (True)
  --bl-embedded BOOL
                   Dump embedded assemblies (True)

Type cf (CodeFort)
  --cf-name REGEX  Valid name regex pattern (!^[a-zA-Z]{1,3}$&!^[_<>{}$.`-]$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --cf-embedded BOOL
                   Dump embedded assemblies (True)

Type cv (CodeVeil)
  --cv-name REGEX  Valid name regex pattern (!^[A-Za-z]{1,2}$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)

Type cw (CodeWall)
  --cw-name REGEX  Valid name regex pattern (!^[0-9A-F]{32}$&!^[_<>{}$.`-]$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --cw-embedded BOOL
                   Dump embedded assemblies (True)
  --cw-decrypt-main BOOL
                   Decrypt main embedded assembly (True)

Type cr (Confuser)
  --cr-name REGEX  Valid name regex pattern (^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$)
  --cr-antidb BOOL Remove anti debug code (True)
  --cr-antidump BOOL
                   Remove anti dump code (True)
  --cr-decrypt-main BOOL
                   Decrypt main embedded assembly (True)

Type co (Crypto Obfuscator)
  --co-name REGEX  Valid name regex pattern (!^(get_|set_|add_|remove_)?[A-Z]{1,3}(?:`\d+)?$&!^(get_|set_|add_|remove_)?c[0-9a-f]{32}(?:`\d+)?$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --co-tamper BOOL Remove tamper protection code (True)
  --co-consts BOOL Decrypt constants (True)
  --co-inline BOOL Inline short methods (True)
  --co-ldnull BOOL Restore ldnull instructions (True)

Type ds (DeepSea)
  --ds-name REGEX  Valid name regex pattern (^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --ds-inline BOOL Inline short methods (True)
  --ds-remove-inlined BOOL
                   Remove inlined methods (True)
  --ds-rsrc BOOL   Decrypt resources (True)
  --ds-embedded BOOL
                   Dump embedded assemblies (True)
  --ds-fields BOOL Restore fields (True)
  --ds-keys BOOL   Rename resource keys (True)
  --ds-casts BOOL  Deobfuscate casts (True)

Type df (Dotfuscator)
  --df-name REGEX  Valid name regex pattern (!^(?:eval_)?[a-z][a-z0-9]{0,2}$&!^A_[0-9]+$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)

Type dr3 (.NET Reactor)
  --dr3-name REGEX Valid name regex pattern (^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --dr3-types BOOL Restore types (object -> real type) (True)
  --dr3-inline BOOL
                   Inline short methods (True)
  --dr3-remove-inlined BOOL
                   Remove inlined methods (True)
  --dr3-ns1 BOOL   Clear namespace if there's only one class in it (True)
  --dr3-sn BOOL    Remove anti strong name code (True)

Type dr4 (.NET Reactor)
  --dr4-name REGEX Valid name regex pattern (^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --dr4-methods BOOL
                   Decrypt methods (True)
  --dr4-bools BOOL Decrypt booleans (True)
  --dr4-types BOOL Restore types (object -> real type) (True)
  --dr4-inline BOOL
                   Inline short methods (True)
  --dr4-remove-inlined BOOL
                   Remove inlined methods (True)
  --dr4-embedded BOOL
                   Dump embedded assemblies (True)
  --dr4-rsrc BOOL  Decrypt resources (True)
  --dr4-ns1 BOOL   Clear namespace if there's only one class in it (True)
  --dr4-sn BOOL    Remove anti strong name code (True)
  --dr4-sname BOOL Rename short names (False)

Type ef (Eazfuscator.NET)
  --ef-name REGEX  Valid name regex pattern (!^[a-zA-Z]$&!^#=&!^dje_.+_ejd$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)

Type go (Goliath.NET)
  --go-name REGEX  Valid name regex pattern (!^[A-Za-z]{1,2}(?:`\d+)?$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --go-inline BOOL Inline short methods (True)
  --go-remove-inlined BOOL
                   Remove inlined methods (True)
  --go-locals BOOL Restore locals (True)
  --go-ints BOOL   Decrypt integers (True)
  --go-arrays BOOL Decrypt arrays (True)
  --go-sn BOOL     Remove anti strong name code (True)

Type il (ILProtector)
  --il-name REGEX  Valid name regex pattern (^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)

Type mc (MaxtoCode)
  --mc-name REGEX  Valid name regex pattern (!^[oO01l]+$&!^[A-F0-9]{20,}$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --mc-cp INT      String code page (936)

Type mp (MPRESS)
  --mp-name REGEX  Valid name regex pattern (^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)

Type rm (Rummage)
  --rm-name REGEX  Valid name regex pattern (!.)

Type sk (Skater .NET)
  --sk-name REGEX  Valid name regex pattern (!`[^0-9]+&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)

Type sa (SmartAssembly)
  --sa-name REGEX  Valid name regex pattern (^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --sa-error BOOL  Remove automated error reporting code (True)
  --sa-tamper BOOL Remove tamper protection code (True)
  --sa-memory BOOL Remove memory manager code (True)

Type sn (Spices.Net)
  --sn-name REGEX  Valid name regex pattern (!^[a-zA-Z0-9]{1,2}$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)
  --sn-inline BOOL Inline short methods (True)
  --sn-remove-inlined BOOL
                   Remove inlined methods (True)
  --sn-ns1 BOOL    Clear namespace if there's only one class in it (True)
  --sn-rsrc BOOL   Restore resource names (True)

Type xc (Xenocode)
  --xc-name REGEX  Valid name regex pattern (!^[oO01l]{4,}$&!^(get_|set_|add_|remove_|_)?[x_][a-f0-9]{16,}$&^[\u2E80-\u9FFFa-zA-Z_<{$][\u2E80-\u9FFFa-zA-Z_0-9<>{}$.`-]*$)

String decrypter types
//如何使用字符串解密器
  none             Don't decrypt strings
  //不解密
  default          Use default string decrypter type (usually static)
  //默认(?)
  static           Use static string decrypter if available
  //静态(?)
  delegate         Use a delegate to call the real string decrypter
  //创建一个委托,传入相应参数,获取解密后的字符串
  emulate          Call real string decrypter and emulate certain instructions
  //模拟(?)

Multiple regexes can be used if separated by '&'.
//如果要用多个正则,可以使用&连接
Use '!' if you want to invert the regex. Example: !^[a-z\d]{1,2}$&!^[A-Z]_\d+$&^[\w.]+$
//要反转正则表达式可以使用"!"

Examples:
de4dot.exe -r c:\my\files -ro c:\my\output
de4dot.exe file1 file2 file3
de4dot.exe file1 -f file2 -o file2.out -f file3 -o file3.out
de4dot.exe file1 --strtyp delegate --strtok 06000123


de4dot的参数格式是:先输入全局参数,再输入文件参数/去混淆器参数(这2个不用分顺序)
比如:de4dot.exe --dont-rename x.exe --strtype delegate --strtok 0x0600001F


1.Options(全局参数)
--dont-rename
和翻译一样,有的时候要用,因为混淆器会对反射代码特别处理,而de4dot可能没有处理好,导致反射时出错
可以看我的这个帖子 https://www.52pojie.cn/forum.php?mod=viewthread&tid=762380 里面就是因为de4dot没正确处理反射代码,导致需要加上这个参数重新破解一次


--preserve-*
相当于dnSpy中的这些选项,有的时候要加上
<ignore_js_op> 


-v和-vv
有时de4dot就抛出个"Hmmmm... something didn't work. Try the latest version.",谁也不知道为什么de4dot会不起作用。所以需要添加-v或-vv使de4dot显示更详细的信息。


2.File Options(局部参数)


-p TYPE
如果不指明这个参数,de4dot会自动查明混淆器类型,并且使用对应的去混淆器来去混淆。
如果查明有多个混淆器,则使用查明的的第一个混淆器对应的去混淆器来去混淆。
tuts4you上有一个crackme,加了2层壳 https://forum.tuts4you.com/topic/36942-crackme-unpackme-deepsea-obfuscator-41-and-cryptoobfuscator/
<ignore_js_op> UnpackMe &amp; CrackMe .rar (20.32 KB, 下载次数: 34) 
如果我们直接把它拖入de4dot
<ignore_js_op> 
<ignore_js_op> 
打开dnSpy,可以发现这个和没脱壳一样。
所以我们需要手动指定先去哪一层混淆
这里我们用-p ds(ds是DeepSea)
<ignore_js_op> 
<ignore_js_op> 
可以发现效果非常好,再把"UnpackMe & CrackMe -cleaned.exe"直接拖入de4dot,让de4dot处理剩下的那一个混淆器,完成
<ignore_js_op> 


--*-name REGEX
没啥说的,但是挺有用。
现在de4dot这么有名,很多时候混淆器为了逃避de4dot重命名使用了合法字符来重命名,比如我写了一个重命名:

[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public static class Renamer
{
    private static readonly Regex _validNameRegex = new Regex("^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$");
 
    private static void RenameAll(ModuleDef module)
    {
        foreach (TypeDef type in module.GetTypes())
            if (!type.IsGlobalModuleType)
            {
                type.Namespace = GenerateNamespaceName();
                type.Name = GenerateName();
                foreach (FieldDef field in type.Fields)
                    field.Name = GenerateName();
                foreach (MethodDef method in type.Methods)
                {
                    if (!(method.IsSpecialName || method.IsAbstract || method.IsVirtual))
                        method.Name = GenerateName();
                    foreach (ParamDef param in method.ParamDefs)
                        param.Name = GenerateName();
                }
            }
    }
 
    private static string GenerateName()
    {
        StringBuilder stringBuilder;
        string name;
 
        do
        {
            stringBuilder = new StringBuilder(_random.Next(10, 30));
            for (int i = 0; i < stringBuilder.Capacity; i++)
                stringBuilder.Append(_nameChars[_random.Next(_nameChars.Length)]);
            name = stringBuilder.ToString();
        } while (!_validNameRegex.IsMatch(name));
        return name;
    }
 
    private static string GenerateNamespaceName()
    {
        string name;
 
        name = GenerateName();
        foreach (string part in name.Split('.'))
            if (!_validNameRegex.IsMatch(part))
                return GenerateNamespaceName();
        return name;
    }
}


<ignore_js_op> 
de4dot的默认正则表达式对这个重命名完全无效,所以我们使用参数--un-name "^[*删掉留下星号]",表示重命名所有内容
<ignore_js_op> 
<ignore_js_op> 

--strtyp TYPE和--strtok METHOD
这2个参数一般一起用,很多情况下还会和"-p un"一起用,--strtyp一般只接delegate,即--strtyp delegate,因为我把剩下的none static emulate default都试了一遍,没啥用...
--strtok接一个方法token,比如刚才这个crackme,就可以直接解密字符串来破解
演示一遍:
用dnSpy打开刚才的crackme,随便翻(翻不出可以同dnspy调试)
<ignore_js_op> 
可以发现我鼠标指着的方法是字符串解密器
<ignore_js_op> 
复制出token
我只需要解密字符串,而de4dot会自动使用对应的去混淆器,所以我还要指定-p un
<ignore_js_op> 
dnspy打开解密之后的程序集,找到Form1类,看看哪些方法符合这个签名:void XX(object,EventArgs)
<ignore_js_op> 
<ignore_js_op> 
是不是非常简单呢

 

https://www.52pojie.cn/forum.php?mod=viewthread&tid=762674