function hijacking
Σ' αυτό το post σημειώνουμε μία παλιά τεχνική για function hijacking βασισμένη στην LD_PRELOAD environmental variable. Στον παρακάτω κώδικα θα κάνουμε hijack την strcmp() ενός προγράμματος, αλλοιώνοντας έτσι τη ροή του.
Όταν κάνουμε compile ένα πρόγραμμα με τον gcc έχουμε την επιλογή για static ή dynamic compilation. Κατά το static οι βιβλιοθήκες (λάϊμπραρεις) από τις οποίες εξαρτάται το πρόγραμμά μας θα συμπεριληφθούν στο εκτελέσιμο που θα παραχθεί από τον gcc. Στο dynamic compilation το εκτελέσιμο γίνετε linked με τις libraries.
Η εντολή ldd δείχνει από ποιες libraries εξαρτάται ένα πρόγραμμα.
mpeimpiii@gohan:~# ldd /usr/bin/ssh
linux-gate.so.1 => (0xffffe000)
libresolv.so.2 => /lib/tls/libresolv.so.2 (0xb7f4c000)
libcrypto.so.0.9.8 => /usr/lib/i686/cmov/libcrypto.so.0.9.8 (0xb7e10000) libutil.so.1 => /lib/tls/libutil.so.1 (0xb7e0b000)
libz.so.1 => /usr/lib/libz.so.1 (0xb7df7000)
libnsl.so.1 => /lib/tls/libnsl.so.1 (0xb7de1000)
libcrypt.so.1 => /lib/tls/libcrypt.so.1 (0xb7db3000)
libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0xb7d97000)
libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0xb7d1b000)
libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0xb7cf5000)
libcom_err.so.2 => /lib/libcom_err.so.2 (0xb7cf2000)
libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0xb7ced000)
libc.so.6 => /lib/tls/libc.so.6 (0xb7bbb000)
libdl.so.2 => /lib/tls/libdl.so.2 (0xb7bb7000)
/lib/ld-linux.so.2 (0xb7f6d000)
mpeimpiii@gohan:~#
Έτσι μπορούμε να ξέρουμε ποιες libraries χρειάζεται/καλεί το ssh. Δίνοντας το filename μιας library σαν τιμή στην LD_PRELOAD environmental library δημιουργούμε μία δυναμική σύνδεση του προγράμματός μας με αυτή τη βιβλιοθήκη. Οι συνδέσεις μέσω της LD_PRELOAD έχουν προτεραιότητα σε σχέση με τις βιβλιοθήκες που χρησιμοποιήθηκαν για το dynamic compilation.
Για παράδειγμα
mpeimpiii@gohan:~# LD_PRELOAD=”./px.so” /usr/bin/test
Θα ψάξει πρώτα τη library px.so και μετά όλες όσες χρειάζεται.
Στο δικό μας παράδειγμα έχουμε ένα πρόγραμμα το οποίο δέχεται ένα input από τον χρήστη και το συγκρίνει με ένα αποθηκευμένο char [].
[c]
#include <stdio.h>
#include <string.h>
int
main (int argc, char **argv)
{
char serial[] = "123456789";
if (argc < 2)
{
fprintf (stderr, "usage: %s <give-serial-number>n", argv[0]);
return 0;
}
if (!strncmp (serial, argv[1], strlen (serial)))
{
fprintf (stdout, "Product registered!n");
return 1;
}
else
{
fprintf (stderr, "You gave a wrong serial numbern");
}
return 0;
}
[/c]
mpeimpiii@gohan:~/lab/utils/hijack$ ldd ./prog
linux-gate.so.1 => (0xffffe000)
libc.so.6 => /lib/tls/libc.so.6 (0xb7e5e000)
/lib/ld-linux.so.2 (0xb7fa3000)
mpeimpiii@gohan:~/lab/utils/hijack$
Αυτό που θα κάνουμε είναι να φτιάξουμε μία library hijackme.so με τη function που θέλουμε να κάνουμε hijack, στην περίπτωσή μας την strncmp().
[c]
#include <stdio.h>
#include <string.h>
int
strncmp (const char *s1, const char *s2, size_t len)
{
printf ("S1=%sn", s1);
printf ("S2=%sn", s2);
return 0; //always return true
}
[/c]
mpeimpiii@gohan:~/lab/utils/hijack$ gcc -shared -o hijackme.so hijackme.c
Τώρα αν τρέξουμε το ./prog με ένα τυχαίο input έχουμε το παρακάτω αποτέλεσμα:
mpeimpiii@gohan:~/lab/utils/hijack$ ./p abc1234567
You gave a wrong serial number
mpeimpiii@gohan:~/lab/utils/hijack$
Αν όμως δώσουμε την τιμή του hijack.so στην LD_PRELOAD θα δούμε το εξής:
mpeimpiii@gohan:~/lab/utils/hijack$ LD_PRELOAD="./hijackme.so" ./prog abc1234567
S1=123456789
S2=123456
Product registered!
mpeimpiii@gohan:~/lab/utils/hijack$

Leave a Reply