AndroidApp

Als je nieuwsgierig bent aangelegd, is het leuk om te weten wat een bepaalde apps op je Android device allemaal versturen en ophalen van het internet. In dit artikel vindt je alles om dat voor elkaar te krijgen.

In de tijd vóór Android 6, was het relatief makkelijk om app verkeer ‘af te luisteren’ en wel om 2 redenen: In het verleden werd vaak gewone, onversleutelde HTTP gebruikt in plaats van HTTPS. Als tweede hadden het apps die wel HTTPS gebruikte geen moeite met een willekeurige onvertrouwde CA.

HTTP in plaats van HTTPS

Veel apps communiceerde in het verleden zonder problemen onversleuteld, dus gewoon via clear text HTTP. Sinds de laatste versie van Android kan dit niet meer zomaar. Je kunt alleen nog ‘gewone’ clear text HTTP gebruiken als je de configuratieinstellingen aanpast in je app, Bij iOS was dat trouwens al langer het geval.

HTTPS met onvertrouwd Root-CA-certificaat

Tot en met Android 6 was het gemakkelijk om een Man-In-The-Middle in te zetten om mee te luisteren met het HTTPS verkeer van je mobiele device. Het komt er simpelweg op neer dat je al het verkeer van je smartphone via een door jezelf gecontroleerde proxy laat lopen. De proxy doet zich voor als de HTTPS server waar de app mee wil praten. Je kunt met zo’n proxy al het verkeer meelezen. De proxy geeft dit verkeer dan weer door aan de ‘echte’ webservice. De proxy presenteert zijn eigen SSL certificaat aan de app, gemaakt mijn zijn eigen onvertrouwde Root CA.  Dit was mogelijk omdat in de oudere Android versies elk Root CA certificaat werd geaccepteerd. Hieronder meer daarover.

>= Android 7 HTTPS

Om verkeer van apps mee te kunnen lezen op een modern Android OS, moet je met wat meer geschut inzetten. Wat is er dan veranderd in Android 7? De beveiliging is op verschillende manieren verbeterd, waaronder die voor SSL verbindingen.

Alleen vertrouwde Root CA’s

Vanaf deze versie controleert Android het root-CA certificaat waarmee het SSL certificaat is getekend. Android accepteert alleen vertrouwde Root-CA certificaten. Is het SSL certificaat van een HTTPS verbinding getekend met een onbekende CA, dan blokkeert het Android OS de verbinding.

De proxy heeft geen vertrouwd Root CA-certificaat

Een Man-In-The-Middle proxy levert SSL certificaat via zijn eigen, zelfgemaakt, Root CA-certificaat. Dit CA-certificaat wordt NIET vertrouwd. Dus, meelezen kan alleen, als je Android of de de app zover krijgt een willekeurig Root-CA certificaat te accepteren.

Kortom, de missie is dus om de app, waarvan we de communicatie mee willen lezen, zover te krijgen elke Root-CA te accepteren, dus ook die van onze proxy. Daarvoor moet de source code van de app worden aangepast. Hoe je dat doet lees je hieronder.

Het aanvalsplan

  1. App sources bemachtigen.
  2. App sources aanpassen.
  3. App signen en installeren
  4. Meeluisteren via proxy

1. App sources bemachtigen

Benodigde tools:

  • Chrome Browser
  • Chrome Extensie: APK Downloader

