Torna indietro   Hardware Upgrade Forum > Software > Programmazione

 Hisense 55U7SE: tuttofare e accessibile, il MiniLED per film, sport e gioco
Hisense 55U7SE: tuttofare e accessibile, il MiniLED per film, sport e gioco
MiniLED di fascia media con local dimming a 192 zone, 144 Hz nativi e audio firmato Devialet. La prova strumentale riscontra colori affidabili e gaming reattivo, per un prodotto molto accessibile e convincente. Ma la soundbar aggiuntiva è quasi d'obbligo
Kindle Scribe Colorsoft: riduce le cornici e diventa a colori, ma il prezzo è alto
Kindle Scribe Colorsoft: riduce le cornici e diventa a colori, ma il prezzo è alto
Amazon porta i colori sul suo Kindle da scrittura più grande: schermo Colorsoft a 11 pollici, processore quad-core, penna premium più reattiva e strumenti IA per le note, sono le note salienti. Il salto di prezzo rispetto al modello in bianco e nero si fa sentire, anche se la percezione è quella di trovarsi di fronte a un prodotto di fascia altissima, per veri appassionati
L'IA cambia tutte le regole della sicurezza tra vulnerabilità e sorveglianza. Intervista al CEO di Proofpoint
L'IA cambia tutte le regole della sicurezza tra vulnerabilità e sorveglianza. Intervista al CEO di Proofpoint
Abbiamo intervistato Sumit Dhawan, CEO di Proofpoint, per capire come stia cambiando il mondo della sicurezza con l'avvento dell'intelligenza artificiale e con il ritmo sempre più serrato a cui vengono trovate vulnerabilità nel software. Un problema significativo, che richiederà del tempo per essere risolto (o quantomeno arginato)
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 12-12-2005, 20:45   #1
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
una fork per Windows [x ilsensine, ma non solo :)]

l'altro giorno sulla mailing list del corso di Laboratorio di SO arriva un niubbo e fa: "ho fatto per esercitarmi un programma che usa la funzione fork bla bla e su Windows non compila (lol ) esiste una funzione analoga alla fork su Windows?"; dopodiché arriva un altro niubbo (un po' meno niubbo del precedente però) e fa "ah bla bla bla la fork è una prerogativa dei sistemi Unix ecc. ecc.".
allora io prendo spunto e realizzo una mini-fork per Windows
non vi immaginate che sia un granché, è molto rudimentale: altro non fa che creare il processo figlio sospeso, ricopiarci tutte le sezioni non shared e non discardable impostate con permessi di scrittura oltre che di lettura, settare opportunamente il contesto del thread interrotto, ed infine riesumarlo; una fork simile funziona solo a patto che siano verificate le seguenti condizioni:
1) il programma è single-threaded
2) il programma non chiama VirtualAlloc e HeapAlloc prima della fork (dopo volendo si, ma prima no)
3) il programma non alloca handles non ereditabili prima della fork (dopo magari si, ma prima no )

comunque quel poco che fa lo fa bene
siccome ricordo che ilsensine una volta chiese a fek di spiegargli come hanno fatto quelli di Cygwin a realizzare la fork su Windows, ora la incollo qui di seguito; BTW, per l'occasione mi sono anche letto il codice della fork di Cygwin: la loro funziona un po' meglio della mia perché hanno un vantaggio: se ho ben capito come funziona questo Cygwin, si assume che un programma usi solamente le funzioni di Cygwin, quindi loro nel realizzare la fork avevano controllo sull'heap; ma per fare un bel crash anche su Cygwin è sufficiente tenere memoria di un handle non ereditabile prima di una fork

Codice:
#include <windows.h>

int fork();

int main() {
	TCHAR pszMsg[0x100];
	wsprintf(pszMsg, TEXT("questo è il processo padre, PID = %d"), GetCurrentProcessId());
	MessageBox(NULL, pszMsg, TEXT("fork on Windows"), MB_ICONINFORMATION);

	if (fork()) {
		wsprintf(pszMsg, TEXT("questo invece è il figlio, PID = %d"), GetCurrentProcessId());
		MessageBox(NULL, pszMsg, TEXT("fork on Windows"), MB_ICONINFORMATION);
	}

	return 0;
}


#define TESTFLAG(mask, flag) ((flag) == ((mask) & (flag)))

HANDLE hStarted = NULL;

