0


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

文章目录


前言

下面介绍两个反编译工具

  • 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

一、Illusion

1.题目

在这里插入图片描述

2.答题

1、jadx-gui

使用jadx-gui打开apk文件

在这里插入图片描述

package monkeylord.illusion;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.InputStreamReader;/* loaded from: classes.dex */publicclassMainActivityextends Activity {public native StringCheckFlag(String str,String str2);static{
        System.loadLibrary("native-lib");}

    @Override // android.app.ActivityprotectedvoidonCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.button).setOnClickListener(newView.OnClickListener(){// from class: monkeylord.illusion.MainActivity.1
            @Override // android.view.View.OnClickListenerpublicvoidonClick(View view){try{String flag =((EditText) MainActivity.this.findViewById(R.id.editText)).getText().toString();String encflag =newBufferedReader(newInputStreamReader(MainActivity.this.getAssets().open("Flag"))).readLine();if(encflag !=null){((TextView) MainActivity.this.findViewById(R.id.sample_text)).setText(MainActivity.this.CheckFlag(flag, encflag));}}catch(Exception e){((TextView) MainActivity.this.findViewById(R.id.sample_text)).setText("Something Wrong");}}});}}

调用CheckFlag函数进行校验,这个函数传入两个参数,一个是flag,一个是encflag。其中flag是我们输入的值,encflag是存在文中进行读取的

在这里插入图片描述
2、ida pro进行So文件分析

搜索找到函数,进行伪代码分析
在这里插入图片描述

int__fastcallJava_monkeylord_illusion_MainActivity_CheckFlag(_JNIEnv *a1,int a2,int a3,int a4){size_t v4;// r0size_t i;// [sp+28h] [bp-34h]char*v7;// [sp+30h] [bp-2Ch]char*v8;// [sp+34h] [bp-28h]char*v9;// [sp+38h] [bp-24h]

  v9 =(char*)j_j_Jstring2CStr(a1, a3);
  v4 =j_strlen(v9);
  v8 =(char*)j_calloc(1u, v4 +1);
  v7 =(char*)j_j_Jstring2CStr(a1, a4);for( i =0; i <j_strlen(v9);++i )
    v8[i]=((unsigned __int64)sub_10C0((unsigned __int8)v9[i]+(unsigned int)(unsigned __int8)aE116c5c66e7b37[i]-64,93)>>32)+32;if(!j_strcmp(v8, v7))return j__JNIEnv::NewStringUTF(a1,"Correct!");elsereturn j__JNIEnv::NewStringUTF(a1,"Try Again!");}

2、sub_10C0

而sub_10C0函数,则是判断a2是否等于0,然后来判断执行哪个函数
由于a2的值恒定为93,所以只执行sub_1028()函数

在这里插入图片描述

int__fastcallsub_10C0(int a1,int a2){if( a2 )returnsub_1028();elsereturnsub_10AC();}

3、sub1028

sub1028虽然有些长,但是逻辑很简单

在这里插入图片描述

int__fastcallsub_1028(unsigned int a1, unsigned int a2){int v2;// r12
  unsigned int v3;// r3int v4;// r2int result;// r0

  v2 = a1 ^ a2;
  v3 =1;
  v4 =0;if((a2 &0x80000000)!=0)
    a2 =-a2;if((a1 &0x80000000)!=0)
    a1 =-a1;if( a1 >= a2 ){while( a2 <0x10000000&& a2 < a1 ){
      a2 *=16;
      v3 *=16;}while( a2 <0x80000000&& a2 < a1 ){
      a2 *=2;
      v3 *=2;}while(1){if( a1 >= a2 ){
        a1 -= a2;
        v4 |= v3;}if( a1 >= a2 >>1){
        a1 -= a2 >>1;
        v4 |= v3 >>1;}if( a1 >= a2 >>2){
        a1 -= a2 >>2;
        v4 |= v3 >>2;}if( a1 >= a2 >>3){
        a1 -= a2 >>3;
        v4 |= v3 >>3;}if(!a1 )break;
      v3 >>=4;if(!v3 )break;
      a2 >>=4;}}
  result = v4;if( v2 <0)return-v4;return result;}

将用户输入的每个字符,加上内置data字符串对应的下标的字符,然后再减去64;
得到的结果,取余93后,进行比较

3.脚本

enc_flag ="Ku@'G_V9v(yGS"
data ="(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"
data =[ord(i)for i in data]defmain():
    enc =[ord(i)for i in enc_flag]
    flag =[0]*len(enc)for i inrange(len(enc)):
        flag[i]=(enc[i]-32)+64-data[i]while flag[i]<0x32:
            flag[i]+=93while flag[i]>125:
            flag[i]-=93print("".join([chr(i)for i in flag]))if __name__ == '__main__':main()# CISCN{GJ5728}

或者暴力破解

package com.test;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.arm.HookStatus;
import com.github.unidbg.hook.HookContext;
import com.github.unidbg.hook.ReplaceCallback;
import com.github.unidbg.hook.hookzz.HookZz;
import com.github.unidbg.linux.android.AndroidARMEmulator;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.dvm.array.ByteArray;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.pointer.UnidbgPointer;
import com.sun.jna.Pointer;
import unicorn.Arm64Const;
import unicorn.ArmConst;

import java.io.File;
import java.util.ArrayList;
import java.util.List;publicclassillusionextends AbstractJni {private final AndroidEmulator emulator;private final VM vm;private final Module module;privateDvmClass cNative;privatestaticString r0;private illusion (){// 创建模拟器实例,进程名建议依照实际进程名填写,可以规避针对进程名的校验
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("monkeylord.illusion").build();// 获取模拟器的内存操作接口
        final Memory memory = emulator.getMemory();// 设置系统类库解析
        memory.setLibraryResolver(newAndroidResolver(23));// 创建Android虚拟机,传入APK,Unidbg可以替我们做部分签名校验的工作//        vm =  emulator.createDalvikVM(new File("unidbg-android/src/test/java/com/test/llusion.apk"));
        vm =  emulator.createDalvikVM();// 加载目标SODalvikModule dm = vm.loadLibrary(newFile("unidbg-android/src/test/java/com/test/libnative-lib.so"),true);// 加载so到虚拟内存//获取本SO模块的句柄,后续需要用它
        module = dm.getModule();
        vm.setJni(this);// 设置JNI
        vm.setVerbose(false);// 打印日志

        dm.callJNI_OnLoad(emulator);// 调用JNI OnLoad}publicstaticvoidmain(String[] args){illusion test =newillusion();
        test.hook();String flag_enc ="Ku@'G_V9v(yGS";String flag ="";for(int index =0; index < flag_enc.length(); index++){for(int i =33; i <127; i++){
                test.CheckFlag(flag + String.valueOf((char) i), flag_enc);// 进行判断if((illusion.r0.length()> index)&&(flag_enc.charAt(index)== illusion.r0.charAt(index))){
                    flag += String.valueOf((char) i);break;}}
            System.out.println("Flag[0:"+index+"]: "+flag);}

        System.out.println("Completely Flag is: "+flag);}privatevoidCheckFlag(String flag,String flag_enc){//创建jobject对象DvmObject<?> thiz = vm.resolveClass("monkeylord.illusion").newObject(null);List<Object> list =newArrayList<>(10);
        list.add(vm.getJNIEnv());
        list.add(0);  
        list.add(vm.addLocalObject(newStringObject(vm, flag)));// arg 3
        list.add(vm.addLocalObject(newStringObject(vm, flag_enc)));// arg 4Number number =  module.callFunction(emulator,0xdc9, list.toArray());//        System.out.print("result:");//        DvmObject<?> object = vm.getObject(number.intValue());//        System.out.print(object.getValue().toString());}publicvoidhook(){HookZz hook = HookZz.getInstance(emulator);
        hook.replace(module.base+0x00000E64+1,newReplaceCallback(){
            @Override
            publicHookStatusonCall(Emulator<?> emulator,HookContext context,long originFunction){//                System.out.println(context.getPointerArg(0).getString(0));  // 入参1 R0寄存器
                illusion.r0 = context.getPointerArg(0).getString(0);//                System.out.println(context.getPointerArg(1).getString(0));  // 入参2 R1寄存器return super.onCall(emulator, context,originFunction);}},true);}}

得到flag为:

CISCN{GJ5728}

本文转载自: https://blog.csdn.net/aa2528877987/article/details/130363466
版权归原作者 愚公搬代码 所有, 如有侵权,请联系我们删除。

“【愚公系列】2023年04月 攻防世界-MOBILE(Illusion)”的评论:

还没有评论