Foundations and Practice of Security by Unknown

Foundations and Practice of Security by Unknown

Author:Unknown
Language: eng
Format: epub, pdf
ISBN: 9783030453718
Publisher: Springer International Publishing


2.Validating the integrity of the installed Android application.

3.Executing statement w using JNI to preserve semantic equivalence between the transformed and original application.

We write the code to be encrypted (all but the decryption procedure) to a dedicated function that will be decrypted at runtime. We can use a function pointer to obtain the memory location of the function that needs to be decrypted in the context of the decryption routine with the supplied key that is passed as an argument. Before decrypting the instructions that are located within the text segment, we must ensure that the memory pages where the decrypted instructions will be written to are marked as writable. Note that as the decryption of the instructions are performed in-place, the memory locations of the encrypted and decrypted instructions are the same. As specified by the p_flags field in the ELF header of the compiled shared object file, the text segment is by default marked as readable and executable. Thus, the memory pages that contain the encrypted instructions are first marked as writable using the mprotect system call. We mark the relevant memory pages as writable in preparation for decrypting the instructions in-place. Encryption and decryption is performed with a stream cipher, as we want to preserve the length of instructions in the ELF binary so we can statically encrypt during the transformation phase in-place, and decrypt during runtime in-place. We decided to use AES-128 in CTR mode, which turns the block cipher into a usable stream cipher for our purpose. Each byte to be decrypted is XORed with the byte generated by the stream cipher based on the chosen key.

After decrypting the instructions, the permissions of the memory pages can be restored to readable and executable for security reasons. A static boolean within each generated method is set to indicate that the code has already been decrypted such that the instructions are only decrypted once.

After the native code has been decrypted, the instruction pointer enters the instructions that were previously encrypted. We validate the integrity of the running application by obtaining the path to the APK file that contains the code of the currently running app. We can obtain this path by invoking the Android PackageManager binary, located at /system/bin/pm when supplying it with the package name of the currently running application. We compute hashes of parts of the files within the APK archive to verify its integrity.

Each generated native method computes and compares the hash of a section of a file with the precomputed hash that was determined statically during the transformation procedure. At this point in the transformation process, we are generating C/C++ code for the native library. This implies that we can statically compute the hash of every file that will be bundled with the APK, except for the shared library file itself and files added after compilation such as the developer’s code signature. Note that we can also assert integrity of the developer’s certificate file, which might be a good choice when all applications signed by this certificate are trusted by the developer.



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.