Cookies op Tweakers

Tweakers maakt gebruik van cookies, onder andere om de website te analyseren, het gebruiksgemak te vergroten en advertenties te tonen. Door gebruik te maken van deze website, of door op 'Ga verder' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt, bekijk dan ons cookiebeleid.

Meer informatie

Door , , 33 reacties
Bron: The Register, submitter: FFWD

The Register merkte op dat Intel sinds afgelopen maandag desktopprocessors aan zijn leveringsprogramma heeft toegevoegd, die beschikken over ondersteuning voor de beveiligingsmaatregel die Intel Execute Disable Bit (EDB) noemt. Deze feature is vergelijkbaar met AMD's oplossing, No-eXecute (NX) geheten. Ook andere chips, waaronder die van Transmeta zullen een dergelijke beveiliging gaan krijgen. Deze hardwarematige Data Execution Prevention wordt ondersteund door Windows XP vanaf Service Pack 2, Windows Server 2003 met SP1, Red Hat Enterprise Linux 3 Update 3 en SUSE linux 9.2 en moet bescherming bieden tegen bepaalde 'buffer overflow'-aanvallen door malware.

CeleronIntel biedt niet alleen de Pentium 4 maar ook Celerons in 'J'-uitvoering. De feature heeft geen invloed op de prijs ten opzichte van voorgaande processors zonder deze ingebakken functionaliteit. Het wachten is nog op het verschijnen in de prijslijst van de 64-bit Xeon Nocona J-modellen. Ook de Mobile-processors van Intel zullen deze feature gaan krijgen. Intel introduceerde zijn Execute Disable Bit-functionaliteit in Itanium-processors al in 2001.

Moderatie-faq Wijzig weergave

Reacties (33)

Twee vragen die in mij opkomen:

Wat is zou precies de werking van dit systeem moeten zijn? Hoe leg je de link met buffers(overflows) en een extra bit in je proc?

En hoeveel heeft dit te maken met dat toekomstige protected computing environment van intel en microsoft waar drm ook zo'n grote rol in speelt?
De no-execute zorgt voor een striktere scheiding tussen stukken geheugen met data en stukken geheugen met executable code.

Buffer overflows proberen misbruik te maken van de mogelijkheid om meer data weg te schrijven in een stuk dat voor data bedoelt is, dan dat er werkelijk in kan. Dat deel dat dan te veel is, kan bij cpus zonder die beveiliging in een deel van het geheugen terecht komen dat executable code bevat. Hierdoor kun je het voor elkaar krijgen dat je een programma iets anders kan laten uitvoeren dan de bedoeling was. En als je dat goed uitkient, dan heb je een buffer overflow exploit.
De no-execute bit zorgt er voor dat je data kan wegschrijven in een stuk geheugen dat als data-page staat aangemerkt en daar niets uit kan uitvoeren en code uitvoeren uit een page die als executalbe staat aangemerkt, maar daar geen data kan wegschrijven.
Er is echter wel ondersteuning in het OS nodig omdat de bitjes wel gezet moeten worden.
Geen expert in dit soort zaken, dus flame me maar weg als dit dom gezeik is.
Er is echter wel ondersteuning in het OS nodig omdat de bitjes wel gezet moeten worden.
Dus als iemand een exploit vindt in het gedeelte van het OS dat deze bit ondersteunt. Zijn we dan gewoon weer terug bij af?
Je kan bijvoorbeeld die bit ook weer uitzetten en toch weer een buffer overflow maken?
Waarom doen ze niet het volgende.
Alle data in geheugen.
Alle exe in procesor cache?
Die bit uitzetten, dan zou je toch wat meer moeten doen dan alleen het OS kraken.

Met dit NX-bit kun je ook eigenlijk alleen de simpelere buffer overflows tegenhouden. Maar dat zijn wel de meest voorkomende tegenwoordig.


[quote]Alle data in geheugen.
Alle exe in procesor cache?[quote]

Omdat je de executable code eerst vanaf storage moet halen en dat gaat meestal via het geheugen.
Verder zijn er ook zat applicaties die niet in de cache van de processor passen.
Als laatste heb je dan ook nog dat de data die je wilt gebruiken alleen in de registers aangepast kan worden en om die data daar te krijgen gaat dat gebruikelijk via de cache.
Het flat memory model wordt gebruikt omdat dat gewoon makkelijker is om mee te programmeren, geen geknoei met allemaal segment registers die elk weer een verschillend deel van het geheugen aanspreken.
paerad heeft dus gelijk als hij zegt dat Windows OS programmeurs er niet voor hebben gekozen omdat het dan complexer wordt.

Natuurlijk is dit al wel een verbetering ten opzichte van geen beveiliging, maar het OS is toch voor het grootste gedeelte verantwoordelijk. Dit mag geen excuus voor slechte code worden.
Je kan data en instructies nooit scheiden. Een CPU zal steeds de waarden uit het geheugen moeten laden, en dat is trager dan de cache. Ook instructies komen in het geheugen terecht omdat de cache te klein is om een heel programma in te laden.
Je idee zou wel handig zijn, maar dan heb je een nieuw type CPU nodig die instructies en gegevens in een apparate cache steekt, dat lijkt mij wel mogelijk en als je nu dan toch al NX invoert, heb je niet zo'n groot voordeel daaraan.
paerad heeft dus gelijk als hij zegt dat Windows OS programmeurs er niet voor hebben gekozen omdat het dan complexer wordt.
Welk modern OS gebruikt geen flat memory model dan?
Dus als iemand een exploit vindt in het gedeelte van het OS dat deze bit ondersteunt. Zijn we dan gewoon weer terug bij af?
Je kan bijvoorbeeld die bit ook weer uitzetten en toch weer een buffer overflow maken?
Dat kan in theorie. Een CPU maakt echter niet alleen onderscheid tussen code en data, maar ook tussen kernel-geheugen en user-geheugen (voor applicaties). Er is hardwarematige bescherming tegen het overschrijven van kernel-geheugen vanuit een applicatie. Een goed OS laat applicaties die onder een gewoon user-account draaien niet zomaar bij kernel-geheugen komen.
Waarom doen ze niet het volgende.
Alle data in geheugen.
Alle exe in procesor cache?
Omdat een cache dan zo groot wordt dat het geen cache meer is. Als je exes in de processor cache kan proppen, dan kun je ook rottigheid uithalen. Omdat er al voldoende bescherming is voor code, maar deze bescherming niet goed wordt gebruikt.
Welk modern OS gebruikt geen flat memory model dan?
Geen enkel OS. Flatmemory model is een groot segment (32-bit), als de segment-registers eenmaal ingesteld zijn, zijn alleen offsets nog relevant. Hoewel in elk modern OS applicaties zich niet bezig hoeven te houden met segment-registers (omdat enkel die brakke x86-architectuur segment-registers heeft, iets dat stamt uit 16-bit tijden) is er geen sprake van flatmemory omdat elk moderne OS gebruik maakt van paging.
Een buffer overflow zorgt dat er te veel data geschreven wordt naar een variable (bijvoorbeeld een string waar maar voor 32 karakters plaats is, maar waar 100 karakters naar geschreven worden - doordat de programmeur de lengte niet goed controleert).

Door in die extra data geen string maar code te stoppen kun je dus willekeurige code in iemands computergeheugen plaatsen.

Als nu de code zover te krijgen is dat hij dat stukje geheugen gaat uitvoeren, dan heb je dus een beveiligings probleem.

Omdat veel functies in programma's gebruik maken van 'tijdelijk' geheugen op de stack, die ook gebruikt wordt om adrespointers op te slaan kan het zijn dat de processor na het uitvoeren van een functie terugspringt naar deze foutieve code (het oorspronkelijke retour-adres is immers overschreven met de 'foutieve' code).

Door nu het bewuste geheugen (in dit geval de stack) te markeren als 'data' geheugen in plaats van 'code' geheugen wordt op deze manier duidelijk gemaakt dat het stack-geheugen alleen voor data is, en zal de processor ophouden zodra de sprong naar de foutieve code gemaakt wordt.

Zo wordt dus een beveiligingslek dichtgemaakt.

