【Android 逆向】【攻防世界】easyjni

android,逆向,攻防,世界,easyjni · 浏览次数 : 46

小编点评

The code you provided is a Java class that implements a Base64 decoder. **How it works:** 1. The class receives a string containing a Base64-encoded string. 2. It splits the string into a sequence of 16-bit chunks. 3. For each chunk, it converts it to a byte array. 4. It iterates over the byte array and constructs the decoded string by combining the bytes in the correct order. 5. If the encoded string matches a predefined pattern, it returns the flag. **Example usage:** ```java // Get the Base64-encoded string from somewhere String encodedString = "i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN"; // Decode the string String decodedString = Base64.decode(encodedString); // Print the decoded string System.out.println(decodedString); ``` **Output:** ``` flag{just_ANot#er_@p3} ``` **Note:** * The code assumes that the Base64-encoded string is a valid string. * It uses a specific pattern to determine if the encoded string is a valid flag. * The flag is returned as a string with the format "flag{string}".

正文

1. apk 安装到手机,提示需要输入flag

2. jadx打开apk

public class MainActivity extends c {
    static {
        System.loadLibrary("native");
    }

    /* JADX INFO: Access modifiers changed from: private */
    public boolean a(String str) {
        try {
            return ncheck(new a().a(str.getBytes()));
        } catch (Exception e) {
            return false;
        }
    }

    private native boolean ncheck(String str);

    /* JADX INFO: Access modifiers changed from: protected */
    @Override // android.support.v7.app.c, android.support.v4.a.i, android.support.v4.a.aa, android.app.Activity
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { // from class: com.a.easyjni.MainActivity.1
            @Override // android.view.View.OnClickListener
            public void onClick(View view) {
                if (MainActivity.this.a(((EditText) ((MainActivity) this).findViewById(R.id.edit)).getText().toString())) {
                    Toast.makeText(this, "You are right!", 1).show();
                } else {
                    Toast.makeText(this, "You are wrong! Bye~", 1).show();
                }
            }
        });
    }
}

/* loaded from: classes.dex */
public class a {
    private static final char[] a = {'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N'};

    public String a(byte[] bArr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i <= bArr.length - 1; i += 3) {
            byte[] bArr2 = new byte[4];
            byte b = 0;
            for (int i2 = 0; i2 <= 2; i2++) {
                if (i + i2 <= bArr.length - 1) {
                    bArr2[i2] = (byte) (b | ((bArr[i + i2] & 255) >>> ((i2 * 2) + 2)));
                    b = (byte) ((((bArr[i + i2] & 255) << (((2 - i2) * 2) + 2)) & 255) >>> 2);
                } else {
                    bArr2[i2] = b;
                    b = 64;
                }
            }
            bArr2[3] = b;
            for (int i3 = 0; i3 <= 3; i3++) {
                if (bArr2[i3] <= 63) {
                    sb.append(a[bArr2[i3]]);
                } else {
                    sb.append('=');
                }
            }
        }
        return sb.toString();
    }
}

这个a类感觉就是自定义字典的base64算法

3. IDA打开so看看

bool __fastcall Java_com_a_easyjni_MainActivity_ncheck(JNIEnv *nev, jobject a2, jstring key)
{
  const char *key_chars; // r6
  int i; // r0
  char *v7; // r2
  char v8; // r1
  int v9; // r0
  bool v10; // cc
  char v12[32]; // [sp+3h] [bp-35h] BYREF
  char v13; // [sp+23h] [bp-15h]

  key_chars = (*nev)->GetStringUTFChars(nev, key, 0);
  if ( strlen(key_chars) == 32 )
  {
    for ( i = 0; i != 16; ++i )
    {
      v7 = &v12[i];
      v12[i] = key_chars[i + 16];
      v8 = key_chars[i];
      v7[16] = v8;
    }
    (*nev)->ReleaseStringUTFChars(nev, key, key_chars);
    v9 = 0;
    do
    {
      v10 = v9 < 30;
      v13 = v12[v9];
      v12[v9] = v12[v9 + 1];
      v12[v9 + 1] = v13;
      v9 += 2;
    }
    while ( v10 );
    return memcmp(v12, "MbT3sQgX039i3g==AQOoMQFPskB1Bsc7", 0x20u) == 0;
  }
  else
  {
    (*nev)->ReleaseStringUTFChars(nev, key, key_chars);
    return 0;
  }
}

