Debugging with LEDs

août 14th, 2009 at 03:27 admin

Dans la série ‘j’touche le fond et je creuse encore ! ‘ je vous propose une méthode sympa pour debugger vos codes critiques. Récemment j’ai été amené à dev du code noyau tournant dans un contexte critique par rapport à l’OS. Comprendre par là que je tournait à des IRQL >= DIRQL, comme si j’étais dans une Interrupt Service Routine (ISR) déclénché par une interruption extérieur. Dans ces cas lorsqu’on veut débugger ces routines on ne peut pas forcément utiliser des fonctions comme DbgPrint ou KdPrint, même si la doc dit que c’est possible on perd beaucoup en performances et si comme moi vous debuggez votre machine depuis la liaison série l’OS se retrouve vite à genoux.

Alors après on peut très bien me dire de mettre des message de debug en queue et de les envoyer dans un worker thread qui balancera des DbgPrint à un IRQL de PASSIVE_LEVEL, ce n’est pas difficile à implémenter c’est juste que je n’avais pas envie de faire. de la même manière, mettre des breakpoints dans le code ou bien à l’aide du kernel-debugger n’est pas forcément très pratique non plus vu que l’OS notifiera à chaque fois le debugger dès qu’il en verra un.

De plus j’avais juste besoin de savoir si un codepath particulier était prit donc un simple signal me disant « oui ou non » me suffisait. Je me suis dit entre 2 trolls sur IRC concernant l’OS des barbus (qui ne marche pas très bien apparemment) qu’utiliser les LEDs du clavier comme signal pourrait être une solution, certes bizarre, mais efficace.

L’idée est simple, il s’agit juste de demander au code de faire clignoter une LED à un moment précis. Dans un premier temps je me suis donc documenté rapidement sur le contrôleur clavier i8042 pour savoir que 2 I/Os port sont utilisés :

  • Le Read-input buffer sur 1 byte. Port 0×60
  • Le Write-ouput buffer, 1 byte. Port 0×60
  • Le Status-register, 1 byte uniquement accessible en lecture. Port 0×64
  • Le Control-register, 1 byte en lecture/écriture.

Pour le controleur i8042 le Read-input et Write-ouput sont en fait confondus. Le Control-register quand à lui est uniquement accessible en envoyant une commande sur le Status-register qui sert alors de byte de commande lorsqu’on l’écrit. Attention il s’agit alors d’une commande pour le contrôleur clavier et non le clavier lui même !

Justement, la commande qui m’intéresse est celle qui permet de définir les LEDS clavier. Après quelques recherches sur le net je tombe sur The PS/2 Keyboard Interface et The AT Keyboard Controler. La commande qui m’intéresse est donc ’0xED (Set/Reset LEDs)’, comme il s’agit du clavier nous devons écrire cette commande dans le Write-ouput buffer

  • Si 1, SROLL_LOCK est allumée. Éteinte sinon.
  • Si 1, NUM_LOCK est allumée. Éteinte sinon.
  • Si 1, CAPS_LOCK est allumée. Éteinte sinon.
  • Maintenant il ne reste plus qu’a envoyer la commande puis les données. Ce qui se traduit en asm par :

    #define KBD_DATA        0x60    // I/O port for keyboard data
    #define KBD_STATUS      0x64    // I/O port for keyboard status (read)
    
    #define KBD_CMD_SET_LEDS        0xED    // Set keyboard leds
    
    #define SCROLL_LOCK 1
    #define NUM_LOCK 2
    #define CAPS_LOCK 4
    
    xor eax, eax
    mov al, KBD_CMD_SET_LEDS
    out KBD_DATA , al
    mov al, Leds
    out KBD_DATA, al
    

    Oulà, pas trop vite, on oublie que pour écrire dans le Write-ouput buffer il faut d’abord attendre que le controleur nous dise que nous pouvons le faire. Pour cela il faut que le bit 1 du Status-register soit à 0, de plus pour une lecture il faut que le bit 0 soit à 1. On doit donc poller le Status-register afin de savoir quand on peut lire ou écrire le port 0×60. La routine est donc simplement :

    kbd_wait:
    in al, KBD_STATUS
    test al, 2
    jne kbd_wait
    ret
    

    Pour tester au lieu de me faire chier directement avec un driver, j’ai demandé à ce que l’IOPL de mon process soit modifié, pour Windows il faut que le token du process possède le privilège SeTcbPrivilege. Celui-ci peut être attribuer en allant dans Panneau de configuration -> Outils d’administration -> Stratégie de sécurité locale -> Stratégies locales -> Attribution des droits utilisateurs et en ajoutant votre utilisateur dans la stratégie « Agir en tant que partie du système d’exploitation » (après avoir ajouter votre user il faut vous que relanciez votre session).

    Je vous laisse les sources maintenant à vous de vous amuser avec, en tout cas cela m’a bien servit dans mon driver pour tracer mon code.

    Vous trouverez les sources ici :

    http://ivanlef0u.fr/repo/kbd-leds.rar

    Sinon quelques liens à lire :

    Updates: Autoruns v9.53, ProcDump v1.3, Process Monitor v2.6 | New Mark’s Blog post: The Case of the Temporary Registry Profiles | Download Windows Internals 5 sample chapter

    VMWare Cloudburst

    VMware ring3 detection (RF handling)

    Preventing the exploitation of user mode heap corruption vulnerabilities

    Entry Filed under: RE

    11 Comments

    • 1. shutdown76  |  août 14th, 2009 at 16:11

      « j’touche le fond et je creuse encore ! »

      <3


    • 2. newsoft  |  août 15th, 2009 at 13:28

      Firewire debugging FTW !
      (400 Mb/s au lieu de 9600 bauds)


    • 3. Edward  |  août 15th, 2009 at 19:03

      Très bon article.
      Mais plutôt que se casser les pieds à faire clignoter les LEDs du clavier, pourquoi ne pas simplement faire un beep avec le speaker?
      c plus simple non?


    • 4. admin  |  août 15th, 2009 at 19:09

      @Edward :
      Merci, mais c’est complétement équivalent imho, de plus tu as 3 LEDs pour 1 buzzer, donc plus de possibilités :]
      Je l’utiliserais quand j’aurais besoin de faire du son et lumière pour mes projets.


    • 5. Edward  |  août 16th, 2009 at 07:13

      c vrai qu’il y a plus de possibilités avec les 3 LEDs qu’un seul speaker … quoique si on joue avec les fréquences il y en aura bien plus de possibilités.
      Mais au final c une question de « goût ».


    • 6. Geo  |  septembre 16th, 2009 at 21:10

      Yo, Ivan.
      Je n’arrive pas de télécharger l’archive. Est-ce qu’elle fait 0 octet, ou bien est-ce moi ?

      A+

      Geo


    • 7. admin  |  septembre 17th, 2009 at 18:20

      Yo,
      C’est bon c’est corrigé !
      Merci
      +


    • 8. okba  |  mars 6th, 2010 at 17:45

      !!!


    • 9. Dilem  |  mars 8th, 2010 at 03:31

      Oh yeah, dj ivan in da place.

      J’ai beaucoup aimé ton article, sur le coup je me suis dis que soit tu avais fait une overdose de chocapikz, soit tu nous prenais pour des cons, mais non, même pas.

      En tout cas, l’article est fun, bien moins bourin à lire que les autres.

      Bref, j’adhère totalement :)

      Bisous.

      Dilem le tck haha.


    • 10. admin  |  mars 8th, 2010 at 17:50

      <3


    • 11. Francis Provencher  |  octobre 16th, 2010 at 03:40

      Serieux ton blog il tue grave…

      Très fort au niveau techniquemen général..

      Laches pas c’est de la belle job!


    Trackback this post


    Calendar

    décembre 2018
    L Ma Me J V S D
    « fév    
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  

    Most Recent Posts