__declspec(naked) void Stub() {
	SetEvent(hStarted);
	CloseHandle(hStarted);
	SuspendThread(GetCurrentThread());
}

BYTE pbJmp[5] = {0xE9};

int fork() {
	DWORD dwDummy;

	TCHAR pszFileName[0x400];
	if (!GetModuleFileName(NULL, pszFileName, 0x400)) {
		return -1;
	}

	SECURITY_ATTRIBUTES sa = {
		sizeof(SECURITY_ATTRIBUTES),
		NULL,
		TRUE
	};
	hStarted = CreateEvent(&sa, FALSE, FALSE, NULL);

	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	ZeroMemory((PVOID)&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);

	if (!CreateProcess(pszFileName, NULL, NULL, NULL, TRUE, GetPriorityClass(GetCurrentProcess()) |
		CREATE_SUSPENDED, NULL, NULL, &si, &pi))
	{
		return -1;
	}

	WriteProcessMemory(pi.hProcess, (PVOID)&hStarted, (PVOID)&hStarted, 4, &dwDummy);


	PBYTE pbInstBase = (PBYTE)GetModuleHandle(NULL);
	PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)(pbInstBase + *(PDWORD)(pbInstBase + 0x3C));

	PVOID pvEntryAddress = (PVOID)(pbInstBase + pinth->OptionalHeader.AddressOfEntryPoint);

	DWORD dwPrevProtect;
	VirtualProtectEx(pi.hProcess, pvEntryAddress, 5, PAGE_READWRITE, &dwPrevProtect);

	*(PDWORD)(pbJmp + 1) = (DWORD)&Stub - (DWORD)pvEntryAddress - 5;
	WriteProcessMemory(pi.hProcess, pvEntryAddress, (PVOID)pbJmp, 5, &dwDummy);

	ResumeThread(pi.hThread);
	WaitForSingleObject(hStarted, INFINITE);
	CloseHandle(hStarted);

	WriteProcessMemory(pi.hProcess, pvEntryAddress, pvEntryAddress, 5, &dwDummy);

	VirtualProtectEx(pi.hProcess, pvEntryAddress, 5, dwPrevProtect, &dwDummy);


	PIMAGE_SECTION_HEADER pSecHdrs = (PIMAGE_SECTION_HEADER)((PBYTE)pinth +
		sizeof(IMAGE_NT_HEADERS));
	for (UINT u = 0; u < pinth->FileHeader.NumberOfSections; u++) {
		DWORD dwFlags = pSecHdrs[u].Characteristics;
		if (!TESTFLAG(dwFlags, IMAGE_SCN_MEM_DISCARDABLE) &&
			!TESTFLAG(dwFlags, IMAGE_SCN_MEM_SHARED) &&
			TESTFLAG(dwFlags, IMAGE_SCN_MEM_READ) &&
			TESTFLAG(dwFlags, IMAGE_SCN_MEM_WRITE))
		{
			PVOID pvSecAddr = (PVOID)(pbInstBase + pSecHdrs[u].VirtualAddress);
			WriteProcessMemory(pi.hProcess, pvSecAddr, pvSecAddr, pSecHdrs[u].Misc.VirtualSize,
				&dwDummy);
		}
	}


	BOOL InTheChild = FALSE;

	CONTEXT c;
	ZeroMemory((PVOID)&c, sizeof(CONTEXT));
	c.ContextFlags = CONTEXT_FULL;
	GetThreadContext(GetCurrentThread(), &c);

	__asm {
		call near here
here:
		pop eax
		inc eax
		mov c.Eip,eax
		mov c.Esp,esp
		mov c.Ebp,ebp
	}

	if (InTheChild) {
		return GetCurrentProcessId();
	}

	/*
	PUSH EBP
	MOV EBP,ESP
	*/

	DWORD dwFramePtr;
	__asm {
		mov dwFramePtr,ebp
	}
	DWORD dwKernel32 = (DWORD)LoadLibrary(TEXT("kernel32.dll"));
	PIMAGE_NT_HEADERS pinthKernel32 = (PIMAGE_NT_HEADERS)(dwKernel32 +
		*(PDWORD)(dwKernel32 + 0x3C));
	UINT uKernel32Size = pinthKernel32->OptionalHeader.SizeOfImage;
	while (dwFramePtr) {
		DWORD dwRetAddress = *(((PDWORD)dwFramePtr) + 1);
		if ((UINT)(dwRetAddress - dwKernel32) <= uKernel32Size) {
			break;
		}
		dwFramePtr = *(PDWORD)dwFramePtr;
	}

	DWORD dwStackPtr;
	__asm {
		mov dwStackPtr,esp
	}
	DWORD dwDelta = dwFramePtr - dwStackPtr;

	WriteProcessMemory(pi.hProcess, (PVOID)dwStackPtr, (PVOID)dwStackPtr, dwDelta, &dwDummy);


	BOOL RemoteChildFlag = TRUE;
	WriteProcessMemory(pi.hProcess, (PVOID)&InTheChild, (PVOID)&RemoteChildFlag, 4, &dwDummy);

	SetThreadContext(pi.hThread, &c);
	ResumeThread(pi.hThread);

	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);

	return 0;
}
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 20:49   #2
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
dimenticavo: a causa di una particolarità del mio codice, il programma che chiama quella fork non può neanche chiamarla da una funzione di callback che è stata a sua volta richiamata da Kernel32.dll: altre DLL vanno bene, User32 ad esempio va bene, ma Kernel32 no
insomma sta fork fa abbastanza schifo
ma provate voi a farne una migliore su Windows

