The first attempt to reverse the operation bypasses APK’s simple JNI signature verification
After modifying the content of the application, the search for SmalI did not find any signature verification for the application, but after repackaging, the application opened and flashed back directly. Check the log and confirm that the JNI method has performed signature verification.
Caused by: java.lang.UnsatisfiedLinkError: JNI_ERR returned from JNI_OnLoad in "/data/app/pkgpath/lib/arm64/libencryption.so"
The error occurred at
libencryption.soDuring the process of, I checked the Java code and found that this library is used for AES encryption. This method is used for every network request, and the signature verification is put here
JNI_OnloadYou can prevent it from being removed directly from the Java layer
Open (download and install) IDA to see the code.
Because IDA was downloaded for the first time, IDA free at the beginning did not support arm, and started IDA Pro again.
For the first time, I used ida64 to load armeabi-v7a files until I needed to distinguish 64 bits and use different exe.
Finally successfully loaded, search directly
Signature, found one
checkSignatureMethod, and then you see a familiar string in the interface you can’t understand on the right. This should be the local signature cache used for comparison.
Because it is a simple signature verification, just change this value to the MD5 value after our re signature. The simplest and crudest way is to change the data directly…
Find the string in hex view and press F2 to edit it. You can see the value directly changed to hexadecimal, and it will take effect. After replacing this paragraph, save it and repackage it, and it can run normally.
But this change is too low, and I haven’t learned any knowledge. You still need to find the source of the error and try to bypass the verification instead of simply modifying the signature
Use IDA for the first time, check the tutorial and operate at the same time. First use
F5Let IDA decompile a C pseudo code. IDA view is full of instructions and can’t understand it at all.
200KB lib directly exports a C file with more than 30000 lines, which makes people look big. But at last we can manage the logic. Let’s see what’s wrong first
JNI_OnLoadmethod. You can see that when judging that the signature is not empty and
checkSignatureWhere the results are,
return -1Or version number.
Locate the problem and then solve how to change it.
As a vegetable chicken that can only understand a little SmalI, there is nothing that can understand the content displayed in IDA.
The corresponding method location is found. If the SmalI code is really changed casually. This is the first time, I can’t start at all.
I’m still addicted to food and won’t change it
if(!checkSignature()), it will not be changed directly
return 65542, the final decision is from
checkSignatureThe return value of the method, so that he can do it anyway
return trueJust fine. rely on
Copy to assembly, put the decompiled code into the heavenly book, at least let me see where it is.
You can see the call here
strcmpMethod, compare S1 and S2. Just change this to S1 and compare S1.
The idea is beautiful. It took a long time to change this parameter. Finally, it was used
key-patchImplemented, directly change the call here
After modification, look at the decompiled code again to realize the function of bypassing signature verification.
After the 64 – and 32-bit libraries are modified, they are repackaged and signed, and the operation is normal.
It is more stupid to directly change the stored signature information. Later, it is more to try to modify the code of the Lib library.
Manage the code logic. Modifying the content is much more interesting than bypassing the signature verification itself. We still need to learn more later.
As like as two peas, I wrote the first JNI code, which is the signature verification from the Internet, which is almost identical with this.
Application:onCreateThe JNI method is called, then the method is compared with the signed dead signature.
killProcess。 In terms of security, it’s not as good as putting it in the encryption library that must be called. I wrote at that time that it can be bypassed without calling.
When doing this attempt, I couldn’t understand it for several times and wanted to give up. It’s OK to think that the demand can be realized directly in a stupid way.
But I always want to see how I can completely kill the junk code I’ve written before, just check and change it a little bit.
Later, you can learn better signature verification practices of other applications through this. I have encountered an interesting design before. After the signature verification is successful, initialize a static singleton, and then call the singleton method directly elsewhere. If the signature verification fails, the call here will only throw a null pointer error and cause an application crash. At first, it will not be associated with the application error caused by re signature…
Of course, I found the problem when I looked at traces. Maybe it was just that I didn’t consider that null pointers would be caused here during the design. After all, no one would be bored to have nothing to do to re sign someone else’s APK.