Programmazione
Controllo Remoto in C
Come è fatto il server
La struttura del server è semplice: prima saluta il client con una stringa di
benvenuto (utile per far capire che il server è in esecuzione sul computer remoto)E poi si mette in attesa della password. Dopodiché, se questa è
giusta, provvede a spedire al client il codice prodotto (quello che viene richiesto in fase di installazione e che si può leggere in impostazioni->pannello di controllo->sistema) del Windows su cui sta girando (tanto per fare qualcosa, giusto a titolo dimostrativo); poi interrompe la connessione e si riporta in attesa. Altrimenti, se la password è sbagliata, si limita a chiudere la connessione. Non che sia molto complesso, però è pur sempre un esempio. Programmi più maliziosi (tipo Netbus o simili) si basano sullo stesso principio (almeno a grandi linee) ma possiedono una serie di accorgimenti per nasconderre all’utente il fatto di essere Un esecuzione, con la possibilità di caricarsi automaticamente all’avvio del sistema per esempio aggiungendo voci nel registro di Windows, o modificando file di configurazione.
I dettagli
Dato che il server è per Windows, dovremo utilizzare le particolarissime API messe a disposizione dal sistema (WSA, winsock e via dicendo); Il server
chiama la funzione connettiti(), dove sono inserite tutte le istruzioni necessarie allo scopo; si inizializza la WSA (Windows Socket API) tramite la chiamata WSAStartup() passandogli la versione della libreria (wsock32.dll) e un puntatore a una struttura dati di tipo WSADATA, che verrà quindi riempita di informazioni che comunque non tratteremo successivamente per mantenere leggero il codice. Subito dopo si provvede ad aprire il socket locale (s1) specificando la famiglia di protocolli da usare (PF_INET) e il protocollo specifico, ovvero il TCP/IP (SOCK_STREAM). Si passa quindi a impostare in1 con i parametri di protocollo e porta (in1.sin_port=htons(2003)) e si inizializza la socket associando (bind) tale struttura di tipo sockaddr_in con la socket s1. Ci si pone quindi in attesa di connessione con la listen(). Ad avvenutaconnessione, si crea la seconda socket (s2) tramite la accept(); da adesso in poi tale puntatore verrà utilizzato per tutte le operazioni di comunicazione con il client (send/recv), un po’ come avviene per l’handle dei file per leggere, scrivere o agire su di essi. Preso nota dell’IP, ci si connette all’host inserendo i parametri come in Figura 1. Se il server gira sulla stessa macchina del client si inserisce 127.0.0.1 (localhost) specificando la porta. Fatto questo il programma esce da connettiti(), invia tramite la funzione send() la stringa “\rtoc toc neo…\r\inserisci password:” (vedi Figura 2) e torna in ricevi() in attesa della password. Tale funzione è un ciclo for di una coppia recv/send per cui si prende un carattere, lo si registra in memoria e si invia una copia al client remoto, giusto per avere un echo locale sul terminale(e sapere se si sta scrivendo senza errori). La funzione prende come parametri un puntatore a carattere (il buffer) e un ntero che indica il numero di caratteri da acquisire, nel nostro caso 8. Va comunque detto che la password non è necessaria ma può impedire (ai più) di accedere al programma. Inserita la stringa la si compara con “01234567” (la password inserita nel codice, da modificare prima di compilarlo) e in caso di esito positivo si entra in prendi_productID() dove si genera una chiamata al sistema operativo per accedere al registro (Reg- CreateKeyEx()) passando il percorso della chiave e i vari permessi, si copia la chiave “ProductId” nel buffer con RegQueryValueEx() e poi si chiude la “sessione” di registro invocando RegCloseKey(). A questo punto si invia il codice prodotto, dopodiché il server chiude la connessione e torna in ascolto. Il ciclo è infinito come si nota dal while(1) { … } del main(). funzione che permetta al client di impartire comandi arbitrari.
Sorgente:
#include
#include
#include
#include
#include
SOCKET s1,s2;
WSADATA WSAdata;
struct sockaddr_in in1,in2;
HKEY hKey;
void connettiti(void)
{
int lenght;
WSAStartup(0x0202,&WSAdata);
s1=socket(PF_INET,SOCK_STREAM,0);
in1.sin_family=PF_INET;
in1.sin_port=htons(2003); // porta da usare
in1.sin_addr.s_addr=INADDR_ANY;
bind(s1,(struct sockaddr*)&in1,sizeof(struct sockaddr_in));
lenght=sizeof(struct sockaddr);
listen(s1,1);
printf(“\nIN ATTESA…”); // info locali di debug
s2=accept(s1,(struct sockaddr*)&in2,(LPINT)&lenght);
printf(“OK…\n”); // info locali di debug
}
char* ricevi(char* buff,int lenght) // riceve un comando
{
int i;
for(i=0;i {
recv(s2,buff+i,1,0); // riceve il carattere
send(s2,buff+i,1,0); // echo
}
return buff;
}
char* prendi_ProductID(char* buff)
{
unsigned long d=0xFF;
RegCreateKeyEx(HKEY_LOCAL_MACHINE,
“Software\\Microsoft\\Windows\\CurrentVersion”
,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,NULL);
RegQueryValueEx(hKey,”ProductId”,NULL,NULL,(LPBYTE)buff,&d);
RegCloseKey(hKey);
return buff;
}
int main(void)
{
char buffer[100]; // buffer dati
while(1)
{
connettiti(); // inizializza il server
strcpy(buffer,”\rtoc toc neo… \r\ninserisci password:”);
send(s2,buffer,strlen(buffer),0);
if (strncmp(ricevi(buffer,8),”01234567”,8)==0)
{
strcpy(buffer,”\r\nlogin OK\r\nProductID:”);
send(s2,buffer,strlen(buffer),0);
send(s2,prendi_ProductID(buffer),strlen(buffer),0); // invia il ProductID
}
shutdown(s1,2);
closesocket(s1);
shutdown(s2,2);
closesocket(s2);
WSACleanup();
}
return(0);
}
Film Consigliato : The Matrix (1999)
