[WIP] .NET Patcher Library menggunakan dnlib.
Jika Anda memiliki pertanyaan, jangan ragu untuk bertanya kepada saya melalui Gitter! Saya senang membantu Anda! Mengambil permintaan fitur!
Cabang Master memberi Anda build stabil saat ini dari DNPatch. Namun, saya kemungkinan besar tidak akan memberikan dukungan untuk itu lagi karena versi 1.0 sedang dalam perjalanan di cabang V1.
DNPatch adalah perpustakaan utama untuk semua kebutuhan penambalan .NET Anda. Menawarkan penambalan perakitan otomatis, pemindaian tanda tangan dan terakhir tetapi tetapi tidak terkecuali melewati pengabdian dengan kemampuannya untuk menemukan metode dalam jenis yang diganti namanya/dikaburkan. Sejak bintang -bintang di GitHub meledak dalam beberapa hari, DNPatch telah diperpanjang oleh beberapa proyek. Yang paling penting adalah dnpatch.deobfuscation yang mengintegrasikan de4dot langsung ke DNPatch. Juga ada dnpatch.script, yang memberi Anda kemampuan untuk menulis patcher dengan JSON murni! Perpustakaan itu sendiri menggunakan dnlib (lihat bagian selanjutnya).
Karena DNPatch menggunakan DNLIB, sangat disarankan untuk menggunakan DNSPY untuk menganalisis rakitan Anda terlebih dahulu, untuk memastikan bahwa Anda menggunakan nama yang benar, offset, dll, karena menggunakan DNLIB juga.
Sangat disarankan agar Anda menghitung indeks instruksi alih -alih mendefinisikannya, untuk meningkatkan kemungkinan kompatibilitas dengan pembaruan di masa mendatang.
Konstruktor mengambil nama file Majelis.
Patcher patcher = new Patcher ( "Test.exe" ) ;Jika Anda ingin menjaga MaxStack lama (misalnya untuk majelis yang dikaburkan) Gunakan kelebihan beban:
Patcher patcher = new Patcher ( "Test.exe" , true ) ;Semua metode mengambil objek yang disebut target sebagai argumen. Objek didefinisikan sebagai berikut:
public string Namespace { get ; set ; } // needed
public string Class { get ; set ; } // needed
public string Method { get ; set ; } // needed
/* If you want to patch multiple indexes in the method */
public int [ ] Indexes { get ; set ; }
public Instruction [ ] Instructions { get ; set ; }
/* If you want to patch 1 index in the method */
public int Index { get ; set ; } = - 1 ;
public Instruction Instruction { get ; set ; }
/* If the path to the method has more than 1 nested class use this */
public string [ ] NestedClasses { get ; set ; }
/* If the path to the method has 1 nested class use this */
public string NestedClass { get ; set ; }
/* If you want to set the parameters for the method (if it's overloaded) use this */
public string [ ] Parameters { get ; set ; }
/* If you want to set the return type for the method use this */
public string ReturnType { get ; set ; }
/* If you want to rewrite the getters or setters of a property use this */
public string Property { get ; set ; } // The name
public PropertyMethod PropertyMethod { get ; set ; } // See below, determines patch targetReturnType dan parameter adalah case sensitif! Contoh:
Propertimethod didefinisikan sebagai ini:
public enum PropertyMethod
{
Get ,
Set
}Pastikan Anda tidak memberikan nilai yang tidak konsisten, misalnya
var target = new Target
{
Instructions = .. .
Instruction = .. .
}Jika Anda ingin menambal beberapa metode, buat target [] dan berikan ke fungsi, itu diterima oleh sebagian besar dari mereka.
Referensi dnlib dan buat instruksi [] atau instruksi dengan instruksi Anda, lalu tetapkan tetapkan indeks di mana instruksi berada. Anda dapat menemukannya dengan merekayasa balik perakitan Anda melalui DNSPY atau dekompiler lainnya.
Contoh Kecil:
Instruction [ ] opCodes = {
Instruction . Create ( OpCodes . Ldstr , "Hello Sir 1" ) ,
Instruction . Create ( OpCodes . Ldstr , "Hello Sir 2" )
} ;
int [ ] indexes = {
0 , // index of Instruction
2
} ;
Target target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "Print" ,
Instructions = opCodes ,
Indexes = indexes
} ;Untuk menghapus seluruh metode dan menulis instruksi Anda, pastikan Anda tidak menetapkan indeks atau properti indeks.
Inilah contohnya:
Instruction [ ] opCodes = {
Instruction . Create ( OpCodes . Ldstr , "Hello Sir" ) ,
Instruction . Create ( OpCodes . Call , p . BuildCall ( typeof ( Console ) , "WriteLine" , typeof ( void ) , new [ ] { typeof ( string ) } ) ) ,
Instruction . Create ( OpCodes . Ret )
} ;
Target target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "Print" ,
Instructions = opCodes
} ;Untuk menerapkan instruksi yang dimodifikasi, Anda dapat memanggil metode 'patch':
patcher . Patch ( Target ) ;atau
patcher . Patch ( Target [ ] ) ;Dalam beberapa kasus, mungkin berguna untuk menemukan instruksi dalam suatu metode, misalnya jika metode diperbarui.
Instruction opCode = Instruction . Create ( OpCodes . Ldstr , "TheTrain" ) ;
Instruction toFind = Instruction . Create ( OpCodes . Ldstr , "TheWord" ) ;
Target target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "FindMe" ,
Instruction = opCode // you can also set it later
} ;
target . Index = p . FindInstruction ( target , toFind ) ;
// now you have the full Target objectKatakanlah ada beberapa instruksi yang identik. Apa sekarang, Baoss? Nah, itu sederhana. Ada kelebihan beban yang mengambil int yang merupakan kejadian instruksi yang ingin Anda temukan.
Instruction opCode = Instruction . Create ( OpCodes . Ldstr , "TheTrain" ) ;
Instruction toFind = Instruction . Create ( OpCodes . Ldstr , "TheWord" ) ;
Target target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "FindMe" ,
Instruction = opCode // you can also set it later
} ;
target . Index = p . FindInstruction ( target , toFind , 2 ) ; // Sir, find the second occurence!Anda dapat menemukan metode (target []) dengan memindai tubuh mereka untuk tanda tangan opcode
OpCode [ ] codes = new OpCode [ ] {
OpCodes . Ldstr ,
OpCodes . Call
} ;
var result = p . FindMethodsByOpCodeSignature ( codes ) ; // holds Target[]Dalam beberapa kasus mungkin lebih mudah untuk hanya mengganti instruksi. Pada titik pengembangan ini, itu tidak masuk akal, tetapi fitur -fiturnya akan segera hadir.
Instruction opCode = Instruction . Create ( OpCodes . Ldstr , "I love kittens" ) ;
Target target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "ReplaceMe" ,
Instruction = opCode ,
Index = 0
} ;
p . ReplaceInstruction ( target ) ;Katakanlah Anda ingin menghapus instruksi ... baik itu sederhana seperti ini:
Target target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "RemoveMe" ,
Indexes = new [ ] { 0 , 1 } // the indexes, you can also just use 'Index'
} ;
p . RemoveInstruction ( target ) ;Hmmm .... bagaimana jika Anda menemukan output konsol menyinggung? Anda dapat memodifikasi LDSTR bahkan tanpa membuat instruksi :)
Target target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "PrintAlot" ,
Index = 0
} ;
p . PatchOperand ( target , "PatchedOperand" ) ; // pass the Target and a string to replaceatau jika Anda perlu memodifikasi int:
p . PatchOperand ( target , 1337 ) ;Ini juga dapat menambal banyak operan dalam metode yang sama dengan menggunakan int [] atau string [].
Jika Anda ingin menimpa Methodbody dengan pernyataan yang benar/salah, Anda dapat melakukan ini:
target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "VerifyMe"
} ;
p . WriteReturnBody ( target , bool ) ; // bool represents the return valueJika Anda hanya ingin mengosongkan methodbody, gunakan amigo ini:
target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "WriteLog"
} ;
p . WriteEmptyBody ( target ) ;Cukup lakukan ini jika Anda ingin mendapatkan instruksi dari objek target:
target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "WriteLog"
} ;
Instruction [ ] instructions = p . GetInstructions ( target ) ;Jika Anda ingin menimpa tubuh dengan return true/false, lakukan ini:
target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "WriteLog"
} ;
p . WriteReturnBody ( target , bool ) ;
// bool is the return value, e.g. true will return true ;)Jika Anda ingin menghapus tubuh cukup panggil ini:
target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "WriteLog"
} ;
p . WriteEmptyBody ( target ) ;Jika Anda ingin menemukan metode, Anda dapat dengan mudah memindai seluruh file dengan 2 cara:
p . FindInstructionsByOperand ( string [ ] ) ;
// or p.FindInstructionsByOperand(int[]);
// string[] with all operands in the method, if there are multiple identical operands, make sure to have the same amount as in the method.
// or do this via opcodes:
p . FindInstructionsByOpcode ( OpCode [ ] ) ;Kedua cara mengembalikan target [] yang berisi semua target yang menunjuk pada temuan.
Jika Anda ingin menemukan instruksi dan Anda tahu kelas (dan secara opsional metode), Anda dapat membiarkan metode ini mengembalikan target [] dengan jalur dan indeks.
p . FindInstructionsByOperand ( Target , int [ ] , bool ) ;
// int[]: the operands
// bool: if true it will search for the operands once, it will delete the index if the index was found
// for opcodes:
p . FindInstructionsByOpcode ( Target , int [ ] , bool ) ;Sekarang Anda dapat menulis ulang pengambil dan setter properti seperti ini:
target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Property = "IsPremium" , // Property name
PropertyMethod = PropertyMethod . Get , // Getter or Setter
Instructions = new [ ]
{
Instruction . Create ( OpCodes . Ldc_I4_1 ) ,
Instruction . Create ( OpCodes . Ret )
} // the new instructions
} ;
p . RewriteProperty ( target ) ; // Will overwrite it with return true in getter Properti yang disebut 'Properti' memegang nama properti target.
Propertimethod dapat berupa 'propermethod.get' atau 'propermethod.set'.
Instruksi adalah instruksi baru untuk pengambil atau setter.
Untuk membangun panggilan seperti "Console.WriteLine (String)" Anda dapat menggunakan metode ini:
p . BuildCall ( typeof ( Console ) , "WriteLine" , typeof ( void ) , new [ ] { typeof ( string ) } )
/*
* Type -> type, a Type instance
* string -> method, the name of the method
* Type -> returnType, a Type instance of the return value
* Type[] -> parameters, an array with the parameter's Types
*/Berikut adalah contoh IL untuk Console.WriteLine:
Patcher p = new Patcher ( "Test.exe" ) ;
Instruction [ ] opcodesConsoleWriteLine = {
Instruction . Create ( OpCodes . Ldstr , "Hello Sir" ) , // String to print
Instruction . Create ( OpCodes . Call , p . BuildCall ( typeof ( Console ) , "WriteLine" , typeof ( void ) , new [ ] { typeof ( string ) } ) ) , // Console.WriteLine call
Instruction . Create ( OpCodes . Ret ) // Always return smth
} ;
Target target = new Target ( )
{
Namespace = "Test" ,
Class = "Program" ,
Method = "Print" ,
Instructions = opcodesConsoleWriteLine
} ;
p . Patch ( target ) ;
p . Save ( "Test1.exe" ) ;Jika Anda ingin menyuntikkan metode ke dalam kelas, hubungi suntikan Method. Pastikan untuk mengatur MethodDef dan Instruksi. Secara opsional atur penduduk setempat, ParameterDefs.
Target target = new Target ( ) ;
MethodImplAttributes methImplFlags = MethodImplAttributes . IL | MethodImplAttributes . Managed ;
MethodAttributes methFlags = MethodAttributes . Public | MethodAttributes . Static | MethodAttributes . HideBySig | MethodAttributes . ReuseSlot ;
MethodDef meth1 = new MethodDefUser ( "MyMethod" ,
MethodSig . CreateStatic ( mod . CorLibTypes . Int32 , mod . CorLibTypes . Int32 , mod . CorLibTypes . Int32 ) ,
methImplFlags , methFlags ) ;
target . ParameterDefs = new [ ] { new ParamDefUser ( "a" , 1 ) } ;
target . Locals = new [ ] { new Local ( mod . CorLibTypes . Int32 ) } ;
target . MethodDef = meth1 ;
target . Class = "" ;
// ... target as always...
patcher . InjectMethod ( target ) ;Untuk saat ini lihat halaman ini: https://github.com/0xd4d/dnlib/blob/master/examples/example2.cs
Jika Anda ingin menyimpan perakitan dengan nama yang berbeda, gunakan ini:
patcher . Save ( String ) ; // filename hereAtau jika Anda ingin mengganti file asli:
patcher . Save ( bool ) ; // if true it will create a backup first (filename.bak) Baoss, apa yang bisa saya lakukan jika sangat dikaburkan?! Nah, dengarkan dengan hati -hati Kakek Anda Joe. Gunakan 'dnpatch.deobfuscation'! Itu memiliki kekuatan ajaib! Nah, Joe hanyalah Kiddin ', ia menggunakan perpustakaan De4dot. Referensi perpustakaan dnpatch.deobfuscation dan pastikan Anda juga menyalin semua yang lain dari zip! Kemudian lakukan ini:
Deobfuscation d = new Deobfuscation ( string , string ) ;
// string 1 -> file to deobfuscate
// string 2 -> new filename for the deobfuscated file
d . Deobfuscate ( ) ; // Deobfuscates the file and writes it to the disk Dengan dnpatch.script Anda sekarang dapat skrip patchers dengan JSON! Contoh JSON:
{
"target" : " Test.exe " ,
"targets" :[{
"ns" : " Test " ,
"cl" : " Program " ,
"me" : " ReplaceMe " ,
"ac" : " replace " ,
"index" : 0 ,
"instructions" :[{
"opcode" : " ldstr " ,
"operand" : " script working "
}]
},{
"ns" : " Test " ,
"cl" : " Program " ,
"me" : " RemoveMe " ,
"ac" : " empty "
}]
}Beri nama file ini skrip.json dan masukkan ke dalam folder build testscript dan gunakan dengan test.exe. Untuk info lebih lanjut silakan lihat repo mandiri.
Saya ingin mengucapkan terima kasih kepada orang -orang ini: