Assembleur 8086+

Table des matières

Aujourd'hui, je vous propose un petit exercice : programmer un petit programme inutile en assembleur 8086 et supérieur (certaines des instructions que l'on va utiliser sont apparues après le 8086 comme DIV qui est apparue avec le 8088).

Quand je dis inutile, c'est que je pense qu'écrire du code en assembleur est aujourd'hui dépassé car les compilateurs des langages de programmation de haut niveau (ex : C) sont optimisés donc on ne gagnera pas grand chose, en terme de performances, à programmer en assembleur.

Mais, comme toujours, il y a des exceptions : connaitre et/ou coder en assembleur peut être utile dans certains cas, notamment :

  • Coder en assembleur des programmes "cas d'école" peut permettre au programmeur de comprendre un peu mieux le fonctionnement interne d'un ordinateur étant donné que ce langage est le plus proche de la machine. Si vous voulez plus proche, il vous reste le binaire :) . Pour illustrer mes propos, il faut savoir que l'assembleur est enseigné en première année de DUT Informatique dans certains IUT.
  • Un autre cas pour lequel l'assembleur peut s'avérer utile : écrire un mini-bootloader voir un mini-noyau, voir ... .
  • Enfin, lorsque l'on désassemble un programme, mieux vaut connaître l'assembleur de l'architecture visée (rappelons que l'assembleur dépend de l'architecture ;) )

Ceci étant dit, voila ce qui vous sera utile pour comprendre la suite : table des interruptions, la liste des instruction assembleur 8086 et modes d'adressages mémoire.

Exercice 1 : énoncé

Voici maintenant les "fonctionnalités" du programme à écrire :

  1. Afficher une chaine de caractères à l'écran.
  2. En utilisant le mode d'adressage immédiat, afficher une lettre (n'importe laquelle) à l'écran.
  3. En utilisant le mode d'adressage direct, afficher le premier caractère d'une chaine de caractère.
  4. En utilisant le mode d'adressage indirect et le registre BX, afficher deux caractères non consécutifs d'une chaine de caractères.
  5. En utilisant le mode d'adressage de base et le registre BX, afficher afficher un caractère de la chaine.
  6. En utilisant le mode d'adressage indexé direct, afficher un caractère de la chaine.
  7. On stocke un nombre d'une taille moyenne (> 100, < 1000 par exemple) "en dur" dans un registre et on l'affiche à l'écran.

Note : cet énoncé n'est pas de moi : je l'ai repris à T.M. / E.R. et je l'ai légèrement adapté.

Note : Bien que je ne sois pas fan des logiciels privateurs, je tiens à rester accessible pour la majorité de mes visiteurs. C'est pourquoi je propose une solution avec TASM et Windows.

Exercice 1 : sous Windows, avec TASM

Attention : seules les versions 32 bits de Windows ont un sous-système 16 bits (NTVDM pour XP, Windows On Windows depuis) et permettent donc d'exécuter des applications 16 bits. Les versions 64 bits en sont donc dépourvu. Comme compilateur, nous utiliserons TASM. Comme éditeur des liens (linker), nous utiliserons celui fournit avec, à savoir : TLINK.

Pourquoi ne pas faire une version 32 bits ? Parce que, à mon avis, sous Windows, ça manque de panache : on utilise plus les interruptions de la même manière, on se croirait presque plus en ASM vu toutes les fonctions externes que l'on charge ... Néanmoins si ça vous intéresse : Iczelion's Win32 Assembly Homepage.

Il n'y a rien de compliqué en soi. Il faut juste :

  • Ne pas oublier qu'à la fin de la déclaration d'une chaine de caractères, il faut un "$".
  • Il faut connaitre les principaux modes d'adressage du 8086 (je vous ai donné un lien plus haut).
  • Il ne faut pas oublier d'initialiser le segment de données et de quitter le programme en douceur.
  • Il faut connaitre les interruptions fournies par le "DOS" dont nous aurons besoin (afficher une chaine de caractère, afficher un caractère, quitter le programme en douceur). Je vous ai donné un lien plus haut.
  • Il ne faut pas oublier que, dans la table ASCII, pour obtenir un chiffre sous forme de caractère affichable, il suffit de rajouter 30 en hexadécimal à la représentation binaire lui-même.

