bugku安卓逆向题目First_Mobile(xman)
参考资料
题目来源
题目来自bugku的First_Mobile(xman)
工具
JADX 反编译apk。
gcc 用来编写还原算法。
简单看一下
拿到题目,看后缀是安卓APP,直接甩到夜神里看看啥样子。

反编译,提取算法
MainActivity UI 逻辑
将APK拖入JADX工具,获取到MainActivity代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class MainActivity extends AppCompatActivity { private Button button; private EditText editText; /* JADX INFO: Access modifiers changed from: protected */ @Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityGingerbread, android.app.Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final EditText editText = (EditText) findViewById(R.id.editText); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { // from class: com.example.xman.easymobile.MainActivity.1 @Override // android.view.View.OnClickListener public void onClick(View view) { new encode(); if (encode.check(editText.getText().toString())) { Toast.makeText(MainActivity.this.getApplicationContext(), "correct", 1).show(); } else { Toast.makeText(MainActivity.this.getApplicationContext(), "failed", 1).show(); } } }); }} |
MainActivity 代码解读
- 创建Activity时,为button添加click事件。
- button点击时,获取输入的字符串,传入encode的check函数对字符串检测。
- encode的check函数,返回true时,显示正确提示!否则提示错误。
提取算法代码
双击enocode的check函数,直接跳转到encode类的实现页面。
可以看到算法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /* loaded from: classes.dex */public class encode { private static byte[] b = {23, 22, 26, 26, 25, 25, 25, 26, 27, 28, 30, 30, 29, 30, 32, 32}; public static boolean check(String str) { byte[] input = str.getBytes(); byte[] temp = new byte[16]; for (int i = 0; i < 16; i++) { temp[i] = (byte) ((input[i] + b[i]) % 61); } for (int i2 = 0; i2 < 16; i2++) { temp[i2] = (byte) ((temp[i2] * 2) - i2); } String key = new String(temp); return key.equals(str); }} |
编写逆向还原算法
推导过程
逻辑整理得:
((input[i] + b[i]) % 61) * 2 -i = input[i]
设:input[i] = x
1 2 3 4 5 | ((input[i] + b[i]) % 61) * 2 -i = input[i]=> (x % 61) * 2 + (b[i] % 61) * 2 = x=> (b[i] % 61) * 2 - i = x - (x % 61) * 2 |
编写keygen
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include <stdio.h>#include <stdlib.h>void main(){ unsigned char b[] = {23, 22, 26, 26, 25, 25, 25, 26, 27, 28, 30, 30, 29, 30, 32, 32}; char input[20] = {0}; char c; for (int i = 0; i < 16; i++) { c = (b[i] % 61) * 2 - i; printf(" b[i] %% 61 * 2 - i = x - x %% 61 * 2 => x - x %% 61 * 2 = %d\n", c); for (int j = c; j < 255; j++) { if ( (j - (j % 61) * 2) == c) { input[i] = j; printf("input[%d]=%c(%d)\n",i,j,j); break; } } } printf(input);} |
获取flag
运行代码获取str
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 46input[0]=L(76) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 43input[1]=O(79) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 50input[2]=H(72) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 49input[3]=I(73) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 46input[4]=L(76) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 45input[5]=M(77) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 44input[6]=N(78) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 45input[7]=M(77) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 46input[8]=L(76) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 47input[9]=K(75) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 50input[10]=H(72) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 49input[11]=I(73) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 46input[12]=L(76) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 47input[13]=K(75) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 50input[14]=H(72) b[i] % 61 * 2 - i = x - x % 61 * 2 => x - x % 61 * 2 = 49input[15]=I(73)LOHILMNMLKHILKHI |
测试如下

根据题目得到flag
XMAN{LOHILMNMLKHILKHI}

