為了避免被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 & CrackMe .rar
如果我們直接把它拖入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重命名使用了合法字符來重命名,比如我寫了一個重命名:
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