Android逆向题解6-黑客精神

看代码是要先注册,先调doRegister注册,判断已注册再调work
Android逆向题解6-黑客精神_第1张图片doRegister跳到RegActivity
Android逆向题解6-黑客精神_第2张图片输入内容传到saveSN
Android逆向题解6-黑客精神_第3张图片saveSN是个native方法,这里还看到了work也是native方法,就是核心代码都在so里
Android逆向题解6-黑客精神_第4张图片
下面来分析so

直接看导出函数没找到saveSN和work,那应该是动态注册的

直接看JNI_OnLoad,确实是动态注册的,n1就是initSN,n2是saveSN,n3是work
Android逆向题解6-黑客精神_第5张图片Android逆向题解6-黑客精神_第6张图片
n2是saveSN,那直接看n2,这里的加密逻辑大概就是第1、4、7、10、13位是w,2、5、8、11位是_,剩下的3、6、9是a,组合起来的字符串就是“w_aw_aw_aw_aw”,
这里也可以直接动态调试得到解密字符串“w_aw_aw_aw_aw”
这里就是异或,R3是我们输入的,R2就是解密的结果,这里会循环执行;动态调式看R2的值就是循环的0x77、0x5f、0x61,转换就是“w_aw_aw_aw_aw”;

Android逆向题解6-黑客精神_第7张图片
然后拿“w_aw_aw_aw_aw”和用户输入的字符串进行逐位异或,结果保存到/sdcard/reg.dat

int __fastcall n2(_DWORD *a1, int a2, int a3)
{
  JNIEnv **v3; // r6
  int string; // r9
  FILE *v5; // r7
  int *v7; // r4
  const char *v8; // r3
  int v9; // r0
  int v10; // r1
  _WORD *v11; // r5
  JNIEnv **v12; // r0
  int v13; // r4
  JNIEnv *v14; // r3
  signed int v15; // r6
  const char *v16; // r9
  const char *v17; // r5
  signed int v18; // r10
  char v19; // r2
  char v20; // r3
  int v21; // [sp+0h] [bp-38h]
  int v22; // [sp+14h] [bp-24h]
  char v23; // [sp+18h] [bp-20h]
 
  v3 = a1;
  string = a3;
  v5 = fopen("/sdcard/reg.dat", "w+");
  if ( v5 )
  {
    if ( v22 == _stack_chk_guard )
      return j___android_log_print(3, "com.gdufs.xman", &unk_2DCA);
  }
  else
  {
    v7 = &v21;
    v8 = "W3_arE_whO_we_ARE";
    do
    {
      v9 = *v8;
      v8 += 8;
      v10 = *(v8 - 1);
      *v7 = v9;
      v7[1] = v10;
      v11 = v7 + 2;
      v7 += 2;
    }
    while ( v8 != "E" );
    v12 = v3;
    v13 = 2016;
    *v11 = *v8;
    v14 = *v3;
    v15 = 0;
    v16 = (v14[169])(v12, string, 0);
    v17 = v16;
    v18 = strlen(v16);
    while ( v15 < v18 )
    {
      if ( v15 % 3 == 1 )                        //1、4、7、10、13
      {
        v13 = (v13 + 5) % 16;                   // 5
        v19 = *(&v23 + v13 - 23);               // w
      }
      else if ( v15 % 3 == 2 )                  //2、5、8、11
      {
        v13 = (v13 + 7) % 15;                   // 13
        v19 = *(&v23 + v13 - 22);               // _
      }
      else                                      //剩下的就是3、6、9
      {
        v13 = (v13 + 3) % 13;                   // 4
        v19 = *(&v23 + v13 - 21);               // a
      }
      v20 = *v17;
      ++v15;
      *(++v17 - 1) = v20 ^ v19;                 // 拿输入的字符和这里加密的字符异或然后保存到/sdcard/reg.dat
    }
    fputs(v16, 0);
  }
  return j_fclose(v5);
}

到这里都没看到验证的点,不急我们继续看work,也就是n3,这个也啥都没有就调了n1,那验证的代码肯定在n1了

int __fastcall n3(int a1)
{
  int v1; // r4
  int v2; // r0
  JNIEnv *v3; // r0
  void *v4; // r1
  bool v5; // zf
 
  v1 = a1;
  n1(a1);
  v2 = getValue(v1);
  if ( v2 )
  {
    v5 = v2 == 1;
    v3 = v1;
    if ( v5 )
      v4 = &unk_2E6B;  //验证通过之后的toast
    else
      v4 = &unk_2E95;
  }
  else
  {
    v3 = v1;
    v4 = &unk_2E5B;
  }
  return callWork(v3, v4);
}

最后看n1,直接从/sdcard/reg.dat取值和"EoPAoY62@ElRD"比较,到这里就已经很明了了,就是拿用户输入^“w_aw_aw_aw_aw”判断是否等于"EoPAoY62@ElRD",那直接“w_aw_aw_aw_aw”逐位异或"EoPAoY62@ElRD"就得到了用户输入也就是flag了;

int __fastcall n1(int a1)
{
  int v1; // r6
  FILE *v2; // r0
  FILE *v3; // r4
  int v4; // r0
  FILE *v5; // r1
  int v6; // r7
  void *v7; // r5
  int v9; // r0
  signed int v10; // r1
 
  v1 = a1;
  v2 = fopen("/sdcard/reg.dat", "r+");
  v3 = v2;
  if ( !v2 )
  {
    v4 = v1;
    v5 = v3;
    return setValue(v4, v5);
  }
  fseek(v2, 0, 2);
  v6 = ftell(v3);
  v7 = malloc(v6 + 1);
  if ( !v7 )
  {
    fclose(v3);
    v4 = v1;
    v5 = 0;
    return setValue(v4, v5);
  }
  fseek(v3, 0, 0);
  fread(v7, v6, 1u, v3);
  *(v7 + v6) = 0;
  if ( !strcmp(v7, "EoPAoY62@ElRD") )
  {
    v9 = v1;
    v10 = 1;
  }
  else
  {
    v9 = v1;
    v10 = 0;
  }
  setValue(v9, v10);
  return j_fclose(v3);
}

最后得到flag:“201608Am!2333”,看到toast还强行给加个格式,那flag就是:xman{201608Am!2333}

Android逆向题解6-黑客精神_第8张图片
解题思路没啥问题,但其实还可以更简单一些,不用解密“w_aw_aw_aw_aw”也可以。
它的逻辑是这样的:
输入的flag与一个解密的字符串异或得到"EoPAoY62@ElRD",输入的flag就是正确的,它会把异或的结果保存,那么反过来我们输入"EoPAoY62@ElRD"异或后的结果就是flag了,直接从保存的文件中拿到异或的结果就是正确的flag了;

flag^? =“EoPAoY62@ElRD”

那么

"EoPAoY62@ElRD“^?=flag

这里的?就是解密得到的“w_aw_aw_aw_aw”,所以其实根本不用解它,不管它是个啥,我们直接输入"EoPAoY62@ElRD“,那么异或之后的结果就是flag,

前面说过这个结果会保存到/sdcard/reg.dat,所以直接从/sdcard/reg.dat就可以拿到flag了;

你可能感兴趣的:(安卓逆向题解)