Appel de l’adresse putchar depuis C ++

Dans une question précédente , j’ai demandé s’il était possible d’écrire et d’exécuter des commandes d’assemblage en mémoire. J’ai eu quelques bonnes réponses, et après un peu plus de recherches, j’ai compris comment le faire. Maintenant que je peux le faire, j’ai du mal à comprendre ce qu’il faut écrire dans la mémoire (et comment le faire correctement). Je connais un assemblage et comment les mnémoniques se traduisent en codes opération, mais je ne comprends pas comment les utiliser correctement.

Voici un exemple que j’essaie de faire fonctionner:

void(*test)() = NULL; //create function pointer, initialize to NULL void* hold_address = VirtualAlloc(NULL, 5*1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE); //allocate memory, make writable/ readable/ executable unsigned char asm_commands[] = {0x55, 0x89, 0xE5, 0x83, 0xEC, 0x18, 0xC7, 0x04, 0x24, 0x41, 0xE8, 0x1E, 0xB3, 0x01, 0x00, 0xC9, 0xC3}; //create array of assembly commands, hex values memcpy(hold_address, asm_commands, sizeof(asm_commands)[0]*10); //copy the array into the reserved memory test = (void(*)())hold_address; //set the function pointer to start of the allocated memory test(); //call the function 

Le simple fait de placer 0xC3 dans le tableau asm_commands fonctionne (et la fonction revient tout simplement), mais c’est ennuyeux. Les séries d’opcodes (et d’adresses) que j’ai actuellement sont censées imprimer le caractère “A” (majuscule a). J’ai obtenu les codes d’opération et les adresses en déboguant un programme simple qui appelle printf (“A”) et en retrouvant l’appel en mémoire. À l’heure actuelle, le programme renvoie une erreur 0xC00000096, “commande privilégiée”. Je pense que l’erreur provient d’essayer d’appeler directement l’adresse putchar du système, ce que le système n’aime pas. Je pense aussi que je peux contourner cela en donnant à mon programme l’access à Ring 0, mais je ne sais pas ce que cela implique d’autre que de nombreux problèmes potentiels.

Alors, y a-t-il moyen d’appeler la fonction printf () (dans les opcodes d’assemblage) sans avoir besoin de privilèges plus élevés?

J’utilise Windows 7, 64 bits, Code :: Blocks 10.05 (compilateur GNU GCC).

Voici une capture d’écran de l’appel printf () débogué (dans OllyDebug):

 unsigned char asm_commands[] = {0x55, 0x89E5… 

Whoa, accrochez-vous, arrêtez-vous là. 0x89E5 n’est pas une valeur valide pour un caractère unsigned char et votre compilateur devrait probablement s’en plaindre. (Sinon, vérifiez vos parameters; vous avez probablement désactivé certains avertissements très importants.)

Vous devrez diviser votre code dans cet initialiseur en octets individuels, par exemple:

 {0x55, 0x89, 0xE5, … 

Rien ne s’imprime car vous avez oublié ces zéros dans le dword 0x00000041 et écrit par erreur 0x1A à la place de 0x1E.

unsigned char asm_commands [] = {0x55, 0x89, 0xE5, 0x83, 0xEC, 0x18, 0xC7, 0x04, 0x24, 0x41, 0x00, 0x00, 0x00, 0xE8, 0x1E, 0xC7, 0xC7, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 . // crée un tableau de commandes d’assemblage, de valeurs hexadécimales

En plus de ce que @duskwuff et @ user3144770 ont écrit. Avez-vous changé la ligne suivante pour inclure chaque octet?

 memcpy(hold_address, asm_commands, sizeof(asm_commands)[0]*10); 

J’ai compté 20 octets de code d’assemblage!

 memcpy(hold_address, asm_commands, sizeof(asm_commands)[0]*20);