
Boîte à outils de greffage de sections de binaires ELF pour la livraison de charges utiles sans stage, permettant l'attachement de charges utiles sur le terrain, l'évasion de signatures et la résistance au chargement statique/dynamique via la manipulation personnalisée de sections ELF.
.data.payload.h :
const data[3432] = {
0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
...
0x00, 0xff, 0x23
};
Réalisé manuellement ou avec des outils comme bin2c ou xxd -i payload.bin > payload.h avec inclusion ultérieure du fichier d’en-tête.
Stocker les charges utiles dans .text et .data de manière générique est également une mauvaise idée en raison de la facilité du traçage de chargement et de l’introspection des sémantiques comportementales du chargement de données pour exécution.
__attribute__. C’est un peu mieux mais reste bien traçable en raison de la façon dont ELF est créé et chargé.char stack[10000] __attribute__ ((section ("binstack"))) = {
0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
...
0x00, 0xff, 0x23 };
int init_data __attribute__ ((section ("bindata"))) = 0;
main()
{
/* Initialiser le pointeur de pile */
init_sp (stack + sizeof (stack));
/* Initialiser les données initialisées */
memcpy (&init_data, &data, &edata - &data);
}
Une directive de type .incbin dépendante de l’assembleur peut créer une section et intégrer une charge utile.
Ex : gcc -c payload.s ou ld -r -b payload.bin -o payload.o
.section .bindata
.global payload_start
.type payload_start, @object
.section .binddata
.balign 64
payload_start:
.incbin "payload.bin"
.balign 1
payload_end:
.byte 0
Avec récupération ultérieure dans le chargeur :
int main(void) {
extern uint8_t payload_start;
uint8_t *ptrPayload = &payload_start;
...
}
Note : Nous pouvons inclure un ELF entièrement fonctionnel dans le payload.bin, ce qui est important pour créer des binaires « fat », contenant des éléments de plusieurs toolkits.
Note : Des outils plus ergonomiques existent pour accomplir la tâche, comme INCBIN de @graphitemaster [lien]
Une variante sur le thème est l’ASM en ligne comme ceci :
/* Données d'image brutes pour toutes les images intégrées */
#undef EMBED
#define EMBED( _index, _path, _name ) \
extern char embedded_image_ ## _index ## _data[]; \
extern char embedded_image_ ## _index ## _len[]; \
__asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t" \
"\nembedded_image_" #_index "_data:\n\t" \
".incbin \"" _path "\"\n\t" \
"\nembedded_image_" #_index "_end:\n\t" \
".equ embedded_image_" #_index "_len, " \
"( embedded_image_" #_index "_end - " \
" embedded_image_" #_index "_data )\n\t" \
".previous\n\t" );
EMBED_ALL
/* Structures d'image pour toutes les images intégrées */
#undef EMBED
#define EMBED( _index, _path, _name ) { \
.refcnt = REF_INIT ( ref_no_free ), \
.name = _name, \
.data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \
.len = ( size_t ) embedded_image_ ## _index ## _len, \
},
static struct image embedded_images[] = {
EMBED_ALL
};
Note : Remarquez PROGBITS dans la définition d’une section, cela sera important.
L'inclusion binaire de la charge utile via compilateur/éditeur de liens n'est pas idéale
Il y a des compromis :

Le type de section et les indicateurs définis sur la nouvelle section contenant déterminent si le chargeur OS charge la section en mémoire lors du lancement de l’exécutable. Certaines sections sont chargées automatiquement par défaut, d’autres non (par exemple .symtab, .strtab).
En tant qu’offensif, quelles efficacités pouvons-nous en tirer ?
Nous pouvons éviter de définir des indicateurs sur les sections qui supposent un chargement par défaut en mémoire.
Nous pouvons utiliser un type de section différent qui ne charge pas en mémoire.
Un fournisseur ou un ingénieur système peut avoir besoin de marquer un fichier objet avec des informations spéciales que d’autres programmes peuvent vérifier pour la conformité ou la compatibilité. Les sections de type
SHT_NOTEet les éléments d’en-tête de programme de typePT_NOTEpeuvent être utilisés à cette fin.
Dans ce dernier cas, nous pouvons voir l’utilisation de ce type de section dans les binaires système :
$ readelf --sections /bin/tar | grep NOTE
[ 2] .note.gnu.bu[...] NOTE 00000000000002c4 000002c4
[ 3] .note.ABI-tag NOTE 00000000000002e8 000002e8
Et inspecter leur contenu :
$ readelf -p .note.ABI-tag /bin/tar
String dump of section '.note.ABI-tag':
[ c] GNU
Le résultat final de la création d’une section SHT_NOTE ressemblera à ceci dans l’ELF :

Bonus : SHT_NOTE nous donne une structure si nous en avons besoin (et nous l’utiliserons plus loin) :
