2010-12-14 8 views
2

J'ai un fichier jar étrange, il contient une classe que lorsque j'utilise JD Decompiler, il montre un segment comme celui-ci:Java: résultat étrange après décompilation

public final void a(ak aa) { 
    this.jdField_a_of_type_Ak = aa; 
} 

public final void a(cn ccn) { 
    this.jdField_a_of_type_Cn = ccn; 
} 

public final cN a() { 
    return this.jdField_a_of_type_CN; 
} 

public final void a() { 
    super.b(); 
} 

public final boolean a() { 
    return this.jdField_a_of_type_Boolean; 
} 

Je me demande pourquoi un/un compilateur/obfuscator peut produire un code d'octet de classe comme ça, je veux dire la signature de la méthode. Est-ce que quelqu'un savait qu'un obfuscator peut le faire?

+0

Vous avez montré 5 méthodes - quelle signature de méthode vous dérange? –

+2

Vous posez des questions sur les types de retour surchargés (trois derniers)? –

+0

Je veux dire trois derniers, le type 'return' n'est pas inclus dans la signature de la méthode, donc ces méthodes sont en double, n'est-ce pas? – secmask

Répondre

6

Comme @Joachim Sauer correctly points out: La spécification JVM pose moins de contraintes sur la surcharge de méthode dans le bytecode que ne le fait JLS sur les programmes Java.

De l'JVM Specification (Section 4.6, Methods):

Pas deux méthodes dans un fichier de classe peut avoir le même nom et descripteur (§4.3.3).

Et un descripteur de méthode inclut le type de retour: (4.3.3 Method Descriptors)

MethodDescriptor:
        (ParameterDescriptor*) ReturnDescriptor

Les méthodes que vous mentionnez dans votre question ont tous les descripteurs distincts , alors ils vont bien:

public final void a(ak aa)  ->  (Lsomepkg1/ak;)V 
public final void a(cn ccn) ->  (Lsomepkg2/ccn;)V 
public final cN a()   -> ()Lsomepkg3/cN; 
public final void a()   -> ()V 
public final boolean a()  -> ()Z 

Ceci est intelligemment exploité par les obfuscateurs. Un programme bytecode valide n'a plus de programme Java "correspondant directement". ProGuard fait cela par exemple. Voici un extrait de leur manuel:

-overloadaggressively

Indique à appliquer une surcharge agressive tout en obscurcissant. Plusieurs champs et méthodes peuvent ensuite obtenir les mêmes noms, tant que leurs arguments et leurs types de retour sont différents (pas seulement leurs arguments).

Il existe d'autres techniques similaires utilisant par exemple l'instruction bytecode jsr ou utilisant des identifiants de variables qui sont des mots réservés dans le langage Java. Here est une page Web énumérant quelques techniques.


Pour répondre à la question de suivi évidente: Comment la machine virtuelle Java sait-elle quelle méthode appeler sur le site d'appel? Les instructions invoke requièrent que vous spécifiez une référence à une signature de méthode complète (y compris le type de retour de la méthode) à appeler.

1

... Un obfuscateur produit des noms de méthodes/signatures comme ceci parce que c'est son travail. Tout obfuscator devrait travailler à cette fin.

6

Le bytecode Java prend en charge les constructions qui ne sont pas valides dans le code source Java. Les obscurcisseurs exploitent ce fait en modifiant le bytecode pour utiliser ces constructions (tout en donnant le même résultat que le bytecode non obfusqué).

+0

pourriez-vous nommé un logiciel java-obfuscator faire cela? – secmask

+0

@secmask, ProGuard fait cela. Vois ma réponse. – aioobe

1

La classe a été compilée sans informations de débogage (au moins les informations de variables locales sont manquantes) et obfusquée plus tard. Une stratégie d'obfuscation de base consiste à remplacer (presque) tous les noms de package, de classe et de méthode par de nouveaux noms insensés, de sorte que l'on ne puisse pas comprendre le code décompilé.

Les stratégies supplémentaires consistent à obscurcir les chaînes et à ajouter des constructions bytecode qui ne peuvent pas être décompilées en code java.

Vous pourrez toujours créer un équivalent source java pour le fichier de classe obfusqué, mais seulement avec beaucoup d'effort.

Questions connexes