首页
社区
课程
招聘
[原创]bugku CTF安卓逆向LoopAndLoop(阿里CTF)
发表于: 2024-2-9 23:49 13581

[原创]bugku CTF安卓逆向LoopAndLoop(阿里CTF)

2024-2-9 23:49
13581

来自bugku的LoopAndLoop(阿里CTF)

拿到压缩包解压,看到文件时APK格式,直接拖到夜神模拟器看看。

简单的测试了下如下

将APK拖到JADX,找到MainActivity,代码如下

安卓层面主要的逻辑

以上代码逻辑

双击check函数,一层层引用可以找到最终调用的是

JADX保存文件到本地,直接将so文件拖入32位IDA7.5版本,其支持arm F5的版本也行。

查看Exports 页面,下面时部分导出函数

双击函数Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec,直接跳转到汇编代码页面,F5就可得到逻辑代码。简单的修改了下第一个参数的数据类型,代码逻辑看着更清晰了

可以看到so文件的代码又去调用了UI层的逻辑。

结合MainActivity中的代码和so中的代码,整理chec函数逻辑如下

既然是个int值,从0开始穷举就可以了。但是这绝对不是唯一办法。

先看看前0-99的输出吧!

结果

可以看出是结果是线性的。首先我们会想到2分法。

2分法计算如下

通过仔细观察也可以看出i增长1,计算结果也增长1。这样可以直接算出想要的i值。

计算结果。

找到so中函数stringFromJNI2,方法同上

剔除无用参数得到c语言逻辑

最后得到flag如下

public class MainActivity extends AppCompatActivity {
    public native int chec(int i, int i2);
 
    public native String stringFromJNI2(int i);
 
    /* JADX INFO: Access modifiers changed from: protected */
    @Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        final TextView tv1 = (TextView) findViewById(R.id.textView2);
        final TextView tv2 = (TextView) findViewById(R.id.textView3);
        final EditText ed = (EditText) findViewById(R.id.editText);
        button.setOnClickListener(new View.OnClickListener() { // from class: net.bluelotus.tomorrow.easyandroid.MainActivity.1
            @Override // android.view.View.OnClickListener
            public void onClick(View v) {
                String in_str = ed.getText().toString();
                try {
                    int in_int = Integer.parseInt(in_str);
                    if (MainActivity.this.check(in_int, 99) == 1835996258) {
                        tv1.setText("The flag is:");
                        tv2.setText("alictf{" + MainActivity.this.stringFromJNI2(in_int) + "}");
                        return;
                    }
                    tv1.setText("Not Right!");
                } catch (NumberFormatException e) {
                    tv1.setText("Not a Valid Integer number");
                }
            }
        });
    }
 
    @Override // android.app.Activity
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
 
    @Override // android.app.Activity
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
 
    public String messageMe(String text) {
        return "LoopOk" + text;
    }
 
    public int check(int input, int s) {
        return chec(input, s);
    }
 
    public int check1(int input, int s) {
        int t = input;
        for (int i = 1; i < 100; i++) {
            t += i;
        }
        return chec(t, s);
    }
 
    public int check2(int input, int s) {
        int t = input;
        if (s % 2 == 0) {
            for (int i = 1; i < 1000; i++) {
                t += i;
            }
            return chec(t, s);
        }
        for (int i2 = 1; i2 < 1000; i2++) {
            t -= i2;
        }
        return chec(t, s);
    }
 
    public int check3(int input, int s) {
        int t = input;
        for (int i = 1; i < 10000; i++) {
            t += i;
        }
        return chec(t, s);
    }
 
    static {
        System.loadLibrary("lhm");
    }
}
public class MainActivity extends AppCompatActivity {
    public native int chec(int i, int i2);
 
    public native String stringFromJNI2(int i);
 
