BugKuCTF 逆向 LoopAndLoop
程序员文章站
2022-05-15 11:24:39
...
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;
}