Maison Opération et maintenance exploitation et maintenance Linux Introduction à l'analyse du fonctionnement du système sous Linux

Introduction à l'analyse du fonctionnement du système sous Linux

May 27, 2017 am 10:00 AM
linux system 函数

Cet article analyse principalement brièvement le systèmefonction sous linux, qui a une certaine valeur de référence. Les amis intéressés peuvent se référer à l'

analyse simple du contenu pertinent de. la fonction système sous Linux est la suivante :

int
libc_system (const char *line)
{
 if (line == NULL)
  /* Check that we have a command processor available. It might
    not be available after a chroot(), for example. */
  return do_system ("exit 0") == 0;

 return do_system (line);
}
weak_alias (libc_system, system)
Copier après la connexion

Le code se trouve dans glibc/sysdeps/posix/system.c, où system est un alias faible de libc_system, et libc_system est la fonction frontale de do_system. Après avoir vérifié les paramètres, regardons la fonction do_system.

static int
do_system (const char *line)
{
 int status, save;
 pid_t pid;
 struct sigaction sa;
#ifndef _LIBC_REENTRANT
 struct sigaction intr, quit;
#endif
 sigset_t omask;

 sa.sa_handler = SIG_IGN;
 sa.sa_flags = 0;
 sigemptyset (&sa.sa_mask);

 DO_LOCK ();
 if (ADD_REF () == 0)
  {
   if (sigaction (SIGINT, &sa, &intr) < 0)
  {
   (void) SUB_REF ();
   goto out;
  }
   if (sigaction (SIGQUIT, &sa, &quit) < 0)
  {
   save = errno;
   (void) SUB_REF ();
   goto out_restore_sigint;
  }
  }
 DO_UNLOCK ();

 /* We reuse the bitmap in the &#39;sa&#39; structure. */
 sigaddset (&sa.sa_mask, SIGCHLD);
 save = errno;
 if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
  {
#ifndef _LIBC
   if (errno == ENOSYS)
  set_errno (save);
   else
#endif
  {
   DO_LOCK ();
   if (SUB_REF () == 0)
    {
     save = errno;
     (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
    out_restore_sigint:
     (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
     set_errno (save);
    }
  out:
   DO_UNLOCK ();
   return -1;
  }
  }

#ifdef CLEANUP_HANDLER
 CLEANUP_HANDLER;
#endif

#ifdef FORK
 pid = FORK ();
#else
 pid = fork ();
#endif
 if (pid == (pid_t) 0)
  {
   /* Child side. */
   const char *new_argv[4];
   new_argv[0] = SHELL_NAME;
   new_argv[1] = "-c";
   new_argv[2] = line;
   new_argv[3] = NULL;

   /* Restore the signals. */
   (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
   (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
   (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
   INIT_LOCK ();

   /* Exec the shell. */
   (void) execve (SHELL_PATH, (char *const *) new_argv, environ);
   _exit (127);
  }
 else if (pid < (pid_t) 0)
  /* The fork failed. */
  status = -1;
 else
  /* Parent side. */
  {
   /* Note the system() is a cancellation point. But since we call
   waitpid() which itself is a cancellation point we do not
   have to do anything here. */
   if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
  status = -1;
  }

#ifdef CLEANUP_HANDLER
 CLEANUP_RESET;
#endif

 save = errno;
 DO_LOCK ();
 if ((SUB_REF () == 0
    && (sigaction (SIGINT, &intr, (struct sigaction *) NULL)
    | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
   || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
  {
#ifndef _LIBC
   /* glibc cannot be used on systems without waitpid. */
   if (errno == ENOSYS)
  set_errno (save);
   else
#endif
  status = -1;
  }
 DO_UNLOCK ();

 return status;
}

do_system
Copier après la connexion

Tout d'abord, la fonction configure des gestionnaires de signaux pour gérer les signaux SIGINT et SIGQUIT. Nous ne nous en soucions pas trop ici. Les segments de code clés sont ici

#ifdef FORK
 pid = FORK ();
#else
 pid = fork ();
#endif
 if (pid == (pid_t) 0)
  {
   /* Child side. */
   const char *new_argv[4];
   new_argv[0] = SHELL_NAME;
   new_argv[1] = "-c";
   new_argv[2] = line;
   new_argv[3] = NULL;

   /* Restore the signals. */
   (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
   (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
   (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
   INIT_LOCK ();

   /* Exec the shell. */
   (void) execve (SHELL_PATH, (char *const *) new_argv, environ);
   _exit (127);
  }
 else if (pid < (pid_t) 0)
  /* The fork failed. */
  status = -1;
 else
  /* Parent side. */
  {
   /* Note the system() is a cancellation point. But since we call
   waitpid() which itself is a cancellation point we do not
   have to do anything here. */
   if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
  status = -1;
  }
Copier après la connexion
<. 🎜> Passez d'abord la fonction frontale. L'appel de l'appel système fork génère un processus enfant. Fork a deux valeurs de retour. Il renvoie le pid du processus enfant au processus parent et 0 au processus enfant. Ainsi, le processus enfant exécute 6 à 24 lignes de code et le processus parent exécute 30 à 35 lignes de code.

La logique du processus enfant est très claire. execve est appelé pour exécuter le programme spécifié par SHELL_PATH Les paramètres sont passés via new_argv, et la variable d'environnement

est la variable globale environ.

SHELL_PATH et SHELL_NAME sont définis comme suit

#define  SHELL_PATH  "/bin/sh"  /* Path of the shell. */
#define  SHELL_NAME  "sh"    /* Name to give it. */
Copier après la connexion
En fait, il génère un sous-processus et appelle

/bin/sh -c "command" Exécutez la commande transmise au système.

Ce qui suit est en fait la raison et l'objet de mes recherches sur la fonction système :

Dans la question pwn de CTF, l'appel de la fonction système via un débordement de pile échoue parfois, j'ai entendu les maîtres dire. que la variable d'environnement est écrasée, mais j'ai toujours été confus. Je l'ai étudié en profondeur aujourd'hui et j'ai finalement compris.

Les variables d'environnement requises par la fonction système ici sont stockées dans la variable globale environ, alors quel est le contenu de cette variable.

environ est défini dans glibc/csu/libc-start.c. Examinons quelques déclarations clés.

# define LIBC_START_MAIN libc_start_main
Copier après la connexion
libc_start_main est la fonction appelée par _start, qui implique un travail d'initialisation au début du programme. Si vous ne comprenez pas ces termes, vous pouvez lire cet article. Ensuite, regardez la fonction LIBC_START_MAIN.

STATIC int
LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
     int argc, char **argv,
#ifdef LIBC_START_MAIN_AUXVEC_ARG
     ElfW(auxv_t) *auxvec,
#endif
     typeof (main) init,
     void (*fini) (void),
     void (*rtld_fini) (void), void *stack_end)
{
 /* Result of the &#39;main&#39; function. */
 int result;

 libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;

#ifndef SHARED
 char **ev = &argv[argc + 1];

 environ = ev;

 /* Store the lowest stack address. This is done in ld.so if this is
   the code for the DSO. */
 libc_stack_end = stack_end;

    ......
 /* Nothing fancy, just call the function. */
 result = main (argc, argv, environ MAIN_AUXVEC_PARAM);
#endif

 exit (result);
}
Copier après la connexion
On peut voir que la valeur d'environ est définie à la ligne 19 sans définir SHARED. Avant que le programme de démarrage n'appelle LIBC_START_MAIN, il enregistrera d'abord les variables d'environnement et la

chaîne dans argv (en fait, elle est enregistrée sur la pile), puis enregistrera séquentiellement les adresses de chaque chaîne dans la variable d'environnement et chaque chaîne dans argv. L'adresse de la chaîne d'élément et argc sont poussées sur la pile, donc la variable d'environnement tableau doit être située directement derrière le tableau argv, séparée par une adresse vide. Ainsi, l'instruction &argv[argc + 1] à la ligne 17 prend la première adresse du tableau de variables d'environnement sur la pile, l'enregistre dans ev et enfin l'enregistre dans environ. La ligne 203 appelle la fonction principale, qui poussera la valeur environ sur la pile. Il n'y a aucun problème si elle est écrasée par un débordement de pile, tant que l'adresse dans environ n'est pas écrasée.

Ainsi, lorsque la longueur du débordement de pile est trop grande et que le contenu du débordement couvre le contenu important de l'adresse dans environ, l'appel de la fonction système échouera. La distance entre la variable d'environnement spécifique et l'adresse de débordement peut être vérifiée en l'interrompant dans _start.


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

À quoi sert Linux? À quoi sert Linux? Apr 12, 2025 am 12:20 AM

Linux convient aux serveurs, aux environnements de développement et aux systèmes intégrés. 1. En tant que système d'exploitation de serveurs, Linux est stable et efficace, et est souvent utilisé pour déployer des applications à haute monnaie. 2. En tant qu'environnement de développement, Linux fournit des outils de ligne de commande efficaces et des systèmes de gestion des packages pour améliorer l'efficacité du développement. 3. Dans les systèmes intégrés, Linux est léger et personnalisable, adapté aux environnements avec des ressources limitées.

Utilisation de Docker avec Linux: un guide complet Utilisation de Docker avec Linux: un guide complet Apr 12, 2025 am 12:07 AM

L'utilisation de Docker sur Linux peut améliorer l'efficacité du développement et du déploiement. 1. Installez Docker: utilisez des scripts pour installer Docker sur Ubuntu. 2. Vérifiez l'installation: exécutez Sudodockerrunhello-world. 3. Utilisation de base: Créez un conteneur Nginx Dockerrunrun-namemy-nginx-p8080: 80-dnginx. 4. Utilisation avancée: créez une image personnalisée, construisez et exécutez à l'aide de dockerfile. 5. Optimisation et meilleures pratiques: suivez les meilleures pratiques pour écrire des dockerfiles à l'aide de builds en plusieurs étapes et de dockercosive.

Comment démarrer Apache Comment démarrer Apache Apr 13, 2025 pm 01:06 PM

Les étapes pour démarrer Apache sont les suivantes: Installez Apache (Commande: Sudo apt-get install Apache2 ou téléchargez-le à partir du site officiel) Start Apache (Linux: Sudo SystemCTL Démarrer Apache2; Windows: Cliquez avec le bouton droit sur le service "APACHE2.4" et SELECT ") Vérifiez si elle a été lancée (Linux: SUDO SYSTEMCTL STATURE APACHE2; (Facultatif, Linux: Sudo SystemCTL

Que faire si le port Apache80 est occupé Que faire si le port Apache80 est occupé Apr 13, 2025 pm 01:24 PM

Lorsque le port Apache 80 est occupé, la solution est la suivante: découvrez le processus qui occupe le port et fermez-le. Vérifiez les paramètres du pare-feu pour vous assurer qu'Apache n'est pas bloqué. Si la méthode ci-dessus ne fonctionne pas, veuillez reconfigurer Apache pour utiliser un port différent. Redémarrez le service Apache.

Comment commencer la surveillance d'Oracle Comment commencer la surveillance d'Oracle Apr 12, 2025 am 06:00 AM

Les étapes pour démarrer un écouteur Oracle sont les suivantes: cochez l'état de l'écouteur (en utilisant la commande LSNRCTL Status) pour Windows, démarrez le service "TNS Écouteur" dans Oracle Services Manager pour Linux et Unix, utilisez la commande LSNRCTL LSNRCTL pour démarrer l'auditeur pour exécuter la commande LSNRCTL STAT

Comment surveiller les performances de Nginx SSL sur Debian Comment surveiller les performances de Nginx SSL sur Debian Apr 12, 2025 pm 10:18 PM

Cet article décrit comment surveiller efficacement les performances SSL des serveurs Nginx sur les systèmes Debian. Nous utiliserons NginxExporter pour exporter des données d'état NGINX à Prometheus, puis l'afficher visuellement via Grafana. Étape 1: Configuration de Nginx Tout d'abord, nous devons activer le module Stub_Status dans le fichier de configuration NGINX pour obtenir les informations d'état de Nginx. Ajoutez l'extrait suivant dans votre fichier de configuration Nginx (généralement situé dans /etc/nginx/nginx.conf ou son fichier incluant): emplacement / nginx_status {Stub_status

Comment configurer un bac de recyclage dans le système Debian Comment configurer un bac de recyclage dans le système Debian Apr 12, 2025 pm 10:51 PM

Cet article présente deux méthodes de configuration d'un bac de recyclage dans un système Debian: une interface graphique et une ligne de commande. Méthode 1: Utilisez l'interface graphique Nautilus pour ouvrir le gestionnaire de fichiers: Recherchez et démarrez le gestionnaire de fichiers Nautilus (généralement appelé "fichier") dans le menu de bureau ou d'application. Trouvez le bac de recyclage: recherchez le dossier de bac de recyclage dans la barre de navigation gauche. S'il n'est pas trouvé, essayez de cliquer sur "Autre emplacement" ou "ordinateur" pour rechercher. Configurer les propriétés du bac de recyclage: cliquez avec le bouton droit sur "Recycler le bac" et sélectionnez "Propriétés". Dans la fenêtre Propriétés, vous pouvez ajuster les paramètres suivants: Taille maximale: Limitez l'espace disque disponible dans le bac de recyclage. Temps de rétention: définissez la préservation avant que le fichier ne soit automatiquement supprimé dans le bac de recyclage

Comment redémarrer le serveur Apache Comment redémarrer le serveur Apache Apr 13, 2025 pm 01:12 PM

Pour redémarrer le serveur Apache, suivez ces étapes: Linux / MacOS: Exécutez Sudo SystemCTL Restart Apache2. Windows: Exécutez net stop apache2.4 puis net start apache2.4. Exécuter netstat -a | Findstr 80 pour vérifier l'état du serveur.

See all articles