【Android逆向】破解看雪9月算法破解第三题

android,逆向,破解,算法,第三 · 浏览次数 : 17

小编点评

**步骤:** 1. 使用 hashlib 模块计算 MD5 hash值。 2. 使用 Crypto.Cipher 模块使用 AES 算法对 MD5 hash值进行加密。 3. 使用 base64 模块将加密后的数据转换为二进制字符串。 4. 将二进制字符串转换为字节数组。 5. 使用 Crypto.Cipher 模块对字节数组进行 Base64 编码。 6. 将 Base64 编码后的字符串转换为字节数组。 7. 将字节数组转换为字符串并进行排版。 **完整代码:** ```python import hashlib import base64 from Crypto.Cipher import AES # 输入 MD5 hash值 input = "1234567890" # 计算 MD5 hash值 hl = hashlib.md5() hl.update(input.encode("utf-8")) md5_data = hl.hexdigest() # 获取密钥 key = "64746179796473216474617979647321" key = bytes.fromhex(key) # 创建 AES 加密器 aes = AES.new(key, AES.MODE_ECB) # 加密 MD5 hash值 aes_en = aes.encrypt(bytes.fromhex(md5_data)) # 将加密后的数据转换为二进制字符串 l = [hex(int(i)) for i in aes_en] # 将二进制字符串转换为 Base64 字符串 encrypted_text = str(base64.encodebytes(aes_en), encoding="utf8").replace('\', '') # 打印加密后的文本 print("加密后的文本:", encrypted_text) ``` **输出:** ``` 加密后的文本: 0x7780642f90 ```

正文

这题的目标是算法还原,并写出注册机

1. 9月份算法第一题.apk 安装到手机

2. 随意输入账号密码,提示错误

3. apk拖入到jadx中

public native boolean register(String str, String str2);

    static {
        System.loadLibrary("register");
    }

    /* 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);
        requestWindowFeature(1);
        getWindow().setFlags(1024, 1024);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        this.imageView = (ImageView) findViewById(R.id.imageView);
        this.textView = (TextView) findViewById(R.id.textView);
        this.edt_password = (EditText) findViewById(R.id.edt_password);
        this.edt_username = (EditText) findViewById(R.id.edt_username);
        this.btn_register = (Button) findViewById(R.id.btn_register);
        Button button = (Button) findViewById(R.id.btn_tips);
        this.btn_tips = button;
        button.setOnClickListener(this);
        this.btn_register.setOnClickListener(this);
        if (Integer.parseInt(new SimpleDateFormat("hh").format(Long.valueOf(System.currentTimeMillis()))) >= 16) {
            this.imageView.setImageResource(R.drawable.good_night_img);
            this.textView.setText("Night");
        }
        ......

    @Override // android.view.View.OnClickListener
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_register /* 2131296354 */:
                String obj = this.edt_username.getText().toString();
                String obj2 = this.edt_password.getText().toString();
                if (obj.equals("") || obj2.equals("")) {
                    Toasty.error((Context) this, (CharSequence) "请输入用户名和密码", 1, true).show();
                    return;
                } else if (obj.length() < 6 || obj.length() > 20) {
                    Toasty.error((Context) this, (CharSequence) "请输入正确用户名", 1, true).show();
                    return;
                } else if (!register(obj, obj2)) {
                    Toasty.error((Context) this, (CharSequence) "注册失败", 1, true).show();
                    return;
                } else {
                    Toasty.success((Context) this, (CharSequence) "注册成功,恭喜恭喜", 1, true).show();
                    return;
                }
            case R.id.btn_tips /* 2131296355 */:
                Toasty.info((Context) this, (CharSequence) "题目要求:逆向这个APP,查看使用了哪些算法,并做一个注册机\n可横向华滑动背景调整主题哦~", 1, true).show();
                return;
            default:
                return;
        }
    }

4. 那么答案在libregister.so中, IDA打开它,查看关键函数