    /* JADX INFO: Access modifiers changed from: protected */
    @Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        final TextView tv1 = (TextView) findViewById(R.id.textView2);
        final TextView tv2 = (TextView) findViewById(R.id.textView3);
        final EditText ed = (EditText) findViewById(R.id.editText);
        button.setOnClickListener(new View.OnClickListener() { // from class: net.bluelotus.tomorrow.easyandroid.MainActivity.1
            @Override // android.view.View.OnClickListener
            public void onClick(View v) {
                String in_str = ed.getText().toString();
                try {
                    int in_int = Integer.parseInt(in_str);
                    if (MainActivity.this.check(in_int, 99) == 1835996258) {
                        tv1.setText("The flag is:");
                        tv2.setText("alictf{" + MainActivity.this.stringFromJNI2(in_int) + "}");
                        return;
                    }
                    tv1.setText("Not Right!");
                } catch (NumberFormatException e) {
                    tv1.setText("Not a Valid Integer number");
                }
            }
        });
    }
 
    @Override // android.app.Activity
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
 
    @Override // android.app.Activity
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
 
    public String messageMe(String text) {
        return "LoopOk" + text;
    }
 
    public int check(int input, int s) {
        return chec(input, s);
    }
 
    public int check1(int input, int s) {
        int t = input;
        for (int i = 1; i < 100; i++) {
            t += i;
        }
        return chec(t, s);
    }
 
    public int check2(int input, int s) {
        int t = input;
        if (s % 2 == 0) {
            for (int i = 1; i < 1000; i++) {
                t += i;
            }
            return chec(t, s);
        }
        for (int i2 = 1; i2 < 1000; i2++) {
            t -= i2;
        }
        return chec(t, s);
    }
 
    public int check3(int input, int s) {
        int t = input;
        for (int i = 1; i < 10000; i++) {
            t += i;
        }
        return chec(t, s);
    }
 
    static {
        System.loadLibrary("lhm");
    }
}
int in_int = Integer.parseInt(in_str);
if (MainActivity.this.check(in_int, 99) == 1835996258) {
    tv1.setText("The flag is:");
    tv2.setText("alictf{" + MainActivity.this.stringFromJNI2(in_int) + "}");
    return;
}
tv1.setText("Not Right!");
int in_int = Integer.parseInt(in_str);
if (MainActivity.this.check(in_int, 99) == 1835996258) {
    tv1.setText("The flag is:");
    tv2.setText("alictf{" + MainActivity.this.stringFromJNI2(in_int) + "}");
    return;
}
tv1.setText("Not Right!");
public native int chec(int i, int i2);
public native int chec(int i, int i2);
Name    Address Ordinal
Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec   00000E8C   
Java_net_bluelotus_tomorrow_easyandroid_MainActivity_stringFromJNI2 00000F18   
....
Name    Address Ordinal
Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec   00000E8C   
Java_net_bluelotus_tomorrow_easyandroid_MainActivity_stringFromJNI2 00000F18   
....
int __fastcall Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec(JNIEnv *jenv, int a2, int t, int s)
{
  jclass v5; // r7
  int result; // r0
  int v10[9]; // [sp+1Ch] [bp-24h] BYREF
 
  v5 = (*jenv)->FindClass(jenv, "net/bluelotus/tomorrow/easyandroid/MainActivity");
  v10[0] = _JNIEnv::GetMethodID(jenv, v5, "check1", "(II)I");
  v10[1] = _JNIEnv::GetMethodID(jenv, v5, "check2", "(II)I");
  v10[2] = _JNIEnv::GetMethodID(jenv, v5, "check3", "(II)I");
  if ( s - 1 <= 0 )
    result = t;
  else
    result = _JNIEnv::CallIntMethod(jenv, a2, v10[2 * s % 3], t, s - 1);//
                                                // 99 * 2 % 3 = 0
                                                // 98 * 2 % 3 = 1
                                                // 97 * 2 % 3 = 2
                                                // 96 * 2 % 3 = 0
  return result;
}
int __fastcall Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec(JNIEnv *jenv, int a2, int t, int s)
{
  jclass v5; // r7
  int result; // r0
  int v10[9]; // [sp+1Ch] [bp-24h] BYREF
 
  v5 = (*jenv)->FindClass(jenv, "net/bluelotus/tomorrow/easyandroid/MainActivity");
  v10[0] = _JNIEnv::GetMethodID(jenv, v5, "check1", "(II)I");
  v10[1] = _JNIEnv::GetMethodID(jenv, v5, "check2", "(II)I");
  v10[2] = _JNIEnv::GetMethodID(jenv, v5, "check3", "(II)I");
  if ( s - 1 <= 0 )
    result = t;
  else
    result = _JNIEnv::CallIntMethod(jenv, a2, v10[2 * s % 3], t, s - 1);//
                                                // 99 * 2 % 3 = 0
                                                // 98 * 2 % 3 = 1
                                                // 97 * 2 % 3 = 2
                                                // 96 * 2 % 3 = 0
  return result;
}
int chec(int t, int s);
 
int check1(int input, int s)
{
    int t = input;
    for (int i = 1; i < 100; i++)
    {
        t += i;
    }
    return chec(t, s);
}
 
int check2(int input, int s)
{
    int t = input;
    if (s % 2 == 0)
    {
        for (int i = 1; i < 1000; i++)
        {
            t += i;
        }
        return chec(t, s);
    }
    for (int i2 = 1; i2 < 1000; i2++)
    {
        t -= i2;
    }
    return chec(t, s);
}
 
int check3(int input, int s)
{
    int t = input;
    for (int i = 1; i < 10000; i++)
    {
        t += i;
    }
    return chec(t, s);
}
 
typedef int (*pfn_check)(int, int);
 
pfn_check check_fns[3] = {
    check1, check2, check3};
 
int chec(int t, int s)
{
    if (s - 1 <= 0)
    {
        /* code */
        return t;
    }
    else
    {
        return check_fns[2 * s % 3](t, s - 1);
    }
}
int chec(int t, int s);
 
int check1(int input, int s)
{
    int t = input;
    for (int i = 1; i < 100; i++)
    {
        t += i;
    }
    return chec(t, s);
}
 
int check2(int input, int s)
{
    int t = input;
    if (s % 2 == 0)
    {
        for (int i = 1; i < 1000; i++)
        {
            t += i;
        }
        return chec(t, s);
    }
    for (int i2 = 1; i2 < 1000; i2++)
    {
        t -= i2;
    }
    return chec(t, s);
}
 
int check3(int input, int s)
{
    int t = input;
    for (int i = 1; i < 10000; i++)
    {
        t += i;
    }
    return chec(t, s);

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 4
支持
分享
最新回复 (1)
雪    币: 3059
活跃值: (30876)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2024-2-11 21:29
1
游客
登录 | 注册 方可回帖
返回
//