L'ho guardato meglio...

codice:
typedef struct
        {
          int ID;
          char Cognome[32];
          char Nome[32];
        } Persona;

void Inserisci( Persona **New , int *n);
void stampa( Persona *List , int n );

int main(){
   Persona *Contatti;
   int start, choice;
   start = 0;
   Contatti = NULL;

printf("Premi 1 per inserire\n"
       "Premi 2 per terminare\n?");
scanf("%d", &choice);

while(choice!=2){
   Inserisci(&Contatti, &start );
   stampa(Contatti, start );
   printf("?");
   scanf("%d",&choice);
}
   system("PAUSE");
return 0;
}

void Inserisci( Persona **New , int *n ){
   int i, dim;
   Persona *NewP;
  
   dim=*n;
   if (dim == 0){
      dim++;
      NewP=(Persona*)malloc(sizeof(Persona));
   }
   else{
      dim++;
      NewP=(Persona*)realloc(*New, dim);
   }
   NewP[dim].ID=dim;
   printf("Cognome: ");
   scanf("%s" , NewP[dim].Cognome);
   printf("Nome: ");
   scanf("%s" , NewP[dim].Nome);
   *n = dim;
   *New=NewP;
}

void stampa( Persona *List , int n ){
   int i;

   for(i=1; i<=n; i++)
      printf("%s %s\n" , List[i].Cognome , List[i].Nome);
}
Innanzitutto come detto sopra devi fare (*n=dim e non (n=&dim, altrimenti start rimaraà sempre a zero perchè non stavi cambiando il suo valore ma semplicemente stavi facendo puntare n a dim, e uscito dalla funzione start rimane tale e quale a quando è entrato.

Poi il primo parametro di Inserisci dev'essere un puntatore a puntatore, ovvero deve puntare all'indirizzo di memoria del puntatore Contatti se vuoi poter modificare il suo indirizzo da NULL all'elemento che inserisci... e così per ogni volta che reallochi.

Ho messo un while così puoi inserire più nominativi, altrimeti si eseguiva soltanto una volta.