2017-03-12 3 views
0

Ich Codierung Lite-Programm in grundlegenden c, die hinzufügen (oder Sub-) Offset für jedes Byte in Binärdatei im Argument übergeben. Diese Arbeit für alle andere ELF, aber wenn ich versuche zu laufen:
$ ./a.out a.out 1 (add 0x01 zu jedem Byte),
fopen() Absturz mit der Fehlermeldung „Textdatei besetzt“.
Ich habe mit lsof überprüft, ist aber nicht auf dem Dateisystem geöffnet.
Ich dachte, dass, wenn eine ausführbare Datei ausgeführt wird, ein Abbild der Datei in RAM geladen wird und auf die Datei zugegriffen werden kann.
Wenn jemand was darüber wissen, nehme ich es! Vielen Dank, dass Sie sich die Zeit genommen haben, mich zu lesen! HierÖffnen Sie eine running Binärdatei

ist der Code:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

void usage (char *pgr_name); // print usage and exit 
void fatal(char *s); // print s, call perror("") and exit(-1) 

// lite hexdump ([0xff] x16 | ...a...b...c...d) 
void dump (const unsigned char *data_buffer, const unsigned int len); 

int main(int argc, char **argv) { 
    FILE *my, *crypted; 
    void *content; 
    unsigned char *ascii; 
    char output[256] = ""; 
    int i, bytes_read, offset; 

    if (argc < 3) 
     usage(argv[0]); 

    offset = atoi(argv[2]); 
    if (offset < -255 || offset > 0xff) { 
     printf("bad offset\n"); 
     usage(argv[0]); 
    } 

    printf("offset %d\n", offset); 

    // open src 
    if ((my = fopen(argv[1], "rb+")) == NULL) 
     fatal("in opening argv[1]"); 

    // alloc memory for src 
    if ((content = malloc (10000)) == NULL) 
     fatal("in malloc"); 

    // read src 
    bytes_read = fread(content, 1, 9999, my); 
    printf("%d bytes read\n", bytes_read); 

    // for reading easily 
    ascii = (unsigned char *) content; 

    dump(content, bytes_read); 

    // apply offset on each bytes 
    for (i=0; i<bytes_read; i++) 
     ascii[i] = ascii[i] + offset; 
    printf("\n\ntranslation complete\n\n"); 

    dump(content, bytes_read); 

    strncpy(output, argv[1], 250); 
    strcat(output, ".cry"); 

    // open dest 
    if ((crypted = fopen(output, "wb+")) == NULL) 
     fatal("in open crypted"); 

    // write src translated in dest 
    bytes_read = fwrite(content, 1, bytes_read, crypted); 
    printf("%d bytes written\n", bytes_read); 

    // terminate pgrm 
    fclose(crypted); 
    fclose(my); 
    free(content); 

    return 0; 
} 

void fatal(char *s) { 
    if (s) { 
     fprintf(stderr, "[!] Fatal [!] : %s\n", s); 
    } 
    perror(""); 
    exit(-1); 
} 

void usage (char *pgr_name) { 
    printf("Usage : %s <binary input> <offset [-255:255]>\n\n", pgr_name); 
    exit(0); 
} 

void dump (const unsigned char *data_buffer, const unsigned int len) { 
    unsigned char byte; 
    unsigned int i, j; 
    for (i=0; i<len; i++) { 
     byte = data_buffer[i]; 
     printf("%02x ", data_buffer[i]); 
     if (((i%16) == 15) || (i==len-1)) { 
      for (j=0; j < 15-(i%16); j++) 
       printf(" "); 
      printf("| "); 
      for (j=(i-(i%16)); j<=i; j++) { 
       byte = data_buffer[j]; 
       if (byte > 31 && byte < 127) 
        printf("%c", byte); 
       else 
        printf("."); 
      } 
      printf("\n"); 
     } 
    } 
} 
+0

Die Datei wäre beschäftigt, weil Sie sie ausführen. Sobald es fehlgeschlagen ist, wird es nicht mehr ausgeführt, sodass lsof nicht anzeigt, dass es gesperrt ist. EDIT TO ADD, die Datei wird für die gesamte Dauer des Laufs beschäftigt sein, nicht nur in den Speicher geladen werden. – racraman

+0

Also kann eine ausführbare Datei ihn nicht unter Unix neu schreiben? – ghost

+0

Vielen Dank für die Geschwindigkeit der Antwort – ghost

Antwort

1

Unix-Dateisysteme - die in Unix verwendet, BSDs, MacOS, Linux, und so weiter - stützen sich auf inodes. Mehrere Dateinamen können sich auf denselben Inode beziehen.

Wenn der Dateiname gelöscht wird, aber der Inode in einem oder mehreren Prozessen noch geöffnet ist, hat der Inode keine Dateinamen, die darauf verweisen. Sie können immer noch normal mit der geöffneten Datei arbeiten - sie zum Beispiel erweitern -, aber kein anderer Prozess kann sie öffnen (es sei denn, Sie stellen ihnen den offenen Dateideskriptor irgendwie zur Verfügung).

Wenn ELF-Binärdateien ausgeführt werden, wird der zugrunde liegende Inode vom Kernel gesperrt. Hinweis: Es ist der Inode, der gesperrt ist, nicht der Dateiname.

Dies liegt daran, dass die meisten Systeme die Daten einfach "mappen", anstatt sie in den Speicher zu laden. In Linux bedeutet dies zum Beispiel, dass unabhängig davon, wie viele Kopien einer ausführbaren Datei oder einer dynamischen Bibliothek Sie ausführen, nur eine Kopie der Binärdatei im RAM vorhanden ist.

In der Praxis bedeutet dies, dass Sie eine ELF-Binärdatei während der Ausführung nicht ändern können. Sie können die Datei jedoch umbenennen oder sogar löschen, da dies der Inode ist, auf den sich der Dateiname bezieht, und nicht der Dateiname, der vom Kernel gesperrt wird. (Natürlich können ELF-Binärdateien auch dann gut gelesen werden, wenn sie ausgeführt werden. Sie müssen nur sicherstellen, dass sie schreibgeschützt geöffnet werden, da das Öffnen von Lese- und Schreiboperationen fehlschlägt. Dies liegt daran, dass die meisten Unix-Dateisysteme nur Zugriffsberechtigungen überprüfen zur Öffnungszeit.)

Was Sie tun können, ist eine neue Datei erstellen; schreibe die modifizierten Daten; optional die Zeitstempel für Eigentümer, Gruppe, Modus, letzter Zugriff und letzte Änderung und/oder erweiterte Attribute (xattrs) kopieren; und schließlich umbenennen oder hardlink den neuen Dateinamen über den alten Dateinamen. (Das Umbenennen oder Hardlinking über eine vorhandene Datei ändert nur den Inode, auf den sich der vorhandene Dateiname bezieht, und verletzt daher nicht die Inode-Sperre.)

Dies hat den zusätzlichen Vorteil, dass der Austausch (der alten Binärdatei) atomar ist. Ungeachtet des Moments, zu dem andere Prozesse die alte Binärdatei öffnen oder ausführen können, sehen sie immer nur entweder den alten Inode oder den neuen Inode, niemals irgendeine Art von Zwischenversion.

Verwandte Themen