(edit: zoals mijn voorganger zegt kan het ook zijn dat zoveel data geschreven wordt, dat het in een 'code' segment terecht komt. Er wordt dan bijvoorbeeld een bestaande functie overschreven met 'foutieve' code. Echter is die code dan niet gemarkeerd als 'no execute' waardoor het nog steeds fout kan aflopen. Gelukkig is de kans dat er over bestaande code geschreven wordt als vanuit een data-segment begonnen wordt vrijwel nihil (als ik het goed heb is data en code normaal gescheiden in segmenten zodat dit een geheugenfout oplevert). Het moet dus vooral zitten in het beveiligen van de stack-ruimte zodat executable code die daar in terecht is gekomen in ieder geval niet uitgevoerd wordt.

(Blijft een feit dat de programmeur een bug in zijn programma heeft zitten die er uit zou moeten)
Yeah right..

alsof de gemiddelde programmeur enig idee heeft hoe zijn programma er in real-time uit ziet (die-hard c of assembly freaks uitgezonderd }>).

Besides zaken als segmenten en dergelijke bestaan niet meer sinds de introductie van een modern 32bit OS. Je hebt het hier over een flat memory address space en niet over verschillende segmenten - that's a thing of the past.
De no-execute optie is dan ook iets voor een OS om te regelen in niet snel iets voor een applicatie (imho).
Dat is dan ook meteen de reden om WEL in assembler of platter gezegt machinecode te programmeren. (Of om daar iig een zekere kennis over op te doen)

Volgens mij missen de hedendaagse programmeurs een zekere basiskennis voor het werken met de MACHINE, en zijn ze te veel geleid door de status van hun gereedschap, nl de (programeer)taal.

Ik programmeer nog maar zelden, maar ben begonnen met BASIC, heb me daarna grondig in assembler verdiept, en zodoende een grondige kennis van het werken van een CPU verkregen. Voor 'gewoon' gebruik gebruik ik TP (quick'n'dirty dingen) Delphi. Als het echt op de bit aankomt is assembler echt mijn ding.

De bufferoverflows die op diverse plekken hier beschreven worden, zijn imo dingen die relatief eenvoudig (door goed proggen) te voorkomen zijn. In welke taal dan ook, al moet je bij de meer bij de machine staande talen wel steeds beter daarbij nadenken.

Ik ben wel voor de nieuwe HW technieken, maar ze zijn eerder een oplossing voor 'sloppy' coden, dan voor een niet bestaande bug.
als ik het goed heb is data en code normaal gescheiden in segmenten zodat dit een geheugenfout oplevert
Nee, meestal aliased het naar hetzelfde stukje geheugen. Op die manier kun je dus via cs het stukje code executen wat je zojuist via ds geschreven hebt (dit kan handig zijn omdat je niet via cs kunt schrijven, alleen soms heeft het dus ook nadelen ;))
Dat flash-filmpje is gewoon reclame voor Microsoft en Intel, bevat weinig technische informatie. In dat filmpje worden maatregelen op de CPU aangedragen als oplossing voor beveiligingsproblemen, maar het ligt toch echt in de software. Als softwaremakers goed programmeren, is er niks aan de hand en hoeven consumenten geen nieuw spul te kopen om veilig te zijn. Imho veel misleiding hier.
Zo'n hardware-aanpassing (disable-bit) zorgt ervoor dat buffer-overflows niet meer gebruikt kunnen worden als lek om virussen te verspreiden. Dus als in de toekomst meer lekken ontdekt worden, kunnen ze niet meer gebruikt worden om miljoenen schade te veroorzaken.
En zolang mensen blijven programmeren, zal software nooit perfect zijn.
Ik blijf er bij, je moet goed programmeren.
Uiteraard bestaan programma's zonder bugs niet, maar buffer overflows zoals we de laatste tijd zien, bv. via JPEGS, laten zien dat programmeren tegenwoordig steeds haastiger en slordiger plaatsvindt. Zo'n protectie-bit is dan pure symptoombestrijding. Verklaringen genoeg. Bv. het feit dat op veel opleidingen mensen eerder Java leren dan C. Of zelfs beginnen met PHP. Zo wordt je meteen al verwend met garbagecollectors e.d. Terwijl het juist zo belangrijk is om te leren al je gereserveerde geheugen vrij te geven, objecten opruimen, etc.

Naast het argument van symptoombestrijding heb ik nog een belangrijker argument tegen de noodzaak van een NX-bit: De huidige protectiemachanismen bieden op dit gebied al voldoende. De NX-bit is alleen maar meer van hetzelfde. Als OS-kernels hun codesegmenten exact zo groot maken als nodig, dan is er niks aan de hand. Daarnaast moeten datasegmenten exact zo groot zijn als nodig. Als dit in orde is, dan zal iedere poging om code te overschrijven resulteren in een exception en zal het programma gestopt worden.

