Creation De Binaires Multiplateformes.pdf

(243 KB) Pobierz
Création d'un binaire multiplateforme
Depuis quelques temps, nous voyons apparaître ça et là quelques virus multiplateformes. Nous 
citerons par exemple Winux, virus qui a pour cible les OS Linux et Windows...
Bien entendu, les virus ne sont pas les seuls binaires (car on parle ici de binaires, et non de scripts) à 
pouvoir profiter de cette avantageuse programmation. Bien qu’ils soient peu répandus, il peut 
s'avérer intéressant de proposer de tels binaires dans le cas par exemple d'un programme 
d'installation ou autre. En effet, les utilisateurs n'ont alors plus à se préoccuper de savoir à quel OS 
est destiné le programme, le binaire détectant automatiquement son environnement d'installation.
Ceci n'est qu'un exemple parmi tant d'autres et les possibilités d'utilisation sont multiples. Les virus 
multiplateformes semblent toutefois être un des " débouchés " les plus évidents.
Nous verrons ainsi au cours de l'article comment créer un tel binaire. Toute l'astuce repose sur une 
manipulation des en­têtes du binaire et sur les aspects de relocation du segment de code.
Cette étude s'appuie sur un travail préalable de Kuno Woudt (warp­tmt@dds.nl) et Rafal Skoczylas 
(nils@secprog.org).
I. Linux
Il existe plusieurs formats d'exécutables sous Linux. Nous nous intéresserons plus particulièrement 
au format ELF, le plus répandu sous cet OS.
Nous ne reviendrons pas en détail sur ce format, toute la documentation étant largement accessible 
par Internet. Rappelons juste que tout binaire ELF présente un en­tête qui renseigne sur le 
fonctionnement du binaire (format, type de binaire, point d'entrée, taille des sections et autres).
Nous commençons par créer un programme en assembleur tout simple qui affichera un message 
type Hello Strange World... pour ne pas faillir à la tradition. Nous implémenterons nous­mêmes le 
header ELF, de manière à pouvoir le changer par la suite (pas de linker).
Voici donc le corps tout simple d'un programme de ce type :
; Hello Strange World
4 Linux.
;
; Propriétés : Binaire exécutable sur Linux.
; Assemblage : nasm -f bin hello_linux.asm -o hello_linux
BITS 32
%define ELF_RELOC 0x08048000
ELF
%define __NR_write
4
%define __NR_read
3
; 1ere étape : l'en-tête ELF
ehdr
db
db
db
db
db
db
db
db
times 8 db
0x7F
'E'
'L'
'F'
1
1
1
0
0
;
;
;
;
;
;
;
;
;
ELF header
EI_MAG0
EI_MAG1
EI_MAG2
EI_MAG3
EI_CLASS: 32-bit objects
EI_DATA: ELFDATA2LSB
EI_VERSION: EV_CURRENT
EI_PAD
; Adresse de relocation traditionnelle pour un
; EI_NIDENT
dw
dw
dd
dd
dd
dd
dd
dw
dw
2
3
1
_start_unx + ELF_RELOC
phdr
0
0
ehdrsize
phdrsize
;
;
;
;
;
;
;
;
;
e_type
e_machine
e_version
e_entry
e_phoff
e_shoff
e_flags (unused on intel)
e_ehsize
e_phentsize
; Ensuite, nous créons un en-tête de programme...
; Il convient de noter que les 8 premiers octets de phdr cohabitent avec la
; fin de l'en-tête ELF, les valeurs étant identiques...
phdr
dw
dw
dw
dw
equ
dd
dd
dd
dd
dd
dd
phdrsize
_start_unx:
mov
mov
call
call
equ
ecx,
edx,
print
exit
1
0
0
0
$ - ehdr
ELF_RELOC
ELF_RELOC
filesize
filesize
5
0x1000
$ - phdr
;
;
;
;
;
Elf32_Phdr
e_phnum
e_shentsize
e_shnum
e_shstrndx
; p_type
; p_offset
ehdrsize
; Fin de l'entête ELF
; p_vaddr
; p_paddr (ignored)
; p_filesz
; p_memsz
; p_flags
; p_align
; Fin de l'en-tête de programme
hello_unx_msg + ELF_RELOC
hello_unx_msg_length
;-----------------------------------------------
; Définitions de quelques procédures générales |
;-----------------------------------------------
; Print (ecx = string pointer, edx = length)
; ------------------------------------------
print:
xor
eax, eax
mov
ebx, eax
mov
al, __NR_write
int
80h
ret
; Exit function
; -------------
exit:
xor
mov
inc
int
ret
eax, eax
ebx, eax
al
80h
;----------
; Données |
;----------
hello_unx_msg
db
hello_unx_msg_length equ
filesize
equ
$ - $$
"Hello Strange Linux World...", 10, 0
$ - hello_unx_msg
Après assemblage, le programme fonctionne de la manière escomptée et nous affiche le message 
voulu, avant de quitter.
Intéressons­nous maintenant aux programmes destinés aux environnements tels que Windows et 
DOS.
II. DOS
Dans le cas précis d'un binaire DOS, nous codons un .COM. Les fichiers .COM n'ont aucun header 
et exécutent tout simplement les instructions depuis les premiers octets du fichier. Nous 
programmons, toujours en assembleur, un mini binaire qui affiche un texte sous DOS pour 
commencer.
;
; Hello Strange World
4 DOS.
;
; Propriétés : Binaire exécutable sur DOS
; Assemblage : nasm -f bin hello_dos.asm -o hello_dos.com
org 0
%define COM_RELOC 0x100
mov
mov
int
mov
int
hello_dos_msg
dx, hello_dos_msg + COM_RELOC
ah, 0x09
0x21
ax, 0x4C00
0x21
db
"Hello strange dos world...", 13, 10, "$"
Il est possible de faire coexister deux formats dans un même exécutable en exploitant les propriétés 
de ces formats. Voyons cela...
III. Faire coexister ces formats...
À la différence d'un .COM, un binaire ELF commence toujours par un header qui détermine les 
paramètres propres au fichier :
yanisto@kaya:~/Multi-Platform$ readelf -h hello_linux
En-tête ELF:
Magique:
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Classe:
ELF32
Données:
complément à 2, système little endian
Version:
OS/ABI:
...
1 (current)
UNIX - System V
Ce header comporte certaines données indispensables au bon fonctionnement du binaire ELF qu'il 
nous faut impérativement conserver dans notre binaire généraliste. D'autres données pourront en 
revanche être écrasées (version ABI notamment, fin du champ e_ident de l'en­tête ELF cf. elf(5)).
À ce point, nous pourrions nous dire que cela risque d'empêcher la coexistence avec un format 
.COM, qui, lui, exécute les instructions en commençant par le début de l'exécutable, c'est­à­dire 
notre en­tête ELF. Il n'en est rien, car les octets du header se traduisent en instructions tout à fait 
valides :
yanisto@kaya:~/Multi-Platform$ ndisasm -a hello_linux|head
00000000
00000002
00000003
00000004
00000006
00000008
0000000A
0000000C
0000000E
00000010
7F45
4C
46
0101
0100
0000
0000
0000
0000
0200
jg 0x47
dec sp
inc si
add [bx+di],ax
add [bx+si],ax
add [bx+si],al
add [bx+si],al
add [bx+si],al
add [bx+si],al
add al,[bx+si]
(16 bits)
La première instruction est un saut conditionnel, pour lequel nous ne contrôlons pas le résultat. Il 
faut donc prendre en compte les 2 possibilités :
Le saut est exécuté et il faut qu'à 0x47 octets de là se retrouvent nos instructions DOS valides 
pour qu'elles soient immédiatement exécutées. 
Le saut n'est pas exécuté et les octets suivants vont être lus. Nous allons donc devoir 
compenser (annuler) toutes les instructions induites par l'existence du header. Par exemple, la 
séquence dec sp; inc si sera annulée par dec si; inc sp. Nous profitons du fait que tout l'en­
tête n'est pas indispensable (version ABI...) au bon fonctionnement pour insérer un saut dans 
l'en­tête (qui ne sera pas exécuté dans le ELF, mais le sera dans le .COM. 
Traduisons cela en assembleur :
; Hello Strange World
4 Linux \& DOS.
;
; Propriétés : Binaire exécutable sur Linux \& DOS
; Assemblage : nasm -f bin hello_multi.asm -o hello_multi
BITS 32
%define ELF_RELOC 0x08048000
ELF
%define COM_RELOC 0x100
COM
%define __NR_write
%define __NR_read
4
3
; Adresse de relocation traditionnelle pour un
; Adresse de relocation traditionnelle pour un
; 1ere étape : l'en-tête ELF
ehdr
db
db
db
db
db
db
db
db
0x7F
'E'
'L'
'F'
1
1
1
0
;
;
;
;
;
;
;
;
;
ELF header
EI_MAG0
EI_MAG1
EI_MAG2
EI_MAG3
EI_CLASS: 32-bit objects
EI_DATA: ELFDATA2LSB
EI_VERSION: EV_CURRENT
EI_PAD
jmp short _start_dos
précédentes
times 6 db
dw
dw
dd
dd
dd
dd
dd
dw
dw
phdr
dw
dw
dw
dw
ehdrsize
equ
dd
dd
dd
dd
dd
dd
phdrsize
equ
1
0
0
0
$ - ehdr
ELF_RELOC
ELF_RELOC
filesize
filesize
5
0x1000
$ - phdr
0
; saut "Tobogan" pour DOS qui
; compense les instructions
; EI_NIDENT (8-2 = 6...)
;
;
;
;
;
;
;
;
;
e_type
e_machine
e_version
e_entry
e_phoff
e_shoff
e_flags (unused on intel)
e_ehsize
e_phentsize
; p_type
; p_offset
2
3
1
_start_unx + ELF_RELOC
phdr
0
0
ehdrsize
phdrsize
;
;
;
;
;
Elf32_Phdr
e_phnum
e_shentsize
e_shnum
e_shstrndx
; Fin de l'entête ELF
;
;
;
;
;
;
p_vaddr
p_paddr (ignored)
p_filesz
p_memsz
p_flags
p_align
; Fin de l'en-tête de programme
; ---------------( Code DOS )-------------
BITS 16
_start_dos:
.compensation
;00000000 7F45
;00000002 4C
;00000003 46
;00000004 0101
;00000006 0100
sub
sub
dec
inc
[bx+si],ax
[bx+di],ax
si
sp
dx, hello_dos_msg + COM_RELOC
jg 0x47
dec sp
inc si
add [bx+di],ax
add [bx+si],ax
.affichage
mov
Zgłoś jeśli naruszono regulamin