Comment jouer à un colocataire

Du traducteur


Un étudiant de l'Université Tufts raconte comment taquiner son colocataire. Il m'a même épinglé quand il a commencé son histoire avec le fait qu'ils ont un téléviseur 4K dans l'auberge.

Présentation


Avant de parler de la façon dont j'ai amené le malheureux Logan, je dois expliquer le système médiatique dans notre chambre. Bientôt, vous comprendrez pourquoi.

Logan, si tu lis ça, j'espère que tu t'es plus amusé qu'autrement.

Disposition


Nous avons un ordinateur avec un bureau Ubunt connecté à un téléviseur. Il agit comme un serveur multimédia. Puisqu'il a toujours besoin d'une connexion Internet permanente, un serveur Web avec quelques pages, un serveur SSH et un certain nombre d'autres services y tournent toujours.

En raison du fait que la télé est 4K, et l'ordinateur est assemblé à partir de ce qui était à portée de main, sa carte vidéo ne tire pas. Logan a décidé d'acheter l'ancien vidyuha NVIDIA, sorti il ​​y a quelques générations (ce qui est encore beaucoup mieux que ce qu'il était) afin de lire normalement la vidéo 4K.

La naissance d'une idée


Peu de temps après l'installation, nous avons eu quelques problèmes avec les pilotes. À ce moment, j'ai pensé qu'il serait amusant de pouvoir afficher manuellement les messages d'erreur.

Après quelques recherches sur Internet, il est devenu clair que l'invocation à distance d'un message sur un téléviseur est aussi simple que:

  1. Connectez-vous via SSH à l'ordinateur en tant qu'utilisateur exécutant la diffusion
  2. DISPLAY=:0 zenity --info --text '!'

DISPLAY=:0 nécessaire, car dans ma session il n'y a pas d'affichage, mais je veux afficher le message sur l'écran principal.

Comme nous avons eu des problèmes avec NVIDIA vidyuha, j'ai décidé de m'attarder sur quelque chose comme:

 DISPLAY=:0 zenity --warning --text '     .' 

Cela a fonctionné, mais chaque fois que vous vous connectez au serveur à l'aide du client SSH pour arrêter Logan, c'est un plaisir. J'ai donc décidé de tricher. J'ai pensé à la tâche de la couronne de le faire enrager selon un calendrier, mais il y avait quelques problèmes:

  1. En fait, la régularité
  2. Nous avions d'autres tâches dans la couronne, ce qui augmentait le risque de divulguer ma tâche insidieuse

D'autres options comme le script SysVInit ont été supprimées pour les mêmes raisons. J'ai donc décidé de créer une page Web publique avec le bouton «Have a Logan».

Préparation du tirage


J'ai pensé que j'aurais besoin de quelques choses pour commencer:

  1. Quelque chose qui gère l'entrée utilisateur
  2. Quelque chose exécutant des commandes arbitraires en tant qu'utilisateur Web

Je suis donc venu à:

  1. Nginx
  2. Extension FPM pour NGINX
  3. Php
  4. Package FPM pour PHP

En conséquence, j'ai créé un site avec la page de logan.html logan.html et la «page d'action» zenity.php :

logan.html
 <!-- logan.html --> <html> <head> <style type="text/css"> form button { font-size: 20px; } div.explanation { width: 400px; } </style> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="HandheldFriendly" content="true"> </head> <body> <form method="POST" action="/zenity.php"> <button> </button> </form> </body> </html> 

Il y a un petit non-sens dans les balises META pour adapter la page pour les téléphones mobiles (rappelez-vous que je la rend facile à utiliser en déplacement?) Pour ceux qui ne savent pas comment rendre le HTML dans ma tête, je vous montre à quoi il ressemble:



Lorsque le bouton est enfoncé, la demande POST vole vers une autre page, qui fait tout le sale boulot:

