shuaiyue 发表于 2019-5-6 23:44

论坛里的crackme 练手留念杂文3

本帖最后由 shuaiyue 于 2019-5-6 23:47 编辑

下载:https://www.52pojie.cn/thread-804580-1-1.html

先声明不是诋毁,只是吐槽。。
----------------------------------------
这个cm坑爹啊。算法感觉是无解的。另外各种模拟器只能运行一次,然后闪退,肉疼TO无懈可击~
期间联系到作者,想窥视下流程来验证下我的判断,回复丢了。无奈~~有空的可以来帮忙验证下我的分析。
流程分析:JAVA->SO 。

JAVA层

public static byte[] MD5(String paramString)    //获取32位MD5
{
    try
    {
      paramString = paramString.getBytes();
      MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
      localMessageDigest.update(paramString);
      paramString = localMessageDigest.digest();
      return paramString;
    }
    catch (Exception paramString) {}
    return (byte[])null;
}
public native byte[] getStr(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2);//动态函数
public byte[] xor(byte[] paramArrayOfByte)   //输入的字符串每一位和"52pojie"亦或
    throws Exception
{
    byte[] arrayOfByte1 = new byte;
    byte[] arrayOfByte2 = "52pojie".getBytes("UTF-8");
    int j = paramArrayOfByte.length;
    int i = 0;
    for (;;)
    {
      if (i >= j) {
      return arrayOfByte1;
      }
      int k = arrayOfByte2[(i % arrayOfByte2.length)];       //取模
      arrayOfByte1 = ((byte)(paramArrayOfByte ^ k));//亦或
      i += 1;
    }
}
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt)
      {
      try
      {
          HelloJni.input = this.val$et.getText().toString();
          this.val$tv.setText(HelloJni.this.getStr(HelloJni.this.xor(HelloJni.MD5(HelloJni.input)), HelloJni.input.getBytes()).toString());    //直接输出so返回的字符串
          return;
      }



SO层


int __fastcall Java_com_wuaipojie_CCCM_HelloJni_getStr(JNIEnv *a1, int a2, int xor_md5_input, int input_byte)
{
int v4; // r10
int v5; // r6
JNIEnv *env; // r4
const char *v7; // r9
size_t len; // r7
char *inputStr; // r8
char *name; // r5
const char *mark; // r2
const char *v12; // ST0C_4
int v13; // r1
char *buffer; // r5
int v15; // r0
int jbyteArray; // r7
int ArrayLength; // r0
const char *v18; // r1

v4 = input_byte;
v5 = xor_md5_input;
env = a1;
v7 = ((*a1)->GetByteArrayElements)(xor_md5_input);         // byte[] 输入的参数
len = strlen(v7);   //长度
inputStr = malloc(len);//分配内存空间
memcpy(inputStr, v7, len); //拷贝输入参数到inputStr字符串中
name = inputStr;
mark = "52pojie";
while ( name != &inputStr )            //循环的作用和JAVA层的XOR是一样的.取反回到最初JAVA层的MD5
{
    v12 = mark;                                          
    sub_5B068930(name - inputStr, 7);         //取模
    mark = v12;
    *name ^= v12;                              
    ++name;
}
buffer = &name[-len];                         // 指针重新指向
v15 = ((*env)->GetArrayLength)(env, v5, mark);// 0x10
jbyteArray = ((*env)->NewByteArray)(env, v15);// 初始化了一个数组并未赋值
ArrayLength = ((*env)->GetArrayLength)(env, v5);
((*env)->SetByteArrayRegion)(env, jbyteArray, 0, ArrayLength, buffer);// 操作将buffer拷贝到数组中
((*env)->ReleaseByteArrayElements)(env, v5, v7, 0);
free(buffer);
if ( jbyteArray == v4 )                     // 比较 jbyteArray是上面循环得到的最初MD5 , V4 是什么,是JAVA层的第二个参数
    v18 = "Congratulations!";
else
    v18 = "incorrect";
return ((*env)->NewStringUTF)(env, v18);
}

这里有个问题: if ( jbyteArray == v4 ) 相等才是正确的没错。但是jbyteArray是MD5。V4也是个byte数组但是值是JAVA层传递的第二个参数。

HelloJni.input = this.val$et.getText().toString();   //输入的字符串
this.val$tv.setText(HelloJni.this.getStr(HelloJni.this.xor(HelloJni.MD5(HelloJni.input)), HelloJni.input.getBytes()).toString());

可以看到V4是字符串的BYTE。如果条件为TRUE必须要输入的字符串等于MD5字符串,有这种可能么,百度一下有但是几率很小。
最开始我以为V4是个动态值,于是我决定还是动态调试看看吧。发现是并非我所愿。货真价实的JAVA层参数2。
所以暂且总结这个是个坑,只能爆破了。。

huzpsb 发表于 2019-5-7 07:51

所以,?
爆破有何妨?

shuaiyue 发表于 2019-5-7 19:48

huzpsb 发表于 2019-5-7 07:51
所以,?
爆破有何妨?

避免较真的在浪费时间。

quaternion 发表于 2019-5-7 21:36

谢谢分享
页: [1]
查看完整版本: 论坛里的crackme 练手留念杂文3