然后把加密后的字符串与str2相比较。str2的值为e3nifIH9b_C@n@dH,先把循环逆向了。
#!usr/bin/env python #!coding=utf-8 __author__ = 'zhengjim' str2 ='e3nifIH9b_C@n@dH' flag ='' for i in range(len(str2)): flag += chr(ord(str2[i])- i) print flag得到e2lfbDB2ZV95b3V9
然后看sub_4110BE()函数。一串长算法,发现首先将输入的flag每3位变成4位。然后有64位密码表。其实就是个base64加密(记下来,base64加密算法的特征)。
也就是将刚刚得到的值base64解密就是flag。
LoopAndLoop(阿里CTF)下载文件发现是apk ,先安装运行下发现有一个输入框,随便输入点getyourflag 跳出Not Right
用jadx-gui反编译,双击看MainActivity查看
package net.bluelotus.tomorrow.easyandroid; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends AppCompatActivity { public native int chec(int i, int i2); public native String stringFromJNI2(int i); protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView((int) R.layout.activity_main); 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) findViewById(R.id.button)).setOnClickListener(new OnClickListener() { public void onClick(View v) { try { int in_int = Integer.parseInt(ed.getText().toString()); 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"); } } }); } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == 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; int i; if (s % 2 == 0) { for (i = 1; i < 1000; i++) { t += i; } return chec(t, s); } for (i = 1; i < 1000; i++) { t -= i; } 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 void onClick(View v) { try { int in_int = Integer.parseInt(ed.getText().toString()); 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"); } }流程为:将用户输入作为参数1(one),99作为参数2(two)传入check函数里,如果返回的值为1835996258,则将用户输入作为参数传入stringFromJNI2函数计算,返回值与alictf{和}拼接组成flag 。
于是我们只要逆向出check函数,将1835996258带入得到的值,拿到apk里边运行即可得到flag。
追过去发现check函数调用了chec函数 为Native层的函数
stringFromJNI2函数也为Native层的函数
加载了System.loadLibrary("lhm");,所以逆向liblhm.so文件。
用IDA打开,还是上面的办法,找到了chec函数
这部分看得比较混乱,查了比较多的资料,所以有不对之处请指出来。