[Tutorial] AutoIt Scripts Deobfuscaten

06/25/2012 16:30 K1ramoX#1
Hallo und herzlich wilkommen zu meinem Tutorial bezüglich des deobfuscaten von AutoIt Scripts.

Viele Obfuscatoren die versuchen den Code möglichst unleserlich zu machen halten nicht wirklich was sie versprechen. Damit ihr mir dies auch glauben tut werde ich in meinem Tutorial mal auf einen der auf Elitepvp bekanntesten Obfuscatoren eingehen.

[Only registered and activated users can see links. Click Here To Register...]

Dieser Obfuscator ist sehr interessant doch lässt sich relativ simpel entschlüsseln. Angenommen unser Script sieht so aus:

Code:
MsgBox(0, "Test", "Ein einfacher Test")
würde es nach einer Obfuscation so aussehen:


Viele würden jetzt hier verzweifeln da es einfach zu kompliziert aussieht. Doch eigentlich ist das ganz einfach. Jeder Befehl fängt mit einem Execute an, dahinter ist ein BinaryToString mit variierenden Sachen. Wie könnten wir das ganz einfach nun deobfuscaten? Nunja, was obfuscatet ist muss auch deobfuscatet werden damit es der Compiler versteht. Der eigentlich Code befindet sich hinter dem Execute, der Execute Befehl ist nur dazu da um den Code, der in dieser Zeile entschlüsselt wird auszuführen. Also brauchen wir nur das Execute weglassen und danach und ausgeben lassen was encryptet werden würde. Das lässt sich ganz einfach so ausgeben:


Code:
$Command = 

MsgBox(0, "Ausgabe", $Command)

In die Variable setzt ihr dann einfach den BinaryToString rein. So packt ihr es dann Zeile für rein, ihr seht es sind auch noch Funktionen da, deobfuscatet sie auch. Wenn alles fertig ist sollte es so aussehen:



Das war es nun auch schon zu meinem kleinen Tutorial. Dieses Prinzip lässt sich nebenbei bei allen Obfuscatoren anwenden in jeder Sprache, nur die Befehle untereinander variieren.

Hier ist auch noch ein besseres prinzip was euch die Arbeit erleichtern könnte:

Code:
$Command = 

ConsoleWrite($Command & @CRLF)
ClipPut($Command)
Natürlich gibt es noch viele andere möglichkeiten doch diese ist die wesentlichste. Ihr könnt das ganze ja auch in einem Programm automatisieren wenn ihr wollt.

Ich wünsche euch noch einen schönen Tag!
06/25/2012 18:03 Jeoni#2
Hab mich schon vor einem Jahr damit beschäftigt und eine Art deobfuscator geschrieben. Trotzdem bleibt der Code doof / unbequem zu lesen, da die Variablen- und Funktionsnamen ja nicht wiederhergestellt werden können.
Trotzdem gute Arbeit ;)
06/25/2012 18:13 Hybrid~#3
May I ask for an English version? Thanks
06/25/2012 19:14 Miichiii#4
Mh.. Wie kann man so thanks geil sein.. Jeder der Ahnung davon hat, auch wenns nur ein bisschen ist, dürfte das alleine rausbekommen...
06/25/2012 19:26 Lawliet#5
Jop. Die die nicht so viel Ahnung halt nicht ;) Jetzt rate mal, wovon es mehr gibt :p
06/25/2012 19:29 Miichiii#6
Dann frag ich mich was die damit anfangen wollen.. :)
Code:
 Func _II0x8C4E676E1871074BCE66087601ADFDEA()
	Global $I_I0x6217371214A8F54C725CBF59E0C24B92
	Assign('I_I0x6217371214A8F54C725CBF59E0C24B92', 'Test')
	Global $I_I0x1FE348C7489D8A2612E628DCA11E8BB4
	Assign('I_I0x1FE348C7489D8A2612E628DCA11E8BB4', 'Ein einfacher Test')
EndFunc
kann bestimmt jeder von denen flüssig lesen, nen tut wie man hashs knacken kann wär sinnvoller, auch wenns naja nicht wirklich möglich ist, zumindest bei shadow da er ja random krams nutzt...
06/25/2012 19:39 Lawliet#7
Wenn man herausgefunden hat, wozu eine Funktion da ist, muss man den Hash nicht knacken ;)
06/25/2012 19:40 Miichiii#8
jao, aber das wär nen tut wert :P
06/25/2012 20:10 lolkop#9
Quote:
Originally Posted by ™Hybrid™ View Post
May I ask for an English version? Thanks
all he said was, that you should replace all the starting executes in each line by something like ConsoleWrite...

