Le funzioni della libreria C in binario ELF32 collegato staticamente non usano più int 0x80

2

Ho praticato la codifica della shell su Linux per un po '. Ho usato una VM per sviluppare e testare il mio codice shell. La VM ha funzionato all'interno di VMware workstation 12 pro, su Windows 10. Tutto andava bene e potevo usare il solito int 0x80 per passare alla modalità kernel fino ad ora. Di recente, ho aggiornato il mio Windows 10 dal 1607 al 1703 e ho utilizzato lo stesso VMware e la stessa macchina virtuale Linux. Tuttavia, non vi è alcun 0x80 int in qualsiasi momento nel richiamo di syscall ora. Ho compilato gli stessi codici sorgente che ho provato in precedenza, che prima mostravano int 0x80 ora non li mostro più. Ad esempio, il dump dell'assembler di gdb per la funzione exit ha le istruzioni come

<Address> jmp DWORD PTR ds: <address>
<Address> push 0x8
<Address> jmp  <Address>

Mi chiedo quale potrebbe essere la ragione.

EDITS 1. Non ho aggiornato il mio Linux 2. Non ho aggiornato il mio VMware 3. Utilizzare un VM 32 ma Linux su una macchina a 64 bit.

    
posta user148898 10.06.2017 - 20:58
fonte

1 risposta

1

int $0x80 viene infatti eseguito da alcune delle funzioni della libreria C nel binario collegato staticamente, ma non da quasi altrettante funzioni di libreria che ci si aspetterebbe dato quante funzioni di libreria sono incluse nel binario:

$ objdump -dj .text binary | grep "cd 80"
 8049401:   cd 80                   int    $0x80
 806c465:   cd 80                   int    $0x80
 806ea5e:   cd 80                   int    $0x80
 806f040:   cd 80                   int    $0x80
 807b5c5:   cd 80                   int    $0x80
 807b5ce:   cd 80                   int    $0x80
 8092651:   cd 80                   int    $0x80
 8094092:   cd 80                   int    $0x80

Esaminiamo alcune funzioni della libreria per vedere cosa sta succedendo:

_exit

$ objdump -dj .text binary | grep -A10 "<_exit>:"
0806c451 <_exit>:
 806c451:   8b 5c 24 04             mov    0x4(%esp),%ebx
 806c455:   b8 fc 00 00 00          mov    $0xfc,%eax
 806c45a:   ff 15 f0 a9 0e 08       call   *0x80ea9f0
 806c460:   b8 01 00 00 00          mov    $0x1,%eax
 806c465:   cd 80                   int    $0x80            <---
 806c467:   f4                      hlt    
 806c468:   66 90                   xchg   %ax,%ax
 806c46a:   66 90                   xchg   %ax,%ax
 806c46c:   66 90                   xchg   %ax,%ax
 806c46e:   66 90                   xchg   %ax,%ax

Nessun problema qui. Tieni presente che exit è diverso da _exit .

__execve :

$ objdump -dj .text binary | grep -A10 "<__execve>:"
0806c470 <__execve>:
 806c470:   53                      push   %ebx
 806c471:   8b 54 24 10             mov    0x10(%esp),%edx
 806c475:   8b 4c 24 0c             mov    0xc(%esp),%ecx
 806c479:   8b 5c 24 08             mov    0x8(%esp),%ebx
 806c47d:   b8 0b 00 00 00          mov    $0xb,%eax     <-- 11 in eax == sys_execve
 806c482:   ff 15 f0 a9 0e 08       call   *0x80ea9f0
 806c488:   3d 00 f0 ff ff          cmp    $0xfffff000,%eax
 806c48d:   77 02                   ja     806c491 <__execve+0x21>
 806c48f:   5b                      pop    %ebx
 806c490:   c3                      ret

__libc_open e __open_nocancel :

0806cdb0 <__libc_open>:
 806cdb0:   65 83 3d 0c 00 00 00    cmpl   $0x0,%gs:0xc
 806cdb7:   00 
 806cdb8:   75 25                   jne    806cddf <__open_nocancel+0x25>