Pour compiler, linker et exécuter votre programme, il suffit d'ouvrir une invite de commande, de naviguer (commande cd) jusqu'au dossier dans lequel sont stockés TASM et TLINK (a moins d'avoir ajouter le dossier à la variable d'environnement PATH) et de taper :

> tasm votrefichier.asm
> tlink votrefichier
> votrefichier

Voici ce que j'ai écris :

DOSSEG
.MODEL SMALL

 
; 1 ko sera attribué au segment de pile
.STACK
 
.DATA
	message db 'Une chaine de caracteres bidon $'
	message1 db 'Question 1 : $'

	message2 db 13,10,'Question 2 : $'
	message3 db 13,10,'Question 3 : $'

	message4 db 13,10,'Question 4 : $'
	message5 db 13,10,'Question 5 : $'

	message6 db 13,10,'Question 6 : $'
	message7 db 13,10,'Question 7 : $'

 
.CODE
	; Initialisation du segment de données
	mov ax, @DATA
	mov ds, ax

 
	; 1) Affichage d'une chaine
	mov ah, 09h
	mov dx, offset message1
	int 21h

 
	mov ah, 09h
	mov dx, offset message
	int 21h

 
 
	; 2) On affiche le caractère 'H' à l'écran
	mov ah, 09h
	mov dx, offset message2
	int 21h

 
	mov ah, 02h
	mov dl, 'H'

	int 21h
 
	; 3) On affiche la 1ere lettre de message
	mov ah, 09h

	mov dx, offset message3
	int 21h
 
	mov ah, 02h

	mov dl, message
	int 21h
 
	; 4) On affiche la 1ere et 21eme lettre de message
	mov ah, 09h

	mov dx, offset message4
	int 21h
 
	mov bx, offset message

 
	mov ah, 02h
	mov dl, [bx]

	int 21h
 
	; N'oubliez pas que l'on compte à partir de 0
	mov bx, offset message+20

 
	mov ah, 02h
	mov dl, [bx]

	int 21h
 
	; 5) On affiche la 28eme lettre de message 
	mov ah, 09h

	mov dx, offset message5
	int 21h
 
	mov ah, 02h

	mov bx, offset message
	mov dl, [bx + 27]

	int 21h
 
	; 6) On affiche la 15eme lettre de message
	mov ah, 09h

	mov dx, offset message6
	int 21h
 
	mov SI, 14

	mov ah, 02h
	mov bx, offset message
	mov dl, [bx + SI]

	int 21h
 
	; 7) On stocke le nombre 666 en dur et on l'affiche
	mov ah, 09h

	mov dx, offset message7
	int 21h
 
	mov ax, 666

	mov bl, 100
	div bl
 
	mov cx, ax

	mov ah, 02h
	mov dl, cl
	add dl, 30h

	int 21h
 
 
	mov ax, 0000h
	mov bl, 10

	mov al, ch
	div bl
 
	mov cx, ax

	mov ah, 02h
	mov dl, cl
	add dl, 30h

	int 21h
 
	mov ah, 02h
	mov dl, ch

	add dl, 30h
	int 21h
 
	; FIN

	mov ax, 4C00h
	int 21h
END

Exercice 1 : sous un Windows, avec Nasm et le linker Val

Nasm est un compilateur sous licence BSD. Je vous recommande la lecture de sa documentation qui est bien faite et enrichissante, aussi bien sur le logiciel lui-même que sur l'assembleur.

Concernant le linker, je vous recommande Val qui est dans le domaine public et dont les sources sont disponibles. La seule contrainte est que le nom reste le même.

A part une syntaxe différente, cette solution est la même que celle utilisant TASM et TLINK. Ainsi, je vous recommande d'aller lire la solution utilisant TASM pour plus d'informations.