però c'è di buono che in teoria un programma che usa quella fork può anche avere un'interfaccia grafica perché gli handles delle finestre sono globalmente visibili, e quindi sarebbero validi anche nei processi figli... con l'unico problema che il processo figlio utilizzerebbe le stesse finestre del padre ci sarebbe un'attimino di interferenza
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 21:51   #3
The3DProgrammer
Senior Member
 
Iscritto dal: May 2000
Messaggi: 1459
certo ke tu e kernel32.dll vi parlate eh?


ciau
The3DProgrammer è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 21:59   #4
VegetaSSJ5
Senior Member
 
L'Avatar di VegetaSSJ5
 
Iscritto dal: Sep 2002
Città: Celano (AQ) Segno_Zodiacale: Leone Ascendente: Cammello Segni_Particolari: Quello
Messaggi: 9571



VegetaSSJ5 è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 22:17   #5
jappilas
Senior Member
 
L'Avatar di jappilas
 
Iscritto dal: Apr 2003
Città: Genova
Messaggi: 4747
bello, bello, tutta "arte che entra"

ancora inpùt, ancora...
__________________
Jappilas is a character created by a friend for his own comic - I feel honored he allowed me to bear his name
Saber's true name belongs to myth - a Heroic Soul out of legends, fighting in our time to fullfill her only wish
Let her image remind of her story, and of the emotions that flew from my heart when i assisted to her Fate
jappilas è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 22:21   #6
The3DProgrammer
Senior Member
 
Iscritto dal: May 2000
Messaggi: 1459
a grandi linee l'ho capita, mi manca solo una parte:


Codice:

	*(PDWORD)(pbJmp + 1) = (DWORD)&Stub - (DWORD)pvEntryAddress - 5;
	WriteProcessMemory(pi.hProcess, pvEntryAddress, (PVOID)pbJmp, 5,      &dwDummy);
Ad occhio, &Stub-pvEntryAddress-5(?) restituisce il numero di byte che comprende la sezione tra l'entry point e la funzione Stub (di cui nn capisco la necessità di dichiararla naked) di cui vai ad effettuare una copia nel nuovo processo... o no?

ciau
The3DProgrammer è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 23:10   #7
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da The3DProgrammer
a grandi linee l'ho capita, mi manca solo una parte:


Codice:

	*(PDWORD)(pbJmp + 1) = (DWORD)&Stub - (DWORD)pvEntryAddress - 5;
	WriteProcessMemory(pi.hProcess, pvEntryAddress, (PVOID)pbJmp, 5,      &dwDummy);
Ad occhio, &Stub-pvEntryAddress-5(?) restituisce il numero di byte che comprende la sezione tra l'entry point e la funzione Stub (di cui nn capisco la necessità di dichiararla naked) di cui vai ad effettuare una copia nel nuovo processo... o no?
hum, se non hai capito quello ti manca un pezzo piuttosto grosso... ti do un aiutino: guarda il nome del buffer che conteine i dati che vado a copiare nell'altro processo, e guarda anche la dimensione di tale buffer e il valore del primo byte

ciao
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 23:14   #8
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da VegetaSSJ5