Code:
Execute(BinaryToString("0x5F"&Stringlen("FXPN")&"9"&Stringlen("RMH")&"0"&Stringlen("LCCREYO")&(9+3)^2-136&Stringlen("RMH")&"5"&Stringlen("RMH")&"4433934454"&Stringlen("kB")&"353"&Stringlen("LCCREYO")&"4334334"&Stringlen("y")&"3"&Stringlen("kB")&"4541353"&(9+3)^2-136&"353935444"&Stringlen("kB")&"323"&(9+3)^2-136&"3435344230443"&Stringlen("LCCREYO")&"492829"))
Execute(BinaryToString("0x5F"&Stringlen("KUWM")&"949"&Stringlen("GOZ")&"0"&Stringlen("IJPHWSS")&"8"&Stringlen("GOZ")&"8433445363"&Stringlen("IJPHWSS")&"36453"&Stringlen("r")&"383"&Stringlen("IJPHWSS")&"3"&Execute(Binarytostring('0x696E7428436F732853696E202834373539312E3632363633313333303229295E2D3129'))&"3037344"&Stringlen("uZ")&"4345363630383736303"&Execute(Binarytostring('0x696E7428436F732853696E202834373539312E3632363633313333303229295E2D3129'))&"4"&Execute(Binarytostring('0x696E7428436F732853696E202834373539312E3632363633313333303229295E2D3129'))&"444644454"&Execute(Binarytostring('0x696E7428436F732853696E202834373539312E3632363633313333303229295E2D3129'))&Stringlen("uZ")&"829"))
Execute(BinaryToString("0x"&Stringlen("QNYY")&"D"&Stringlen("YWMGKCE")&Stringlen("KHZ")&"6"&Stringlen("YWMGKCE")&Stringlen("QNYY")&Stringlen("rS")&"6F"&Stringlen("YWMGKCE")&"8"&Stringlen("rS")&"8"&Stringlen("KHZ")&"0"&Stringlen("rS")&"C202"&Stringlen("QNYY")&Execute("_I0x44D2DA01DA4C3A52FAAB3F798DAE582A(9*9)-5")&"95F"&Execute("_I0x44D2DA01DA4C3A52FAAB3F798DAE582A(9*9)-5")&"9"&Stringlen("KHZ")&"0"&Stringlen("YWMGKCE")&"836323"&Stringlen("r")&"3"&Stringlen("YWMGKCE")&"33373"&Stringlen("r")&"32313441384635344337323543424635394530433234423932202C2024495F49307831464533343843373438394438413236313245363238444341313145384242342029"))
--->
Code:
ConsoleWrite(BinaryToString("0x5F"&Stringlen("FXPN")&"9"&Stringlen("RMH")&"0"&Stringlen("LCCREYO")&(9+3)^2-136&Stringlen("RMH")&"5"&Stringlen("RMH")&"4433934454"&Stringlen("kB")&"353"&Stringlen("LCCREYO")&"4334334"&Stringlen("y")&"3"&Stringlen("kB")&"4541353"&(9+3)^2-136&"353935444"&Stringlen("kB")&"323"&(9+3)^2-136&"3435344230443"&Stringlen("LCCREYO")&"492829")@CRLF)
ConsoleWrite((BinaryToString("0x5F"&Stringlen("KUWM")&"949"&Stringlen("GOZ")&"0"&Stringlen("IJPHWSS")&"8"&Stringlen("GOZ")&"8433445363"&Stringlen("IJPHWSS")&"36453"&Stringlen("r")&"383"&Stringlen("IJPHWSS")&"3"&Execute(Binarytostring('0x696E7428436F732853696E202834373539312E3632363633313333303229295E2D3129'))&"3037344"&Stringlen("uZ")&"4345363630383736303"&Execute(Binarytostring('0x696E7428436F732853696E202834373539312E3632363633313333303229295E2D3129'))&"4"&Execute(Binarytostring('0x696E7428436F732853696E202834373539312E3632363633313333303229295E2D3129'))&"444644454"&Execute(Binarytostring('0x696E7428436F732853696E202834373539312E3632363633313333303229295E2D3129'))&Stringlen("uZ")&"829")@CRLF)
ConsoleWrite((BinaryToString("0x"&Stringlen("QNYY")&"D"&Stringlen("YWMGKCE")&Stringlen("KHZ")&"6"&Stringlen("YWMGKCE")&Stringlen("QNYY")&Stringlen("rS")&"6F"&Stringlen("YWMGKCE")&"8"&Stringlen("rS")&"8"&Stringlen("KHZ")&"0"&Stringlen("rS")&"C202"&Stringlen("QNYY")&Execute("_I0x44D2DA01DA4C3A52FAAB3F798DAE582A(9*9)-5")&"95F"&Execute("_I0x44D2DA01DA4C3A52FAAB3F798DAE582A(9*9)-5")&"9"&Stringlen("KHZ")&"0"&Stringlen("YWMGKCE")&"836323"&Stringlen("r")&"3"&Stringlen("YWMGKCE")&"33373"&Stringlen("r")&"32313441384635344337323543424635394530433234423932202C2024495F49307831464533343843373438394438413236313245363238444341313145384242342029")@CRLF)
Which returns:
Code:
_I0x54C94EB57C43A2EA58595DB28454B0D7I()
_II0x8C4E676E1871074BCE66087601ADFDEA()
MsgBox(0, $I_I0x6217371214A8F54C725CBF59E0C24B92 , $I_I0x1FE348C7489D8A2612E628DCA11E8BB4 )
now check the functions, which get executed and you'll see that "_I0x54C94EB57C43A2EA58595DB28454B0D7I()" doesn't do anything, so replace the executes in the following function by consolewrite again:
Code:
Execute(BinaryToString("0x"&Stringlen("SPQS")&Stringlen("v")&Stringlen("UOBQXIH")&Stringlen("CAQ")&Stringlen("UOBQXIH")&"369676E"&Stringlen("cC")&(5+1)^2-28&Stringlen("cC")&"7"&Stringlen("SPQS")&"95F49307"&(5+1)^2-28&"363"&Stringlen("cC")&"3"&Stringlen("v")&"373337313"&Stringlen("cC")&"313441384635344337323543424635394530433234423932272C2027546573742729"))
--->
Code:
ConsoleWrite(BinaryToString("0x"&Stringlen("QBKE")&Stringlen("r")&Stringlen("AQOGXZU")&Stringlen("RPW")&Stringlen("AQOGXZU")&"3696"&Stringlen("AQOGXZU")&"6E"&Stringlen("tT")&"8"&Stringlen("tT")&"7"&Stringlen("QBKE")&"95F4930783"&Stringlen("r")&"4645333438433734383944384"&Stringlen("r")&"3"&Stringlen("tT")&"363"&Execute(Binarytostring('0x696E7428436F732853696E202833393736342E3431363733353732393429295E2D3129'))&"324536323844434"&Execute(Binarytostring('0x696E7428436F732853696E202833393736342E3431363733353732393429295E2D3129'))&"3"&Execute(Binarytostring('0x696E7428436F732853696E202833393736342E3431363733353732393429295E2D3129'))&"3"&Execute(Binarytostring('0x696E7428436F732853696E202833393736342E3431363733353732393429295E2D3129'))&"4538424234272C202745696E2065696E666"&Execute(Binarytostring('0x696E7428436F732853696E202833393736342E3431363733353732393429295E2D3129'))&"6368657220546573742729")&@CRLF)
and
Code:
Execute(BinaryToString("0x"&Stringlen("SPQS")&Stringlen("v")&Stringlen("UOBQXIH")&Stringlen("CAQ")&Stringlen("UOBQXIH")&"369676E"&Stringlen("cC")&(5+1)^2-28&Stringlen("cC")&"7"&Stringlen("SPQS")&"95F49307"&(5+1)^2-28&"363"&Stringlen("cC")&"3"&Stringlen("v")&"373337313"&Stringlen("cC")&"313441384635344337323543424635394530433234423932272C2027546573742729"))
--->
Code:
ConsoleWrite(BinaryToString("0x"&Stringlen("SPQS")&Stringlen("v")&Stringlen("UOBQXIH")&Stringlen("CAQ")&Stringlen("UOBQXIH")&"369676E"&Stringlen("cC")&(5+1)^2-28&Stringlen("cC")&"7"&Stringlen("SPQS")&"95F49307"&(5+1)^2-28&"363"&Stringlen("cC")&"3"&Stringlen("v")&"373337313"&Stringlen("cC")&"313441384635344337323543424635394530433234423932272C2027546573742729")&@CRLF)
and you'll get the 2nd function complete:
Code:
Func _II0x8C4E676E1871074BCE66087601ADFDEA()
	Global $I_I0x6217371214A8F54C725CBF59E0C24B92
	Assign('I_I0x1FE348C7489D8A2612E628DCA11E8BB4', 'Ein einfacher Test')
	Global $I_I0x1FE348C7489D8A2612E628DCA11E8BB4
	Assign('I_I0x6217371214A8F54C725CBF59E0C24B92', 'Test')
EndFunc
so after all, your script looks like this:
Code:
_II0x8C4E676E1871074BCE66087601ADFDEA()
MsgBox(0, $I_I0x6217371214A8F54C725CBF59E0C24B92 , $I_I0x1FE348C7489D8A2612E628DCA11E8BB4 )

Func _II0x8C4E676E1871074BCE66087601ADFDEA()
	Global $I_I0x6217371214A8F54C725CBF59E0C24B92
	Assign('I_I0x1FE348C7489D8A2612E628DCA11E8BB4', 'Ein einfacher Test')
	Global $I_I0x1FE348C7489D8A2612E628DCA11E8BB4
	Assign('I_I0x6217371214A8F54C725CBF59E0C24B92', 'Test')
EndFunc
or even more simplyfied:
Code:
MsgBox(0, 'Test', 'Ein einfacher Test' )
06/25/2012 21:11 K1ramoX#10
Quote:
Originally Posted by Miichiii View Post
Mh.. Wie kann man so thanks geil sein.. Jeder der Ahnung davon hat, auch wenns nur ein bisschen ist, dürfte das alleine rausbekommen...
Und du bist?

Nein. Gehirn ist heutzutage knappe Ware.

Was hat das mit Thanksgeilheit zu tun? Bloß weil ich zu der Community etwas beitragen will bin ich Thanksgeil? Denk mal über deine Posts nach... Außerdem hab ich nirgendwo gesagt dass ich dafür Thanks möchte.


Quote:
Originally Posted by Miichiii View Post
Dann frag ich mich was die damit anfangen wollen.. :)
Code:
 Func _II0x8C4E676E1871074BCE66087601ADFDEA()
	Global $I_I0x6217371214A8F54C725CBF59E0C24B92
	Assign('I_I0x6217371214A8F54C725CBF59E0C24B92', 'Test')
	Global $I_I0x1FE348C7489D8A2612E628DCA11E8BB4
	Assign('I_I0x1FE348C7489D8A2612E628DCA11E8BB4', 'Ein einfacher Test')
EndFunc
kann bestimmt jeder von denen flüssig lesen, nen tut wie man hashs knacken kann wär sinnvoller, auch wenns naja nicht wirklich möglich ist, zumindest bei shadow da er ja random krams nutzt...
Klar kann man das Flüssig lesen. Sieht anders ausgedrückt auch nur so aus:

Code:
Func _Declare()
	Global $arg1, $arg2
	$arg1 = "Test"
	$arg2 = "Ein einfacher Test"
EndFunc
Das neue ist halt nur das mithilfe von Assign die Variablen Definiert werden.

Quote:
Originally Posted by Miichiii View Post
jao, aber das wär nen tut wert :P
Die meisten Hashes sind MD5. Da MD5 eine einseite Verschlüsselung ist kommst du nur durch Brutforcen an den Ursprunglichen Wert bzw. Name.

Quote:
Originally Posted by lolkop View Post
[...]
Danke.
06/25/2012 21:51 Miichiii#11
Quote:
Originally Posted by K1ramoX View Post
Und du bist?

Nein. Gehirn ist heutzutage knappe Ware.

Was hat das mit Thanksgeilheit zu tun? Bloß weil ich zu der Community etwas beitragen will bin ich Thanksgeil? Denk mal über deine Posts nach... Außerdem hab ich nirgendwo gesagt dass ich dafür Thanks möchte.

Klar kann man das Flüssig lesen. Sieht anders ausgedrückt auch nur so aus:

Code:
Func _Declare()
	Global $arg1, $arg2
	$arg1 = "Test"
	$arg2 = "Ein einfacher Test"
EndFunc
Das neue ist halt nur das mithilfe von Assign die Variablen Definiert werden.

Die meisten Hashes sind MD5. Da MD5 eine einseite Verschlüsselung ist kommst du nur durch Brutforcen an den Ursprunglichen Wert bzw. Name.
Wer ich bin ist egal?:D
Und wieso willst du denen helfen, bei denen "Gehirn knappe Ware" ist? Bzw, wieso denkst du dass es die interessieren wird? xD
Sie werden die Funktionen nicht flüssig lesen können, das kannst du, das kann ich, die könnens aber nicht, meiner Meinung nach, naja :D

Und "Thanksgeilheit", war meine eigene Meinung, verzeih mir ;D

[Ironie] Das die Hashs MD5 sind, ist mir jetzt auch wieder komplett neu :D
Genauso wie man an die "Entschlüsslung" kommt, brute force.. [/Ironie]
Deswegen wär nen Tut auch gut, falls jemand ne andere Möglichkeit kennt, zumindest im Falle Shadow.. ^^

Naja. 0x47757465205265697365203A29
06/25/2012 22:24 lolkop#12
Quote:
Originally Posted by Miichiii View Post
Wer ich bin ist egal?:D
Und wieso willst du denen helfen, bei denen "Gehirn knappe Ware" ist? Bzw, wieso denkst du dass es die interessieren wird? xD
Sie werden die Funktionen nicht flüssig lesen können, das kannst du, das kann ich, die könnens aber nicht, meiner Meinung nach, naja :D

Und "Thanksgeilheit", war meine eigene Meinung, verzeih mir ;D

[Ironie] Das die Hashs MD5 sind, ist mir jetzt auch wieder komplett neu :D
Genauso wie man an die "Entschlüsslung" kommt, brute force.. [/Ironie]
Deswegen wär nen Tut auch gut, falls jemand ne andere Möglichkeit kennt, zumindest im Falle Shadow.. ^^

Naja. 0x47757465205265697365203A29
hashes sind nicht umkehrbar. es wird bewusst ein string von bestimmter länge erzeugt, welcher möglichst wenig mit dem original zu tun hat, welcher aber nach dem selben algorithmus immer wieder aus ein und dem selben string erstellt werden kann..

selbst mit bruteforce, kann man den ursprung nicht wieder herstellen, da es mehrere ergebnisse geben kann, welche zu ein und dem selben hash führen. genau darin besteht ja der sinn vom hashing. admins von websites, welche mit hashes arbeiten, können dem user so 100%ig garantieren, dass das passwort vom user niemals einsehbar sein kann, da nichteinmal der server selbst das passwort kennt.

für passwörter ist es natürlich ungünstig das mehrere strings zu ein und dem selben hash wert führen können, für variablennamen hingegen bedeutet das, das wir niemals mit 100%iger sicherheit das original wieder herstellen können, egal welchen weg wir einschlagen.
06/25/2012 22:56 Lawliet#13
Quote:
Originally Posted by lolkop View Post
hashes sind nicht umkehrbar. es wird bewusst ein string von bestimmter länge erzeugt, welcher möglichst wenig mit dem original zu tun hat, welcher aber nach dem selben algorithmus immer wieder aus ein und dem selben string erstellt werden kann..

selbst mit bruteforce, kann man den ursprung nicht wieder herstellen, da es mehrere ergebnisse geben kann, welche zu ein und dem selben hash führen. genau darin besteht ja der sinn vom hashing. admins von websites, welche mit hashes arbeiten, können dem user so 100%ig garantieren, dass das passwort vom user niemals einsehbar sein kann, da nichteinmal der server selbst das passwort kennt.

für passwörter ist es natürlich ungünstig das mehrere strings zu ein und dem selben hash wert führen können, für variablennamen hingegen bedeutet das, das wir niemals mit 100%iger sicherheit das original wieder herstellen können, egal welchen weg wir einschlagen.
100% niemals :p Mit passender Hardware und Wordlist kann man innerhalb von Stunden eine Menge erreichen.
06/26/2012 19:18 Cashblood#14
Ist ein Süsses tutorial, aber ich verstehe nicht, wem das nun helfen soll?
Den Leechern?
Oder denen die es schon vorher wussten?

Sonst nett erklärt..!
06/29/2012 08:54 Sarumon#15
Tja KIramox mal wieder gute Arbeit von dir :)
Hast n Thanks bekomm :)