int $0x80
es ejecutado por algunas de las funciones de la biblioteca C en el binario estáticamente vinculado, pero no por tantas funciones de la biblioteca como se esperaría dada la cantidad de funciones de la biblioteca que se incluyen en el 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
Examinemos algunas de las funciones de la biblioteca para ver qué está pasando:
_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
No hay problemas aquí. Tenga en cuenta que exit
es diferente a _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
y __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
Parece que muchas de estas funciones de biblioteca están haciendo llamadas al sistema a través de un intermediario que comienza en la dirección en la ubicación 0x80ea9f0
, que se encuentra en la sección .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
Echemos un vistazo dentro de la sección .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..
Recordando que x86 es little-endian, leemos 40f00608
como 0806f040
.
Buenas noticias: 0x0806f040
está en la sección .text
del 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
Echemos un vistazo al código en esa dirección:
$ 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
La dirección de memoria 0x0806f040
contiene la primera instrucción de la función _dl_sysinfo_int80
, que es la instrucción int
seguida por el vector de interrupción 128.
En conclusión, cada función de biblioteca que llama a *0x80ea9f0
está haciendo una llamada al sistema a través de la función _dl_sysinfo_int80
. No es necesario un análisis dinámico.