zoukankan      html  css  js  c++  java
  • BugKuCTF 逆向 LoopAndLoop

    1.

    下载文件,发现是个APK文件,用模拟器装一下(这里我用的是BlueStack)。

    随便输入几个数字,显示“Not Right”,应该是输入正确的密码就能获得flag,好的,我们打开JEB进行反编译。

    2.

    打开MainActivity,核心代码如下。

    protected void onCreate(Bundle arg6) {
            super.onCreate(arg6);
            this.setContentView(017701000030);
            this.findViewById(0x7F0C0052).setOnClickListener(new View$OnClickListener(this.findViewById(0x7F0C0050), this.findViewById(0x7F0C0051), this.findViewById(0x7F0C0053)) {
                public void onClick(View arg7) {
                    int v1;
                    String v2 = this.val$ed.getText().toString();
                    try {
                        v1 = Integer.parseInt(v2);
                    }
                    catch(NumberFormatException v0) {
                        this.val$tv1.setText("Not a Valid Integer number");
                        return;
                    }
    
                    if(MainActivity.this.check(v1, 99) == 0x6D6F1462) {  // 1835996258
                        this.val$tv1.setText("The flag is:");
                        this.val$tv2.setText("alictf{" + MainActivity.this.stringFromJNI2(v1) + "}");
                    }
                    else {
                        this.val$tv1.setText("Not Right!");
                    }
                }
            });
        }

    可以看到这段代码先对我们输入的字符串进行了检测,如果格式不对就抛出异常,这个暂且不用管。其后有一个判断,调用check方法将我们输入的值与99进行一番操作,如果返回值与1835996258相等就输出flag。好的,接下来看看check函数对我们的输入做了什么。

    3.

    由于check函数在native层,我们需要用IDA打开liblhm.so。找到它的位置,反编译后的代码如下:

    int __fastcall Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec(int a1, int a2, int a3, int a4)
    {
      int v4; // r4
      int v5; // r7
      int result; // r0
      int v7; // [sp+Ch] [bp-34h]
      int v8; // [sp+10h] [bp-30h]
      int v9; // [sp+14h] [bp-2Ch]
      int v10; // [sp+1Ch] [bp-24h]
      int v11; // [sp+20h] [bp-20h]
      int v12; // [sp+24h] [bp-1Ch]
    
      v9 = a2;
      v8 = a4;
      v4 = a1;
      v7 = a3;
      v5 = (*(int (**)(void))(*(_DWORD *)a1 + 24))();
      v10 = _JNIEnv::GetMethodID(v4, v5, "check1", "(II)I");
      v11 = _JNIEnv::GetMethodID(v4, v5, "check2", "(II)I");
      v12 = _JNIEnv::GetMethodID(v4, v5, "check3", "(II)I");
      if ( v8 - 1 <= 0 )
        result = v7;
      else
        result = _JNIEnv::CallIntMethod(v4, v9, *(&v10 + 2 * v8 % 3), v7, v8 - 1);
      return result;
    }

    看一看这段代码,当v8-1<=0时返回第一个参数,为终止条件,*(&v10 + 2 * v8 % 3)决定了调用三个check方法中的哪一个,当2*v8%3=0时调用check1,等于1时调用check2,等于2时调用check3,v7和v8-1为传入方法的变量。总结一下,基本流程为传入两个值,第一个值是我们的输入值,通过调用不同的方法后改变其数值;第二个值初始值为99,用来控制流程终止以及判断调用check1,check2,check3中的哪一个函数,每次调用时第二个值都减1,当返回值等于1835996258时输出flag。

    4.

    知道基本逻辑后,我们可以写出算法求解答案了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int main()
    {
    	long long num=99;
    	long long flag=1835996258;
    	while(num-1>0)
    		{
    			long long tmp=num*2%3;
    			if(tmp==0)
    				for(long long i=0;i<100;i++)
    					flag-=i;
    			if(tmp==1)
    				if((num-1)%2==0)
    					for(long long i=0;i<1000;i++)
    						flag-=i;
    				else
    					for(long long i=0;i<1000;i++)
    						flag+=i;
    			if(tmp==2)
    				for(long long i=0;i<10000;i++)
    					flag-=i;
    			num--;
    		}
    	cout<<flag<<endl;
    	return 0;
    }
  • 相关阅读:
    Python数据分析与机器学习-Pandas_1
    Python数据分析与机器学习-NumPy_5
    Python数据分析与机器学习-NumPy_3
    Python数据分析与机器学习-NumPy_4
    Python数据分析与机器学习-NumPy_2
    Python数据分析与机器学习-NumPy_1
    早起的鸟儿会摔倒
    我讨厌这样的自己
    依然很迷茫?
    孵客总结
  • 原文地址:https://www.cnblogs.com/BlueDoor1999/p/13301381.html
Copyright © 2011-2022 走看看