capisco lo stupore, ma come mai le lacrime?
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 08:17   #9
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Quote:
Originariamente inviato da 71104
1) il programma è single-threaded
Come mai questa limitazione? Una fork non clona i thread

Quote:
comunque quel poco che fa lo fa bene
Non dovrebbe fare molto altro, in effetti. Tieni conto che il 90% delle fork viene fatto prima di una exec (visto che nei sistemi unix non esiste un equivalente di CreateProcess), e il 9.9% sono situazioni che potrebbero essere meglio gestite tramite i thread. Direi quindi che se si intende scrivere un programma multipiattaforma che giri anche su windows, ha molto senso aggiungere quel paio di righe su #ifdef per chiamare CreateProcess oppure fork+exec a seconda della piattaforma (nascoste magari in un metodo StartNewProcess() ). Anche perché con le varie WriteProcessMemory elimini il principale punto di forza della fork (ovvero la COW), rendendo quindi estremamente inefficiente la funzione.

Grazie per la spiegazione comunque
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 08:50   #10
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Quote:
Originariamente inviato da 71104
3) il programma non alloca handles non ereditabili prima della fork (dopo magari si, ma prima no )
Anche questo non dovrebbe essere un problema, se la fork viene usata nella maniera classica (fork+exec). Anche su linux gli fd possono essere marcati "non ereditabili da una exec". In questo caso, gli handler non ereditabili dovrebbero passare inosservati/inuilizzati.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 18:31   #11
VegetaSSJ5
Senior Member
 
L'Avatar di VegetaSSJ5
 
Iscritto dal: Sep 2002
Città: Celano (AQ) Segno_Zodiacale: Leone Ascendente: Cammello Segni_Particolari: Quello
Messaggi: 9571
Quote:
Originariamente inviato da 71104
capisco lo stupore, ma come mai le lacrime?
ops hai ragione! ho dimenticato anche questo -->
VegetaSSJ5 è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 22:56   #12
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da ilsensine
Come mai questa limitazione? Una fork non clona i thread
appunto
il nuovo programma non avrà i thread del primo, avrà solo il thread primario, quindi o il programma è single threaded oppure il programmatore deve essere consapevole della limitazione.

Quote:
Non dovrebbe fare molto altro, in effetti. Tieni conto che il 90% delle fork viene fatto prima di una exec (visto che nei sistemi unix non esiste un equivalente di CreateProcess), e il 9.9% sono situazioni che potrebbero essere meglio gestite tramite i thread. Direi quindi che se si intende scrivere un programma multipiattaforma che giri anche su windows, ha molto senso aggiungere quel paio di righe su #ifdef per chiamare CreateProcess oppure fork+exec a seconda della piattaforma (nascoste magari in un metodo StartNewProcess() ).
si ma che utilità ha secondo te questa fork che non ti permette neanche di usare malloc e free??

Quote:
Anche perché con le varie WriteProcessMemory elimini il principale punto di forza della fork (ovvero la COW), rendendo quindi estremamente inefficiente la funzione.
era solo un esperimento didattico

Quote:
Grazie per la spiegazione comunque
prego
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 22:58   #13
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da ilsensine
Anche questo non dovrebbe essere un problema, se la fork viene usata nella maniera classica (fork+exec). Anche su linux gli fd possono essere marcati "non ereditabili da una exec". In questo caso, gli handler non ereditabili dovrebbero passare inosservati/inuilizzati.
il problema è il seguente:
1) il processo padre crea un handle non ereditabile per, diciamo, un file, e non lo chiude
2) fork
3) il processo figlio fa riferimento a quell'handle...

al punto 3 qualsiasi funzione API semplicemente ritorna errore, ma il processo ne deve essere "aware"; cioè, se tu mi dici che il problema esiste anche su Linux e che i programmatori che usano la fork ne sono coscienti allora va bene, volevo solo dire che è un punto da tenere presente...

Ultima modifica di 71104 : 13-12-2005 alle 23:00.
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 14-12-2005, 07:45   #14
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Quote:
Originariamente inviato da 71104
appunto
il nuovo programma non avrà i thread del primo, avrà solo il thread primario, quindi o il programma è single threaded oppure il programmatore deve essere consapevole della limitazione.
Anche la fork funziona così; un processo forkato contiene un solo thread.

