前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【愚公系列】2023年04月 攻防世界-MOBILE(boomshakalaka-3)

【愚公系列】2023年04月 攻防世界-MOBILE(boomshakalaka-3)

作者头像
愚公搬代码
发布2023-04-28 17:07:31
6030
发布2023-04-28 17:07:31
举报
文章被收录于专栏:历史专栏历史专栏

前言

下面介绍两个反编译工具

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

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

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

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

安装命令

代码语言:javascript
复制
pip3 install objection 

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

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

一、boomshakalaka-3

1.题目

在这里插入图片描述
在这里插入图片描述

2.答题

1、源码分析

jadx打开文件

在这里插入图片描述
在这里插入图片描述

可以看到入口文件为FirstTest

在这里插入图片描述
在这里插入图片描述

这两个方法内部都用到了a类的d方法,接下来看一看这个方法,a类的主要功能是使用SharedPreferences接口进行数据存储。

代码语言:javascript
复制
package com.example.plane;

import android.content.Context;
import android.content.SharedPreferences;

/* loaded from: classes.dex */
public class a {
    private SharedPreferences editor;

    public a(Context arg1, String arg2) {
        this.editor = null;
        this.editor = arg1.getSharedPreferences(arg2, 0);
    }

    public void b() {
        this.editor.edit().putString("DATA", "").commit();
    }

    public String c() {
        return this.editor.getString("DATA", "");
    }

    public void d(String arg1) {
        this.editor.edit().putString("DATA", String.valueOf(String.valueOf(c())) + arg1).commit();
    }
}
在这里插入图片描述
在这里插入图片描述

SharedPreferences接口是一个轻量级的存储类,用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据。

2、IDA打开libcocos2dcpp.so

IDA 打开so,搜索update 或者score看看,发现updateScore函数