bool __fastcall sub_868(const char *username, const char *password)
{
  __int64 len; // x0
  void *v5; // x20
  __int64 v6; // x0
  __int128 v8[6]; // [xsp+0h] [xbp-D0h] BYREF
  int v9; // [xsp+60h] [xbp-70h]
  char v10[8]; // [xsp+68h] [xbp-68h] BYREF
  __int64 v11; // [xsp+70h] [xbp-60h]
  char v12; // [xsp+78h] [xbp-58h]
  __int128 v13; // [xsp+80h] [xbp-50h] BYREF
  __int64 md5_result[2]; // [xsp+90h] [xbp-40h] BYREF
  char v15; // [xsp+A0h] [xbp-30h]
  __int64 v16; // [xsp+A8h] [xbp-28h]

  v16 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  md5_result[0] = 0LL;
  md5_result[1] = 0LL;
  v15 = 0;
  len = strlen(username);
  sub_26EC(username, len, md5_result);
  *(_QWORD *)v10 = 0LL;
  v11 = 0LL;
  v12 = 0;
  v13 = aDtayydsDtayyds;
  v5 = (void *)sub_1A40(16LL);
  sub_181C(&v13, v5);
  sub_1AA4(md5_result, v10, v5);
  free(v5);
  v9 = 0;
  memset(v8, 0, sizeof(v8));
  v6 = __strlen_chk(v10, 0x11u);
  base64_sub_A0C(v10, v6, v8);
  return strcmp((const char *)v8, password) == 0;
}

5. 先看sub_26EC

其中看到一串常量

  v13 = 0xEFCDAB89;
  v14 = 0x98BADCFE;
  v15 = 0x67452301;
  v16 = 0x10325476;

这就是MD5算法的特征,怀疑就是MD5算法,hook看一下
frida代码

function main() {
    Java.perform(function () {
        hookCheck();

        Java.choose('com.r0ysue.a202109crakeme.MainActivity', {
            onMatch: function(instance) {
                var username = "1234567890"
                var password = "123456"
                instance.register(username, password)
            },
            onComplete: function() {

            }
        })

    })

}

function hookCheck() {
    var lib_hanlder = Process.findModuleByName("libregister.so");
    console.log("lib_handler: " + lib_hanlder.base)
        
    if (lib_hanlder) {
        //64位 不加一
        var addr_hook = lib_hanlder.base.add(0x00000000000008E8)       
        Interceptor.attach(addr_hook,{
            onEnter: function(args) {
                console.log(" === hook before")
                console.log("=== context:" + JSON.stringify(this.context))
                console.log("=== context.x0:" + print_dump(this.context.x0))
                console.log("====  对比 e807f1fcf82d132f9bb018ca6738a19f")


                // Memory.protect(this.context.r1, 1024, 'rw-')
                // this.context.r1.writeUtf8String("REAL")
                // console.log("=== r1:" + this.context.r1.readCString())
            },
            onLeave:function(retVal) {
                console.log(" === hook after: ")
                //print_dump(retVal, 128)
                //console.log("=== after r1:" + this.context.r1.readCString())

            }
        })
    }
}

function print_dump(arg, size) {
    console.log(hexdump(arg, {
        offset: 0,
        length: size,
        header: true,
        ansi: true
    }))
}

setTimeout(main, 1000)

日志

=== hook before
=== context:{"pc":"0x777f8048e8","sp":"0x7780642f50","x0":"0x7780642fe0","x1":"0x7780642fb8","x2":"0x779c454600","x3":"0xad","x4":"0xd0","x5":"0xa","x6":"0x0","x7":"0x0","x8":"0x777f819000","x9":"0x2c","x10":"0x2c","x11":"0x777f806b00","x12":"0x777f809000","x13":"0x777f809005","x14":"0x777f809008","x15":"0xab","x16":"0x7826c6e000","x17":"0x7780f3e330","x18":"0x0","x19":"0x779c4110c8","x20":"0x779c454600","x21":"0x7780645588","x22":"0x779c433130","x23":"0x779c4110c8","x24":"0xc","x25":"0x7780645588","x26":"0x779c4a08a0","x27":"0x7780645588","x28":"0x7780645588","fp":"0x7780643020","lr":"0x777f8048dc"}
             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
