2017-09-13 3 views
1

PrésentationComment compiler un programme C qui contient 32bit asm dans le fichier .o?

que je suis dans le livre "Learning Linux analyse binaire". J'ai une certaine expérience de travail avec l'assemblage 32 bits et C (cependant je me considère encore comme un novice). Cependant, j'ai de la difficulté et de la confusion sur la façon de compiler un programme c, qui contient un assemblage 32 bits dans un fichier objet .o. Donc je devine que c'est juste un problème de compilation de ma part.

Le code source fait partie d'un exemple de correctif binaire basé sur l'injection de code.

Source Code

#include <sys/syscall.h> 
int _write (int fd, void *buf, int count) 
{ 
    long ret; 
    __asm__ __volatile__ ("pushl %%ebx\n\t" 
    "movl %%esi,%%ebx\n\t" 
    "int $0x80\n\t""popl %%ebx":"=a" (ret) 
          :"0" (SYS_write), "S" ((long) fd), 
    "c" ((long) buf), "d" ((long) count)); 
    if (ret >= 0) { 
     return (int) ret; 
} 
return -1; 
} 
int evil_puts(void) 
{ 
     _write(1, "HAHA puts() has been hijacked!\n", 31); 
} 

Le problème

je tente de compiler evil_puts.c en fichier .o. Ce qui sera ensuite utilisé pour l'injection dans un autre programme simple.

gcc -c evil_puts.c 

evil_puts.c: Assembler messages:

evil_puts.c:5: Error: invalid instruction suffix for `push'

evil_puts.c:8: Error: invalid instruction suffix for `pop'

J'ai reçu ce avant lorsque vous travaillez avec 32 assemblage avec du gaz. Et pour résoudre cela, j'ai mis le drapeau '-32' lors de la compilation et de la liaison. Ce que je devine est le problème? mais pas tout à fait sûr, et ne pas avoir une idée de la façon de compiler en 32 bits avec C et gcc si c'est le cas? J'ai également essayé de le changer en 64 bits pour voir si cela fonctionnerait, en remplaçant 'l' de chaque commande par 'q' et en changeant les registres pour commencer par 'r'. ce qui semble fonctionner. Cependant, le livre utilise 32 bits. Donc, je souhaite le garder comme ça. Des idées? Désolé si c'est une question vraiment basique.

a également essayé « -m32 », mais reçoivent ceci:

fatal error: sys/syscall.h: No such file or directory

+1

Je suppose que vous devriez utiliser ** '-m32' ...** –

+1

Ne changez pas 32b en 64b pendant que vous venez d'apprendre, il faut généralement beaucoup plus d'efforts que de simplement remplacer les registres, dans ce cas particulier le 'int 0x80' ne devrait pas être utilisé dans 64b, et il n'y a pas de remplacement simple. Le 'syscall' correct peut remplacer ce' int 0x80', mais il s'attend à des arguments différents, donc vous devez toujours tout réécrire. Donc, votre effort pour travailler avec les binaires 32b pour suivre le livre est une bonne décision, le portage de la plate-forme cible 32b à 64b nécessite beaucoup d'expérience et de temps. – Ped7g

+0

@ Ped7g: Également important, vous ne pouvez pas «pousser»/«pop» en toute sécurité à partir d'inline asm dans le code 64 bits, car cela clobbers la zone rouge. https://stackoverflow.com/questions/34520013/using-base-pointer-register-in-c-inline-asm. Pour 'int $ 0x80' en mode 64 bits, voir https://stackoverflow.com/questions/46087730/what-happens-if-you-use-the-32-bit-int-0x80-linux-abi-in -64-bit-code –

Répondre

3

Utilisez gcc -m32 -c evil_puts.c -o evil_puts.o

Vous obtenez cette erreur parce que vous n'avez pas les bibliothèques 32 bits installées.

Si vous utilisez Ubuntu:

sudo apt-get install gcc-multilib

1

connaissances spécifiques à x86 32 bits est d'une utilité limitée de ces jours que fondamentalement tout le monde est passé à 64 bits (ce qui est une bonne chose - 32 bits a beaucoup de pression de registre et de pression d'espace d'adressage).

Heureusement, vous n'avez pas vraiment besoin d'ASM pour ce que vous faites. Je l'ai aussi fait une correction de santé d'esprit couple:

#define _GNU_SOURCE 
#include <string.h> 
#include <unistd.h> 
#include <sys/syscall.h> 

#define write_str(fd, s) my_write(fd, s, strlen(s)) 
static ssize_t my_write(int fd, const void *buf, size_t count) 
{ 
    return syscall(SYS_write, (long)fd, (long)buf, (long)count); 
} 

int puts(const char *s __attribute__((unused))) 
{ 
    write_str(STDOUT_FILENO, "HAHA puts() has been hijacked!\n"); 
    return strlen(s) + 1; 
} 

Je ne sais pas exactement pourquoi vous évitez write(2). Mais si vous avez vraiment besoin d'éviter également syscall(2), il sera encore plus facile d'implémenter cette fonction unique dans l'assemblage que d'écrire l'ensemble partout.