Om bij de source code van de app te komen moeten we eerst zorgen dat we het APK bestand te pakken krijgen. Dit is het uitvoerbare bestand dat Android gebruikt om een app te kunnen starten. Via de stappen hieronder kom je gemakkelijk aan de APK van de app die je op het oog hebt:

  1. Start je Chrome browser
  2. Installeer de APK Downloader extensie in Chrome
  3. Gaan naar de Google Play Store
  4. Zoek de app die je op het oog hebt voor je afluisterpraktijken.
  5. Klik op de app zodat de pagina met app details wordt geopend op de Google Play Store.
  6. Kopieer de url uit het browservenster.
  7. Open de APK Download extensie rechts boven in Chrome.
  8. Plak de url. (in mijn geval: https://play.google.com/store/apps/details?id=com.funda.two voor de Funda app).
  9. Klik op: “Generate Download Link”
  10. Klik daarna op: “Download APK”

Nadat je de APK hebt gedownload kunnen we aan de slag om bij de source code te komen.

Benodigde tools:

De source code verkrijgen van de app gaat als volgt:

  1. Download Apktool van deze site. Met deze tool kunnen we de zojuist gedownloade APK ‘uitpakken’.
  2. Volg de installatieinstructie op de website van Apktool.
  3. Nu voeren we de volgende code uit in de directory waar de APK staat: apktool d <Gedownloade APK> -f
  4. Het resultaat:
    apktool d <Gedownloade APK>.apk -f
    I: Using Apktool 2.4.1 on com.funda.two.apk
    I: Loading resource table...
    I: Decoding AndroidManifest.xml with resources...
    I: Loading resource table from file: C:\Users\ton.snoei\AppData\Local\apktool\framework\1.apk
    I: Regular manifest package...
    I: Decoding file-resources...
    I: Decoding values */* XMLs...
    I: Baksmaling classes.dex...
    I: Baksmaling classes2.dex...
    I: Baksmaling classes3.dex...
    I: Copying assets and libs...
    I: Copying unknown files...
    I: Copying original files...
    I: Copying META-INF/services directory
    Press any key to continue . . .
  5. In de folder is nu een directory aangemaakt met de inhoud van de APK.
  6. Je kunt nu ook de source code van de app bekijken. Als deze niet is ge-obfuscate is daar al best wat interessants terug te vinden. Voor ons doel is dit overigens niet belangrijk.

In de volgende paragraaf gaan we de source code aanpassen om te zorgen dat ‘custom’ CA certificaten worden geaccepteerd. Daarna bouwen we de APK opnieuw.

2. App sources aanpassen

We gaan nu de app aanpassen zodat custom certificaten worden geaccepteerd.

Tools:

Het aanpassen van de APK gaat alsvolgt:

  1. Open met Visual Studio Code de folder met de uitgepakte APK.
  2. Als het volgende bestand: res/xml/network_security_config.xml nog niet bestaat maak het dan aan.
  3. Maak dit bestand aan met de volgende inhoud of voeg toe:
  4. <network-security-config>
     ...
     <base-config>
       <trust-anchors>
         <certificates src="system" />
         <certificates src="user" />
       </trust-anchors>
     </base-config>
     ...
    </network-security-config>

    Hiermee geven we aan dat ook “user” SSL-certificaten moeten worden geaccepteerd. Dus certificaten die zijn getekend met een onvertrouwde CA.

  5. Voeg het attribute “android:networkSecurityConfig” aan het AndroidManifest.xml in de app sources.
  6. <application … android:networkSecurityConfig=”@xml/network_security_config”>

Alle aanpassingen zijn nu gedaan in de app.

3. App signen en installeren

Om te zorgen dat de app weer geïnstalleerd kan worden op een Android apparaat, moet de een nieuwe APK-bestand gemaakt worden. Daarna moet het APK-bestand worden getekend met een zelfgemaakt certificaat.

Benodigde tools:

  1. Een nieuwe APK bouwen met apktool:
    1. Open de directory waarin de app staat.
    2. Voer de volgende opdracht uit: apktool b -f
    3. In de /dist directory staat nu het nieuwe APK-bestand.
  2. Certificaat maken voor het tekenen van het APK-bestand.
    1. Voer het volgende commando uit keytool -genkey -v -keystore release-keystore.keystore -alias release_key -keyalg RSA -keysize 2048 -validity 9999. keytool is onderdeel van de JRE of JDK. Op Windows is deze terug te vinden onder c:\Program Files\Java\<JDK_of_JRE versie>\bin
    2. Voer willekeurige gegevens in op de vragen die voorbijkomen bij het maken van het certificaat.
    3. We hebben nu een bestand met de naam: release-keystore.keystore. Deze bevat het certificaat: release_key, waarmee een handtekening wordt gezet op het APK-bestand.
  3. De handtekening zetten.
    1. Voer het volgende commando uit: jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore release-keystore.keystore <NAME>.apk release_key. Jarsigner is onderdeel van de JDK. Op Windows is deze terug te vinden onder c:\Program Files\Java\<JDK_versie>\bin
    2. Het APK-bestand is nu klaar. Voor de zekerheid controleer je de datum van het APK-bestand.
  4. Het APK-bestand installeren
      1. Start Android Studio.
      2. Open: Tools > AVD Manager
      3. Start 1 van de emulators in de lijst of maak een emulator aan.
      4. Als de emulator helemaal is opgestart kun je het APK-bestand vanaf de folder op je PC naar de emulator slepen.
      5. De APK wordt automatisch geïnstalleerd.
      6. Uiteraard kun je het APK-bestand ook op een fysieke smartphone installeren

4. Meeluisteren via proxy

In deze sectie gaan we actief meeluisteren naar de app die we zojuist hebben aangepast.

Benodigde tools:

We gebruiken Charles Proxy om mee te luisteren met het HTTP verkeer. We leggen hieronder uit welke stappen je moet nemen. Fiddler is trouwens ook een goed alternatief, die stappen beschrijven we hier niet. Al zal de procedure ongeveer dezelfde strekking hebben.

  1. Start Charles Proxy op.
  2. Open het menu: SSL Proxying > Install Charles Root Certificate on Mobile Device or Remote Browser.
  3. Ga nu op de Android emulator naar het settingsscherm.
  4. Kies “Network & Internet”
  5. Kies “Wi-Fi”
  6. Kies het actieve Wi-Fi. Voor de emulator is dat “AndroidWifi”.
  7. Druk op Edit.
  8. Druk op Advanced options.
  9. Kies als proxy: “Manual”
  10. Vul de gegevens in zoals Charles Proxy aangeeft.
  11. Open nu de browser op de emulator en ga naar http://chls.pro/ssl
  12. Download het bestand. Dit is het CA-certificaat van Charles Proxy.
  13. Geef het certificaat de naam “Charles”.
  14. Kies voor Credential Use: “VPN and Apps”.
  15. Start de app op de emulator
  16. Bekijk in Charles het netwerkverkeer.
  17. Vergeet niet de domains toe te voegen aan Charles Proxy die de app gebruikt om te communiceren. Anders zie alsnog alleen ge-encrypte berichten voorbijkomen. Dit doe je door de domains toe te voegen via Proxy > SSL Proxying Settings >. Wildcards zijn toegestaan zoals *.<domain.com>.

That’s it, het meeluisteren kan beginnen. Het lijkt een lang verhaal, maar als je dit een paar keer hebt gedaan is het prepareren van een app op deze manier een fluitje van een cent. Als app-maker, zie je hier dus ook dat alle verkeer tussen app en server kan worden afgeluisterd. Dit kan echter alleen als de afluisteraar controle heeft over het mobiele device dat hij wil afluisteren. In alle andere gevallen biedt SSL gewoon de gedegen beveiliging tegen afluisterpraktijken.

P.S. Certificate pinning

Het kan voorkomen dat het meeluisteren op deze manier toch niet lukt. Dit kan het geval zijn als de app gebruik maakt van certificate pinning. De app verwacht dan een specifieke vaste CA of een vast SSL certificaat. Dit is op een andere manier op te lossen maar dat valt buiten de scope van dit artikel.

Bonus: Source code lezen

Als je benieuwd bent naar de source code van een app, download dan ByteCode Viewer. Dit is een tool waarmee je APK-files kunt disassemblen. De code is niet meer compileerbaar, maar wel leesbaar. Het gebruik daarvan is zo simpel als opstarten en de APK in de UI slepen.

veilige wachtwoorden
Securityvoor dummies

Even een ‘accountje’ maken doen we bijna dagelijks. Er is geen dienstverlener die zonder kan. De tentakels van de AVG zijn nog niet zo ver doorgedrongen dat ook dat aan banden wordt gelegd. Veilig wachtwoord? het hoort wel, en vinden het ook nodig, maar we doen het gewoon niet. Te veel gedoe, moeilijk te onthouden en dus onhandig. Misschien helpt het echte antwoord op het grote “Waarom dan?” om je gedrag aan te passen. Er zit meer achter dan je op het eerste gezicht zou denken. En bovendien heb je met de onderstaande info heb je ook iets leuks bij te dragen aan je buren op het komende buurtfeestje.

In de begindagen van het internet werkte het maken van een account alsvolgt. Je gaf een gebruikersnaam en wachtwoord drukte op OK en de dienstverlener sloeg allebei netjes, zonder verdere aanpassingen, op in een database. Stel je een database voor als een Excel sheet met een lijst met gebruikersnaam en wachtwoorden van alle accounts die ooit werden aangemaakt.

Allemaal prima zolang de database ontoegankelijk is voor buitenstaanders. Maar, wordt het systeem van de dienstverlener gehackt, dan betekende dat alle gebruikersaccounts met gebruikersnaam en wachtwoord direct beschikbaar zijn voor de aanvaller.

Wat bedacht men toen: we gaan wachtwoorden niet meer in clear tekst opslaan, maar “Hashen”. Een zogenaamd cryptografisch valluik mechanisme (in het engels een trap door genoemd). Je stopt willekeurige data, zoals een wachtwoord, in een stukje wiskundige software, het hashing algoritme, dan komt er aan de andere kant een stukje data dat er heel anders uitziet, een “hash“. Stop je er hetzelfde wachtwoord in, dan komt iets onherkenbaars uit, maar wel altijd hetzelfde, uit. Deze hash kan echter nooit meer worden herleidt naar de invoer. Stoppen we het wachtwoord: "12345678" in de hash-software, dan komt daar het volgende uit: "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f". Je kunt het zelf proberen op deze website.

Alle wiskundigen bevestigen het "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f" is op geen enkele manier terug te herleiden naar 12345678. Welnu, een dienstverlener die zijn zaakjes op orde wil hebben zorgt dus dat zijn database er voortaan zo uit ziet.

Maar hoe kun je dan nog inloggen? Hoe weet de dienstverlener dat “12345678” bij de opgegeven hash hoort? Dat is eigenlijk heel simpel. Voordat de dienstverlener controleert of je wachtwoord klopt stopt hij het door jou opgegeven wachtwoord eerst in de hash-software. Als de uitkomst (hash) overeenkomt met de hash van jou wachtwoord in de database, dan heb je blijkbaar het goede wachtwoord ingevoerd. Het grote voordeel is, dat op deze manier de dienstverlener jouw wachtwoord niet hoeft te weten.

Mocht er een dienstverlener zijn die je ooit vertelt dat ze jouw wachtwoord wel even op kunnen zoeken, dan slaan ze dus blijkbaar jouw wachtwoord zonder hash op. Tegenwoordig is dat een praktijk die, met de komst van de AVG, strafbaar is geworden.

Maar “hashen” is ook niet alles…

Maakt het dan uit of je een moeilijk of makkelijk wachtwoord kiest? Ja, absoluut. In het verleden werden nog wel eens databases gestolen met niet-gehashte wachtwoorden. Men heeft van al die wachtwoorden een soort naslagwerk gemaakt: oneindig veel regels met Hash- en wachtwoordcombinaties. Voer een hash in, en het systeem zoekt het bijbehorende wachtwoord op. Uiteraard heeft men voor het gemak voor elke taal de woordenboeken in dit naslagwerk gestopt. Voor elk woord is een hash gemaakt. Zo’n naslagwerk wordt ook wel een Rainbow table genoemd. Deze zijn deels beschikbaar op internet of anders te vinden op het Dark Web.

Naast oude wachtwoorddatabases en woordenboeken, worden ook hashes berekent voor alle karaktercombinaties die mogelijk zijn. Men is begonnen met “a”, “b” … “aa”, “ab” etc… Het berekenen van die hashes kost tijd. Het berekenen van alle variaties voor lange wachtwoorden kost veel computerkracht en dus tijd. Aangenomen wordt dat er geen rainbow tables beschikbaar zijn voor wachtwoorden van 15 karakters en langer. Maar let wel, daarin worden alle karakters gebruikt die mogelijk zijn, dus ook “@(#&$)…0123…”. Dat betekent dus ook, dat er bestanden bestaan die langere wachtwoorden bevatten, maar minder variatie gebruiken, alleen cijfers en letters bijvoorbeeld. Het kiezen van een wachtwoord met bijzondere tekens is dus daarom heel belangrijk.

Kies je een wachtwoord dat in een rainbow table voorkomt, dan is het eigenlijk net alsof je wachtwoord in leesbare tekst in de database staat.

De gouden wachtwoordregels

  1. Kies geen woordenboekwachtwoord.
  2. Kies geen wachtwoord waarvan je weet dat dit al eerder kan zijn gebruikt door iemand anders.
  3. Kies of een heel lang wachtwoord als je geen bijzondere tekens gebruikt (meer dan 30 tot 45 karakters), Een zin bijvoorbeeld.
  4. Kies een korter wachtwoord (vanaf 15 karakters). Maar dan wel met meer dan alleen cijfers en letters.

…en nog iets

Je hebt het vast vaker gehoord: Kies voor elke dienstverlener een ander wachtwoord. Waarom? De bovenstaande eisen aan een wachtwoord zijn best flink. Je weet waarschijnlijk dat je wachtwoorden niet voldoen aan de bovenstaande eisen. De kans is dus groot, als er een hack plaatsvindt en jouw wachtwoord-hash wordt gestolen, dat de aanvallers met een rainbow table vlot je wachtwoord kan achterhalen. Ze zullen dan direct proberen geautomatiseerd bij andere diensten in te loggen met inloggegevens. Gebruik je hetzelfde wachtwoord overal, dan komen ze ook overal zonder problemen binnen met alle bijkomende gevolgen. Het wordt al anders als je aan de gouden wachtwoordregels voldoet. Maar dan nog is het een best practice overal een ander wachtwoord te gebruiken.

Hoe dan?

De moed zakt je misschien in de schoenen als je bedenkt dat je zulke lange moeilijke wachtwoorden moet gaan verzinnen en onthouden. Daarom kun je er voor kiezen om een wachtwoordmanager te installeren of een online dienst af te nemen die dat regelt. Je komt dan met 1 wachtwoord, bij al je andere wachtwoorden. Deze programma’s zijn in staat om moeilijke wachtwoorden voor je te maken en veilig te bewaren en bovendien vaak geautomatiseerd in te loggen. Een programma wat ik zelf altijd gebruik is KeePass Password Safe

Je emailaccount

Een ketting is zo sterk als de zwakste schakel. Je mailaccount is meestal de spin in het web van je veiligheid. Wachtwoord vergeten? Dan laat je je een password reset linkje mailen. Heeft een hacker toegang tot je mail account, dan kun je nog zulke veilige wachtwoorden kiezen voor al je diensten, meestal kan hij dan bijna overal bij. Zorg dus dat je e-mailaccount beter beveiligd is dan de rest. Het is geen overbodige luxe, een tweede factor toe te voegen. Hieronder meer daarover.

De tweede factor

In de security-wereld is beschreven dat je dingen kunt beveiligen met 3 factoren:

  • Iets wat je weet (bijv. een wachtwoord)
  • Iets wat je hebt (bijv. een Identifier van je bank) of
  • Iets wat je bent (bijv. vingerafdruk).

Om de beveiliging op te schroeven kun je, bij sommige dienstverleners, niet slechts 1, maar 2 factoren gebruiken voordat je toegang krijgt. Als je inlogt bij je bank heb je dat vaak al. Je hebt bijvoorbeeld een PIN (iets wat je weet) en een identifier (iets wat je hebt). Zonder die 2 kom je niet binnen. De aanvaller heeft allebei nodig en dat maakt een aanval een stuk moeilijker.

Een tweede factor instellen kan bij veel grote dienstverleners zonder veel moeite. Denk aan Microsoft, Google (gmail) of Amazon. De meestgebruikte tweede factor is een Authenticator App die je installeert op je mobiel. Deze genereert een 6 cijferige nummer dat je na het invoeren van je wachtwoord invoert bij de dienstverlener. Als allebei kloppen, dan ben je binnen.

Ben ik gehackt?

Of de sites van grote dienstverleners zijn gehackt en eventueel wanneer en wat er is gebeurd kun je terugvinden op de site van Have I Been Pwned:. Je kunt daar ook je gebruikersnaam / e-mail invoeren om te controleren of jouw account is gestolen via een gehackte dienstverlener.

Wat te doen als ik ben gehackt?

Als een dienstverlener gehackt blijkt te zijn en jij hebt daar een wachtwoord gebruikt dat je ook bij andere dienstverleners gebruikt? Zorg dan dat je een nieuw en uniek wachtwoord kiest voor elk van deze dienstverleners. Vergewis je ervan dat de betreffende accounts niet ook al zijn misbruikt. Als dat het geval is meld dit dan bij de dienstverlener.

Tot slot

Je kent nu het “waarom” van een veilig wachtwoord. Als je voor veilig gaat, help je daar jezelf mee, maar ook anderen. Want als bijvoorbeeld jouw e-mailadres niet wordt gehackt, kan er ook geen malware via jouw account naar anderen worden verspreidt. Een veilig internet begint dus bij jezelf.

Mocht je nog vragen hebben? Dan hoor ik dat graag. Er zijn geen domme vragen, dus kom maar op 😉

.NETC#Regex

Zoals je in het vorig deel hebt kunnen lezen is de regular expression tester te gebruiken om je regex kennis te praktiseren en expressies uit te testen.

Speciale karakters

Begin van een woord matchen

Het speciale karakter “\b” match een begin van een woord. Hebben we te doorzoeken tekst “Jan loopt met an in het bos met zijn os.” dan vinden we met de volgende reguliere expressie alleen een match op het woord “os”:

\\bos

Een match op de naam “an” maar niet op “Jan” (in dit voorbeeld zonder hoofdletters) verkrijgen we door:

\\ban

Om op elk woord een match te krijgen kan de volgende expressie worden gebruikt:

\\b\\w+

Match op alle karakters

De “.” staat voor een match van alle karakters behalve row breaks en new line karakters:

.+

Bovenstaande matcht de volledige tekst. Overigens heeft de punt (“.”) binnen een karakterklasse (“[.]”) geen speciale betekenis.

Carriage return, Line Feed en Tab

Carriage return en Line Feed worden binnen regex hetzelfde aangeduidt als binnen .NET strings.
De carriage return:

\\r

De line feed:

\\n

De tab:

\\t

Bij het matchen van meerder regels binnen een tekst zijn de karakters van groot belang.

Alternatieven (Alternation)

Binnen karakterklassen wordt er gematcht op karakters binnen de klasse. Dit werkt altijd als een OF. Buiten de klassen wordt standaard als EN gematcht. Een OF match maken op “maandag” of “dinsdag” of “woensdag” gaat via de volgende reguliere expressie:

(maandag|dinsdag|woensdag)

De haken groeperen de opdracht. De pipes (“|”) zorgen voor de OF instructies.

Case (in)sensitive

(?i)

Bovenstaande reguliere expressie maakt alles wat volgt case insensitive. De regulier expressie “(?i)jan” op de te doorzoeken tekst “Jan loopt in het bos” resulteert in een match op “Jan”.

(?-i)

Bovenstaande expressie heft case insensivity weer op.

Gretig of lui repeteren

Stel we hebben de tekst “Jan loopt in het bos. Hij speelt op zijn contrabas.” Als we elke zin willen matchen kunnen we de volgende reguliere expressie maken:

[a-zA-Z\\s]+

Dit zal resulteren in 2 resultaten (gebruik tab 2 in de test tool). Dit is een voorbeeld van greedy repetition. Het matchende resultaat wordt zo lang als mogelijk.
Voegen we echter een “?” aan het speciale repetitiekarakter (“+”) dan schakelen we over naar lazy repetition:

[a-zA-Z\\s]+?

Dit resulteert in 49 resultaten, voor elke letter en spatie 1 resultaat. Zodra er een match is is het afgelopen.

Vooruit en achteruit kijken

Het is mogelijk een match te maken op onderdelen in de tekst zonder ze mee te nemen in het resultaat. We hebben de tekst “Jan loopt in het bos.”. We willen een match op alles wat komt na de tekst “Jan”.

(?<=Jan).*

.* staat voor alle karakters. ?<=Jan is een lookbehind naar de tekst “Jan” zonder deze mee te nemen in het resultaat.
Willen we een match op alles wat komt voor de tekst “bos” dan gebruiken we de volgende regex:

.*(?=bos)

Een combinatie van beide is:

(?<=Jan).*(?=bos)

Alles tussen “Jan” en “bos” wordt gematcht.

Groeperen, verschillende resultaten in een keer matchen

In de tekst: “12 december 2010 19:34:44.999” zouden we bijvoorbeeld de dag en maand + het uur en de minuten kunnen halen. Groepen met namen zijn hier de oplossing. Zo kunnen in een keer op verschillende onderdelen van de tekst matches accuraat worden opgehaald. Dit is vooral handig bij het gebruik in .NET code. Een voorbeeld volgt iets verderop in dit artikel.

(?[1-9][0-9]{0,1}\\s[a-zA-Z]+)\\s[1-9][0-9]{3}\\s(?[1-9][0-9]{0,1}:[0-9]{2}):[0-9]{2}[.][0-9]{3}

De syntax ? binnen de ronde haken zorgt voor naamgeving van een groep. In .NET bevat elke match een groepcollectie waarin de namen en resultaten zijn terug te vinden.

Gebruik van reguliere expressies in .NET

Zoals in de eerste deel van de regex artikelen aangegeven bevindt de regex functionaliteit zich binnen .NET in de System.Text.RegularExpressions namespace. De methode die vooral worden gebruikt voor het valideren en zoeken in de class Regex zijn:

  • IsMatch(string Text, string RegexPattern) resultaat Boolean
  • Matches(string Text, string RegexPattern) resultaat MatchCollection object

Belangrijk is om NIET te vergeten de patterns te escapen:

^\\sbos.$

Wordt in code:

Regex.IsMatch("Jan loopt in het bos.", "\\\\sbos.$");

Bij het gebruik van de Matches functie wordt een MatchCollection object geretourneerd. Dit is een collectie met alle gevonden matches (Match objecten). De gevonden frase kan worden terug in de value property van het Match object.

MatchCollection AllMatches = Regex.Matches("Jan loopt in het bos.", "n"); 
foreach (Match m in AllMatches) 
{ 
  string Frase = m.Value; 
}

Zoals eerder genoemd kan het gebruik van groepsnamen heel handig zijn. In het derde tabblad van de regular expression tester kun je testen met groepen. Voorbeeld:

string text = "12 december 2010 19:34:44.999"; 
string regexPattern = "(?[1-9][0-9]{0,1}\\\\s[a-zA-Z]+)\\\\s[1-9][0-9]{3}\\\\s(?[1-9][0-9]{0,1}:[0-9]{2}):[0-9]{2}[.][0-9]{3}" 
MatchCollection Matches = Regex.Match(text, regexPattern); //er is 1 match 
int GroupCount = Matches[0].Groups.Count; //3 groepen, nl: 1. de gehele match, 2. Groep: DATUM en 3. Groep: TIJD) 
string Datum = Matches[0].Groups["DATUM"].Value; //of Matches[0].Groups[1].Value 
string Tijd = Matches[0].Groups["TIJD"].Value;

Conclusie

Er is nog veel meer te vertellen over regular expressions. Ik hoop dat dit helpt om een eind op weg te komen met regular expressions. Echt de puntjes op de spreekwoordelijke “i” ?. Het boek: Mastering Regular Expressions van O’Reilly vond ik heel leerzaam, het behandeld ook de toepassing van reguliere expressies in .NET.

Vragen of opmerkingen? Aarzel niet, elke reactie is van harte welkom!

.NETC#Regex

Om direct met de regels aan de slag te kunnen die we hieronder gaan bespreken is het handig de snoei.net Regex Tester te gebruiken. Denk nu vooral niet dat dit een hele spannende applicatie is. Het stelt weinig voor, net zoals het gebruik van reguliere expressies binnen het .NET framework.

Door veel softwareontwikkelaars worden regular expressions gebruikt voor de validatie van velden zoals e-mailadres, url, postcode etc… Voor het zoeken van gegevens in grote stukken tekst wordt regex over het algemeen minder gebruikt. De manier waarop regex wordt gebruikt verschilt in beide gevallen niet veel van elkaar. Op beide zijn dezelfde regels van toepassing. We beginnen met de uitleg voor het doorzoeken van tekst. Het valideren van gegevens is dan appeltje/eitje.

In de voorbeelden hieronder worden dubbele quotes (“) gebruikt om een bepaalde tekst, frase of regex aan te duiden. Neem deze dus niet mee in de tests.

Hieronder overzichtelijk een aantal voorbeelden met een stuk tekst en een regular expression om bepaalde gegevens uit de tekst te halen.

Voorbeelden

‘Gewone’ karakters (literals) gebruiken

Tekst: “Jan loopt in het bos”
Zoekopdracht: Komt het woord: “loopt” voor?
Regex:

"loopt"

Uitleg: Voer dit bovenstaande voorbeeld in in op het eerste tabblad van de regular expression tester. Resultaat: een match. Het woord “loopt” komt tenminste 1 keer voor.

Het gebruik van ^ en $

Tekst: “Jan loopt in het bos.”
Zoekopdracht: Bevat de zin exact “Jan loopt in het bos.”?
Regex:

"^Jan loopt in het bos.$"

Uitleg: Het dakje (“^”) duidt aan dat de daaropvolgende tekst aan het begin van de te doorzoeken tekst moet staan. De reguliere expressie “^Jan” levert bijvoorbeeld een match op bij alle teksten die beginnen met “Jan”. Het dollar-teken (“$”) duidt het einde van de tekst aan. De regex “bos.$” levert een match op bij alle teksten die eindigen met “bos.”. Deze 2 in combinatie gebruiken betekent dat alles tussen deze 2-tekens exact overeen moet komen met de te doorzoeken tekst. Herkenbaar? Ja, deze worden bijna altijd samen gebruikt bij validaties.

Omzeilen van speciale karakters
^ en $ zijn dus speciale karakters en geen literals. Als met speciale tekens toch als literals wil gebruiken. Stel je wil een match maken op een dollar teken. Plaats dan een “\” voor het speciale teken. Dus tekst: “$500,-“, regex: “\$500,-” geeft een match.

Wat is een karakter klassen (character classes)

Tekst: “Jan loopt in het bos. Hij speelt op zijn contrabas.”
Zoekopdracht: De termen “bos” en “bas”.
Regex:

"b[oa]s"

Uitleg: Gebruik voor deze test het tweede tabblad van de Regular Expression tester.

Er zijn 2 resultaten, “bos” en “bas”. We maken gebruiken van de zogenaamde character classes. Character classes zijn verzamelingen van karakters die worden omsloten met rechte haken (“[” en “]”). Een karakter klasse definieert welke karakters mogen voorkomen op een bepaalde positie binnen de tekst. In dit geval mag “o” OF “a” voorkomen op een plek tussen “b” en “s”. Het wordt “boos”, “boas” of “baas” zal dus niet in de zoekresultaten voorkomen omdat het hier slechts om 1 positie gaat.

Karakter klassen en karakterreeksen (a-z A-Z)

Tekst: “Jan loopt in het bos. Hij speelt op zijn contrabas.”
Zoekopdracht: Alle termen die beginnen met een “b” en eindigen op een “s” met daartussen 1 ander willekeurig karakter.
Regex:

"b[a-zA-Z]s"

Uitleg: a-z duiden alle kleine letters in het alfabet aan. A-Z alle hoofdletters. “b[a-z]s” zou dus alleen resulteren in een match als er een kleine letter tussen de “b” en de “s” staan. Alle reeksen op een rij:

a-z Kleine letters van “a” tot “z”. Mogelijke variatie: “a-f” = alle kleine letters van “a” tot en met “f”.
A-Z Hoofdletters van “A” tot en met “Z”.
0-9 Alle cijfers van “0” tot en met “9”.
\d Cijfers.
\w Alle woord karakters (alle alfanumerieke karakters inclusief underscore “_”).

Uitsluiten van karakters in een klasse

Tekst: “Jan loopt in het bos. Hij speelt op zijn contrabas.”
Zoekopdracht: Alle termen die beginnen met een “b” en eindigen op een “s” met daartussen 1 ander willekeurig karakter behalve de “a”.
Regex:

"b[^a]s"

Uitleg: Het dakje (“^”) binnen een karakterklasse heeft een geheel andere betekenis als daarbuiten (begin van de te doorzoeken tekst). Met het dakje binnen een karakterklasse wordt een uitsluiting aangeduidt. Er is 1 resultaat: “bos”.

Karakter klasse en herhaling

Tekst: “Jan loopt in het bos. Hij speelt op zijn contrabas.”
Zoekopdracht: Alle termen die beginnen met een “l” en eindigen op een “pt” met daartussen een willekeurig aantal karakters.
Regex;

"l[o]+pt"

Uitleg: Direct achter een karakter klasse kan een herhaling worden aangeduid. “+” staat voor 1 of meer. In dit geval matcht “loopt” omdat tussen “l” en “pt” 1 of meerdere o’s voorkomen. Maar “loooopt” kan ook.

+ 1 of meer
* 0 of meer
{x} (vb. {3}) x aantal keer zoals aangeduid. (vb. 3 keer)
{x,y} (vb. {1,3}) x tot y keer. (vb. 1 tot 3 keer)
\w Alle woord karakters (alle alfanumerieke karakters inclusief underscore “_”).

Conclusie

Een hoop informatie. Met deze informatie zou je al behoorlijk uit de voeten moeten kunnen met regulier expressies. In het 3de een laatste deel de puntjes op de i met betrekking tot reguliere expressies.

In deel 3:

  • Alternation
  • Ankers (Anchors)
  • Special Characters
  • Reguliere expressies in .NET
  • Groeperen

Heb je vragen? Stuur een reactie.

.NETC#Regex

Regular Expressions, Wikipedia zegt er het volgende over:

Een reguliere expressie (afgekort tot “regexp”, “regex” of RE) is een manier om patronen te beschrijven waarmee een computer tekst kan herkennen. Er bestaat hiervoor een formele syntaxis, die grotendeels gestandaardiseerd is.

Kortom regular expressions zijn een krachtige manier om teksten te doorzoeken. Iets om niet zomaar naast je neer te leggen. Een krachtiger taal om tekst te doorzoeken is er bijna niet. Regex worden veel gebruikt voor de validatie van datainvoer zoals het verifiëren van e-mail invoer, numerieke invoer, datums (data ;-)) etc…

Wat ik persoonlijk de moeilijkheid aan regex vond is het onthouden van de regels die erbij horen. Regex is typisch iets wat je in vlagen gebruikt. Zit er een wat langere tijd tussen het toepassen ervan dan zakt alle kennis weer weg. In eerste instantie lijken regular expressions behoorlijk ingewikkeld. Dat dat best meevalt zul je kunnen lezen in de rest van de serie.

Het mooie is dat regex ook in Microsoft .NET goed wordt ondersteund. De regex functionaliteit is terug te vinden in de namespace System.Text.RegularExpressions.

Een goed startpunt is de .NET regular expressions testapplicatie. In deel 2 aandacht voor het het onder de knie krijgen van de regels met behulp van de Snoei.net Regex Tester. Deze Silverlight testapplicatie is een handig hulpmiddel voor mensen die minder van lezen houden en meer van ‘hands-on’ oplossingen.

C# codevoorbeeld:

using System.Text.RegularExpressions; 

public void Test() { 
   string Value = "12345"; 
   string RegexPattern = "^[0-9]{5}$" 
   bool Match = Regex.IsMatch(Value, RegexPattern); //Match = true; 
}