Concernant les différences de syntaxe entre Nasm et TASM :

  • exit les symboles peu clairs comme DOSSEG, .DATA, END, etc.
  • exit le mot-clé OFFSET. Pour demander l'adresse mémoire d'une variable, on indique juste son nom
  • Pour demander le contenu d'une adresse mémoire, on utilise [ ]

Pour compiler, linker et exécuter votre programme, il suffit d'ouvrir une invite de commande, de naviguer (commande cd) jusqu'au dossier dans lequel sont stockés Nasm et Val (a moins d'avoir ajouter le dossier à la variable d'environnement PATH) et de taper :

> nasm -f obj votrefichier.asm
> val votrefichier.obj
> votrefichier

Vous savez l'essentiel pour refaire le même programme.

Voici ce que j'ai écris :

segment .data
	message db 'Une chaine de caracteres bidon $'
	message1 db 'Question 1 : $'

	message2 db 13,10,'Question 2 : $'
	message3 db 13,10,'Question 3 : $'

	message4 db 13,10,'Question 4 : $'
	message5 db 13,10,'Question 5 : $'

	message6 db 13,10,'Question 6 : $'
	message7 db 13,10,'Question 7 : $'

 
segment stack stack
	resb 64
	stackstop:
 

segment .code
..start:
	mov ax, data
	mov ds, ax

 
	mov ax, stack
	mov ss, ax

	mov sp, stackstop
 
	; 1) Affichage d'une chaine
	mov ah, 09h

	mov dx, message1
	int 21h
 
	mov ah, 09h

	mov dx, message
	int 21h
 
 
	; 2) On affiche le caractère "H" à l'écran

	mov ah, 09h
	mov dx, message2
	int 21h

 
	mov ah, 02h
	mov dl, 'H'

	int 21h
 
	; 3) On affiche la 1ere lettre de message
	mov ah, 09h

	mov dx, message3
	int 21h
 
	mov ah, 02h

	mov dl, [message]
	int 21h
 
	; 4) On affiche la 1ere et 21eme lettre de message

	mov ah, 09h
	mov dx, message4
	int 21h

 
	mov bx, message
 
	mov ah, 02h

	mov dl, [bx]
	int 21h
 
	mov bx, message+20

 
	mov ah, 02h
	mov dl, [bx]

	int 21h
 
	; 5) On affiche la 28eme lettre de message 
	mov ah, 09h

	mov dx, message5
	int 21h
 
	mov ah,02h

	mov bx, message
	mov dl, [bx + 27]

	int 21h
 
	; 6) On affiche la 15eme lettre de message
	mov ah, 09h

	mov dx, message6
	int 21h
 
	mov si,14

	mov ah,02h
	mov bx, message
	mov dl, [bx + si]

	int 21h
 
	; 7) On stocke le nombre 666 en dur et on l'affiche
	mov ah, 09h

	mov dx, message7
	int 21h
 
	mov ax, 666

	mov bl, 100
	div bl
 
	mov cx, ax

	mov ah, 02h
	mov dl, cl
	add dl, 30h

	int 21h
 
 
	mov ax, 0000h
	mov bl, 10

	mov al, CH
	div bl
 
	mov cx, ax

	mov ah, 02h
	mov dl, cl
	add dl, 30h

	int 21h
 
	mov ah, 02h
	mov dl, CH

	add dl, 30h
	int 21h
 
	; FIN

	mov ax, 4C00h
	int 21h

Exercice 1 : sous un Windows, avec le compilateur Nasm mais sans linker

Cette solution est très semblable à celle utilisant Nasm et Val, seule la syntaxe change un peu. Ainsi, je vous recommande d'aller lire la solution utilisant Nasm et Val pour plus d'informations. Je pense que cette solution n'est pas très propre. Néanmoins je vous la montre, libre à vous après de faire un choix.

Pour compiler, linker et exécuter votre programme, il suffit d'ouvrir une invite de commande, de naviguer (commande cd) jusqu'au dossier dans lequel est stocké Nasm (a moins d'avoir ajouter le dossier à la variable d'environnement PATH) et de taper :

> nasm -f bin votrefichier.asm -o nom.exe
> nom.exe