En voor wie mij niet gelooft en mijn bovenstaande post (waarop erkje heeft geantwoord) beschouwd als flame, troll, overbodig o.i.d.: Lees voor de aardigheid eens een boek over hoe een x86 CPU werkt, dan snap je het tenminste. 99% van de lezers en modders hiero weten niks van GDT's, segment-selectors, paging, traps en faults. Online leesvoer: http://www.x86.org/articles/pmbasics/tspec_a1_doc.htm
Haastiger en slordiger programmeren heeft meer te maken met idiote deadlines en een gebrek aan controle/disipline dan aan verweningen als garbage collerctors e.d.

Een hogere orde taal gebruiken zou hier eerder een oplossing kunnen zijn dan een probleem.
Je kunt namelijk in de implementatie van de taal al de protectiemechanismen inbouwen, zodat je het ook niet meer kan vergeten.

Codesegmenten exact zo groot maken als nodig is trouwens ook niet een oplossing omdat het niet de grote van de buffer maar juist het schrijven buiten de grote van de buffer (en dus in programmacode) het probleem is.

Dat hardware probeert typische software problemen op te lossen door twijvelachtige constructies zoals het NX-bit vind ik trouwens ook niet zo mooi. Maar ja, hardware boeren willen ook verkopen en hardware staat minder beken om zijn bugs, dus dit soort dingen word al rap opgepikt.
Haastiger en slordiger programmeren heeft meer te maken met idiote deadlines en een gebrek aan controle/disipline dan aan verweningen als garbage collerctors e.d.

Een hogere orde taal gebruiken zou hier eerder een oplossing kunnen zijn dan een probleem.
Idiote deadlines of niet, dit is onafhankelijk van hoe de dicipline is. Of ontwikkelaars nu veel of weinig tijd hebben, zelden zie ik ze hun code regel voor regel langslopen op boundary checks. Als er tijd over is, wordt er een extra feature ingebouwd die niet nodig is en als er tijd te weinig is, is dat de oorzaak.

Ook een hogere orde taal zal hier niets aan verbeteren en zorgt juist eerder voor een grotere luiheid. Enkel heb ik wel eens het gevoel dat assembler modules beter in elkaar zaten als de hedendaagse oplossingen (die ook veel complexer zijn).

Het besef moet van hoog naar laag maar eens doordringen dat elke programma joekels van fouten bevat. Elke range (van string naar enorme database) moet gewoon altijd gecontroleerd worden ... regelmatig moeten er extra controlles plaatsvinden of een module wel eens logischer wijs mag worden opgestart. Het nadeel is dan dat de hoeveelheid code enorm toeneemt.

Net zo als de meest ontwikkelaars een ontwerp maken, zouden ze ook eens een risico analyse moeten inbouwen van gevaarlijke software punten. De onwil op dit punt ligt vaak niet bij het management maar bij de ontwikkelaar zelf omdat dit minder interessant werk is.
Al hoewel het op het oog een goede zet lijkt, denk ik dat AMD & Intel het eerder er inzetten om de verkoop van CPU's te stimuleren dan als exclusieve beveilegings feature.

Als je straks de nieuwste database wil instaleren, word er wel bijverteld dat je ook een CPU/PC moet hebben die deze features ondersteund want anders ondersteund hun helpdesk jou niet meer. Omdat hun software/patch afdeeling niet meer debugged voor niet NX/DB-bit chips.
Is wel makkelijk gezegd, maar zolang programmeurs nog vrolijk in C en C++ met pointers door blijven knutselen en de meest ranzige code hiermee schrijven, blijf je buffer overflows houden.

Als bij mij op school wordt geleerd om het volgende stukje code te schrijven:

void main() {
int aantal, i=1;
cin >> aantal;
while (i < aantal) {
printf("%d", aantal);
i++;
}
}

dan zie je toch zelf ook wel in dat je een infinte loop te wachten staat op het moment dat iemand daar een negatief of enorm groot getal, of nog erger, een string ingooit op de stdin?

Talen als java slaan je meteen om de oren als je bovenstaande doet, talen als C++ vinden het heel gewoon dat je een stream zo in een integer drukt, er is vast wel een convertor voor die de gare string naar een int weet te converteren.

