0x00 前言 Native层逆向,主动调一下就可以了
0x01 解 先进jadax看看
MainActivity的判断逻辑如下:
其中legal函数如下:
1 2 3 private boolean legal (String paramString) { return paramString.length() == 38 && paramString.startsWith("flag{" ) && paramString.charAt(paramString.length() - 1 ) == '}' && !inspect.inspect(paramString.substring(5 , paramString.length() - 1 )); }
可以知道flag总长为38bytes,会对flag{
和}
做判断,中间部分看inspect
类的inspect
函数
跟进去看
用到了java里面的crypto库,使用DES加密,模式是CBC,padding用的是PKCS5,最后还有base64
密文是JqslHrdvtgJrRs2QAp+FEVdwRPNLswrnykD/sZMivmjGRKUMVIC/rw==
因此需要获取key
和iv
这两个的来源一个是str2
,一个是ivBytes
,都是jni
这个类里面的
去so库里面找找,直接看apk里面的lib
-arm64-v8a
-libSecret_entrance.so
,导出表里面就可以看到这两个函数
都是静态的
直接上frida在java层hook看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function hook ( ){ let jni = Java .use ("com.example.re11113.jni" ); jni["getiv" ].implementation = function ( ) { console .log (`jni.getiv is called` ); let result = this ["getiv" ](); console .log (`jni.getiv result=${result} ` ); return result; }; } function main ( ){ Java .perform (function ( ){ hook (); }); } setImmediate (main);
iv能成功获取,为Wf3DLups
之后再试试getkey
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function hook ( ){ let jni = Java .use ("com.example.re11113.jni" ); jni["getkey" ].implementation = function ( ) { console .log (`jni.getkey is called` ); let result = this ["getkey" ](); console .log (`jni.getkey result=${result} ` ); return result; }; } function main ( ){ Java .perform (function ( ){ hook (); }); } setImmediate (main);
一运行就炸
试试在native层hook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function hook ( ) { var getKeyBase = Module .findExportByName ("libSecret_entrance.so" , "Java_com_example_re11113_jni_getkey" ); Interceptor .attach (getKeyBase, { onEnter : function (args ) { }, onLeave : function (retval ) { console .log (Java .vm .getEnv ().getStringUtfChars (retval, null ).readCString ()) } }); } function main ( ){ Java .perform (function ( ){ hook (); }); } setImmediate (main);
可以正常输出,key是A8UdWaeq
但尝试直接主动调用这个函数就会直接报错
1 2 3 4 5 6 7 8 9 function hook ( ) { Java .perform (function ( ) { var getKeyBase = Module .findExportByName ("libSecret_entrance.so" , "Java_com_example_re11113_jni_getkey" ); let key_func = new NativeFunction (getKeyBase, 'pointer' , ['pointer' ]); let result = key_func (Java .vm .getEnv ()); }) } hook ();
看雪上有个[CISCN2024]androidso_re题解以及崩溃原因分析
大致意思是直接主动调用这个getkey会导致传给NewStringUTF
的值出错,只有在先hook的情况下才能主动调用,如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function hook ( ) { var getKeyBase = Module .findExportByName ("libSecret_entrance.so" , "Java_com_example_re11113_jni_getkey" ); Interceptor .attach (getKeyBase, { onEnter : function (args ) { }, onLeave : function (retval ) { } }); var key_func = new NativeFunction (getKeyBase , 'pointer' , ['pointer' ]); var res = key_func (Java .vm .getEnv ()); console .log ("Key: " + Java .vm .getEnv ().getStringUtfChars (res, null ).readCString ()) } function main ( ){ Java .perform (function ( ){ hook (); }); } setImmediate (main);
或者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function hook ( ) { var getKeyBase = Module .findExportByName ("libSecret_entrance.so" , "Java_com_example_re11113_jni_getkey" ); Interceptor .attach (getKeyBase, { onEnter : function (args ) { }, onLeave : function (retval ) { } }); var key = jni.getkey (); console .log ("Key: " + key); } function main ( ){ Java .perform (function ( ){ hook (); }); } setImmediate (main);
才能正常输出
就,挺弱智的
最后没什么别的操作,直接base64+des解就行
flag{188cba3a5c0fbb2250b5a2e590c391ce}