zenity.php
 <?php /* zenity.php */ $messages = Array( " .", " .", " .", " .", " .", " .", "       .", "   .", "   .", "   .", "    and has recovered.", "     .", "     .", "     .", "     .", "     .", "     .", " NVIDIA  .", "NVIDIA    - . ( 43)", "    wlx10bef54d395c." ); $statuses = Array("error", "warning"); $msg = $messages[array_rand($messages)]; $status = $statuses[array_rand($statuses)]; $timeout = "--timeout 10"; exec("sudo -u thedisplayuser /usr/sbin/zenity --$status --display=:0 --text ': $msg' $timeout > /dev/null &"); include 'logan.html'; ?> <div class="explanation">                ,       .   ,        // .. </div> <br /> <img src='/logan.jpg' /> 

Cette page fait un certain nombre de choses:

  1. Sélectionne un message d'erreur aléatoire
  2. Sélectionne le type de boîte de dialogue.
  3. Montre un message pendant une période de temps spécifiée (10 secondes)
  4. Il dessine un bouton et explique ce qui se passe - le tout accompagné de la drôle d'image de Logan en personne

Pour ceux qui ne peuvent toujours pas rendre HTML dans leur tête (encore une fois, espérons-le, la plupart des gens), la page ressemble à ceci:



Si vous vous demandez pourquoi la page Web est autorisée à exécuter du code de cette manière, et pourquoi le propriétaire de la session du serveur Web ( www-data ) peut exécuter des commandes en tant qu'utilisateur d'affichage ( thedisplayuser ), vous serez peut-être heureux de savoir que j'ai strictement limité cela à fichier sudoers :

 # /etc/sudoers www-data ALL=(thedisplayuser) NOPASSWD: /usr/bin/zenity 

Cette partie spécifique de la configuration permet à www-data d'exécuter uniquement / usr / bin / zenity en tant qu'utilisateur d'affichage sans mot de passe. Je l'ai fait après avoir commis des erreurs stupides dans les paramètres PHP et NGINX. J'ai ensuite envoyé l'URL à quelques amis sur le campus qui connaissent Logan.

Résultat du tirage


Louez le ciel, Logan a réagi aussi violemment que possible. S'il avait été légèrement agacé, la pensée que mes efforts avaient été vains m'aurait énervé. Mais non! Il a perdu son sang-froid. Je ne peux pas compter le nombre de redémarrages, de réinstallations de pilotes et de modifications du noyau. Je regrette seulement de n'avoir pas tourné de vidéo sur la façon dont il est devenu fou après avoir démarré VLC, quand quelqu'un a jeté un tas de fenêtres avec des messages sur les erreurs de la carte vidéo.

Mais je me suis trop emporté et Chris, notre autre colocataire, a décidé d'intervenir ...

Chasse au chasseur


Première étape


Un beau jour, alors que Logan dormait, j'ai remarqué un message d'erreur qui disait: "Max est derrière tout ça." Choooo? J'ai une blague! J'ai donc commencé à comprendre et à découvrir que quelqu'un (Chris) avait introduit cette phrase dans un ensemble de messages aléatoires dans zenity.php . Je l'ai rapidement supprimé (jusqu'à ce que Logan apprenne qu'ils le jouaient) et j'ai décidé que le plaisir était terminé. Ça y était.

Deuxième étape


Après environ une semaine, le message est apparu à nouveau. Je pensais que Chris m'a brûlé et l'a rajouté à la liste. Pas une putain de chose. Il n'était pas là. Après une étude approfondie du fichier, j'ai remarqué qu'il s'appelle maintenant /usr/sbin/zenity au lieu de /usr/bin/zenity (la valeur par défaut du système), et sudoers avait une entrée permissive correspondante. Alors, qu'est-ce que /usr/sbin/zenity ? Script shell:

 #!/bin/bash echo '.' >> /tmp/log.txt if [ 0 -eq $((RANDOM % 100)) ]; then /usr/bin/zenity --error --display=:0 --text "   ." --timeout 10 > /dev/null & else /usr/bin/zenity "$@" fi 