Et voici ce que j'ai écris :

org 100h
 
section .data

	message db 'Une chaine de caracteres bidon $'
	[... Pareil que précédemment ... ]
 
section .text

start:
	; 1) Affichage d'une chaine
	mov ah, 09h
	mov dx, message1
	int 21h

 
	[... Pareil que précédemment ... ]
 
	; FIN
	mov ax, 4C00h

	int 21h

Exercice 1 : sous un GNU/Linux, avec Nasm et ld

D'après la doc de Nasm, le format de fichier ELF ne supporte pas les relocations 32 bits -> 16 bits. Néanmoins ld les supporte comme une extension. J'ai essayé pas mal de choses, j'ai cherché sur le net mais je ne suis pas parvenu à linker mon programme 16 bits (utilisation de [BITS 16] dans le code) car ld me renvoi toujours un "relocation truncated to fit: R_386_16 against `.data'".

Néanmoins ce n'est pas une grande perte : cette méthode n'est pas recommandable comme on peut le lire un certain nombre de fois sur internet. Même la documentation de Nasm ne traite pas le fait d'écrire des programmes 16 bits sous GNU/Linux alors qu'elle le fait pour Windows.

Il est néanmoins possible d'écrire du code 32 bits. Ce qui va changer par rapport à Windows, c'est qu'on ne fera plus int 21h mais int 80h pour appeler le noyau et lui demander un service. Les services sont ici les fonctions qu'on a l'habitude d'utiliser en C : exit, write, open, etc. On leur passe les arguments nécessaires, dans l'ordre, dans les registres eax, ebx, ecx, edx ou par la pile (attention à bien empiler : on commence par empiler le dernier argument, ..., puis le premier). Plus de détails : i386 Linux 2.2+ Syscalls et FreeBSD Assembly Language Programming

Pour compiler :

$ nasm -f elf32 votrefichier.asm
$ ld -s votrefichier.o -o nom

ou (sur un OS 64 bits (x86_64)) :

$ nasm -f elf64 votrefichier.asm
$ ld -s votrefichier.o -o nom

ÉDIT du 03/04/2012 à 16h15 :
Sur un OS 64 bits, il vaut mieux compiler et linker de cette manière :

$ nasm -f elf votrefichier.asm
$ ld -m elf_i386 -s votrefichier.o -o nom

En effet, en utilisant la première méthode, la compilation et le linkage s'effectueront sans problèmes mais vous pourriez rencontrer des erreurs de segmentation sur certains programmes et notamment ceux qui font des manipulations sur des variables mémoires (logique ...) ou qui manipulent la pile. Fin de l'édit.

Et voici ce que j'ai écris :

section .data
	message db 'Une chaine de caractères bidon'

	lenMessage equ $-message
 
	message1 db 'Question 1 : '
	lenMessage1 equ $-message1

 
	message3 db 10,'Question 3 : '
	lenMessage3 equ $-message3
 

	message4 db 10,'Question 4 : '
	lenMessage4 equ $-message4
 
	message7 db 10,'Question 7 : '

	lenMessage7 equ $-message7
 
	fin: db 10,'FIN',10

	lenFin: equ $-fin	
 
; On déclare des variables non initialisées
section .bss
	chiffre1: resb 1

	chiffre2: resb 1
	chiffre3: resb 1
 