代码语言:javascript
复制
cocos2d::CCUserDefault *__fastcall ControlLayer::updateScore(cocos2d::CCUserDefault *result, const char *a2)
{
  int v2; // r3
  int v4; // r7
  cocos2d::CCUserDefault *v5; // r0
  int v6; // r5
  char *v7; // r0
  int v8; // r5
  int v9; // r5
  int v10; // r5
  int v11; // r5
  int v12; // r5
  int v13; // r5
  int v14; // r5
  int v15; // r5
  int v16; // r5
  int v17; // r0
  cocos2d::CCUserDefault *v18; // [sp+4h] [bp-64h]
  char v19[4]; // [sp+Ch] [bp-5Ch] BYREF
  char v20[4]; // [sp+10h] [bp-58h] BYREF
  char v21[4]; // [sp+14h] [bp-54h] BYREF
  char v22[4]; // [sp+18h] [bp-50h] BYREF
  char v23[4]; // [sp+1Ch] [bp-4Ch] BYREF
  char v24[4]; // [sp+20h] [bp-48h] BYREF
  char v25[4]; // [sp+24h] [bp-44h] BYREF
  char v26[4]; // [sp+28h] [bp-40h] BYREF
  char v27[4]; // [sp+2Ch] [bp-3Ch] BYREF
  char v28[4]; // [sp+30h] [bp-38h] BYREF
  char v29[4]; // [sp+34h] [bp-34h] BYREF
  char v30[4]; // [sp+38h] [bp-30h] BYREF
  char v31[4]; // [sp+3Ch] [bp-2Ch] BYREF
  char v32[8]; // [sp+40h] [bp-28h] BYREF
  int v33; // [sp+48h] [bp-20h] BYREF
  char v34; // [sp+4Ch] [bp-1Ch]

  strcpy(v32, "data");
  v2 = 0;
  v34 = 0;
  v18 = result;
  v33 = 0;
  do
  {
    *((_BYTE *)&v33 + v2) = v32[v2] ^ 0x20;
    ++v2;
  }
  while ( v2 != 4 );
  if ( (unsigned int)a2 <= 0x3B9ACA00 )
  {
    v4 = cocos2d::CCUserDefault::sharedUserDefault(result);
    sub_3A34D8(v21, &unk_3F92A0, v19);
    cocos2d::CCUserDefault::getStringForKey(v20, v4, &v33, v21);
    v5 = (cocos2d::CCUserDefault *)sub_3A1DDC(v21);
    if ( a2 == (const char *)&dword_64 )
    {
      v6 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v22, v20, "MW");
      cocos2d::CCUserDefault::setStringForKey(v6, &v33, v22);
      v7 = v22;
    }
    else if ( a2 == (const char *)&stru_254.st_value )
    {
      v8 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v23, v20, "Rf");
      cocos2d::CCUserDefault::setStringForKey(v8, &v33, v23);
      v7 = v23;
    }
    else if ( a2 == (const char *)&stru_2B4.st_size )
    {
      v9 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v24, v20, "Rz");
      cocos2d::CCUserDefault::setStringForKey(v9, &v33, v24);
      v7 = v24;
    }
    else if ( a2 == (const char *)&stru_BB4.st_value )
    {
      v10 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v25, v20, "Bt");
      cocos2d::CCUserDefault::setStringForKey(v10, &v33, v25);
      v7 = v25;
    }
    else if ( a2 == (const char *)&stru_15D4.st_info )
    {
      v11 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v26, v20, "RV");
      cocos2d::CCUserDefault::setStringForKey(v11, &v33, v26);
      v7 = v26;
    }
    else if ( a2 == (const char *)&stru_26A4.st_size )
    {
      v12 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v27, v20, "9Z");
      cocos2d::CCUserDefault::setStringForKey(v12, &v33, v27);
      v7 = v27;
    }
    else if ( a2 == (const char *)&stru_4644.st_info )
    {
      v13 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v28, v20, "b1");
      cocos2d::CCUserDefault::setStringForKey(v13, &v33, v28);
      v7 = v28;
    }
    else if ( a2 == (const char *)&stru_15AD4.st_info )
    {
      v14 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v29, v20, "Vf");
      cocos2d::CCUserDefault::setStringForKey(v14, &v33, v29);
      v7 = v29;
    }
    else if ( a2 == (const char *)&stru_18694.st_info )
    {
      v15 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v30, v20, "S2");
      cocos2d::CCUserDefault::setStringForKey(v15, &v33, v30);
      v7 = v30;
    }
    else
    {
      if ( a2 != (const char *)1000000000 )
      {
LABEL_25:
        v17 = cocos2d::CCString::createWithFormat((cocos2d::CCString *)"%d", a2);
        (*(void (__fastcall **)(_DWORD, _DWORD))(**((_DWORD **)v18 + 66) + 428))(
          *((_DWORD *)v18 + 66),
          *(_DWORD *)(v17 + 20));
        return (cocos2d::CCUserDefault *)sub_3A1DDC(v20);
      }
      v16 = cocos2d::CCUserDefault::sharedUserDefault(v5);
      std::operator+<char>(v31, v20, "4w");
      cocos2d::CCUserDefault::setStringForKey(v16, &v33, v31);
      v7 = v31;
    }
    sub_3A1DDC(v7);
    goto LABEL_25;
  }
  return result;
}

得到最终写入的字符串:MWRfRzBtRV9Zb1VfS24w

3、进入模拟器的 /data/data/com.example.plane/shared_prefs

玩几把游戏分析配置文件,可得

代码语言:javascript
复制
ZntDMGNvUzJkX0FuRHJv + 得分 + dz99

最后得出:MGN0ZntDMGNvUzJkX0FuRHJvMWRfRzBtRV9Zb1VfS24wdz99

进行base64解密解密得到

在这里插入图片描述
在这里插入图片描述

flag为:0ctf{C0coS2d_AnDro1d_G0mE_YoU_Kn0w?}

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、boomshakalaka-3
    • 1.题目
      • 2.答题
      相关产品与服务
      数据保险箱
      数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档