2017-07-24 7 views
0

J'ai un problème avec le chargement d'une adresse 64 bits dans un registre à partir d'un LKM en utilisant l'assemblage en ligne arm64. J'essaye de configurer un crochet de fonction dans la mémoire de noyau. Donc, à chaque fois qu'une fonction spécifique est appelée, elle doit se connecter à ma fonction à la place.ARM64 - branche d'assemblage à l'adresse de fonction

Mon idée était de charger une adresse dans un registre, qui est obtenu lors de l'exécution en utilisant ceci:

unsigned long address = &hooked_do_undefinstr; 

Et puis écrire l'opcode correspondant de

BLR X3 

dans la mémoire.

J'ai essayé de charger l'adresse dans X3 registre (parce que son un OS 64 bits) avec

__asm__ __volatile__ ("MOV x3, %[var]" : [var] "=r" (address)); 

Parce que je dois obtenir l'adresse lors de l'exécution, je ne peux pas utiliser la commande LDR. lors de l'insertion du module je reçois l'erreur suivante:

[email protected]___ :~# insmod mod_init.ko 
[ 70.386938] mod_init: Unknown symbol x19 (err 0) 
[ 70.391508] mod_init: Unknown symbol x3 (err 0) 

Avec cette commande, la sortie quand j'imprimer le contenu X3 est égal à zéro:

[ 558.948492]   MOV x3 Register value 0x0 

Ma question est maintenant, est-il un moyen de charger une adresse 64bit dans un registre? Ou y a-t-il une meilleure façon d'implémenter ma fonction hook pour passer à mon adresse?

Salutations et merci pour votre aide

Répondre

1

Ce n'est pas tout à fait clair ce que vous faites. Si vous voulez accrocher une fonction, vous ne pouvez pas y coller votre blr x3 et attendez pour conserver une valeur que vous avez définie en utilisant inline asm ailleurs (à moins que vous sachiez que ce n'est pas touché, mais je trouve cela peu probable). Vous devez mettre le code de chargement aussi dans la fonction accroché, quelque chose comme cela pourrait fonctionner:

ldr x3, .+8 
blr x3 

Création du code machine en utilisant un assembleur donne: 43 00 00 58 60 00 3F D6

Lorsque le rapiéçage, votre code doit ajouter la cible adresse à la fin:

void patch(unsigned char* target) 
{ 
    unsigned char code[] = { 0x43, 0x00, 0x00, 0x58, 0x60, 0x00, 0x3F, 0xD6 }; 
    memcpy(target, code, 8); 
    *(void (**)())(target + 8) = hooked_do_undefinstr; 
} 

Notez également que tout ce que vous avez écrasé devrait être compensée par votre fonction de crochet. Comme d'habitude, vous devez également vous assurer que la section que vous corrigez est accessible en écriture.

+0

Merci pour votre réponse. Je n'ai pas pensé, que le registre pourrait être écrasé. J'ai déjà désactivé la protection en écriture de la mémoire et créé une sauvegarde pour le code que j'écrase. De plus, je dois convertir votre code hexadécimal en little endian. Avec votre code je devrais enregistrer (à partir des entrées d'origine) 8Byte pour les deux commandes plus 8 octets pour l'adresse droite? Mais j'essaie ça. Merci encore – MajorasKid

+0

Edit: je viens de vérifier et j'ai vu que votre OPCode est déjà en petit boutiste – MajorasKid

0

J'ai été capable de résoudre ce problème en utilisant l'idée de @ Jester. Notez simplement que si vous utilisez son code, vérifiez si votre système fonctionne en petit ou en gros caractères. Cela peut se faire par:

//Get the SCTLR_EL1 content 
__asm__ __volatile__ ("MRS %[result], SCTLR_EL1" : [result] "=r" (sctlr_el1)); 

//Check the 25th bit. if 1 -> big, else little 
if(sctlr_el1 & (1<<25)) 
{ 
    printk(KERN_INFO "   Big Endian Found\n"); 
    create_hook_big(addresse); 
}else 
{ 
    printk(KERN_INFO "   Little Endian found\n"); 
    create_hook_little(addresse); 
} 

Else: voici mon code de travail:

//Backup original entries 
memcpy(original_blr, (void*)el1_sync,sizeof(original_blr)); 


//Set function hook, el1_sync is my used target 
memcpy((void*)el1_sync,replace_jump_offset,sizeof(replace_jump_offset)); 
*(void (**)(void))(el1_sync + 8) = &hooked_do_undefinstr;