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; }