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.