El crackMe de leyer resuelto medianamente en el 2017 por mi Solución lycrackme, veo una mejor manera de hacerlo con Instrumentación dinamica usando el api de ByteBuddy, para construir un agente y adjuntarlo en tiempo de ejecución al crackME o proceso de este.
- Importante: para usar el APi de Java de instrumentación, estoy usando la JDK 8, dado en contiene el tools.jar, si o si es necesario para poder crear el agente, abria que investigar como hacerlo con versiones mas nuevas de Java.
- El código del crackME para que no se pierda, y recordarlo, leyer me odiara ya...
- Aún asi es un escenario fácil ya que el código no esta ni cifrado, ni ofuscado, podemos leer las variables incluso, decompilar también el .jar del crackME, o sea ventajas, en otros escenarios, un decompilador de Java con un .jar ofuscado no lograria decompilar bien y se confundiría.
Código
import... public class CrackMe { static int[] _$$Y_sy76 = new int[]{7414755, 3219665, 175186692, 136322726, 136419744, 4066036, 15685602, 103481, 8331326, 14522496, 254443529, 117440530, 0x100000, 10066673, 0xEEE122, 0x421442, 1183806, 11019024, 140529167, 118489840, 19071234, 0xF00004, 3109537, 594494, 7406141, 9476832, 18812418, 9969838, 34803714, 3298805, 2302368, 15368608, 8916253, 9445024, 51519491, 31, 241696768, 7414181, 2299045, 39441, 9539087, 16392240, 0x9090090, 117641473, 258080912, 16115104, 0x120120, 0x10101A, 1183501, 7413822, 236060690, 257294849, 125830118, 66016, 8983278, 624289, 16609425, 14844138, 27270816, 239404033, 51389454, 7414690, 593951, 7709524, 9969409, 9847050, 118646528, 158482433, 0x1110011, 2299045, 2299045, 3739700}; byte[] _$$d_defaultBytes_ = _$s_String_.getBytes(); try { } // empty catch block } _$$a_algorithm.reset(); _$$a_algorithm.update(_$$d_defaultBytes_); byte[] messageDigest = _$$a_algorithm.digest(); int _$I_Index = 0; while (_$I_Index < messageDigest.length) { ++_$I_Index; } _$s_String_ = "" + hexString; return _$s_String_; } public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException { int _$$2341s = 0; boolean _$_$2edwb$ = true; block0: while (_$_$2edwb$) { int _yx$; int _index$ = _DEFF_$.length(); while (_index$ > 1) { _IX$ = String.valueOf(_IX$) + _DEFF_$.substring(_DEFF_$.indexOf("0") + 2, _DEFF_$.lastIndexOf("0") - _index$); _$_$2edwb$ = false; continue block0; } --_index$; } } _$$f_dwquig11__.getContentPane().add(_$$p_Tetxta1Field_); _$$f_dwquig11__.getContentPane().add($$l_Label_); _$$f_dwquig11__.setSize(500, 100); int _$$i_INDEX_ = 0; while (_$$i_INDEX_ < _$$Y_sy76.length) { if (_$$Y_sy76[_$$i_INDEX_] == _$$Y_sy76[_$$zaq1I1]) { int index = 0; while (index < _$$i_INDEX_) { ++index; } } ++_$$i_INDEX_; } _$$f_dwquig11__.getContentPane().add(_$$b__$$hsqqso_); _$$f_dwquig11__.getContentPane().add(_$$s_poqh1120); _$$f_dwquig11__.setResizable(false); _$$f_dwquig11__.setLocationRelativeTo(null); _$$f_dwquig11__.setDefaultCloseOperation(3); _$$f_dwquig11__.setVisible(true); @Override if (_$$I_pos123.equalsIgnoreCase(_$$r_easte)) { } else { } } }); } }
Esta es la manera en que byteBuddy nos permite crear un agente usando su DSL (domain specific language) si, un pedaso de Builder gigantesco.
Código
new AgentBuilder.Default() .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE) .with(AgentBuilder.TypeStrategy.Default.REDEFINE) .disableClassFormatChanges() .ignore(ElementMatchers.nameStartsWith("net.bytebuddy.")) .ignore(ElementMatchers.nameStartsWith("java.")) .ignore(ElementMatchers.nameStartsWith("javax.")) .ignore(ElementMatchers.nameStartsWith("sun.")) .type(ElementMatchers.nameContains("CrackMe")) .transform((builder, typeDescription, classLoader, module, protectionDomain) -> builder.visit(Advice.to(StringEqualsAdvice.class) .on(ElementMatchers.named("actionPerformed"))) ) .installOn(inst); } }
Pues resulta que podemos interceptar la clase CrackMe y el botón que hace la comparación de input con la key, además byteBuddy necesita un Advice, que lo llamo StringEqualsAdvice
- Aplicando instrumentación estática
Aquí por medio del APi de Java de Instrumentación, cuando generamos nuestro agente, y lo ejecutamos como el modo siguiente, el método premain es el que se va a disparar esta vez.
Código
java -javaagent:agent-1.0.0.jar -jar Ly-CrackME.jar <1> Execute premain method ██████████████████████ Ly-Crackme @Leyer ██████████████████▓▓█ █████████████████████▓▓▓▓▓▓█▓▓▓▒▓▓▒▓▓▓▓▓▓██████████████▓███▓██ ███████ Key: ███ ███████ ██████▓▒░░▒▓▓▓█ X=231231321 ███(Validar)██████████████▓███████ █████████████████████▓███▓▓███▓███████████████████████████████ ███████████████▓▒▓▓█▓░▒▒▒▒▒▓▓▒▒█▓▓▓▓▒▒▒▒▒▒▓▓▓█████████████████ ██████████████████████████████████████████████████████████████ ██████████████████████████████████████████████████████████████ Starting monkey patching :D by rubn0x52.com [+] Interceptor instalado en clases CrackMe [*] Botón Validar presionado! Clave encontrada Campo: val$_$$r_easte Clave: 6ff173f14d9384c6b897b4be810e5699ca997e18.0 <2> [*] Botón Validar presionado! Clave encontrada Campo: val$_$$r_easte
- Aplicando instrumentación dinámica
Para el adjuntado dinámico, necesitamos el PID del crackME, por lo tanto lo ejecutamos con el tipico
Código
java -jar LyCrackME.jar
Ahora extraemos el PID con el comando jps como lo siguiente:
Código
rubn > jps 4113 Main 163776 RemoteMavenServer36 212017 jar 4555 SonarLintServerCli 34763 RemoteMavenServer36 12718 RemoteMavenServer36 212061 Jps 171085 java rubn > java -jar patch-lycrackme-1.0.0.jar 212017 rubn https://rubn0x52.com Attached to target jvm correctly
La linea 10, es como ejecutamos el agente.
El pid es 212017 del crackME, luego pobramos a introducir en el input del crackME y en la consola, el Agente interceptara el click en el botón, más precisamente el método llamado actionListener
Aqui entra en juego el Advice previamente comentado
Código
package com.prueba.lycrackme.advice; import net.bytebuddy.asm.Advice; public class StringEqualsAdvice { @Advice.OnMethodEnter try { // Extraer todos los campos del ActionListener anónimo field.setAccessible(true); // La clave correcta será un string largo (hash SHA1 + número) if (field.getName().contains("easte")) { } } } e.printStackTrace(); } } }
Entonces podemos recorrer por todos los campos, y machear por uno que se llama _$$r_easte línea 20, que es el que contiene la key.
- He generado una release con el agente.
- https://github.com/rucko24/Instrumentacion-con-bytebuddy/releases/tag/1.0.3
- source: https://github.com/rucko24/Instrumentacion-con-bytebuddy/tree/1.0.3/patch-lycrackme





Autor




En línea