section .text
	global _start
 
	_start:
	; 1) Affichage d’une chaine
	; Sous les systèmes de type UNIX, tout est fichier.

	; La console est un fichier. On écrit dedans avec write().
	mov eax, 4
	mov ebx, 1

	mov ecx, message1
	mov edx, lenMessage1
	int 80h

 
	mov eax, 4
	mov ebx, 1

	mov ecx, message
	mov edx, lenMessage
	int 80h

 
	 ; 2) On affiche le caractère « H » à l’écran
	 ; La solution revient à faire 3) car il faut declarer le
	; caractère 'H' dans le segment de données et l'afficher
 
	 ; 3) On affiche la 1ere lettre de message
	mov eax, 4

	mov ebx, 1
	mov ecx, message3
	mov edx, lenMessage3
	int 80h

 
	mov eax, 4
	mov ebx, 1

	mov ecx, message
	mov edx, 1
	int 80h

 
	; 4) On affiche la 1ere et la 21eme lettre
	mov eax, 4
	mov ebx, 1

	mov ecx, message4
	mov edx, lenMessage4
	int 80h

 
	mov esi, message
 
	mov eax, 4

	mov ebx, 1
	mov ecx, esi
	mov edx, 1

	int 80h
 
	mov esi, message+20
 

	mov eax, 4
	mov ebx, 1
	mov ecx, esi

	mov edx, 1
	int 80h
 
	; 5) On affiche la 28eme lettre de message

	; Pas possible
 
 
	 ; 6) On affiche la 15eme lettre de message
	; pas possible
 
	 ; 7) On stocke le nombre 666 en dur et on l’affiche
	mov eax, 4

	mov ebx, 1
	mov ecx, message7
	mov edx, lenMessage7
	int 80h

 
	mov dx, 0
	mov ax, 666

	mov bl, 100
	div bl
 
	add al, 30h

	mov [chiffre1], al
 
	mov bl, 10

	mov al, ah
	mov ah, 0
	div bl

 
	add al, 30h
	mov [chiffre2], al

 
	add ah, 30h
	mov [chiffre3], ah

 
	mov eax, 4
	mov ebx, 1

	mov ecx, chiffre1
	mov edx, 1
	int 80h

 
	mov eax, 4
	mov ebx, 1

	mov ecx, chiffre2
	mov edx, 1
	int 80h

 
	mov eax, 4
	mov ebx, 1

	mov ecx, chiffre3
	mov edx, 1
	int 80h

 
	; FIN
	mov eax, 4
	mov ebx, 1

	mov ecx, fin
	mov edx, lenFin
	int 80h

 
	mov eax, 1
	mov ebx, 0

	int 80h

Comme vous le constater, certains adressages ne sont pas possibles. Cela est dû au fait que la fonction write attend une adresse mémoire. Or, certains adressages retournent le contenu d'une adresse mémoire. On parait toujours trouver une parade mais cela reviendrait à un adressage direct ou à un adressage indirect via un registre (ou alors n'ai-je pas assez réfléchis ?).

Les expressions régulieres

Ceux qui me connaissent savent que je suis assez fan des expressions régulières depuis que je les ai connues.

Je me souviens encore de quelques unes des regex que j'ai écrit, il y a entre 3 et 5 ans et pour cause : elles trainent toujours dans un coin de mon disque dur. Toutes n'étaient pas optimisées, loin s'en faut. Mais, comme on l'entend fréquemment, l'expérience est le nom que nous donnons à nos erreurs :) .

J'ai découverts les regex en PHP et à l'époque ça donnait ça :

*Retour dans le passé*

Pour récupérer la version d'Apache dans un phpinfo() :
#Apache/(.+) \(Fedora\)#

Pour récupérer la version de PHP dans un phpinfo() :
#PHP Version (.+)</h1>#

Pour contrôler un nom de fichier passé en GET afin d'éviter la remontée de répertoires :
'`\.`'

