NJCTF (easycrack)

安装app查看。一个输入框,输入随便输入显示Try again.

放入JEB反编译。

关于输入框监听是第一次见,具体可以看看这个博客https://www.jianshu.com/p/f976c677189a

函数的作用是,如果字符串s变动,将会执行具体的实现。这里是调用了native层的parseText函数。

接下来反编译apk,用IDA打开位于lib文件夹中的so文件,如下图所示。

 具体关于JNI,可以看这个博客,https://blog.csdn.net/smbroe/article/details/44133741

jni方法有两种映射:

动态注册的native方法,必须实现JNI_OnLoad方法,同时实现一个JNINativeMethod[]数组, 实现Java方法与native方法的映射绑定 
静态注册的native方法,必须是以Java+类完整路径+方法名的格式来命名native方法。

这里是静态注册的,首先要选中这里的a1,按Y,改成下图所示,这样IDA才能够正确分析。

返回Java层,查看messageMe函数。函数很简单,直接赋值java包的名字,复制黏贴代码到java编译器中跑出即可。

 1 public class easycrack100 {
 2     public static void main(String[] args) {
 3         String v3 = "";
 4         int v4 = 51;
 5         String[] v1 = "com.njctf.mobile.easycrack".split("\\.");
 6         /*1、如果用“.”作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split(".");
 7         2、如果用“|”作为分隔的话,必须是如下写法,String.split("\\|"),这样才能正确的分隔开,不能用String.split("|");
 8         “.”和“|”都是转义字符,必须得加"\\";*/
 9         char[] v6 = v1[v1.length - 1].toCharArray();
10         int v7 = v6.length;
11         int v5;
12         for(v5 = 0; v5 < v7; ++v5) {
13             v4 ^= v6[v5];
14             v3 += ((char)v4);
15         }
16         System.out.println(v3);
17     }
18 }

message='V7D=^,M.E'

返回IDA继续分析。

这个循环也容易理解,异或后的字符串放入了v23。再往下。

打开init函数。

稍微改一下放到c编译器中得到key数组。

#include<stdio.h>
using namespace std;
int main()
{
  string a2 = "I_am_the_key";
  string v11 = a2;
  int res[256];
  int v3 = 256;
  int v14[256];
  int *v8;
  int v4 = 0;
  int v5 = 0;
  int *v7;
  int i = 0;
  do
  {
    res[v5] = v5;                               
    v14[v5++] = v11[i];
    i++;
    i%=12;
  }
  while ( v5 != 256 );
  v7=v14;
  v8 = res;
  int v9;
  do
  {
    v9 = *v8;
    v4 = (v9 + v4 + *v7) % 256;
    *v8 = res[v4];
    res[v4] = v9;
    --v3;
    ++v7;
    ++v8;
  }
  while ( v3 );
  for(int i=0;i<256;i++) printf("0x%02x,",res[i]);
  return 0;
}

再往下,将得到key和异或后的字符串进行加密。

因为我们要逆向得到正确的输入(即flag),所以需要知道经过整个加密过程后的对比字符串。

这里双击compare就能看到了。这是一串十六进制。

在它的上面,还有一步,就是把经过crypt后的字符串转成16进制,如下图。

下面画个流程图,梳理一下思路。

最后跟据crypt函数写出脚本即可。

#include<iostream>
using namespace std;
int main()
{
    int a3 = 30;
    int v3 = 0;
    int v4 = 0;
    int v5;
    int i = 0;
    int a2[32] = {0xC8,0xE4,0xEF,0x0E,0x4D,0xCC,0xA6,0x83,0x08,0x81,0x34,0xF8,0x63,0x5E,0x97,0x0E,0xEA,0xD9,0xE2,0x77,0xF3,0x14,0x86,0x9F,0x7E,0xF5,0x19,0x8A,0x2A,0xA4};
    int result[256] = {0x39,0xa9,0x72,0x2d,0xe8,0x58,0x26,0x32,0x81,0xd,0xac,0x49,0xbb,0x10,0x46,0x65,0xb3,0x92,0xf,0x84,0xb8,0xbf,0xf2,0x52,0xe3,0x5b,0xfc,0xd5,0x59,0x6a,0xf0,0x5d,0x60,0x69,0x16,0x8e,0xfb,0x94,0x48,0xbc,0x71,0x36,0x57,0xad,0x44,0x7c,0x95,0xda,0xb7,0x47,0xdb,0x35,0x3c,0xd2,0x23,0xc5,0xa8,0xb,0x9f,0x31,0xd8,0x1f,0x3f,0xb0,0x2e,0xe1,0x5a,0x4a,0xf9,0x1,0x54,0xa7,0xa5,0xee,0x8,0x99,0x63,0x9b,0x50,0xbd,0x5,0xf7,0xcb,0xab,0x22,0xc2,0x8a,0x38,0x7d,0x6,0xb1,0xc0,0x4e,0x74,0x3a,0xe5,0x67,0x2b,0xa3,0x73,0x89,0x9e,0xba,0x88,0x3d,0x28,0x62,0x8f,0xfd,0x43,0x98,0x4d,0x56,0xb2,0xc,0x29,0x6e,0x78,0x25,0xe0,0xe9,0xf6,0x9c,0x13,0xed,0xf8,0xc4,0x20,0x87,0x2,0x7b,0xf1,0x6d,0xc7,0x8c,0x9d,0x86,0x3b,0x66,0xfa,0xb6,0x42,0x6f,0x14,0xd0,0x19,0xaf,0x11,0x21,0x96,0x85,0x91,0xb5,0xa0,0x1b,0x18,0xa6,0xa2,0x4b,0x40,0xd4,0x8d,0x2a,0x8b,0x5c,0x2c,0xe6,0xfe,0xa4,0x30,0xe7,0xff,0xc8,0x5f,0xe2,0x1c,0xdf,0xae,0x7f,0xc3,0x61,0xef,0x90,0x6c,0x51,0x2f,0xec,0x12,0x7a,0xaa,0xdd,0x77,0xf5,0x4,0xd9,0x83,0x33,0xeb,0x80,0x27,0x3,0xb4,0x9,0x37,0x6b,0x41,0x4f,0x7e,0xf3,0x24,0xf4,0xc9,0x7,0xd1,0x45,0x70,0xa1,0xd7,0x34,0x93,0x15,0xca,0x4c,0xcd,0x97,0xb9,0xea,0x0,0x5e,0x1a,0x9a,0xcf,0x79,0xa,0x3e,0x82,0xd3,0x68,0x75,0x64,0xce,0x55,0xe,0xbe,0x1d,0xe4,0xc1,0xc6,0xde,0xcc,0x1e,0x17,0xd6,0xdc,0x53,0x76};
    do
    {
      v3 = (v3 + 1) % 256;
      v5 = *(int *)(result + v3);
      v4 = (v5 + v4) % 256;
      *(int *)(result + v3) = *(int *)(result + v4);
      *(int *)(result + v4) = v5;
      a2[i] ^= *(int *)(result + ((*(int *)(result + v3) + v5) & 0xFF));
      --a3;
      ++i;
    }
    while ( a3 );
  string ss="V7D=^,M.E";
  string flag="";
  for(int i=0;i<30;i++)
  {
      int j=i%9;
      flag+=ss[j]^a2[i];
  }
  cout << flag;
  return 0;
}
原文地址:https://www.cnblogs.com/sweetbaby/p/10933268.html