Overigens hebben we bovenstaande ook een keer mogen toepassen bij een char buffer[12] en daar meteen met cin in proppen, heerlijk op het moment dat er 13 stuks in gaan ;)

De i386 instructieset heeft al sinds het begin mogelijkheden om een geheugengebied als data of als codegeheugen aan te duiden, echter werd hier nooit veel mee gedaan. Met de hardwarematige protectie in CPUs is het een kwestie van bitje omzetten en de CPU weigert code in datasegmenten uit te voeren. Niet alleen is het feilloos, het is ook nog eens een stuk sneller om de check in hardware te doen. Overigens kan windows XP SP2 deze truc ook zonder NX ondersteuning doen, het gaat alleen iets trager. Linux heeft dit soort ongein al tijden mbv kernelpatches als PaX en Grsecurity. Veel hiervan is afgekeken uit OpenBSD, welke dit soort technieken al sinds de oertijd ondersteunt.
en das nou net weer de kracht van C/C++
je KUNT alles doen wat je wilt. En das toch ook heel de bedoeling hiervan?

Heb je echt belangrijke software, die je door MBOer of slechte HBOer laat maken, kun je dat dan het beste in java laten doen zodat je minste problemen hebt.

Als je fatsoenlijk programeert doe je dat gewoon lekker in C. Is netjes mooi en eigenlijk wel simpel als je weet wat je doet.

Das ook btw ff belangrijk, weten wat je doet. Het is belangrijk dat je verstand van je vak hebt. Je moet weten wat je doet. Ik breng mijn auto (die ik niet heb) ook niet naar Harries Auto Worksjop omdat ie goedkoper is. Kans is vrij groot dat je auto er straks erger aan toe is dan dat je hem heenbracht. Kwaliteit komt van kennis. Niet door tools alles voor je te laten doen. Das gewoon lomp en had je beter een ander vak kunnen kiezen.
Heb je echt belangrijke software, die je door MBOer of slechte HBOer laat maken, kun je dat dan het beste in java laten doen zodat je minste problemen hebt.

Als je fatsoenlijk programeert doe je dat gewoon lekker in C. Is netjes mooi en eigenlijk wel simpel als je weet wat je doet.
Je zegt zelf dat je bij programmeren in java het 'minste problemen hebt'. Waarom zou je dan NIET voor java kiezen? Alleen voor de hogere patsfactorvan C?

Als je voor C kiest omdat jij daar gewoon beter mee kan omgaan dan heb je groot gelijk, en moet je dat vooral doen. Maar als je voor C kiest omdat 'java voor n00bs is' dan ben je toch echt verkeerd bezig hoor.
Heb je echt belangrijke software, die je door MBOer of slechte HBOer laat maken, kun je dat dan het beste in java laten doen zodat je minste problemen hebt.
Zie voor diverse Java vacatures dat men mensen met een universitaire opleiding vragen (of toppers van HBO).

C++ en Java hebben beiden hun krachten, voor- en nadelen.

Ikzelf ben eigenlijk beetje met Java opgeleid, door zeer slechte/saaie/weinig les in C++ vind ik die taal ook niet leuk. Mijn voorkeur als hbo'er gaat persoonlijk dan ook uit naar Java (en C#).
Als je fatsoenlijk programeert doe je dat gewoon lekker in C. Is netjes mooi en eigenlijk wel simpel als je weet wat je doet.
Je beargumenteerd ook niet echt lekker, ik zou ook kunnen zeggen:
C++ bestaat nu alweer zo lang, het wordt tijd dat we gaan moderniseren en met nieuwere en moderenere talen aan de slag gaan, zoals Java en C#.
Dit is een van de eerste onderdelen van basis programmeren om de propositielogica te leren, en de excepties ook te ondervangen ja. Echt belangrijk is dit niet en eerlijk gezegd mis ik de relevantie t.a.v. DOS attacks.

Je kan het wel op fout programmeren gooien, of menselijkheid, maar wat betrefd veiligheid: ieder slot op elke deur is te openen, de betere sloten duren gewoon langer om te openen.

Niets is potdicht te krijgen.

laatste oneliner:
echt hacken is saai.
Het gros van de code in deze wereld wordt gehacked door mensen die geen jota van propositielogica afweten.
Talen als java slaan je meteen om de oren als je bovenstaande doet, talen als C++ vinden het heel gewoon dat je een stream zo in een integer drukt, er is vast wel een convertor voor die de gare string naar een int weet te converteren.
Wat heeft dat met de infinite loop te maken?
Alsof je in Java geen infinite loops kunt creeeren.