Quote:
si ma che utilità ha secondo te questa fork che non ti permette neanche di usare malloc e free??
<me gnurant>
Vuoi dire che questo:
Quote:
2) il programma non chiama VirtualAlloc e HeapAlloc prima della fork
implica che non puoi chiamare malloc/free? Oh bè questo è un problema...
Quote:
3) il processo figlio fa riferimento a quell'handle...
Se l'handle non è ereditabile è corretto che il figlio lo veda chiuso
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 14-12-2005, 10:02   #15
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da ilsensine
implica che non puoi chiamare malloc/free? Oh bè questo è un problema...
esatto... ^^
il problema è che su Windows un processo crea uno o più heap usando HeapCreate (poi li distruggerà con HeapDestroy), e in ciascuno di questi può allocare e riallocare memoria con HeapAlloc e HeapRealloc; siccome è anche possibile enumerare tutti gli heap presenti nel processo, io potrei anche provare ad enumerarli e allocare tanti blocchi nel nuovo quanti ne vedo nel vecchio, ma non è detto che avrebbero tutti gli stessi indirizzi virtuali: servirebbero delle rilocazioni... il problema si può risolvere utilizzando VirtualAlloc al posto di HeapAlloc per allocare i blocchi dell'heap: VirtualAlloc infatti permette di specificare l'indirizzo virtuale desiderato, ma c'è un problema anche qui: gli heap in Windows sono oggetti del kernel, ovvero sono identificati da un handle, il quale ovviamente viene creato come non ereditabile; se fosse ereditabile sarebbe un gran macello perché il processo figlio accederebbe alla stessa memoria dinamica del padre senza sincronizzarsi... d'altra parte però, non essendo ereditabile, il processo figlio non vede gli handle degli heap che aveva il padre, e quindi (siccome si suppone che esso tenga memoria dell'handle dell'heap, magari all'interno del CRT di Visual C++) qualsiasi HeapAlloc, HeapRealloc ed HeapFree per lui fallirà.
in user mode insomma non si va molto lontano, a meno che non si faccia come hanno fatto su Cygwin, ovvero non si realizza un intero framework che abbia controllo su queste cose e quindi abbia anche controllo sugli handle degli heap e li possa cambiare a piacere.
quindi stavo pensando l'altro giorno a quale potrebbe essere una soluzione un po' migliore realizzata in kernel mode: in kernel mode dopo aver creato il processo si potrebbe fare un po' quello che fa Linux, ovvero ricopiare pari pari la directory e le tabelle delle pagine mettendole in protezione Copy-On-Write; il problema degli handle degli heap però rimane comunque... uqesta soluzione altro non sarebbe che una versione più efficiente della soluzione in cui uso VirtualAlloc per ricopiare gli heap nel processo figlio.
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 14-12-2005, 14:06   #16
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
O bella questa...
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


 Hisense 55U7SE: tuttofare e accessibile, il MiniLED per film, sport e gioco Hisense 55U7SE: tuttofare e accessibile, il Min...
Kindle Scribe Colorsoft: riduce le cornici e diventa a colori, ma il prezzo è alto Kindle Scribe Colorsoft: riduce le cornici e div...
L'IA cambia tutte le regole della sicurezza tra vulnerabilità e sorveglianza. Intervista al CEO di Proofpoint L'IA cambia tutte le regole della sicurezza tra ...
L'Europa conta nella tecnologia e può essere autonoma. Cosa si è detto al Nextcloud Summit 2026 L'Europa conta nella tecnologia e può ess...
Dreame X60 Pro Ultra Complete: i bracci si estendono sempre di più Dreame X60 Pro Ultra Complete: i bracci si esten...
Intel ha rivisto al rialzo i prezzi cons...
Batterie domestiche, boom da record nei ...
Lenovo Idea Tab Plus: 12,1 pollici e Dol...
Fiat svela Multiplina Concept: l’erede e...
Facebook e Instagram sono progettati per...
Amazon lancia la sfida dei chip AI: semi...
The Elder Scrolls VI: lo sviluppo c...
Samsung Galaxy S25 Edge 256GB al minimo ...
Un pianeta sette volte più grande della ...
Fastweb, quinta rimodulazione del 2026: ...
Gli scienziati hanno appena trovato il '...
Recensione OPPO Enco Air5 Pro: il perfet...
'Completamente falso': Elon Musk spegne ...
OnePlus invita gli utenti a provare i di...
Grand Theft Auto VI arriva su Amazon al ...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 12:12.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v