Eh bien, c'était le prochain niveau de merde, si jamais je rencontrais quelque chose comme ça. 99% du temps, tout fonctionnait comme il se doit, et dans le 1% restant, le message «Max se tient derrière» est apparu. J'ai supprimé le fichier (je sais, cela n'en valait pas la peine) et écrire aux sudoers ramené zenity.php à sa forme d'origine. Les messages ont cessé d'apparaître. Mais ils sont revenus.

Troisième étape


J'ai vérifié zenity.php . Rien de nouveau. /usr/sbin/zenity ? Disparu. Je suis découragé. J'ai alors décidé de regarder à l'intérieur de /usr/bin/zenity :

 #!/bin/bash # ---    --- # ---    --- # ---    --- # ---    --- # ---    --- if [ 0 -eq $((RANDOM % 70)) ]; then /usr/bin/rpmdb-client --error --display=:0 --text """"" """""" """""""""""" """"""""." --timeout 10 > /dev/null & else /usr/bin/rpmdb-client "$@" fi 

Petit bâtard rusé. Il a corrigé le binaire zenity, ce qui en fait un script bash qui fonctionne une fois et 70. Que diable? Et quel genre de rpmdb-client ? J'ai donc riposté en le changeant:

 # <> if [ 0 -eq $((RANDOM % 70)) ]; then /usr/sbin/rpmdb-client --error --display=:0 --text """"" """""" """""""""""" """"""""." --timeout 10 > /dev/null & else /usr/bin/rpmdb-client "$@" fi 

Avez-vous compris la différence? Sinon, /usr/sbin/rpmdb-client est appelé à la place de /usr/bin/rpmdb-client , qui lance un script bash qui ne fait rien. Avec assez de chance, il ne remarquera pas de personnage supplémentaire et son message n'apparaîtra jamais.

TODO: Comprenez la différence entre les exécutables ELF /usr/sbin/zenity et le /usr/bin/rpmdb-client que Chris a créé. Il y a une étrange différence dans les binaires que je n'ai pas encore compris.

Quatrième étape


J'ai décidé de renforcer la défense, jusqu'à ce que Chris remarque la différence dans une lettre décrite ci-dessus. J'ai annulé toutes mes modifications et décidé de corriger la zenity place. Une profonde gratitude à Tom Hebb (comme dans tous mes articles techniques) pour son aide. Voici ce que j'ai fait:

  1. Configuré apt pour télécharger les sources (dans ce cas, ajouter deb-src à /etc/apt/sources.list )
  2. apt-get source zenity
  3. Fabriqué un patch avec quilt :
    1. quilt new myPatch.diff
    2. Un patch pour src/msg.c qui détermine la présence du mot «Max» dans le corps du message:

      msg.c
       Index: zenity-3.18.1.1/src/msg.c =================================================================== --- zenity-3.18.1.1.orig/src/msg.c +++ zenity-3.18.1.1/src/msg.c @@ -21,6 +21,8 @@ * Authors: Glynn Foster <glynn.foster@sun.com> */ +#include <string.h> + #include "config.h" #include "zenity.h" @@ -85,6 +87,11 @@ zenity_msg (ZenityData *data, ZenityMsgD GObject *text; GObject *image; + if (strstr(msg_data->dialog_text, "Max") + || strstr(msg_data->dialog_text, "max")) { + return; + } + switch (msg_data->mode) { case ZENITY_MSG_WARNING: builder = zenity_util_load_ui_file ("zenity_warning_dialog", NULL); 
    3. quilt add src/msg.c
    4. quilt pop
  4. dpkg-source --commit
  5. dpkg-buildpackage -us -uc
  6. Je me suis rendu compte que créer et installer un nouveau paquet est plus pâle que de remplacer un binaire
  7. Remplacé tranquillement le rpmdb-client (sa zenity ) par ma version
  8. Lui tapota le dos

Ce correctif modifie le comportement de la zenity de telle manière que dès que le mot «Max» apparaît dans le texte du message, l'application ne fait rien en silence.

Conclusion


Jusqu'à la fin du mois de mars, Chris n'a jamais découvert que j'avais corrigé le binaire. En conséquence, Logan n'a pas vu un seul message avec mon nom. J'ai donc décidé de continuer le rallye jusqu'à ce que je lui dise tout après la fin du parcours. Mais à la fin des cours, nous nous sommes séparés. Bien que Logan et moi vivrons à nouveau ensemble l'année prochaine, nous ne passerons probablement pas autant de temps dans la salle pour que le rallye ait du sens. J'ai donc décidé de publier ce post avant de commencer de nouveaux trucs.

Source: https://habr.com/ru/post/fr417915/


All Articles