0806cdba <__open_nocancel>:
 806cdba:   53                      push   %ebx
 806cdbb:   8b 54 24 10             mov    0x10(%esp),%edx
 806cdbf:   8b 4c 24 0c             mov    0xc(%esp),%ecx
 806cdc3:   8b 5c 24 08             mov    0x8(%esp),%ebx
 806cdc7:   b8 05 00 00 00          mov    $0x5,%eax      <-- 5 in eax == sys_open
 806cdcc:   ff 15 f0 a9 0e 08       call   *0x80ea9f0
 806cdd2:   5b                      pop    %ebx
 806cdd3:   3d 01 f0 ff ff          cmp    $0xfffff001,%eax
 806cdd8:   0f 83 82 32 00 00       jae    8070060 <__syscall_error>
 806cdde:   c3                      ret    
 806cddf:   e8 cc 1b 00 00          call   806e9b0 <__libc_enable_asynccancel>
 806cde4:   50                      push   %eax
 806cde5:   53                      push   %ebx
 806cde6:   8b 54 24 14             mov    0x14(%esp),%edx
 806cdea:   8b 4c 24 10             mov    0x10(%esp),%ecx
 806cdee:   8b 5c 24 0c             mov    0xc(%esp),%ebx
 806cdf2:   b8 05 00 00 00          mov    $0x5,%eax      <-- 5 in eax == sys_open
 806cdf7:   ff 15 f0 a9 0e 08       call   *0x80ea9f0

Sembra che molte di queste funzioni di libreria stiano effettuando chiamate di sistema attraverso un intermediario che inizia all'indirizzo in posizione 0x80ea9f0 che si trova nella sezione .data .

$ readelf -SW binary

[23] .got.plt          PROGBITS        080ea000 0a1000 000044 04  WA  0   0  4
[24] .data             PROGBITS        080ea060 0a1060 000f20 00  WA  0   0 32
[25] .bss              NOBITS          080eaf80 0a1f80 00136c 00  WA  0   0 32
[26] __libc_freeres_ptrs NOBITS        080ec2ec 0a1f80 000018 00  WA  0   0  4
[27] .comment          PROGBITS        00000000 0a1f80 00002b 01  MS  0   0  1
[28] .shstrtab         STRTAB          00000000 0a1fab 00014c 00      0   0  1

Diamo uno sguardo alla sezione .data :

readelf -x .data binary | less :

0x080ea9d0 00000000 00000000 00000000 00000000 ................
0x080ea9e0 00000000 01000000 00000000 00000000 ................
0x080ea9f0 40f00608 b0ad0908 07000000 7f030000 @...............
0x080eaa00 03000000 02000000 00100000 107a0908 .............z..

Ricordando che x86 è little-endian, si legge 40f00608 come 0806f040 .

Buone notizie: 0x0806f040 è nella sezione .text del file binario:

[ 3] .rel.plt          REL             08048138 000138 000070 08   A  0   5  4
[ 4] .init             PROGBITS        080481a8 0001a8 000023 00  AX  0   0  4
[ 5] .plt              PROGBITS        080481d0 0001d0 0000e0 00  AX  0   0 16
[ 6] .text             PROGBITS        080482b0 0002b0 075b64 00  AX  0   0 16
[ 7] __libc_freeres_fn PROGBITS        080bde20 075e20 000b36 00  AX  0   0 16

Diamo un'occhiata al codice all'indirizzo:

$ objdump -dj .text binary | grep -A5 0806f040
0806f040 <_dl_sysinfo_int80>:
 806f040:   cd 80                   int    $0x80      <--- !!!!!!!!!
 806f042:   c3                      ret    
 806f043:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
 806f049:   8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi

L'indirizzo di memoria 0x0806f040 contiene la prima istruzione della funzione _dl_sysinfo_int80 , che è l'istruzione int seguita dal vettore di interruzione 128.

In conclusione, ogni funzione di libreria che chiama *0x80ea9f0 sta effettuando una chiamata di sistema tramite la funzione _dl_sysinfo_int80 . Nessuna analisi dinamica necessaria.

    
risposta data 05.07.2017 - 22:31
fonte

Leggi altre domande sui tag