2010-11-12 5 views
10

J'ai trouvé un article sur le code auto-modifiable et j'ai essayé de faire quelques exemples, mais j'ai toujours des fautes de segmentation. Aussi fas que je peux comprendre, il y a une violation dans les permissions de mémoire. Le segment de code est (r) ead/e (x) ecute et ainsi la tentative d'écriture aboutit à cette faute. Existe-t-il un moyen de tester le programme en modifiant les autorisations de mémoire au moment de l'exécution ou avant? J'utilise linux et l'exemple est écrit dans l'assembly GAS.Auto-modification du code toujours des erreurs de segmentation sous Linux

.extern memcpy 
.section .data 
string: 
     .asciz "whatever" 
string_end: 
.section .bss 
     .lcomm buf, string_end-string 
.section .text 
.globl main 
main: 
     call changer 
     mov $string, %edx 
label: 
     push string_end-string 
     push $buf 
     push $string 
     call memcpy 
changer: 
     mov $offset_to_write, %esi 
     mov $label, %edi 
     mov $0xb, %ecx 
loop1: 
     lodsb 
     stosb 
     loop loop1 
     ret 
offset_to_write: 
     push 0 
     call exit 
end: 

donc après la modification proposée par osgx est un code de travail ici. (En fait, si vous assemblez & lien & terme, il se bloque, mais si vous regardez avec gdb il ne modifie son code!)

.extern memcpy 
.section .data 
string: 
     .asciz "Giorgos" 
string_end: 
.section .bss 
     .lcomm buf, string_end-string 
.section .text 
.globl main 
main: 
     lea (main), %esi    # get the start of memory region to 
             # change its permissions (smc-enabled) 
     andl $0xFFFFF000, %esi   # align to start of a pagesize 
     pushl $7      # permissions==r|w|x 
     pushl $4096     # page size 
     pushl %esi     # computed start address 
     call mprotect 

     call changer     # function that does smc 
     mov  $string, %edx 
label: 
     push string_end-string  # this code will be overridden 
     push $buf     # and never be executed! 
     push $string 
     call memcpy 
changer: 
     mov  $offset_to_write, %esi # simple copy bytes algorithm 
     mov  $label, %edi 
     mov  $0xb, %ecx 
loop1: 
     lodsb 
     stosb 
     loop loop1 
     ret 
offset_to_write:      # these instructions will be 
     push $0      # executed eventually 
     call exit 
end: 
+0

Vous ne savez pas comment cela fonctionne sous linux, mais vous pouvez demander à votre éditeur de liens d'utiliser des indicateurs personnalisés pour la section .text, pour pouvoir les spécifier dans la source (par défaut .data est RW, pour .text est RX – ruslik

+0

@ruslik puis-je spécifier à partir de la source l'autorisation du segment de code (texte) en utilisant rwx? –

Répondre

14

Vous devez modifier les autorisations d'accès en mémoire lors de l'exécution.

#include <sys/mman.h> 

void *addr = get_address_of_instruction_pointer(); 
int length = 4096; /* size of a page */ 

if (mprotect(addr, length, PROT_READ | PROT_WRITE | PROT_EXEC) == 0) { 
    /* current code page is now writable and code from it is allowed for execution */ 
} 
+0

puis-je utiliser cette fonction de l'assemblage? Ai-je besoin de privilèges spéciaux pour pouvoir l'utiliser? –

+1

Oui, vous pouvez. La méthode la plus simple consiste à compiler le code C avec mprotect dans le fichier .S (-S) et à copier-coller l'appel mprotect dans votre code. Les privilèges spéciaux ne sont pas nécessaires pour la mémoire, appartenant à votre processus, et il ne doit pas y avoir de correctifs de super-sécurité pour le noyau. – osgx

+0

il y a un bon article (le seul inconvénient - il utilise la syntaxe Intel) http: //asm.sourceforge. net/articles/smc.html – osgx

5

Les processeurs modernes ont une fonctionnalité appelée DEP qui empêche l'exécution du code sur la pile. Auparavant, c'était possible. maintenant, ça ne l'est pas. Le binaire est chargé dans la mémoire morte par défaut. Avec cela, vous pouvez utiliser l'appel système mprotect pour marquer l'emplacement de votre binaire dans la mémoire en tant qu'exécutable - TANT QUE VOTRE CODE N'EST PAS DEP-PROTÉGER. Donc, n'essayez pas de mettre du code et de la pile, et sautez dedans.

+1

'mprotect PROT_READ | PROT_WRITE | PROT_EXEC' devrait désactiver DEP. Aussi, cela s'appelle DEP seulement dans le monde MS – osgx

+0

Mais je n'essaie pas de manipuler la pile, j'essaie juste de changer/générer des instructions dans le segment de code. –

+0

@osgx: _ "cela s'appelle DEP seulement dans le monde MS" _ [Ce n'est tout simplement pas vrai] (http://oleb.net/blog/2012/07/ios-hackers-handbook/); DEP est un terme commun. –

1

Vous pouvez également désactiver la protection en écriture pour l'ensemble du programme en passant le commutateur -N à l'éditeur de liens. Si vous appelez l'éditeur de liens à partir de gcc, transmettez Wl,-N. Si vous appelez directement ld, transmettez -N.

Questions connexes