[Android Security] APK Self Protection - String Handling

cp : https://segmentfault.com/a/1190000005128037

Strings are inevitable in the development process, but these strings may also be the key points of cracking, such as server addresses and error prompts for these sensitive string information. If these strings are hardcoded, they can be easily obtained by static analysis. A previous blog used the prompt string to  reverse the analysis of Android programs as a breakthrough point

Normal way to define strings

Define a string in Java:

private String normalString(){
    String str = "Hello world";
    return str;
}

 

Decompiled .smali code

.method private normalString()Ljava/lang/String;
    .registers 2

    .prologue
    .line 16
    const-string v0, "Hello world"

    .line 17
    .local v0, "str":Ljava/lang/String;
    return-object v0
.end method

 

It can be seen that  const-string the keyword is followed by the defined string value, and it can even be extracted in batches using automated analysis tools.

solution

1. StringBuilder splicing

The StringBuilder class constructs the required string through the append method. This method can increase the difficulty of automatic analysis. If you want to obtain a complete string, you must perform corresponding lexical parsing.

String concatenation code in Java:

private String buildString(){
    StringBuilder builder = new StringBuilder();
    builder.append("Hello");
    builder.append(" ");
    builder.append("world");
    return builder.toString();
}

 

Decompiled .smali code:

.method private buildString()Ljava/lang/String;
    .registers 3

    .prologue
    .line 21
    new-instance v0, Ljava/lang/StringBuilder;

    invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

    .line 22
    .local v0, "builder":Ljava/lang/StringBuilder;
    const-string v1, "Hello"

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    .line 23
    const-string v1, " "

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    .line 24
    const-string v1, "world"

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    .line 25
    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    return-object v1
.end method

 

It can be seen that the decompiled .smali code adds a certain degree of difficulty to cracking, and cannot be recognized at a glance.

2. Coding Obfuscation

Encoding confusion is to convert the string into a  hexadecimal  array or  Unicode  encoding when hard-coding, and convert it back to a string when using it. This method is more difficult to directly identify when decompiled into .smali code than StringBuilder method.

Java code:

private String encodeString(){
    byte[] strBytes = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64};
    String str = new String(strBytes);
    return str;
}

 

Decompile the .smali code:

.method private encodeString()Ljava/lang/String;
    .registers 4

    .prologue
    .line 29
    const/16 v2, 0xb

    new-array v1, v2, [B

    fill-array-data v1, :array_e

    .line 30
    .local v1, "strBytes":[B
    new-instance v0, Ljava/lang/String;

    invoke-direct {v0, v1}, Ljava/lang/String;-><init>([B)V

    .line 31
    .local v0, "str":Ljava/lang/String;
    return-object v0

    .line 29
    nop

    :array_e
    .array-data 1
        0x48t
        0x65t
        0x6ct
        0x6ct
        0x6ft
        0x20t
        0x77t
        0x6ft
        0x72t
        0x6ct
        0x64t
    .end array-data
.end method

 

It can be seen in the .smali code that all characters have been hidden.

3. Encryption processing

Encryption processing is to encrypt the string locally, then hardcode the ciphertext into it, and decrypt it at runtime.  
Encryption steps:

  • String encryption

  • hard-coded into the program

  • compile and run

  • decrypt ciphertext

Of course, because Java code is relatively easy to decompile, and this method requires the decryption method to be placed locally in the APK, we can implement the decryption method through JNI to increase the difficulty of decompilation.

Summarize

Any kind of reinforcement method only increases the difficulty of anti-cracking, and cannot completely prevent Android programs from being cracked.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324734165&siteId=291194637