Ceci est purement expérimental et n'a aucune réelle utilité (du moins pas à ma connaissance). Je lis de la littérature sur le format PE et je voulais essayer cela si cela était possible.

J'ai créé un programme simple qui imprime "Hello World" en C et je l'ai compilé en EXE sur un ordinateur Windows, après quoi j'ai ouvert le fichier dans un éditeur hexadécimal et enregistré le contenu en tant que fichier C (l'éditeur hexadécimal a cela comme une option) et l'ajoute en tant que chaîne dans un autre script C.

Le programme C:

#include <stdio.h>

int main(void)
{
    printf("Hello World");
    return 0;
}

Code binaire pour C:

0x23, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x20, 0x3C, 0x73, 0x74,
0x64, 0x69, 0x6F, 0x2E, 0x68, 0x3E, 0x0D, 0x0A, 0x23, 0x69, 0x6E, 0x63,
0x29, 0x3B, 0x0D, 0x0A, 0x09, 0x0D, 0x0A, 0x09, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6E, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A [...]

Cet autre script C écrit le contenu de la chaîne sur le disque et l'enregistre en tant que fichier EXE qui (selon ma théorie) serait capable d'exécuter. Cependant, lorsque je l'exécute, je reçois le message "Cette application ne peut pas fonctionner sur votre PC".

L'autre programme C:

#include <stdio.h>

int main()
{
    FILE* file_ptr = fopen("test_file.exe", "w");

    unsigned char rawData[106] = {
    0x23, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x20, 0x3C, 0x73, 0x74,
    0x64, 0x69, 0x6F, 0x2E, 0x68, 0x3E, 0x0D, 0x0A, 0x23, 0x69, 0x6E, 0x63,

    [...]   

    0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x22,
    0x29, 0x3B, 0x0D, 0x0A, 0x09, 0x0D, 0x0A, 0x09, 0x72, 0x65, 0x74, 0x75,
    0x72, 0x6E, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A
    };

    fprintf(file_ptr, "%s", rawData);
    fclose(file_ptr);
    return 0;
}

Pourquoi ça ne marche pas? Je veux dire, c'est du code machine pur du fichier EXE qui fonctionnait parfaitement auparavant. Je suppose que quelque chose doit se passer dans le compilateur mais je ne comprends pas exactement quoi.

Quelqu'un qui pourrait expliquer?

c
1
Lavonen 20 nov. 2018 à 20:14

3 réponses

Meilleure réponse

Le spécificateur de format "%s" est pour les chaînes d'octets à terminaison nulle . Le terminateur nul est égal à l'octet 0 (0x00). Il est très probable qu’il existe quelque part dans les données du tableau. Vous avez besoin d'une autre façon de l'écrire, comme par exemple fwrite.

De plus, puisque vous écrivez un fichier binaire, vous devez également l'ouvrir en mode binaire. Sinon tout octet correspondant au caractère de nouvelle ligne ('\n', 0x0a dans Encodage ASCII) sera traduit en séquence de nouvelle ligne Windows "\r\n".

Enfin, les attributs du fichier que vous créez n'incluront pas l'indicateur exécutable.

3
Some programmer dude 20 nov. 2018 à 17:18

fprintf sert à écrire du texte dans un fichier ou un flux. Le spécificateur de format %s s'arrêtera sur un caractère nul, ce qui ne fonctionnera évidemment pas pour les données binaires qui peuvent contenir des valeurs nulles n'importe où.

Le simple fait que ce soit des données binaires devrait suffire à vous dissuader d'utiliser fprintf et d'autres fonctions d'E / S de texte, mais en particulier, le format PE-EXE est garanti d'avoir des valeurs nulles dans son contenu grâce à son en-tête même qui commence par le nombre magique "PE\0\0".

Utilisez la fonction fwrite pour écrire des données binaires dans un fichier:

fwrite(rawData, 1, sizeof(rawData), file_ptr);
2
Govind Parmar 20 nov. 2018 à 17:18

Le fichier "binaire" que vous écrivez est un fichier source, pas un exécutable. Si je traduis vos données brutes:

unsigned char rawData[106] = {
0x23, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x20, 0x3C, 0x73, 0x74,
0x64, 0x69, 0x6F, 0x2E, 0x68, 0x3E, 0x0D, 0x0A, 0x23, 0x69, 0x6E, 0x63,

Cela correspond au texte:

#include

(etc)

Ce n'est pas un exécutable, c'est le fichier source!

Vous ne pouvez pas simplement enregistrer un fichier source C avec une extension "exe" et le faire fonctionner. Vous devez réellement le compiler.

1
davmac 21 nov. 2018 à 11:45