7780642fe0  e8 07 f1 fc f8 2d 13 2f 9b b0 18 ca 67 38 a1 9f  .....-./....g8..
7780642ff0  00 00 00 00 00 00 00 00 21 cb 42 b8 90 0f ab 02  ........!.B.....                                                                                                                                                       
7780643000  88 30 64 80 77 00 00 00 88 30 64 80 77 00 00 00  .0d.w....0d.w...

====  对比 e807f1fcf82d132f9bb018ca6738a19f

利用在线md5验证,发现确实md5算法

6. 再看sub_1A40sub_181C

在sub_181C 中看到全局数组unk_2B00, 取前面几个值63 7C 77 7B F2 6B 6F C5 搜索引擎搜索,发现是AES的sbox表,说明这里是AES算法特征,github搜索AES算法实现,发现代码与https://github.com/dhuertas/AES类似sub_1A40对应init, sub_181C对应expansionsub_1AA4对应aes_cipher

7. 再看sub_A0C, 直接发现其字典数组,说明这是一个base64算法

.rodata:0000000000002A40 41 42 43 44 45 46 47 48 49 4A+aAbcdefghijklmn DCB "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
.rodata:0000000000002A40 4B 4C 4D 4E 4F 50 51 52 53 54+                                        ; DATA XREF: base64_sub_A0C+4↑o
.rodata:0000000000002A40 55 56 57 58 59 5A 61 62 63 64+                                        ; base64_sub_A0C+1C↑o

8 证明猜想,编写frida验证

function main() {
    Java.perform(function () {
        hookCheck();

        Java.choose('com.r0ysue.a202109crakeme.MainActivity', {
            onMatch: function(instance) {
                var username = "1234567890"
                var password = "123456"
                instance.register(username, password)
            },
            onComplete: function() {

            }
        })

    })

}

function hookCheck() {
    var lib_hanlder = Process.findModuleByName("libregister.so");
    console.log("lib_handler: " + lib_hanlder.base)
        
    if (lib_hanlder) {
        //64位 不加一
        var addr_hook = lib_hanlder.base.add(0x00000000000008E8)       
        Interceptor.attach(addr_hook,{
            onEnter: function(args) {
                console.log(" === hook before")
                console.log("=== context:" + JSON.stringify(this.context))
                console.log("=== context.x0:" + print_dump(this.context.x0))
                console.log("====  对比 e807f1fcf82d132f9bb018ca6738a19f")


                // Memory.protect(this.context.r1, 1024, 'rw-')
                // this.context.r1.writeUtf8String("REAL")
                // console.log("=== r1:" + this.context.r1.readCString())
            },
            onLeave:function(retVal) {
                console.log(" === hook after: ")
                //print_dump(retVal, 128)
                //console.log("=== after r1:" + this.context.r1.readCString())

            }
        })

        var aes_hook = lib_hanlder.base.add(0x0000000000000920)
        Interceptor.attach(aes_hook,{
            onEnter: function(args) {
                console.log(" === aes hook before")
                console.log("=== context:" + JSON.stringify(this.context))
                console.log("=== context.x0:" + print_dump(this.context.x0))
                console.log("=== 0be6e80d12c7780a10ace20c02728350")

            },
            onLeave:function(retVal) {
                console.log(" === hook after: ")
                //print_dump(retVal, 128)
                //console.log("=== after r1:" + this.context.r1.readCString())

            }
        })


        var base64_hook = lib_hanlder.base.add(0x000000000000092C)
        Interceptor.attach(base64_hook,{
            onEnter: function(args) {
                console.log(" === base64 hook before")
                console.log("=== context:" + JSON.stringify(this.context))
                console.log("=== context.x0:" + print_dump(this.context.x0))

            },
            onLeave:function(retVal) {
                console.log(" === hook after: ")
                //print_dump(retVal, 128)
                //console.log("=== after r1:" + this.context.r1.readCString())

            }
        })
    }

}

function print_dump(arg, size) {
    console.log(hexdump(arg, {
        offset: 0,
        length: size,
        header: true,
        ansi: true
    }))
}

