【Android逆向】算法还原2

这题比较简单

1. app-release.apk 安装至手机

提示需要输入账号和密码

2. jadx 打开看看

public native boolean check(byte[] bArr, byte[] bArr2);

    static {
        System.loadLibrary("native-lib");
    }

    /* JADX INFO: Access modifiers changed from: protected */
    @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        this.edt_username = (EditText) findViewById(R.id.edt_username);
        this.edt_code = (EditText) findViewById(R.id.edt_code);
        Button button = (Button) findViewById(R.id.btn_check);
        this.btn_check = button;
        button.setOnClickListener(this);
    }

    @Override // android.view.View.OnClickListener
    public void onClick(View view) {
        if (view.getId() != R.id.btn_check) {
            return;
        }
        String obj = this.edt_username.getText().toString();
        String obj2 = this.edt_code.getText().toString();
        if (obj.length() == 0 || obj2.length() == 0) {
            Toast.makeText(this, "输入不完整!", 1).show();
        } else if (check(obj.getBytes(), obj2.getBytes())) {
            Toast.makeText(this, "验证通过!", 1).show();
            congratulation();
        } else {
            Toast.makeText(this, "验证失败!", 1).show();
        }
    }

    private void congratulation() {
        startActivity(new Intent(this, Congratulation.class));
        finish();
    }

check 在native层

2. so 使用IDA打开看看

bool __fastcall Java_com_r0ysue_crackme_MainActivity_check(JNIEnv *env, jobject object, int username, int password)
{
  int v7; // r11
  jbyte *v8; // r10
  jbyte *password_chars; // r5
  jsize v10; // r6
  int v11; // r5
  int v12; // r0
  int v13; // r0
  int v14; // r4
  char *t_passwd_chars; // [sp+8h] [bp-100h]
  int v17; // [sp+Ch] [bp-FCh] BYREF
  int v18; // [sp+10h] [bp-F8h] BYREF
  int v19; // [sp+14h] [bp-F4h] BYREF
  char v20[104]; // [sp+18h] [bp-F0h] BYREF
  char v21[104]; // [sp+80h] [bp-88h] BYREF

  v7 = 0;
  v8 = (*env)->GetByteArrayElements(env, username, 0);
  password_chars = (*env)->GetByteArrayElements(env, password, 0);
  v10 = (*env)->GetArrayLength(env, (jarray)username);
  if ( (unsigned int)(v10 - 6) <= 0xE )
  {
    t_passwd_chars = password_chars;
    v11 = EVP_CIPHER_CTX_new();
    v12 = EVP_CIPHER_CTX_set_padding(v11, 1);
    v13 = EVP_aes_128_ecb(v12);
    EVP_EncryptInit(v11, v13, "kanxuenbkanxuenb", 0);
    memset(v21, 0, 0x64u);
    v18 = 0;
    v19 = 0;
    EVP_EncryptUpdate(v11, v21, &v19, v8, v10);
    EVP_EncryptFinal(v11, &v21[v19], &v18);
    EVP_CIPHER_CTX_free(v11);
    v18 += v19;
    v14 = EVP_ENCODE_CTX_new();
    EVP_EncodeInit();
    memset(v20, 0, 0x64u);
    v17 = 0;
    EVP_EncodeUpdate(v14, v20, &v17, v21, v18);
    EVP_EncodeFinal(v14, &v20[v17], &v17);
    return strncmp(t_passwd_chars, v20, v17 - 1) == 0;
  }
  return v7;
}

直接搜 EVP_CIPHER_CTX_new 和 EVP_EncodeInit ,发现是Openssl 的标准实现,那么猜测是先进行AES加密 , 再进行base64 encode
直接打开 https://gchq.github.io/CyberChef/ 验证猜想,发现还真是的

3. 编写注册机

from Crypto.Cipher import AES
from base64 import b64encode
 
key = b"kanxuenbkanxuenb"
mode = AES.MODE_ECB
 
 
bs = 16
PADDING = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs)
 
 
# 在这里输入username
text = "helloworld"
generator = AES.new(key, mode)
crypt = generator.encrypt(PADDING(text).encode())
b64 = b64encode(crypt)
print("username --> " + "helloworld")
print("code --> " + b64.decode())

日志

# python lesson202111.py 
username --> helloworld
code --> TyjG/EYaUC8EXxz7/sXiCA==

手机上输入,验证ok,没毛病

posted @ 2023-03-07 18:47  明月照江江  阅读(90)  评论(0编辑  收藏  举报