入门逆向 下载完成是一个baby.exe
使用Exeinfo pe查下壳
gcc编写 32位
拖入ida
按两下 空格转换成 汇编模式
选择66h 按R 即可转换成ascii
从上图可以看到 _printf 的地址是 0x00401475
打开lcg 按住ctrl+G 搜索这个地址
找到指令后按住 f12 下断点
可以看到 flag是从esp+0x2f开始的 拿计算器算一下
记得按 f8 步过和f7单步执行
打开显示ascii数据
signin 给了一个apk
使用 jeb打开
这里可以看到 string 是在 0x7F0B0020 取出的
ctrl + f 直接搜索 发现该变量名字就是toString
在string.xml下面找到 字符串的值
我们对着源码 写下逆向函数
import base64s= '991YiZWOz81ZhFjZfJXdwk3X1k2XzIXZIt3ZhxmZ' s = s[::-1 ] print (base64.b64decode(s))
jeb动态调试 雷电模拟器开启 usb调试
root权限
使用androidkiller 添加debug
加入 debug
android:debuggable="true"
adb -s emulator-5554 install -r Sign_in_killer.apk
adb -s emulator-5554 shell am start -D -n re.sdnisc2018.sdnisc_apk1/.MainActivity
ctrl + B 添加断点
查看变量类型需要将int 改为string
Android Studio动态调试
adb shell am start -D -n re.sdnisc2018.sdnisc_apk1/.MainActivity
apk转jar 将apk重命名为zip 解压
d2j-dex2jar.bat D:\Download\Sign_in_killer.apk\classes.dex -o D:\Download\Sign_in_killer.apk\class.jar
Timer(阿里CTF)
jeb打开
package net.bluelotus.tomorrow.easyandroid;import android.os.Bundle;import android.os.Handler;import android.support.v7.app.AppCompatActivity;import android.view.Menu;import android.view.MenuItem;import android.widget.TextView;public class MainActivity extends AppCompatActivity { int beg; int k; int now; long t; static { System.loadLibrary("lhm" ); } public MainActivity () { this .beg = ((int )(System.currentTimeMillis() / 1000L )) + 200000 ; this .k = 0 ; this .t = 0L ; } public static boolean is2 (int arg4) { if (arg4 <= 3 ) { return arg4 > 1 ; } if (arg4 % 2 == 0 || arg4 % 3 == 0 ) { return false ; } int i; for (i = 5 ; i * i <= arg4; i += 6 ) { if (arg4 % i == 0 || arg4 % (i + 2 ) == 0 ) { return false ; } } return true ; } @Override protected void onCreate (Bundle arg7) { super .onCreate(arg7); this .setContentView(0x7F040018 ); TextView tv1 = (TextView)this .findViewById(0x7F0C0050 ); TextView tv2 = (TextView)this .findViewById(0x7F0C0051 ); Handler handler = new Handler (); handler.postDelayed(new Runnable () { @Override public void run () { MainActivity.this .t = System.currentTimeMillis(); MainActivity.this .now = (int )(MainActivity.this .t / 1000L ); MainActivity.this .t = 1500L - MainActivity.this .t % 1000L ; tv2.setText("AliCTF" ); if (MainActivity.this .beg - MainActivity.this .now <= 0 ) { tv1.setText("The flag is:" ); String v1 = "alictf{" + MainActivity.this .stringFromJNI2(MainActivity.this .k) + "}" ; tv2.setText(v1); } if (MainActivity.is2(MainActivity.this .beg - MainActivity.this .now)) { MainActivity.this .k += 100 ; } else { --MainActivity.this .k; } tv1.setText("Time Remaining(s):" + (MainActivity.this .beg - MainActivity.this .now)); handler.postDelayed(this , MainActivity.this .t); } }, 0L ); } @Override public boolean onCreateOptionsMenu (Menu arg3) { this .getMenuInflater().inflate(0x7F0D0000 , arg3); return true ; } @Override public boolean onOptionsItemSelected (MenuItem arg3) { return arg3.getItemId() == 0x7F0C005F ? true : super .onOptionsItemSelected(arg3); } public native String stringFromJNI2 (int arg1) { } }
因此我们需要模拟k的值生成过程
public class Test { public static void main (String[] args) { int k = 0 ; int n=0 ; for (int i = 200000 ; i >0 ; i--) { if (is2(i)) { k += 100 ; } else { --k; } } System.out.println(k); } public static boolean is2 (int arg4) { if (arg4 <= 3 ) { return arg4 > 1 ; } if (arg4 % 2 == 0 || arg4 % 3 == 0 ) { return false ; } int i; for (i = 5 ; i * i <= arg4; i += 6 ) { if (arg4 % i == 0 || arg4 % (i + 2 ) == 0 ) { return false ; } } return true ; } }
这里首先需要进入if 接着要 修改k的值
在下面添加
还需要修改 if语句
这里是如果v0 >0 就跳转到cond_0
可以看到cond_0是else中的内容
这里修改成lez
adb install -r .\Timer_killer.apk
mobile1(gctf) 简单读一下代码就知道 只需要输入 22个字符就可以出flag
mobile2(gctf) 解压后是一个 这样的结构 可以发现是apk 先改名zip后解压之后的结果
但是这里打开 发现是乱码 发现fl4g
First_Mobile(xman) 去检查是否相等
这里是encode类
public class Test { public static void main (String[] args) { byte [] b = {23 , 22 , 26 , 26 , 25 , 25 , 25 , 26 , 27 , 28 , 30 , 30 , 29 , 30 , 0x20 , 0x20 }; for (int i=0 ;i<16 ;++i){ for (int a=0 ;a<127 ;++a){ if (((a+b[i]) %61 )*2 -i ==a){ System.out.print((char )a); } } } } public class encode { private static byte [] b; static { b = new byte []{23 , 22 , 26 , 26 , 25 , 25 , 25 , 26 , 27 , 28 , 30 , 30 , 29 , 30 , 0x20 , 0x20 }; } public static boolean check (String str) { byte [] input = str.getBytes(); byte [] temp = new byte [16 ]; int i; for (i = 0 ; i < 16 ; ++i) { temp[i] = (byte )((input[i] + encode.b[i]) % 61 ); } int v0_1; for (v0_1 = 0 ; v0_1 < 16 ; ++v0_1) { temp[v0_1] = (byte )(temp[v0_1] * 2 - v0_1); } return new String (temp).equals(str); } } }
LoopAndLoop(阿里CTF)
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.OnClickListener;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class MainActivity extends AppCompatActivity { static { System.loadLibrary("lhm" ); } public native int chec (int arg1, int arg2) { } public int check (int arg2, int arg3) { return this .chec(arg2, arg3); } public int check1 (int arg4, int arg5) { int t = arg4; int i; for (i = 1 ; i < 100 ; ++i) { t += i; } return this .chec(t, arg5); } public int check2 (int arg5, int arg6) { int t = arg5; if (arg6 % 2 == 0 ) { int i; for (i = 1 ; i < 1000 ; ++i) { t += i; } return this .chec(t, arg6); } int v0_1; for (v0_1 = 1 ; v0_1 < 1000 ; ++v0_1) { t -= v0_1; } return this .chec(t, arg6); } public int check3 (int arg4, int arg5) { int t = arg4; int i; for (i = 1 ; i < 10000 ; ++i) { t += i; } return this .chec(t, arg5); } public String messageMe (String arg3) { return "LoopOk" + arg3; } @Override protected void onCreate (Bundle arg6) { super .onCreate(arg6); this .setContentView(0x7F040018 ); Button button = (Button)this .findViewById(0x7F0C0052 ); TextView tv1 = (TextView)this .findViewById(0x7F0C0051 ); TextView tv2 = (TextView)this .findViewById(0x7F0C0053 ); button.setOnClickListener(new View .OnClickListener() { @Override public void onClick (View v) { int in_int = Integer.parseInt(((EditText)this .findViewById(0x7F0C0050 )).getText().toString()); if (MainActivity.this .check(in_int, 99 ) == 0x6D6F1462 ) { tv1.setText("The flag is:" ); String v4 = "alictf{" + MainActivity.this .stringFromJNI2(in_int) + "}" ; tv2.setText(v4); return ; } tv1.setText("Not Right!" ); } }); } @Override public boolean onCreateOptionsMenu (Menu menu) { this .getMenuInflater().inflate(0x7F0D0000 , menu); return true ; } @Override public boolean onOptionsItemSelected (MenuItem item) { return item.getItemId() == 0x7F0C0061 ? true : super .onOptionsItemSelected(item); } public native String stringFromJNI2 (int arg1) { } }
简单分析一下就可以发现我们现在需要去 找本地链接库lhm文件
先将apk转换为zip 在解压即可 找到so文件
在chec 可以发现关键代码
int __fastcall Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec (int a1, int a2, int a3, int a4) { int v5; int result; int v10[9 ]; v5 = (*(int (__fastcall **)(int , const char *))(*(_DWORD *)a1 + 24 ))( a1, "net/bluelotus/tomorrow/easyandroid/MainActivity" ); v10[0 ] = _JNIEnv::GetMethodID(a1, v5, "check1" , "(II)I" ); v10[1 ] = _JNIEnv::GetMethodID(a1, v5, "check2" , "(II)I" ); v10[2 ] = _JNIEnv::GetMethodID(a1, v5, "check3" , "(II)I" ); if ( a4 - 1 <= 0 ) result = a3; else result = _JNIEnv::CallIntMethod(a1, a2, v10[2 * a4 % 3 ], a3, a4 - 1 ); return result; }
大致的意思就是根据 2 * a4 % 3 的值来决定调用哪一个check 比如a4是99因为这里的a4 是99 所以 2*99 %3 而后面的两个参数 是 调用 java层的 check(int arg2, int arg3) 的两个参数 在这里每次调用chec() 都会后一个参数都会减一
def chec (result, i ): while True : if i == 100 : print (result) return 0 if 2 * i % 3 == 0 : result, i =check0(result, i +1 ) elif 2 * i % 3 == 1 : result, i =check1(result, i +1 ) else : result, i =check2(result, i+1 ) def check0 (result, i ): for t in range (1 , 100 ): result -= t return result, i def check1 (result, i ): if i % 2 == 0 : for t in range (1 , 1000 ): result -= t return result, i for t in range (1 , 1000 ): result += t return result, i def check2 (result, i ): for t in range (1 , 10000 ): result -= t return result, i result = 0x6D6F1462 chec(result,2 )
这里要注意的是 循环的开始和结束的点
alictf{Jan6N100p3r}
SafeBox(NJCTF)
可以发现有一个 Test包
比较一下发现只是一个是3 一个是4
这里根本不用管原来的代码实在干啥直接爆破就可以
public class Test { public static void main (String[] args) { for (int i = 10000000 ;i<=0x5F5E0FF ;i++){ if (i > 10000000 && i < 0x5F5E0FF ) { int t = 1 ; int t1 = 10000000 ; int flag = 1 ; if (Math.abs(i / 1000 % 100 - 36 ) == 3 && i % 1000 % 584 == 0 ) { int j; for (j = 0 ; j < 4 ; ++j) { if (i / t % 10 != i / t1 % 10 ) { flag = 0 ; break ; } t *= 10 ; t1 /= 10 ; } if (flag == 1 ) { System.out.println("NJCTF{" + ((char )(i / 1000000 )) + ((char )(i / 10000 % 100 )) + ((char )(i / 100 % 100 )) + "f4n}" ); } } } } } }
public class Test { public static void main (String[] args) { for (int i = 10000000 ;i<=0x5F5E0FF ;i++){ if (i > 10000000 && i < 0x5F5E0FF ) { int t = 1 ; int t1 = 10000000 ; int flag = 1 ; if (Math.abs(i / 1000 % 100 - 36 ) == 3 && i % 1000 % 584 == 0 ) { int j; for (j = 0 ; j < 3 ; ++j) { if (i / t % 10 != i / t1 % 10 ) { flag = 0 ; break ; } t *= 10 ; t1 /= 10 ; } if (flag == 1 ) { System.out.println("NJCTF{have" + ((char )(i / 1000000 )) + ((char )(i / 10000 % 100 )) + ((char )(i / 100 % 100 + 10 )) + "f4n}" ); } } } } } }
HelloSmali2