/*
    Exemple de buffer overflow.

    Il faut tout d'abords se convaincre que la fonction f est écrite en C et non
    pas en assembleur. Mais les compilo moderne font trop de vérification pour
    que l'on puisse leur laisser la possibilité d'écrire le prologue et l'épilogue
    de ce genre de code.

    Pour que ça fonctionne, il faut compiler le code avec Visual C++ en désactivant
    les options de vérification de la pile.
    
    Puis il faut comprendre que l'écriture de l'adresse de g dans le buffer de la
    fonction f devrait être fait par une fonction de genre scanf qui ne vérifierait
    pas la taille de son buffer, ou, plus probable encore, par une lecture sur un
    socket de données venant du réseau. L'adresse de la fonction que l'on va écrire,
    peut être n'importe quoi, y compris une fonction système, si o sait où est-ce
    qu'elle est chargé. De plus, en effacant plus d'information sur la pile, on peut
    donner n'importe quel paramètre à la fonction appelée (ici, le paramètre 42).
*/

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

void g(int i)
{
    printf("Security violation : %d!\n",i);
    exit(1);
}

__declspec(naked) void f()
{
    __asm
    {
        push ebp
	    mov ebp, esp
        
        // char str[16];
	    sub esp, 16;

        // *(long*)(str+20) = (long)(g);
        mov	eax, OFFSET g
	    mov	DWORD PTR [esp+20], eax

        // *(long*)(str+28) = 42;
        mov DWORD PTR [esp+28], 42

        // return
	    mov	esp, ebp
        pop ebp
	    ret	0
    }
}

int main()
{
    f();
    printf("Optimum security !\n");
    return 0;
}

