【愚公系列】2023年05月 攻防世界-MOBILE(easy-so)


前言

下面介绍两个反编译工具

  • jadx是一个用于反编译Android APK文件的开源工具,静态反编译,查找索引功能强大
  • jeb和IDA很像,属于动态调试,可以看java汇编也可以生成伪代码,还可以动态attach到目标调试

对于so文件的逆向工具选择

  • IDA逆向工具是一款反汇编器,被广泛应用于软件逆向工程领域,能够反汇编各种不同平台的二进制程序代码,并还原成可读的汇编代码。

Objection是一款移动设备运行时漏洞利用工具,该工具由Frida驱动,可以帮助研究人员访问移动端应用程序,并在无需越狱或root操作的情况下对移动端应用程序的安全进行评估检查。

安装命令

pip3 install objection 

frida是一款便携的、自由的、支持全平台的hook框架,可以通过编写JavaScript、Python代码来和frida_server端进行交互

frida的安装可以参考:https://www.jianshu.com/p/60cfd3f6afde

一、easy-so

1.题目

在这里插入图片描述

2.答题

2.1 运行app

点击check提示
在这里插入图片描述

2.2 jadx反编译apk文件

搜索验证失败字符串
在这里插入图片描述
找到源码
在这里插入图片描述
发现核查字符串函数:CheckString

2.3 IDA修改apk逻辑实现破解

上IDA,搜索刚才的方法名check,只有一个结果,双击跳过去,F5转伪代码,大概看一下,就是TestDec输出的字符串和f72c5a36569418a20907b55be5bf95ad进行对比,如果相等则返回1,也就是验证通过。

_BOOL8 __fastcall Java_com_testjava_jack_pingan2_cyberpeace_CheckString(__int64 a1, __int64 a2, __int64 a3)
{
  const char *v3; // r14
  size_t v4; // rax
  int v5; // er15
  unsigned __int64 v6; // r12
  char *v7; // rax
  char *v8; // r13
  bool v9; // cc
  size_t v10; // r12
  size_t v11; // rbx
  char v12; // al
  char v13; // al
  size_t v14; // rbx
  char v15; // al

  v3 = (const char *)(*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 1352LL))(a1, a3, 0LL);
  v4 = strlen(v3);
  v5 = v4;
  v6 = (__int64)((v4 << 32) + 0x100000000LL) >> 32;
  v7 = (char *)malloc(v6);
  v8 = v7;
  v9 = v6 <= v5;
  v10 = v6 - v5;
  if ( v9 )
    v10 = 0LL;
  memset(&v7[v5], 0, v10);
  memcpy(v8, v3, v5);
  if ( strlen(v8) >= 2 )
  {
    v11 = 0LL;
    do
    {
      v12 = v8[v11];
      v8[v11] = v8[v11 + 16];
      v8[v11++ + 16] = v12;
    }
    while ( strlen(v8) >> 1 > v11 );
  }
  v13 = *v8;
  if ( *v8 )
  {
    *v8 = v8[1];
    v8[1] = v13;
    if ( strlen(v8) >= 3 )
    {
      v14 = 2LL;
      do
      {
        v15 = v8[v14];
        v8[v14] = v8[v14 + 1];
        v8[v14 + 1] = v15;
        v14 += 2LL;
      }
      while ( strlen(v8) > v14 );
    }
  }
  return strcmp(v8, "f72c5a36569418a20907b55be5bf95ad") == 0;
}

在这里插入图片描述
const char * v3是传入的字符串,接下来逐个分析代码逻辑:
第一步:两两交换

v4 = strlen(v3);//取变量v4=v3的字符串长度,假设v3="abcd",v4=4
v5 = v4;
v6 = (__int64)((v4 << 32) + 0x100000000LL) >> 32;
v7 = (char *)malloc(v6);//为字符指针v7请求一块长度为v6的内存空间
v8 = v7;
v9 = v6 <= v5;
v10 = v6 - v5;
if ( v9 )
  v10 = 0LL;
memset(&v7[v5], 0, v10);//将v7扩增一倍并后面扩增的部分初始化为0,此行代码结束,v7=----0000
memcpy(v8, v3, v5);//将v3的内容复制到v8中
if ( strlen(v8) >= 2 )//若v8的长度大于等于2则执行花括号内的内容
{
  v11 = 0LL;//初始化v11=0
  do//执行循环
  {
    v12 = v8[v11];//从第0个开始读取v8的每个字符
    v8[v11] = v8[v11 + 16];//逐个将v8的第v11个字符与第v11+16个字符交换位置
    v8[v11++ + 16] = v12;//v6自增1
  }
  while ( strlen(v8) >> 1 > v11 );
}

假设传入字符串为abcd,则上述代码执行完之后的v8为cdab
继续分析接下来的代码:
第二步:头尾互换

v13 = *v8;
if ( *v8 )
{
  *v8 = v8[1];
  v8[1] = v13;
  if ( strlen(v8) >= 3 )
  {
    v14 = 2LL;
    do
    {
      v15 = v8[v14];
      v8[v14] = v8[v14 + 1];
      v8[v14 + 1] = v15;
      v14 += 2LL;
    }
    while ( strlen(v8) > v14 );
  }
}

根据上述我们直接手动得到flag的code:

1.将f7 2c 5a 36 56 94 18 a2 09 07 b5 5b e5 bf 95 ad两两交换得到7f c2 a5 63 65 49 81 2a 90 70 5b b5 5e fb 59 da

2.将7fc2a5636549812a 90705bb55efb59da从中间砍断,头尾互换得到90705bb55efb59da 7fc2a5636549812a

得到flag:flag{90705bb55efb59da7fc2a5636549812a}

2.4 脚本解题和Java源码

python脚本

data = list('f72c5a36569418a20907b55be5bf95ad') //把字符串传入,并转为列表
for i in range(len(data)//2):  //第一个循环体
    a = data[i]
    data[i] = data[i+16]
    data[i+16] = a
for i in range(0,len(data),2):  //第二个循环体
    a2 = data[i]
    data[i]=data[i+1]
    data[i+1]=a2
key=''.join(data) //拼接字符串
print("flag{"+key+"}")  //把题目中的flag{}和最终字符串拼接并输出

java源码解析

@Test
public void demo2() {
    String str = "f72c5a36569418a20907b55be5bf95ad";
    char[] data = str.toCharArray();
 
    //伪代码中的第二次循环
    int index2 = 0;
    int result;
    int v9;
    do {
        char v8 = data[index2 + 2];
        data[index2 + 2] = data[index2 + 3];
        data[index2 + 3] = v8;
        result = data.length;
        v9 = index2 + 4;
        index2 += 2;
    }
    while (v9 < result);
 
 
    //循环后进行的简单的互换
    result = data[0];
    data[0] = data[1];
    data[1] = (char) result;
    result = data.length;
 
 
    //伪代码中第一次循环
    int index = 0;
    do
    {
        char v4 = data[index];
        data[index] = data[index + 16];
        data[index+16] = v4;
        ++index;
    }
    while ( index < data.length >> 1 );
 
    System.out.println(data);
    //输出结果 -> 90705bb55efb59da7fc2a5636549812a
}

总结

  • APK
  • JADX
  • IDA
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愚公搬代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值