Pour récupérer plusieurs liens sur un site donné (j'ai oublié lequel :/) :
#<p><font face=\"Arial\"><a href="(.+)">(.+)</a>(.+) (.+)</font></p>#isU

La même mais pour des adresses email :
#<A HREF="mailto:(.+)">.+</A>#isU

Et on parle même pas de celles liées au BBCode :
#\[b:[a-z0-9]{8}\](.+)\[/b:[a-z0-9]{8}\]#isU
#\[i:[a-z0-9]{8}\](.+)\[/i:[a-z0-9]{8}\]#isU
#\[u:[a-z0-9]{8}\](.+)\[/u:[a-z0-9]{8}\]#
#\[color=(.+):[a-z0-9]{8}\](.+)\[/color:[a-z0-9]{8}\]#isU

#\[size=(.+):[a-z0-9]{8}\](.+)\[/size:[a-z0-9]{8}\]#isU
#\[quote:[a-z0-9]{8}\](.+)\[/quote:[a-z0-9]{8}\]#isU
#\[quote="(.+)":[a-z0-9]{8}\](.+)\[/quote:[a-z0-9]{8}\]#isU
#\[code:[a-z0-9]{8}\](.+)\[/code:[a-z0-9]{8}\]#isU
#\[list:[a-z0-9]{8}\]#isU
#\[list=[0-9]:[a-z0-9]{8}\]#isU
#\[/list:u:[a-z0-9]{8}\]#isU
#\[/list:o:[a-z0-9]{8}\]#isU

#\[\*:[a-z0-9]{8}\](.+)\[/\*:[a-z0-9]{1}:[a-z0-9]{8}\]#
#(<ul>|<ol>)<br />#
#</li><br />#
#\[img:[a-z0-9]{8}\](.+)\[/img:[a-z0-9]{8}\]#isU

#\[url:[a-z0-9]{8}\](.+)//(.+)\[/url:[a-z0-9]{8}\]#isU
#\[url=(.+)//(.+):[a-z0-9]{8}\](.+)\[/url:[a-z0-9]{8}\]#isU

*Retour dans le présent*

Récemment, j'ai eu à vérifier la validité d'un NIR pour un cas d'école et j'ai de suite pensé aux regex.

Voila les regex que j'ai écrit. Comme pour les autres regex présentées dans cet article, je n'en garantit pas la validité. J'ai testé tous les cas possibles mais une erreur peut toujours arriver (un code sans bugs est un code insuffisamment testé). On peut également les optimiser, ne serai-ce qu'en utilisant les classes de caractères. Ce coup-là, c'est Java qui sera utilisé :

Pour vérifier la validité de la clé :

^[0][1-9]|[1-8][0-9]|9[0-7]$

Pour le reste du NIR :

^[12][0-9][0-9](?:0[1-9]|1[012]|20)(?:(?:2[aA]|2[bB]|[0-8][1-9]|9[0-5])(?:[0-9][0-8][1-9]|[1-9][1-8][0-9]|990)|(?:(?:9[78][0-9](?:0[1-9]|[1-8][0-9]|90)))|99(?:[0-9][0-8][1-9]|[1-9][1-8][0-9]|990))(?:[0-9][0-9][1-9]|[1-9][1-9][0-9])$

L'avantage des regex, c'est qu'on trouve toujours quelqu'un qui en a un jour écrit une plus longue que la nôtre. Mais je pense que la reine des regex, c'est celle qui contrôle la validité d'une adresse email, et pour cause : la RFC 5322 (qui remplace la 2822 qui elle-même remplace la 822) qui définit le format des adresses email est à la fois diabolique et sadique. Quelques liens pour se faire une idée : Mail::RFC822::Address: regexp-based address validation et How to Find or Validate an Email Address.

Kubuntu 10.10

Table des matières

Dès aujourd'hui, j'ai mis à niveau la version de Kubuntu qui était installé sur mon ordinateur portable.

Pour réaliser cette mise à niveau, j'ai choisis la méthode "alternate CD + apt-get" :

  1. Télécharger le CD alternate de Kubuntu.
  2. Monter l'image :
    ~$ sudo mkdir /media/iso
    ~$ sudo mount -o loop -t iso9660 ./kubuntu-10.10-alternate-amd64.iso /media/iso
  3. Lancer l'installation :
    ~$ sudo /media/iso/cdromupgrade
  4. Attendre un peu car l'assistant pose quelques questions (même après avoir validé les logiciels à supprimer).
  5. Laisser l'installation se faire toute seule et redémarrer.
  6. Au redémarrage, on note que, par défaut, si on ne touche rien pendant le timeout de GRUB, on boot sur le noyau 2.6.32-25. Demandons à booter sur le 2.6.35-22.
  7. Après avoir saisi mon login, l'écran devient noir et le reste. Ne paniquons pas, passons en mode console (ctrl+alt+F1), authentifions-nous et tapons :
    ~$ sudo /etc/init.d/kdm restart
  8. Afin de finir de mettre à jour tous les paquets, réactivons les dépôts alternatifs qui ont été désinstallés durant l'installation (j'utilise ubuntu-tweak) et lançons :
    ~$ sudo apt-get update && sudo apt-get dist-upgrade