Een negatief getal (zoals -1) geeft trouwens helemaal niet direct problemen. Een heel groot positief getal geeft ook geen probleem.

Op welke school zit jij?
De i386 instructieset heeft al sinds het begin mogelijkheden om een geheugengebied als data of als codegeheugen aan te duiden, echter werd hier nooit veel mee gedaan.
Dat komt omdat i386 dat alleen op segment niveau kan en (vrijwel) alle moderne OSs gebruik maken van een flat memory space zonder segment.
Op page niveau had je nog geen execute bit (wel write en ik gok ook read).
Volgens mij is het gewoon marketing (en slechte compilers).
En van de voordelen van de Intel processoren was de segment registers. En je kon dus meerdere registers gebruiken bv eentje voor data, eentje voor coding. Bij de modernere processoren (dus na de 8088) kon je, als je dat wilde in het OS alles al goed regelen.
Je hebt bv bij 386 (ouwetje) een segment descriptor die grofweg bestaat uit een base adress, een limiet, en attribute (bv. readonly, executable). Dus je kom als je dat in assembler goed deed ale heel goed executable code, data scheiden. Helaas was er ook ineens 4Gb aan ruimte waardoor men, in tegenstelling tot 286, 1 register ging gebruiken voor het programma. Tja en dan kun je niet meer zeggen dit stuk is code, en dat stuk is data.
De Opa's onder ons weten nog het verschil tussen .com (1 adres ruimte voor code en data) en .exe files. Wellicht zijn er nog die weten dat je allerlei memory modellen kon gebruiken (/AL /AH etc).

Met de 386 is alles weer op n hoop gegooid en alle gevolgen vandien.

M.a.w. deze beveiliging is met een goed OS en goede compilers al 15 jaar mogelijk.
Windows Server met SP1
Welke Windows Server? Ik neem aan 2003?
Zou dan SP2 voor windows XP wel werken met de intel cpu's aangezien er nogal problemen zijn met de AMD 64?
Dat vind ik de juiste conclusie, dat ik in een eerder post pagina met segment verwisselde en een hoos reacties van oisyn . Lees het artikel in CT magazine, daar wordt dit in bevestigd.
En het gaat hier om de ontwikkelaars van het OS die voor de flat modus kozen, missen mooie features die al in de 386 bestonden!

*mijn statement sloeg dus wel ergens op, negatief score vind ik dan ook belachelijk!
En zon techniek hebben hedendaagse processoren al, dit kennen we uit het dos tijdperk: protected mode. Geheugen opgedeeld in paginas, hierin kan je per geheugen pagina opgeven wat zon pagina mag (read/write/execute).

Maar omdat de windows os ontwikkelaars zo programmeren ingewikkeld vinden, is er gekozen voor flat-memory en dus 1 instelling voor all. Niet veilig meer. En nu komen ze met iets anders, het no-execute flag...

(lees hiermeer over in CT-magazine)
Blaat, dit slaat nergens op.

Het flat memory model wordt gebruikt omdat dat gewoon makkelijker is om mee te programmeren, geen geknoei met allemaal segment registers die elk weer een verschillend deel van het geheugen aanspreken.

Per pagina aangeven wat die pagina is heeft nooit gekunt op 386+ processoren, je kunt slechts per segment descriptor aangeven wat ermee gedaan kan worden (read, write, execute). Dat werkt echter op het gehele stuk geheugen dat door de descriptor wordt beschreven, en dus niet per pagina. Dan moet je denken aan een complete scheiding van data en code segmenten, wat programmeertechnisch niet handig is, mede omdat je soms ook gewoon code wilt runnen uit het datasegment.

Deze feature maakt het echter mogelijk om het per pagina op te geven, een page die niet gemerkt is als executable geeft een fijne exception als je er naartoe springt.

Op dit item kan niet meer gereageerd worden.



Apple iOS 10 Google Pixel Apple iPhone 7 Sony PlayStation VR AMD Radeon RX 480 4GB Battlefield 1 Google Android Nougat Watch Dogs 2

© 1998 - 2016 de Persgroep Online Services B.V. Tweakers vormt samen met o.a. Autotrack en Carsom.nl de Persgroep Online Services B.V. Hosting door True