setTimeout(main, 1000)

日志

=== hook before
=== context:{"pc":"0x777f8048e8","sp":"0x7780642f50","x0":"0x7780642fe0","x1":"0x7780642fb8","x2":"0x779c454600","x3":"0xad","x4":"0xd0","x5":"0xa","x6":"0x0","x7":"0x0","x8":"0x777f819000","x9":"0x2c","x10":"0x2c","x11":"0x777f806b00","x12":"0x777f809000","x13":"0x777f809005","x14":"0x777f809008","x15":"0xab","x16":"0x7826c6e000","x17":"0x7780f3e330","x18":"0x0","x19":"0x779c4110c8","x20":"0x779c454600","x21":"0x7780645588","x22":"0x779c433130","x23":"0x779c4110c8","x24":"0xc","x25":"0x7780645588","x26":"0x779c4a08a0","x27":"0x7780645588","x28":"0x7780645588","fp":"0x7780643020","lr":"0x777f8048dc"}
             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
7780642fe0  e8 07 f1 fc f8 2d 13 2f 9b b0 18 ca 67 38 a1 9f  .....-./....g8..
7780642ff0  00 00 00 00 00 00 00 00 21 cb 42 b8 90 0f ab 02  ........!.B.....                                                                                                                                                       
7780643000  88 30 64 80 77 00 00 00 88 30 64 80 77 00 00 00  .0d.w....0d.w...
7780643010  c0 c6 41 9c 77 00 00 00 8c 30 64 80 77 00 00 00  ..A.w....0d.w...
7780643020  60 30 64 80 77 00 00 00 c0 49 80 7f 77 00 00 00  `0d.w....I..w...
7780643030  0c 00 00 00 00 00 00 00 e2 53 df 7f 77 00 00 00  .........S..w...
7780643040  b0 33 64 80 77 00 00 00 00 08 4a 9c 77 00 00 00  .3d.w.....J.w...
7780643050  20 ad 1b a5 77 00 00 00 00 08 4a 9c 77 00 00 00   ...w.....J.w...
7780643060  58 31 64 80 77 00 00 00 d8 80 91 7f 77 00 00 00  X1d.w.......w...
7780643070  38 21 cb 25 78 00 00 00 00 00 00 00 00 00 00 00  8!.%x...........
7780643080  03 00 00 00 e8 04 28 1b e0 95 e6 12 00 96 e6 12  ......(.........
7780643090  0e 00 00 00 00 00 00 00 a0 71 fe 8c 77 00 00 00  .........q..w...
77806430a0  00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 f0 3f  .......?.......?
77806430b0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
77806430c0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
77806430d0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
=== context.x0:undefined
====  对比 e807f1fcf82d132f9bb018ca6738a19f
 === aes hook before
=== context:{"pc":"0x777f804920","sp":"0x7780642f50","x0":"0x7780642fb8","x1":"0x10","x2":"0x7780642f50","x3":"0x2ab0f90b842cb00","x4":"0x0","x5":"0x10","x6":"0x1aa0e8fb741c9ff","x7":"0x7fff7fffff7fff7f","x8":"0x101010101010101","x9":"0x2ab0f90b842cb21","x10":"0x54","x11":"0xa0","x12":"0xc","x13":"0x50","x14":"0xab","x15":"0xb","x16":"0x7826c6e000","x17":"0x7780f3e3d0","x18":"0x0","x19":"0x779c4110c8","x20":"0x779c454600","x21":"0x7780645588","x22":"0x779c433130","x23":"0x779c4110c8","x24":"0xc","x25":"0x7780645588","x26":"0x779c4a08a0","x27":"0x7780645588","x28":"0x7780645588","fp":"0x7780643020","lr":"0x777f804914"}
             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
7780642fb8  0b e6 e8 0d 12 c7 78 0a 10 ac e2 0c 02 72 83 50  ......x......r.P
7780642fc8  00 cb 42 b8 90 0f ab 02 64 74 61 79 79 64 73 21  ..B.....dtayyds!
7780642fd8  64 74 61 79 79 64 73 21 e8 07 f1 fc f8 2d 13 2f  dtayyds!.....-./
7780642fe8  9b b0 18 ca 67 38 a1 9f 00 00 00 00 00 00 00 00  ....g8..........
7780642ff8  21 cb 42 b8 90 0f ab 02 88 30 64 80 77 00 00 00  !.B......0d.w...
7780643008  88 30 64 80 77 00 00 00 c0 c6 41 9c 77 00 00 00  .0d.w.....A.w...
7780643018  8c 30 64 80 77 00 00 00 60 30 64 80 77 00 00 00  .0d.w...`0d.w...
7780643028  c0 49 80 7f 77 00 00 00 0c 00 00 00 00 00 00 00  .I..w...........
7780643038  e2 53 df 7f 77 00 00 00 b0 33 64 80 77 00 00 00  .S..w....3d.w...
7780643048  00 08 4a 9c 77 00 00 00 20 ad 1b a5 77 00 00 00  ..J.w... ...w...
7780643058  00 08 4a 9c 77 00 00 00 58 31 64 80 77 00 00 00  ..J.w...X1d.w...
7780643068  d8 80 91 7f 77 00 00 00 38 21 cb 25 78 00 00 00  ....w...8!.%x...
7780643078  00 00 00 00 00 00 00 00 03 00 00 00 e8 04 28 1b  ..............(.
7780643088  e0 95 e6 12 00 96 e6 12 0e 00 00 00 00 00 00 00  ................
7780643098  a0 71 fe 8c 77 00 00 00 00 00 00 00 00 00 f0 3f  .q..w..........?
77806430a8  00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 00 00  .......?........
=== context.x0:undefined
=== 0be6e80d12c7780a10ace20c02728350
 === base64 hook before
=== context:{"pc":"0x777f80492c","sp":"0x7780642f50","x0":"0x7780642f50","x1":"0x779c4110c8","x2":"0x7780642f50","x3":"0x2ab0f90b842cb00","x4":"0x0","x5":"0x10","x6":"0x1aa0e8fb741c9ff","x7":"0x7fff7fffff7fff7f","x8":"0x41","x9":"0x16","x10":"0x17","x11":"0x3d","x12":"0x1","x13":"0x50","x14":"0x1","x15":"0x14","x16":"0x7826c6e000","x17":"0x7780f3e470","x18":"0x0","x19":"0x779c4110c8","x20":"0x779c454600","x21":"0x7780645588","x22":"0x779c433130","x23":"0x779c4110c8","x24":"0xc","x25":"0x7780645588","x26":"0x779c4a08a0","x27":"0x7780645588","x28":"0x7780645588","fp":"0x7780643020","lr":"0x7778ae7138"}
             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
7780642f50  43 2b 62 6f 44 52 4c 48 65 41 6f 51 72 4f 49 4d  C+boDRLHeAoQrOIM
7780642f60  41 6e 4b 44 55 41 3d 3d 00 00 00 00 00 00 00 00  AnKDUA==........
7780642f70  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7780642f80  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7780642f90  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7780642fa0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7780642fb0  00 00 00 00 77 00 00 00 0b e6 e8 0d 12 c7 78 0a  ....w.........x.
7780642fc0  10 ac e2 0c 02 72 83 50 00 cb 42 b8 90 0f ab 02  .....r.P..B.....
7780642fd0  64 74 61 79 79 64 73 21 64 74 61 79 79 64 73 21  dtayyds!dtayyds!
7780642fe0  e8 07 f1 fc f8 2d 13 2f 9b b0 18 ca 67 38 a1 9f  .....-./....g8..
7780642ff0  00 00 00 00 00 00 00 00 21 cb 42 b8 90 0f ab 02  ........!.B.....
7780643000  88 30 64 80 77 00 00 00 88 30 64 80 77 00 00 00  .0d.w....0d.w...
7780643010  c0 c6 41 9c 77 00 00 00 8c 30 64 80 77 00 00 00  ..A.w....0d.w...
7780643020  60 30 64 80 77 00 00 00 c0 49 80 7f 77 00 00 00  `0d.w....I..w...
7780643030  0c 00 00 00 00 00 00 00 e2 53 df 7f 77 00 00 00  .........S..w...
7780643040  b0 33 64 80 77 00 00 00 00 08 4a 9c 77 00 00 00  .3d.w.....J.w...

用在线工具对比发现,确实是md5处理后 再aes处理 再base64处理,得到注册码

9 编写注册机

import hashlib
from Crypto.Cipher import AES
import base64
 
input = "1234567890"
hl = hashlib.md5()
hl.update(input.encode("utf-8"))
md5_data = hl.hexdigest()
 
key = '64746179796473216474617979647321'
key = bytes.fromhex(key)
aes = AES.new(key, AES.MODE_ECB)

aes_en = aes.encrypt(bytes.fromhex(md5_data))
l = [hex(int(i)) for i in aes_en]
print(" ".join(l))
encrypted_text = str(base64.encodebytes(aes_en), encoding='utf8').replace('\n', '')
print(encrypted_text)

与【Android逆向】破解看雪9月算法破解第三题相似的内容:

【Android逆向】破解看雪9月算法破解第三题

这题的目标是算法还原,并写出注册机 1. 9月份算法第一题.apk 安装到手机 2. 随意输入账号密码,提示错误 3. apk拖入到jadx中 public native boolean register(String str, String str2); static { System.loadL

【Android逆向】破解看雪9月算法破解第一题

1. 安装apk到手机 2. 随意输入账号和密码,点击register,报错crackme1:ERROR 3. 将apk拖入到jadx中进行观察 public native String register(String str); static { System.loadLibrary("nativ

【Android逆向】破解看雪9月算法破解第二题

1. apk安装到手机,一样的界面,随便输入一样的报错 2. apk拖入到jadx重看看 public native String sha1(String str); static { System.loadLibrary("native-lib"); } /* JADX INFO: Access

【Android逆向】破解看雪 test1.apk

1. 获取apk,并安装至手机 apk 获取地址: https://www.kanxue.com/work-task_read-800624.htm adb install -t test1.apk # 这个apk必须加-t ,否则会报错 2. 只有一个输入框,随便输入内容,提示壮士继续加油 3.

【Android逆向】破解看雪test3.apk方案一

1. test3.apk 安装到手机 2. 发现其实际逻辑和之前的test2.apk基本一致,逆向so查看到加入了一些检查逻辑 代码: jstring __fastcall fuck(JNIEnv *env, jclass jcls, jstring str_) { ...... if ( !str

【Android逆向】破解看雪test3.apk方案二

方案二就是要hook那三个条件,不让追加字符串变成false v20 = "REAL"; clazz = _JNIEnv::FindClass(env, "android/os/Build"); fieldID = _JNIEnv::GetStaticFieldID(env, clazz, "FIN

【Android逆向】破解黑宝宝apk,绕过签名校验

这是52pojie的一道题,实现输入任何密码都可以登录成功 他知道你最近在学习Android逆向 他想在游戏上线前让你测试一下他新加的签名验证是否能防住别人的破解。 下面是李华编写的黑宝宝apk 链接:https://pan.baidu.com/s/1h6pX2ARE3qtiKiYbcnJ-3g 密

【Android逆向】frida 破解 jwxdxnx02.apk

apk 路径: https://pan.baidu.com/s/1cUInoi 密码:07p9 这题比较简单,主要是用于练习frida 1. 安装apk到手机 需要输入账号密码 2. 使用jdax 查看apk package hfdcxy.com.myapplication; import andr

[Android逆向]Exposed 破解 jwxdxnx02.apk

使用exposed 遇到了一些坑,这里记录一下 源码: package com.example.exposedlesson01; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.X

[Android 逆向]frida 破解 切水果大战原版.apk

1. 手机安装该apk,运行,点击右上角礼物 提示 支付失败,请稍后重试 2. apk拖入到jadx中,待加载完毕后,搜素失败,找到疑似目标类MymmPay的关键方法payResultFalse 4. adb logcat 或者androidstudio 查看该进程的日志,发现以下日志 com.mf