Et voila : la mise à niveau est finie. On n'oubliera pas de désactiver les effets visuels depuis "Configuration du sytème" parce que là c'est un peu "too much" quand même.

Le cas Wireshark

J'ai cependant remarqué que Wireshark avait été désinstallé. Voici, vite fait, comment le réinstaller même si il n'y a rien de compliqué :

~$ sudo apt-get install wireshark

Il faut rajouter manuellement (via l'éditeur de menu) le raccourci dans le menu K. Je n'ai pas compris pourquoi Wireshark (et c'est le seul logiciel concerné par ce "problème") n'a pas été automatiquement ajouté cette fois-ci.

Pour pouvoir voir les interfaces réseau et capturer le trafic sans utiliser le compte root sur Wireshark (ce qui reviendrait à donner des droits supplémentaires à un programme qui n'en a pas directement besoin), il suffit d'activer le setuid bit sur le programme qui est chargé de la capture :

~$ chmod u+s /usr/bin/dumpcap

Désinstaller l'ancien noyau

~$ sudo apt-get remove linux-image-2.6.32-25-generic

Vous pouvez aussi désinstaller les "vieux" headers 2.6.32-25.

Créer un compte utilisateur sans droits sur OpenWRT

À quoi peut bien servir la création d'un compte utilisateur sans droits mais avec un mot de passe sur OpenWRT ? Imaginons par exemple que vous utilisez votre routeur afin de réaliser des tunnels SSH ou plus si affinités : vous restez longtemps connecté à votre routeur, tout en étant authentifié avec le compte root, sans avoir besoin des droits que vous octroie ce compte. Côté sécurité, même Microsoft fais mieux. ;)

Cela peut aussi servir pour distribuer quelques comptes à des amis afin qu'ils puissent profiter des joies du port forwarding et du contournement d'un pare-feu sans tout casser.

Maintenant que je vous ai convaincus avec ces arguments subtils et percutants ;) , voici la marche à suivre pour un compte nommé "guest" :

Créons un "home directory" pour ce compte (ça fais moins porchou que de lui donner /var) :

~# mkdir -p /home/guest

Éditons le fichier qui contient les utilisateurs autorisés à ce connecter au système :

vi /etc/passwd

A la fin du fichier, rajoutez une ligne comme celle-ci :

guest:*:65533:65533:guest:/home/guest:/bin/ash

Vérifiez que l'UID n'existe pas déjà. Changez le shell d'arrivé si besoin.

Créons un groupe pour cet utilisateur. Oui, on pourrait utiliser le group "nogroup/daemon" mais il vaut mieux créer un nouveau groupe afin de bien séparés les privilèges (droits d'accès à certains fichiers, etc.).

vi /etc/group

A la fin du fichier, rajoutez une ligne comme celle-ci :

guestg:x:65533:

Le g à la fin de guest signifie "group", ce n'est pas une coquille, c'est pour différencier le groupe du login. Vérifiez que le GID n'existe pas déjà et qu'il correspond au GID que vous avez donné au compte utilisateur.

Maintenant donnons un mot de passe à ce compte :

~# passwd guest

Donnons l'autorisation au compte guest d'écrire dans son home directory :

~# chown -R guest:guestg /home/guest

C'est terminé.

Pour vous connecter à votre routeur via SSH :

  • Si vous voulu effectuer une tâche de maintenance :
    ssh root@ip-du-routeur
  • Si vous n'avez pas besoin d'effectuer une tâche de maintenance (exemple du tunnel SSH) :
    ssh guest@ip-du-routeur

Si vous voulez utiliser l'authentification par clé publique avec ce compte utilisateur, sa clé publique ne devra pas être mise dans /etc/dropbear/authorized_keys mais dans /home/guest/.ssh/authorized_keys .

4 astuces pour Windows

Table des matières

Dans ce billet, nous allons revenir sur 4 astuces bien connues concernant Windows.

  • La première vous permettra de faire un sorte qu'un compte utilisateur n'ai plus les droits d'administration alors que le panneau de configuration vous refuse cette modification.
  • La deuxième astuce vous permettra de cacher un compte utilisateur sur l'écran de connexion.
  • La troisième astuce vous permettra de désactiver certains partages administratifs de Windows.
  • Enfin, la dernière astuce vous permettra de faire en sorte que votre PC ne s'annonce plus sur le réseau via les protocoles Netbios/SMB.

Note : j'ai testé ces astuces uniquement sur Windows 7. Mais elles doivent fonctionner à coup sûr sous Vista et certainement sous XP.

Enlever les droits "administrateur" à un compte utilisateur

Parfois, vous voulez qu'un compte utilisateur n'ait plus les droits d'administration. Par exemple : si vous utilisez le compte Administrateur pour la maintenance, vous n'avez pas besoin que votre autre compte ait les droits d'administration. Pourtant Windows vous refuse cette suppression de droits sous prétexte qu'il faut au moins un compte avec les droits administrateur ... Ce qui est déjà le cas. Pour outrepasser ceci, il suffit d'utiliser la commande "net" et son argument "localgroup". Ouvrez une invite de commande et tapez :

net localgroup Administrateurs GuiGui /delete

En replaçant GuiGui par le nom du compte à destituer. Puis tapez :

net localgroup Utilisateurs GuiGui /add

Note : si vous utilisez un domaine, utilisez la commande "net group".

Cacher un compte utilisateur sur l'écran de connexion

Puisque je n'ai pas trouvé cette astuce tout seul ou via le bouche-à-oreille, contrairement à la première astuce, et plutôt que de répéter ce qui a déjà été dit, je préfère vous donner le lien qui m'a aidé quand j'ai moi-même voulu réaliser cette opération : Masquer un compte utilisateur dans Windows 7 ou Vista.

Désactiver les partages administratifs de Windows

Là aussi, tout ce résume en un lien : Partage administratif.

Note : contrairement à ce qui se dit parfois sur la toile, les partages administratifs n'ont pas disparus ou n'ont pas été désactivés par défaut dans Windows 7. En tout cas pas chez moi ...

Empêcher Windows de s'annoncer sur le réseau via les protocoles Netbios et SMB

Qui n'a jamais vu, lors d'une capture des flux réseau, les nombreux messages de diffusion (broadcast) envoyés par une machine Windows pour s'enregistrer sur d'autres machines Windows via les protocoles Netbios et SMB ?

Pourquoi vouloir empêcher cela ? Pour avoir moins de trafic réseau, pour ne pas encombrer le réseau sur lequel on vous invite (cas d'un ordinateur portable) et car cela n'empêche pas le transfert de fichier via le protocole SMB de fonctionner : il suffit de connaitre le nom de la machine et tout fonctionne comme d'habitude.

Pour faire cela, il suffit d'aller dans le registre, de naviguer jusqu'à HKEY_LOCAL_MACHINE\system\currentcontrolset\services\lanmanserver\parameters puis de créer ou modifier les valeurs dword "hidden" et "Lmannounce" et de leur donner respectivement la valeur 1 et 0.

Note : tout comme la désactivation des partages administratifs, cette manipulation nécessite un redémarrage du système pour prendre effet.

Le .reg de la fin

Pour la désactivation des partages administratifs et de l'annonce sur le réseau, je m'étais fait un fichier .reg que je pouvais facilement intégrer à mes installations allégées et automatisées de Windows 7 grâce au logiciel RT Se7en Lite. Cela permet de désactiver ces deux "features" dès l'installation et ainsi de ne pas oublier de le faire. Le voici pour ceux que ça peut intéresser :

Windows Registry Editor Version 5.00
 
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanServer\Parameters] 
"Lmannounce" = dword:00000000
"Hidden" = dword:00000001
"AutoShareWks" = dword:00000000