整理以下算法

	for ( i = 0; i != 16; ++i )
    {
      //v7 = &v12[i];
      v12[i] = key_chars[i + 16];
      tmp = key_chars[i];
      v12[i+16] = tmp;
    }
    (*nev)->ReleaseStringUTFChars(nev, key, key_chars);
    
    i = 0;
    do
    {
      v10 = i < 30;
      tmp = v12[i];
      v12[i] = v12[i + 1];
      v12[i + 1] = tmp;
      i += 2;
    }
    while ( v10 );
    return memcmp(v12, "MbT3sQgX039i3g==AQOoMQFPskB1Bsc7", 0x20u) == 0;

也和之前的一样,先前16位和后16位交换,然后两两交换,借助之前写的python还原算法

key = 'MbT3sQgX039i3g==AQOoMQFPskB1Bsc7'

def main():
    print(key)
    key_list = list(key)
    t_len = len(key)
    i = 0
    v19 = 0
    while v19 < t_len:
        tmp = key_list[i+2]
        key_list[i+2] = key_list[i+3]
        key_list[i+3] = tmp
        v19 = i+4
        i += 2

    tmp = key_list[1]
    key_list[1] = key_list[0]
    key_list[0] = tmp
    print("after ======")
    print(''.join(key_list))

    i = 0
    while i < t_len >> 1:
        tmp = key_list[i+16]
        key_list[i+16] = key_list[i]
        key_list[i] = tmp
        i += 1
    print("after ======")
    print(''.join(key_list))

main()

# 得到 
QAoOQMPFks1BsB7cbM3TQsXg30i9g3==

4. 借助 CyberChef 的from base64 ,输入字典i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN 得到flag :flag{just_ANot#er_@p3}

与【Android 逆向】【攻防世界】easyjni相似的内容:

【Android 逆向】【攻防世界】easyjni

1. apk 安装到手机,提示需要输入flag 2. jadx打开apk public class MainActivity extends c { static { System.loadLibrary("native"); } /* JADX INFO: Access modifiers cha

【Android 逆向】【攻防世界】基础android

1. 下载并安装apk,提示要输入密码 2. apk拖入到jadx中看一下 this.login.setOnClickListener(new View.OnClickListener() { // from class: com.example.test.ctf02.MainActivity.1

【Android 逆向】【攻防世界】android2.0

这是一道纯算法还原题 1. apk安装到手机,提示输入flag,看来输入就是flag 2. jadx 打开apk查看 this.button.setOnClickListener(new View.OnClickListener() { // from class: com.example.test

【Android 逆向】【攻防世界】APK逆向

1. apk安装到手机,提示输入flag 2. jadx打开apk 定位到checkSN方法 public boolean checkSN(String userName, String sn) { if (userName != null) { try { if (userName.length(

【Android 逆向】【攻防世界】人民的名义-抓捕赵德汉1-200

1. 这一题下载下来是个jar文件,感觉很android关系不大,但还是放在了mobile这个分类下了 2. 直接java jar运行,提示需要输入密码 # java -jar 169e139f152e45d5ae634223fe53e6be.jar Enter password: 1234 Inc

【Android 逆向】【攻防世界】ill-intentions

1. apk 安装到手机, 啥输入框都没有 2. apk拖入到jadx中看看 public class MainActivity extends Activity { @Override // android.app.Activity public void onCreate(Bundle save

【Android 逆向】【攻防世界】boomshakalaka-3

1. apk 安装到手机,是一个cocos2dx 写的打飞机的游戏 题目描述跟得分有关(题目描述: play the game, get the highest score) 2. jadx 打开apk public class FirstTest extends Cocos2dxActivity

【Android 逆向】【攻防世界】easy-apk

apk 安装到手机,随便输入点内容,提示错误 2. apk 拖入到jadx中看看 public class MainActivity extends AppCompatActivity { /* JADX INFO: Access modifiers changed from: protected

【Android 逆向】【攻防世界】app1

1. apk安装到手机, 老套路了 2. jadx打开 this.btn.setOnClickListener(new View.OnClickListener() { // from class: com.example.yaphetshan.tencentgreat.MainActivity.1

【Android 逆向】【攻防世界】app2

1. 手机安装apk,随便点击,进入到第二个页面就停了 2. jadx打开apk,发现一共有三个activity,其中第三个activity: FileDataActivity 里面有东西 public class FileDataActivity extends a { private TextV