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 

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<

 

你可能感兴趣的:(BugKuCTF 逆向 LoopAndLoop)