αž€αŸ†αž–αž»αž„αžšαž€αž˜αžΎαž› LD_PRELOAD

αž€αŸ†αžŽαžαŸ‹αž…αŸ†αžŽαžΆαŸ†αž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžšαžŸαŸαžšαž€αŸ’αž“αž»αž„αž†αŸ’αž“αžΆαŸ† 2014 αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαŸ’αž‰αž»αŸ†αž‘αžΎαž”αžαŸ‚αžŸαŸ’αžαž·αžαž“αŸ…αž€αŸ’αžšαŸ„αž˜αž€αžΆαžšαž‚αžΆαž”αžŸαž„αŸ’αž€αžαŸ‹αž›αžΎ Habre αž αžΎαž™αžœαžΆαž˜αž·αž“αž”αžΆαž“αžƒαžΎαž‰αž–αž“αŸ’αž›αžΊαž“αŸƒαžαŸ’αž„αŸƒαž‘αŸαŸ” αž€αŸ’αž“αž»αž„αž’αŸ†αž‘αž»αž„αž–αŸαž›αž αžΆαž˜αžƒαžΆαžαŸ‹αžαŸ’αž‰αž»αŸ†αž—αŸ’αž›αŸαž…αž’αŸ†αž–αžΈαžœαžΆ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž₯αž‘αžΌαžœαž“αŸαŸ‡αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αžšαž€αžƒαžΎαž‰αžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸαž…αž€αŸ’αžαžΈαž–αŸ’αžšαžΆαž„αŸ” αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž‚αž·αžαž’αŸ†αž–αžΈαž€αžΆαžšαž›αž»αž”αžœαžΆ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž”αŸ’αžšαž αŸ‚αž›αž‡αžΆαžœαžΆαž“αžΉαž„αž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž“αžšαžŽαžΆαž˜αŸ’αž“αžΆαž€αŸ‹αŸ”

αž€αŸ†αž–αž»αž„αžšαž€αž˜αžΎαž› LD_PRELOAD

αž‡αžΆαž‘αžΌαž‘αŸ…αž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžαŸ’αž„αŸƒαžŸαž»αž€αŸ’αžšαž”αž“αŸ’αžαž·αž…αž’αžΆαž“αž›αžΎαž”αŸ’αžšαž’αžΆαž“αž”αž‘αž“αŸƒαž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€ "αžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›" LD_PRELOAD.

1. αž€αžΆαžšαž”αž€αžŸαŸ’αžšαžΆαž™αžαŸ’αž›αžΈαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αžŠαŸ‚αž›αž˜αž·αž“αžŸαŸŠαžΆαŸ†αž“αžΉαž„αž€αžΆαžšαž‡αŸ†αž“αž½αžŸαž˜αž»αžαž„αžΆαžš

αž“αŸ…αžŸαž›αŸ‹αž’αžΆαž…αž‘αŸ…αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹ ΠΏ αŸ₯.

αžαŸ„αŸ‡αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‡αžΆαž˜αž½αž™αž§αž‘αžΆαž αžšαžŽαŸαž”αž»αžšαžΆαžŽαŸ–

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
  srand (time(NULL));
  for(int i=0; i<5; i++){
    printf ("%dn", rand()%100);
  }
}

αž™αžΎαž„αž…αž„αž€αŸ’αžšαž„αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž‘αž„αŸ‹αžŽαžΆαž˜αž½αž™αŸ–

$ gcc ./ld_rand.c -o ld_rand

αž αžΎαž™αžαžΆαž˜αž€αžΆαžšαžšαŸ†αž–αžΉαž„αž‘αž»αž€ αž™αžΎαž„αž‘αž‘αž½αž›αž”αžΆαž“αž›αŸαžαž…αŸƒαžŠαž“αŸ’αž™αž…αŸ†αž“αž½αž“ 5 αžαž·αž…αž‡αžΆαž„ 100αŸ–

$ ./ld_rand
53
93
48
57
20

αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αžŸαžΌαž˜β€‹αžŸαŸ’αžšαž˜αŸƒβ€‹αžαžΆβ€‹αž™αžΎαž„β€‹αž˜αž·αž“β€‹αž˜αžΆαž“β€‹αž€αžΌαžŠβ€‹αž”αŸ’αžšαž—αž–β€‹αž“αŸƒβ€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹αž“αŸ„αŸ‡β€‹αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αž™αžΎαž„β€‹αžαŸ’αžšαžΌαžœβ€‹αž•αŸ’αž›αžΆαžŸαŸ‹β€‹αž”αŸ’αžαžΌαžšβ€‹αž₯αžšαž·αž™αžΆαž”αžαŸ”

αž…αžΌαžšαž™αžΎαž„αž”αž„αŸ’αž€αžΎαžαž”αžŽαŸ’αžŽαžΆαž›αŸαž™αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αž™αžΎαž„αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž‚αŸ†αžšαžΌαž˜αž»αžαž„αžΆαžšαž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αž™αžΎαž„ αž§αž‘αžΆαž αžšαžŽαŸαŸ–

int rand(){
  return 42;
}

$ gcc -shared -fPIC ./o_rand.c -o ld_rand.so

αž αžΎαž™αž₯αž‘αžΌαžœαž“αŸαŸ‡αž‡αž˜αŸ’αžšαžΎαžŸαž…αŸƒαžŠαž“αŸ’αž™αžšαž”αžŸαŸ‹αž™αžΎαž„αž‚αžΊαž’αžΆαž…αž‘αžΆαž™αž‘αž»αž€αž‡αžΆαž˜αž»αž“αž”αžΆαž“αŸ–

# LD_PRELOAD=$PWD/ld_rand.so ./ld_rand
42
42
42
42
42

αž›αŸ’αž”αž·αž…αž“αŸαŸ‡αž˜αžΎαž›αž‘αŸ…αž‚αž½αžšαž±αŸ’αž™αž…αžΆαž”αŸ‹αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸαž‡αžΆαž„αž“αŸαŸ‡αž‘αŸ…αž‘αŸ€αž αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž™αžΎαž„αž“αžΆαŸ†αž…αŸαž‰αž”αžŽαŸ’αžŽαžΆαž›αŸαž™αžšαž”αžŸαŸ‹αž™αžΎαž„αž‡αžΆαž›αžΎαž€αžŠαŸ†αž”αžΌαž„αžαžΆαž˜αžšαž™αŸˆ

$ export LD_PRELOAD=$PWD/ld_rand.so

αž¬αž™αžΎαž„αž“αžΉαž„αž’αŸ’αžœαžΎαžœαžΆαž‡αžΆαž˜αž»αž“αžŸαž·αž“

# echo "$PWD/ld_rand.so" > /etc/ld.so.preload

αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαžΌαž…αž’αž˜αŸ’αž˜αžαžΆαŸ” αž™αžΎαž„β€‹αž˜αž·αž“β€‹αž”αžΆαž“β€‹αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžŠαžΌαžšβ€‹αž€αžΌαžŠβ€‹αž˜αž½αž™β€‹αž‡αž½αžšβ€‹αž€αŸ’αž“αž»αž„β€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹αž“αŸ„αŸ‡β€‹αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αž₯αžšαž·αž™αžΆαž”αž‘β€‹αžšαž”αžŸαŸ‹β€‹αžœαžΆβ€‹αž₯αž‘αžΌαžœβ€‹αž“αŸαŸ‡β€‹αž’αžΆαžŸαŸ’αžšαŸαž™β€‹αž›αžΎβ€‹αž˜αž»αžαž„αžΆαžšβ€‹αžŠαŸβ€‹αžαžΌαž…β€‹αž˜αž½αž™β€‹αž€αŸ’αž“αž»αž„β€‹αž”αžŽαŸ’αžŽαžΆαž›αŸαž™β€‹αžšαž”αžŸαŸ‹β€‹αž™αžΎαž„αŸ” αž›αžΎαžŸβ€‹αž–αžΈβ€‹αž“αŸαŸ‡β€‹αž‘αŸ…β€‹αž‘αŸ€αžβ€‹αž“αŸ…β€‹αž–αŸαž›β€‹αžŸαžšαžŸαŸαžšβ€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹αž“αŸ„αŸ‡β€‹ αžšαŸ‰αž„αŸ‹ αž˜αž·αž“αž˜αžΆαž“αžŸαžΌαž˜αŸ’αž”αžΈαžαŸ‚αŸ”

αž’αŸ’αžœαžΈαžŠαŸ‚αž›αž’αŸ’αžœαžΎαž±αŸ’αž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž™αžΎαž„αž”αŸ’αžšαžΎαž€αŸ’αž›αŸ‚αž„αž€αŸ’αž›αžΆαž™ αžšαŸ‰αž„αŸ‹? αž…αžΌαžšβ€‹αž™αžΎαž„β€‹αž™αž€β€‹αžœαžΆβ€‹αž‡αžΆβ€‹αž‡αŸ†αž αžΆαž“αŸ—αŸ”
αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜ αž”αžŽαŸ’αžŽαžΆαž›αŸαž™αž˜αž½αž™αž…αŸ†αž“αž½αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‘αž»αž€αžŠαŸ‚αž›αž˜αžΆαž“αž˜αž»αžαž„αžΆαžšαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž€αžΆαžšαžŠαŸ„αž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ” αž™αžΎαž„αž’αžΆαž…αž˜αžΎαž›αž–αž½αž€αžœαžΆαžŠαŸ„αž™αž”αŸ’αžšαžΎ αž’αž·αž›αžŒαžΈ:

# ldd ./ld_rand
        linux-vdso.so.1 (0x00007ffc8b1f3000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe3da8af000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe3daa7e000)

αž”αž‰αŸ’αž‡αžΈαž“αŸαŸ‡αž’αžΆαž…αž”αŸ’αžšαŸ‚αž”αŸ’αžšαž½αž›αž’αžΆαžŸαŸ’αžšαŸαž™αž›αžΎαž€αŸ†αžŽαŸ‚ OS αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαŸ’αžšαžΌαžœαžαŸ‚αž˜αžΆαž“αž―αž€αžŸαžΆαžšαž“αŸ…αž‘αžΈαž“αŸ„αŸ‡ libc.so. αžœαžΆβ€‹αž‚αžΊβ€‹αž‡αžΆβ€‹αž”αžŽαŸ’αžŽαžΆαž›αŸαž™β€‹αž“αŸαŸ‡β€‹αžŠαŸ‚αž›β€‹αž•αŸ’αžαž›αŸ‹β€‹αž“αžΌαžœβ€‹αž€αžΆαžšβ€‹αž αŸ…β€‹αž‘αžΌαžšαžŸαŸαž–αŸ’αž‘β€‹αž”αŸ’αžšαž–αŸαž“αŸ’αž’β€‹αž“αž·αž„β€‹αž˜αž»αžαž„αžΆαžšβ€‹αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“β€‹αžŠαžΌαž…β€‹αž‡αžΆβ€‹ αž€αžΆαžšαž”αžΎαž€αž…αŸ†αž αžš, Malloc, printf αž›αŸ” αžšαŸ‰αž„αŸ‹ αž€αŸαžŸαŸ’αžαž·αžαž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αž–αž½αž€αž‚αŸαžŠαŸ‚αžšαŸ” αž…αžΌαžšβ€‹αž’αŸ’αžœαžΎβ€‹αž±αŸ’αž™β€‹αž”αŸ’αžšαžΆαž€αžŠβ€‹αžαžΆβ€‹αž“αŸαŸ‡β€‹:

# nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep " rand$"
000000000003aef0 T rand

αžŸαžΌαž˜αž˜αžΎαž›αžαžΆαžαžΎαžŸαŸ†αžŽαž»αŸ†αž“αŸƒαž”αžŽαŸ’αžŽαžΆαž›αŸαž™αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž“αŸ…αž–αŸαž›αž”αŸ’αžšαžΎ LD_PRELOAD

# LD_PRELOAD=$PWD/ld_rand.so ldd ./ld_rand
        linux-vdso.so.1 (0x00007ffea52ae000)
        /scripts/c/ldpreload/ld_rand.so (0x00007f690d3f9000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f690d230000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f690d405000)

αž”αž„αŸ’αž αžΆαž‰αžαžΆαž’αžαŸαžšαžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹ LD_PRELOAD αž”αž„αŸ’αžαŸ†αž™αžΎαž„αž±αŸ’αž™αž•αŸ’αž‘αž»αž€ ld_rand.so αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž€αžΆαžšαž–αž·αžαžŠαŸ‚αž›αžαžΆαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αž›αž½αž“αž―αž„αž˜αž·αž“αž‘αžΆαž˜αž‘αžΆαžšαžœαžΆαž€αŸαžŠαŸ„αž™αŸ” αž αžΎαž™αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈαž˜αž»αžαž„αžΆαžšαžšαž”αžŸαŸ‹αž™αžΎαž„αŸ” "αžšαŸ‰αž“" αž•αŸ’αž‘αž»αž€αž›αžΏαž“αž‡αžΆαž„ αžšαŸ‰αž„αŸ‹ αž–αžΈ libc.soαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž“αžΆαž„αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž”αž“αŸ’αž‘αž”αŸ‹αŸ”

αž™αž›αŸ‹αž–αŸ’αžšαž˜ αž™αžΎαž„αž”αžΆαž“αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžŠαžΎαž˜αŸ’αž”αžΈαž‡αŸ†αž“αž½αžŸαž˜αž»αžαž„αžΆαžšαžŠαžΎαž˜ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαžΎαž™αžΎαž„αž’αžΆαž…αž”αŸ’αžšαžΆαž€αžŠαžαžΆαž˜αž»αžαž„αžΆαžšαžšαž”αžŸαŸ‹αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€ αž“αž·αž„αžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αž˜αž½αž™αž…αŸ†αž“αž½αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αžŠαŸ„αž™αžšαž”αŸ€αž”αžŽαžΆαŸ” αžαŸ„αŸ‡αž€αŸ‚αž”αŸ’αžšαŸ‚αž…αŸƒαžŠαž“αŸ’αž™αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ–

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
 
typedef int (*orig_rand_f_type)(void);
 
int rand()
{
  /* ВыполняСм Π½Π΅ΠΊΠΈΠΉ ΠΊΠΎΠ΄ */
  printf("Evil injected coden");
  
  orig_rand_f_type orig_rand;
  orig_rand = (orig_rand_f_type)dlsym(RTLD_NEXT,"rand");
  return orig_rand();
}

αž“αŸ…αž‘αžΈαž“αŸαŸ‡ αž‡αžΆ "αž€αžΆαžšαž”αž“αŸ’αžαŸ‚αž˜" αžšαž”αžŸαŸ‹αž™αžΎαž„ αž™αžΎαž„αž”αŸ„αŸ‡αž–αž»αž˜αŸ’αž–αžαŸ‚αž˜αž½αž™αž”αž“αŸ’αž‘αžΆαžαŸ‹αž“αŸƒαž’αžαŸ’αžαž”αž‘ αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž™αžΎαž„αž”αž„αŸ’αž€αžΎαžαž‘αŸ’αžšαž“αž·αž…αž‘αŸ…αž˜αž»αžαž„αžΆαžšαžŠαžΎαž˜ αžšαŸ‰αž„αŸ‹. αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αž“αŸƒαž˜αž»αžαž„αžΆαžšαž“αŸαŸ‡αž™αžΎαž„αžαŸ’αžšαžΌαžœαž€αžΆαžš dlsym αž‚αžΊαž‡αžΆαž˜αž»αžαž„αžΆαžšαž–αžΈαž”αžŽαŸ’αžŽαžΆαž›αŸαž™ libdlαžŠαŸ‚αž›αž“αžΉαž„αžšαž€αžƒαžΎαž‰αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ” αžšαŸ‰αž„αŸ‹ αž“αŸ…αž€αŸ’αž“αž»αž„αž”αžŽαŸ’αžαž»αŸ†αž“αŸƒαž”αžŽαŸ’αžŽαžΆαž›αŸαž™αžαžΆαž˜αžœαž“αŸ’αžαŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž“αŸ„αŸ‡αž™αžΎαž„αž“αžΉαž„αž αŸ…αž˜αž»αžαž„αžΆαžšαž“αŸαŸ‡ αž αžΎαž™αžαŸ’αžšαž‘αž”αŸ‹αžαž˜αŸ’αž›αŸƒαžšαž”αžŸαŸ‹αžœαžΆαŸ” αžŠαžΌαž…αŸ’αž“αŸ„αŸ‡αž αžΎαž™αž™αžΎαž„αž“αžΉαž„αžαŸ’αžšαžΌαžœαž€αžΆαžšαž”αž“αŸ’αžαŸ‚αž˜ "-ldl" αž€αŸ†αž‘αž»αž„αž–αŸαž›αž‡αž½αž”αž”αŸ’αžšαž‡αž»αŸ†αž‚αŸ’αž“αžΆαŸ–

$ gcc -ldl -shared -fPIC ./o_rand_evil.c -o ld_rand_evil.so

$ LD_PRELOAD=$PWD/ld_rand_evil.so ./ld_rand
Evil injected code
66
Evil injected code
28
Evil injected code
93
Evil injected code
93
Evil injected code
95

αž αžΎαž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž™αžΎαž„αž”αŸ’αžšαžΎ "ដើម" αžšαŸ‰αž„αŸ‹αžŠαŸ„αž™β€‹αž”αžΆαž“β€‹αž”αŸ’αžšαž–αŸ’αžšαžΉαžαŸ’αžβ€‹αž’αŸ†αž–αžΎβ€‹αž’αžΆαžŸαž’αžΆαž—αžΆαžŸβ€‹αž˜αž½αž™β€‹αž…αŸ†αž“αž½αž“β€‹αž€αž“αŸ’αž›αž„β€‹αž˜αž€αŸ”

2. αž€αžΆαžšαžˆαžΊαž…αžΆαž”αŸ‹αž“αŸƒαž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€

αžŠαŸ„αž™αžŠαžΉαž„αž–αžΈαž€αžΆαžšαž‚αŸ†αžšαžΆαž˜αž€αŸ†αž αŸ‚αž„αžŠαŸ‚αž›αž’αžΆαž…αž€αžΎαžαž˜αžΆαž“ αž™αžΎαž„αž…αž„αŸ‹αžšαž€αžƒαžΎαž‰αž“αŸ„αŸ‡αŸ” αž•αŸ’αž‘αž»αž€αž‡αžΆαž˜αž»αž“ αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαŸ” αžœαžΆαž…αŸ’αž”αžΆαžŸαŸ‹αžŽαžΆαžŸαŸ‹αžαžΆαžœαž·αž’αžΈαž›αŸ’αž’αž”αŸ†αž•αž»αžαžŠαžΎαž˜αŸ’αž”αžΈαžšαž€αž±αŸ’αž™αžƒαžΎαž‰αž‚αžΊαžšαž»αž‰αžœαžΆαž‘αŸ…αž€αŸ’αž“αž»αž„αžαžΊαžŽαŸ‚αž› αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαŸ’αž‰αž»αŸ†αž…αžΆαž”αŸ‹αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸαž›αžΎαž‡αž˜αŸ’αžšαžΎαžŸαž“αŸƒαž€αžΆαžšαžšαž€αžƒαžΎαž‰αž“αŸ…αž€αŸ’αž“αž»αž„αžαŸ†αž”αž“αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžšαž€αžƒαžΎαž‰ αž“αž·αž„αž€αžΆαžšαž”αžŠαž·αžŸαŸαž’αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαž“αžΉαž„αž˜αž€αž‡αžΆαž‚αžΌαŸ”

្.៑. αž…αžΌαžšαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŸαžΆαž˜αž‰αŸ’αž‰

αžŠαžΌαž…αžŠαŸ‚αž›αž”αžΆαž“αžšαŸ€αž”αžšαžΆαž”αŸ‹αžαžΆαž„αž›αžΎ αž’αŸ’αž“αž€αž’αžΆαž…αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž”αžŽαŸ’αžŽαžΆαž›αŸαž™αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž•αŸ’αž‘αž»αž€αžŠαŸ„αž™αž”αŸ’αžšαžΎαž’αžαŸαžš LD_PRELOAD αž¬αžŠαŸ„αž™αžŸαžšαžŸαŸαžšαžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžš /etc/ld.so.preload. αžαŸ„αŸ‡αž”αž„αŸ’αž€αžΎαžαž§αž”αž€αžšαžŽαŸαž…αžΆαž”αŸ‹αžŸαž‰αŸ’αž‰αžΆαžŸαžΆαž˜αž‰αŸ’αž‰αž–αžΈαžšαŸ”

αž‘αžΈαž˜αž½αž™αž‚αžΊαžαŸ’αžšαžΌαžœαž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αž’αžαŸαžšαž”αžšαž·αžŸαŸ’αžαžΆαž“αžŠαŸ‚αž›αž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αŸ–

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int main()
{
  char*  pGetenv = getenv("LD_PRELOAD");
  pGetenv != NULL ?
    printf("LD_PRELOAD (getenv) [+]n"):
    printf("LD_PRELOAD (getenv) [-]n");
}

αž‘αžΈαž–αžΈαžšαž‚αžΊαžαŸ’αžšαžΌαžœαž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαžαžΎαž―αž€αžŸαžΆαžšαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αžΎαž€αŸ–

#include <stdio.h>
#include <fcntl.h>

int main()
{
  open("/etc/ld.so.preload", O_RDONLY) != -1 ?
    printf("LD_PRELOAD (open) [+]n"):
    printf("LD_PRELOAD (open) [-]n");
}

αžαŸ„αŸ‡αž•αŸ’αž‘αž»αž€αž”αžŽαŸ’αžŽαžΆαž›αŸαž™αŸ–

$ export LD_PRELOAD=$PWD/ld_rand.so
$ echo "$PWD/ld_rand.so" > /etc/ld.so.preload

$ ./detect_base_getenv
LD_PRELOAD (getenv) [+]
$ ./detect_base_open
LD_PRELOAD (open) [+]

αž“αŸ…αž‘αžΈαž“αŸαŸ‡ αž“αž·αž„αžαžΆαž„αž€αŸ’αžšαŸ„αž˜ [+] αž”αž„αŸ’αž αžΆαž‰αž–αžΈαž€αžΆαžšαžšαž€αžƒαžΎαž‰αž‡αŸ„αž‚αž‡αŸαž™αŸ”
αžŠαžΌαž…αŸ’αž“αŸ„αŸ‡ [-] αž˜αžΆαž“αž“αŸαž™αžαžΆ αžšαŸ†αž›αž„αž€αžΆαžšαžšαž€αžƒαžΎαž‰αŸ”

αžαžΎαž§αž”αž€αžšαžŽαŸαž…αžΆαž”αŸ‹αžŸαž‰αŸ’αž‰αžΆαž”αŸ‚αž”αž“αŸαŸ‡αž˜αžΆαž“αž”αŸ’αžšαžŸαž·αž‘αŸ’αž’αž—αžΆαž–αž”αŸ‰αž»αžŽαŸ’αžŽαžΆ? αž…αžΌαžšαž™αžΎαž„αž€αŸ’αžšαž‘αŸαž€αž˜αžΎαž›αž’αžαŸαžšαž”αžšαž·αžŸαŸ’αžαžΆαž“αž‡αžΆαž˜αž»αž“αžŸαž·αž“αŸ–

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>

char* (*orig_getenv)(const char *) = NULL;
char* getenv(const char *name)
{
    if(!orig_getenv) orig_getenv = dlsym(RTLD_NEXT, "getenv");
    if(strcmp(name, "LD_PRELOAD") == 0) return NULL;
    return orig_getenv(name);
}

$ gcc -shared -fpic -ldl ./ld_undetect_getenv.c -o ./ld_undetect_getenv.so
$ LD_PRELOAD=./ld_undetect_getenv.so ./detect_base_getenv
LD_PRELOAD (getenv) [-]

αžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆαž“αŸαŸ‡αžŠαŸ‚αžšαž™αžΎαž„αž€αž˜αŸ’αž…αžΆαžαŸ‹αž˜αžΌαž›αž”αŸ’αž”αž‘αžΆαž“αž”αŸαžαŸ’αžš αž€αžΆαžšαž”αžΎαž€αž…αŸ†αž αžš:

#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>

int (*orig_open)(const char*, int oflag) = NULL;

int open(const char *path, int oflag, ...)
{
    char real_path[256];
    if(!orig_open) orig_open = dlsym(RTLD_NEXT, "open");
    realpath(path, real_path);
    if(strcmp(real_path, "/etc/ld.so.preload") == 0){
        errno = ENOENT;
        return -1;
    }
    return orig_open(path, oflag);
}

$ gcc -shared -fpic -ldl ./ld_undetect_open.c -o ./ld_undetect_open.so
$ LD_PRELOAD=./ld_undetect_open.so ./detect_base_open
LD_PRELOAD (open) [-]

αž”αžΆαž‘/αž…αžΆαžŸ αžœαž·αž’αžΈαž•αŸ’αžŸαŸαž„αž‘αŸ€αžαžŠαžΎαž˜αŸ’αž”αžΈαž…αžΌαž›αž”αŸ’αžšαžΎαž―αž€αžŸαžΆαžšαž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαž“αŸ…αž‘αžΈαž“αŸαŸ‡ αžŠαžΌαž…αž‡αžΆ αž”αžΎαž€ 64, αžŸαŸ’αžαž·αžαž· αž‡αžΆαžŠαžΎαž˜αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαžΆαž˜αž–αž·αž αž›αŸαžαž€αžΌαžŠ 5-10 αžŠαžΌαž…αž‚αŸ’αž“αžΆαž‚αžΊαžαŸ’αžšαžΌαžœαž€αžΆαžšαžŠαžΎαž˜αŸ’αž”αžΈαž”αž‰αŸ’αž†αŸ„αžαž–αž½αž€αž‚αŸαŸ”

្.្. αžαŸ„αŸ‡αž”αž“αŸ’αžαž‘αŸ…αž˜αž»αžαž‘αŸ€αžαŸ”

αžαžΆαž„αž›αžΎαž™αžΎαž„αž”αžΆαž“αž”αŸ’αžšαžΎ getenv() αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αžαž˜αŸ’αž›αŸƒ LD_PRELOADαž”αŸ‰αž»αž“αŸ’αžαŸ‚αž€αŸαž˜αžΆαž“αžœαž·αž’αžΈ "αž€αž˜αŸ’αžšαž·αžαž‘αžΆαž”" αž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαžŠαžΎαž˜αŸ’αž”αžΈαž‘αŸ…αžŠαž›αŸ‹ αž’αŸαž“αžœαžΈ- αž’αžαŸαžšαŸ” αž™αžΎαž„β€‹αž“αžΉαž„β€‹αž˜αž·αž“β€‹αž”αŸ’αžšαžΎβ€‹αž˜αž»αžαž„αžΆαžšβ€‹αž€αž˜αŸ’αžšαž·αžβ€‹αž˜αž’αŸ’αž™αž˜β€‹αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αž“αžΉαž„β€‹αž™αŸ„αž„β€‹αž‘αŸ…β€‹αž›αžΎβ€‹αž’αžΆαžšαŸ ** αž”αžšαž·αžŸαŸ’αžαžΆαž“αžŠαŸ‚αž›αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž…αŸ’αž”αžΆαž”αŸ‹αž…αž˜αŸ’αž›αž„αž“αŸƒαž”αžšαž·αžŸαŸ’αžαžΆαž“αŸ–

#include <stdio.h>
#include <string.h>

extern char **environ;
int main(int argc, char **argv) {
  int i;
  char env[] = "LD_PRELOAD";
  if (environ != NULL)
    for (i = 0; environ[i] != NULL; i++)
    {
      char * pch;
      pch = strstr(environ[i],env);
      if(pch != NULL)
      {
        printf("LD_PRELOAD (**environ) [+]n");
        return 0;
      }
    }
  printf("LD_PRELOAD (**environ) [-]n");
  return 0;
}

αžŠαŸ„αž™αžŸαžΆαžšαž“αŸ…αž‘αžΈαž“αŸαŸ‡ αž™αžΎαž„αž€αŸ†αž–αž»αž„αž’αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž–αžΈαž’αž„αŸ’αž‚αž…αž„αž…αžΆαŸ† αž€αžΆαžšαž αŸ…αž‘αžΌαžšαžŸαž–αŸ’αž‘αž”αŸ‚αž”αž“αŸαŸ‡αž˜αž·αž“αž’αžΆαž…αžŸαŸ’αž‘αžΆαž€αŸ‹αž…αžΆαž”αŸ‹αž”αžΆαž“αž‘αŸ αž αžΎαž™αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ” undetect_getenv αžœαžΆαž›αŸ‚αž„αžšαŸ†αžαžΆαž“αžŠαž›αŸ‹αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αž’αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαžŽαž€αžΆαžšαžˆαŸ’αž›αžΆαž“αž–αžΆαž“αž‘αŸ€αžαž αžΎαž™αŸ”

$ LD_PRELOAD=./ld_undetect_getenv.so ./detect_environ
LD_PRELOAD (**environ) [+]

αžœαžΆαž αžΆαž€αŸ‹αžŠαžΌαž…αž‡αžΆαžαžΆαž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™? αžœαžΆαž“αŸ…αžαŸ‚αž‘αžΎαž”αžαŸ‚αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜ αžαž˜αŸ’αž›αŸƒαž“αŸƒαž’αžαŸαžš LD_PRELOAD αž–αž½αž€ Hacker αž›αŸ‚αž„αžαŸ’αžšαžΌαžœαž€αžΆαžšαžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž’αž„αŸ’αž‚αž…αž„αž…αžΆαŸ†αž‘αŸ€αžαž αžΎαž™ αž–αŸ„αž›αž‚αžΊαž–αž½αž€αž‚αŸαž’αžΆαž…αž’αžΆαž“αžœαžΆ αž“αž·αž„αž›αž»αž”αžœαžΆαž˜αž»αž“αž–αŸαž›αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†αžŽαžΆαž˜αž½αž™αŸ” αž‡αžΆαž€αžΆαžšαž–αž·αžαžŽαžΆαžŸαŸ‹ αž€αžΆαžšαž€αŸ‚αžŸαž˜αŸ’αžšαž½αž›αž’αžΆαžšαŸαž“αŸ…αž€αŸ’αž“αž»αž„αž’αž„αŸ’αž‚αž…αž„αž…αžΆαŸ† αž‡αžΆαž’αž”αŸ’αž”αž”αžšαž˜αžΆ αžšαž…αž“αžΆαž”αŸαž‘αŸ’αž˜αžŸαžšαžŸαŸαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž˜αž·αž“αž›αŸ’αž’ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαžΎαž“αŸαŸ‡αž’αžΆαž…αž”αž‰αŸ’αžˆαž”αŸ‹αž“αžšαžŽαžΆαž˜αŸ’αž“αžΆαž€αŸ‹αžŠαŸ‚αž›αž–αž·αžαž‡αžΆαž˜αž·αž“αž”αŸ’αžšαžΆαžαŸ’αž“αžΆαž™αžΎαž„αž™αŸ‰αžΆαž„αžŠαžΌαž…αž˜αŸ’αžŠαŸαž…?

αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαžŠαžΌαž…αž“αŸαŸ‡αž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αž„αŸ’αž€αžΎαžαž˜αž»αžαž„αžΆαžšαž€αŸ’αž›αŸ‚αž„αž€αŸ’αž›αžΆαž™αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ” αž“αŸ…β€‹αž€αŸ’αž“αž»αž„β€‹αžœαžΆ()αžŠαŸ‚αž›αž™αžΎαž„αžŸαŸ’αž‘αžΆαž€αŸ‹αž…αžΆαž”αŸ‹αž”αžΆαž“αžŠαŸ†αž‘αžΎαž„ LD_PRELOAD αž αžΎαž™αž”αž‰αŸ’αž‡αžΌαž“αžœαžΆαž‘αŸ…αž’αŸ’αž“αž€αž—αŸ’αž‡αžΆαž”αŸ‹αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ–

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <stdlib.h>

extern char **environ;
char *evil_env;
int (*orig_execve)(const char *path, char *const argv[], char *const envp[]) = NULL;


// Π‘ΠΎΠ·Π΄Π°Ρ‘ΠΌ Ρ„Π΅ΠΉΠΊΠΎΠ²ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ init
// которая Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹
// Π΄ΠΎ выполнСния ΠΊΠ°ΠΊΠΈΡ…-Π»ΠΈΠ±ΠΎ инструкций

void evil_init()
{
  // Π‘Π½Π°Ρ‡Π°Π»Π° сохраним Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ LD_PRELOAD
  static const char *ldpreload = "LD_PRELOAD";
  int len = strlen(getenv(ldpreload));
  evil_env = (char*) malloc(len+1);
  strcpy(evil_env, getenv(ldpreload));

  int i;
  char env[] = "LD_PRELOAD";
  if (environ != NULL)
    for (i = 0; environ[i] != NULL; i++) {
      char * pch;
      pch = strstr(environ[i],env);
      if(pch != NULL) {
        // ИзбавляСмся ΠΎΡ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ LD_PRELOAD
        unsetenv(env);
        break;
      }
    }
}

int execve(const char *path, char *const argv[], char *const envp[])
{
  int i = 0, j = 0, k = -1, ret = 0;
  char** new_env;
  if(!orig_execve) orig_execve = dlsym(RTLD_NEXT,"execve");

  // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠΌ Π½Π΅ сущСствуСт Π»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… установлСнных LD_PRELOAD
  for(i = 0; envp[i]; i++){
    if(strstr(envp[i], "LD_PRELOAD")) k = i;
  }
  // Если LD_PRELOAD Π½Π΅ Π±Ρ‹Π»ΠΎ установлСно Π΄ΠΎ нас, Ρ‚ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π΅Π³ΠΎ
  if(k == -1){
    k = i;
    i++;
  }
  // Π‘ΠΎΠ·Π΄Π°Ρ‘ΠΌ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅
  new_env = (char**) malloc((i+1)*sizeof(char*));

  // ΠšΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ староС ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅, Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ LD_PRELOAD
  for(j = 0; j < i; j++) {
    // пСрСзаписываСм ΠΈΠ»ΠΈ создаём LD_PRELOAD
    if(j == k) {
      new_env[j] = (char*) malloc(256);
      strcpy(new_env[j], "LD_PRELOAD=");
      strcat(new_env[j], evil_env);
    }
    else new_env[j] = (char*) envp[j];
  }
  new_env[i] = NULL;
  ret = orig_execve(path, argv, new_env);
  free(new_env[k]);
  free(new_env);
  return ret;
}

αž™αžΎαž„αž’αž“αž»αžœαžαŸ’αžαž“αž·αž„αž–αž·αž“αž·αžαŸ’αž™αŸ–

$ gcc -shared -fpic -ldl -Wl,-init,evil_init  ./ld_undetect_environ.c -o ./ld_undetect_environ.so
$ LD_PRELOAD=./ld_undetect_environ.so ./detect_environ
LD_PRELOAD (**environ) [-]

្.៣. /proc/αžαŸ’αž›αž½αž“αž―αž„/

αž‘αŸ„αŸ‡αž‡αžΆαž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž€αžΆαžšαž…αž„αž…αžΆαŸ†αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αž…αž»αž„αž€αŸ’αžšαŸ„αž™αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αžŸαŸ’αžœαŸ‚αž„αžšαž€αž€αžΆαžšαž‡αŸ†αž“αž½αžŸαž”αžΆαž“αž‘αŸαŸ” LD_PRELOAD, αž€αŸαž˜αžΆαž“ /proc/. αž…αžΌαžšαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„ /proc/{PID}/αž”αžšαž·αžŸαŸ’αžαžΆαž“.

αžαžΆαž˜αž–αž·αžαž˜αžΆαž“αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž‡αžΆαžŸαž€αž›αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ αžšαž€αž˜αž·αž“αžƒαžΎαž‰ ** αž”αžšαž·αžŸαŸ’αžαžΆαž“ ΠΈ /proc/self/environ. αž”αž‰αŸ’αž αžΆαž‚αžΊαž’αžΆαž€αž”αŸ’αž”αž€αž·αžšαž·αž™αžΆ "ខុស" unsetenv(env).

αž‡αž˜αŸ’αžšαžΎαžŸαžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαŸ”

void evil_init()
{
  // Π‘Π½Π°Ρ‡Π°Π»Π° сохраним Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ LD_PRELOAD
  static const char *ldpreload = "LD_PRELOAD";
  int len = strlen(getenv(ldpreload));
  evil_env = (char*) malloc(len+1);
  strcpy(evil_env, getenv(ldpreload));
 
  int i;
  char env[] = "LD_PRELOAD";
  if (environ != NULL)
    for (i = 0; environ[i] != NULL; i++) {
      char * pch;
      pch = strstr(environ[i],env);
      if(pch != NULL) {
        // ИзбавляСмся ΠΎΡ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ LD_PRELOAD 
        //unsetenv(env);
        // ВмСсто unset просто ΠΎΠ±Π½ΡƒΠ»ΠΈΠΌ Π½Π°ΡˆΡƒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ
        for(int j = 0; environ[i][j] != ' '; j++) environ[i][j] = ' ';
        break;
      }
    }
}
$ gcc -shared -fpic -ldl -Wl,-init,evil_init  ./ld_undetect_environ_2.c -o ./ld_undetect_environ_2.so
$ (LD_PRELOAD=./ld_undetect_environ_2.so cat /proc/self/environ; echo) | tr " 00" "n" | grep -F LD_PRELOAD
$

αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αžŸαžΌαž˜β€‹αžŸαŸ’αžšαž˜αŸƒβ€‹αžαžΆβ€‹αž™αžΎαž„β€‹αžšαž€β€‹αž˜αž·αž“β€‹αžƒαžΎαž‰β€‹αž αžΎαž™β€‹ /proc/self/environ αž˜αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™ "αž”αž‰αŸ’αž αžΆ" αŸ”

αžŠαŸ†αž”αžΌαž„αžŸαžΌαž˜αžŸαžΆαž€αž›αŸ’αž”αž„αž‡αžΆαž˜αž½αž™ "αž€αŸ’αž›αŸ‚αž„αž”αž“αŸ’αž›αŸ†" αž–αžΈαž˜αž»αž“αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ–

$ (LD_PRELOAD=./ld_undetect_environ.so cat /proc/self/environ; echo) | tr " 00" "n" | grep -F LD_PRELOAD
LD_PRELOAD=./ld_undetect_environ.so

αž†αŸ’αž˜αžΆ αž”αŸ’αžšαžΎαžŠαžΌαž…αž‚αŸ’αž“αžΆαžŠαžΎαž˜αŸ’αž”αžΈαž”αžΎαž€αž―αž€αžŸαžΆαžš αž”αžΎαž€ ()αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž‚αžΊαžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆαž‘αŸ…αž“αžΉαž„αž’αŸ’αžœαžΈαžŠαŸ‚αž›αž”αžΆαž“αž’αŸ’αžœαžΎαžšαž½αž…αž αžΎαž™αž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€ 2.1 αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž₯αž‘αžΌαžœαž“αŸαŸ‡αž™αžΎαž„αž”αž„αŸ’αž€αžΎαžαž―αž€αžŸαžΆαžšαž”αžŽαŸ’αžαŸ„αŸ‡αž’αžΆαžŸαž“αŸ’αž“αž˜αž½αž™αžŠαŸ‚αž›αž™αžΎαž„αž…αž˜αŸ’αž›αž„αžαž˜αŸ’αž›αŸƒαž“αŸƒαž’αž„αŸ’αž‚αž…αž„αž…αžΆαŸ†αž–αž·αžαžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž”αž“αŸ’αž‘αžΆαžαŸ‹αŸ” LD_PRELOAD.

#define _GNU_SOURCE
#include <dlfcn.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>

#define BUFFER_SIZE 256

int (*orig_open)(const char*, int oflag) = NULL;
char *soname = "fakememory_preload.so";

char *sstrstr(char *str, const char *sub)
{
  int i, found;
  char *ptr;
  found = 0;
  for(ptr = str; *ptr != ' '; ptr++) {
    found = 1;
    for(i = 0; found == 1 && sub[i] != ' '; i++){
      if(sub[i] != ptr[i]) found = 0;
    }
    if(found == 1)
      break;
  }
  if(found == 0)
    return NULL;
  return ptr + i;
}

void fakeMaps(char *original_path, char *fake_path, char *pattern)
{
  int fd;
  char buffer[BUFFER_SIZE];
  int bytes = -1;
  int wbytes = -1;
  int k = 0;

  pid_t pid = getpid();

  int fh;
  if ((fh=orig_open(fake_path,O_CREAT|O_WRONLY))==-1) {
    printf("LD: Cannot open write-file [%s] (%d) (%s)n", fake_path, errno, strerror(errno));
    exit (42);
  }
  if((fd=orig_open(original_path, O_RDONLY))==-1) {
    printf("LD: Cannot open read-file.n");
    exit(42);
  }
  do
  {
    char t = 0;
    bytes = read(fd, &t, 1);
    buffer[k++] = t;
    //printf("%c", t);
    if(t == ' ') {
      //printf("n");
  
      if(!sstrstr(buffer, "LD_PRELOAD")) {
        if((wbytes = write(fh,buffer,k))==-1) {
          //printf("write errorn");
        }
        else {
          //printf("writed %dn", wbytes);
        }
      }
      k = 0;
    }
  }
  while(bytes != 0);
    
  close(fd);
  close(fh);
}

int open(const char *path, int oflag, ...)
{
  char real_path[PATH_MAX], proc_path[PATH_MAX], proc_path_0[PATH_MAX];
  pid_t pid = getpid();
  if(!orig_open)
  orig_open = dlsym(RTLD_NEXT, "open");
  realpath(path, real_path);
  snprintf(proc_path, PATH_MAX, "/proc/%d/environ", pid);
  
  if(strcmp(real_path, proc_path) == 0) {
    snprintf(proc_path, PATH_MAX, "/tmp/%d.fakemaps", pid);
    realpath(proc_path_0, proc_path);
    
    fakeMaps(real_path, proc_path, soname);
    return orig_open(proc_path, oflag);
  }
  return orig_open(path, oflag);
}

αž αžΎαž™αžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›αž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αŸ–

$ (LD_PRELOAD=./ld_undetect_proc_environ.so cat /proc/self/environ; echo) | tr " 00" "n" | grep -F LD_PRELOAD
$

αž€αž“αŸ’αž›αŸ‚αž„αž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž‚αžΊ /proc/self/maps. αžœαžΆαž‚αŸ’αž˜αžΆαž“αž“αŸαž™αž’αŸ’αžœαžΈαž‘αŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαžšαžŸαŸ‹αž“αŸ…αž›αžΎαžœαžΆαŸ” αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž‚αžΊαžŠαžΌαž…αž‚αŸ’αž“αžΆαž”αŸαŸ‡αž”αž·αž‘αž‘αŸ…αž“αžΉαž„αž―αž€αžŸαžΆαžšαž˜αž»αž“αŸ– αž…αž˜αŸ’αž›αž„αž‘αž·αž“αŸ’αž“αž“αŸαž™αž–αžΈαž―αž€αžŸαžΆαžšαžŠαž€αž”αž“αŸ’αž‘αžΆαžαŸ‹αžšαžœαžΆαž„ libc.so ΠΈ αž’αž·αž›.

្.ៀ. αž‡αž˜αŸ’αžšαžΎαžŸαž–αžΈ Chokepoint

αž‡αžΆαž–αž·αžŸαŸαžŸαžαŸ’αž‰αž»αŸ†αž…αžΌαž›αž…αž·αžαŸ’αžαžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž“αŸαŸ‡αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž—αžΆαž–αžŸαžΆαž˜αž‰αŸ’αž‰αžšαž”αžŸαŸ‹αžœαžΆαŸ” αž™αžΎαž„αž”αŸ’αžšαŸ€αž”αž’αŸ€αž”αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αž“αŸƒαž˜αž»αžαž„αžΆαžšαžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‘αž»αž€αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž–αžΈ libcαž“αž·αž„αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“ "αž”αž“αŸ’αž‘αžΆαž”αŸ‹"αŸ”

#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>

#define LIBC "/lib/x86_64-linux-gnu/libc.so.6"

int main(int argc, char *argv[]) {
  void *libc = dlopen(LIBC, RTLD_LAZY); // Open up libc directly
  char *syscall_open = "open";
  int i;
  void *(*libc_func)();
  void *(*next_func)();
  
  libc_func = dlsym(libc, syscall_open);
  next_func = dlsym(RTLD_NEXT, syscall_open);
  if (libc_func != next_func) {
    printf("LD_PRELOAD (syscall - %s) [+]n", syscall_open);
    printf("Libc address: %pn", libc_func);
    printf("Next address: %pn", next_func);
  }
  else {
    printf("LD_PRELOAD (syscall - %s) [-]n", syscall_open);
  }
  return 0;
}

αž€αŸ†αž–αž»αž„αž•αŸ’αž‘αž»αž€αž”αžŽαŸ’αžŽαžΆαž›αŸαž™αžŠαŸ„αž™αžŸαŸ’αž‘αžΆαž€αŸ‹αž…αžΆαž”αŸ‹ "αž”αžΎαž€ ()" αž“αž·αž„αž–αž·αž“αž·αžαŸ’αž™αŸ–

$ export LD_PRELOAD=$PWD/ld_undetect_open.so
$ ./detect_chokepoint
LD_PRELOAD (syscall - open) [+]
Libc address: 0x7fa86893b160
Next address: 0x7fa868a26135

αž€αžΆαžšαž”αžŠαž·αžŸαŸαž’αž”αžΆαž“αž”αŸ’αžšαŸ‚αž‘αŸ…αž‡αžΆαžŸαžΆαž˜αž‰αŸ’αž‰αž‡αžΆαž„αž“αŸαŸ‡αŸ–

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>

extern void * _dl_sym (void *, const char *, void *);
void * dlsym (void * handle, const char * symbol)
{
  return _dl_sym (handle, symbol, dlsym);
}

# LD_PRELOAD=./ld_undetect_chokepoint.so ./detect_chokepoint
LD_PRELOAD (syscall - open) [-]

្.αŸ₯. Syscalls

αžœαžΆαž αžΆαž€αŸ‹αžŠαžΌαž…αž‡αžΆαžαžΆαž“αŸαŸ‡αž‚αžΊαž‘αžΆαŸ†αž„αž’αžŸαŸ‹ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž™αžΎαž„αž“αžΉαž„αž“αŸ…αžαŸ‚αž‡αž½αž”αž”αž‰αŸ’αž αžΆαŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž™αžΎαž„αžŠαžΉαž€αž“αžΆαŸ†αž€αžΆαžšαž αŸ…αž”αŸ’αžšαž–αŸαž“αŸ’αž’αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž‘αŸ…αžαžΊαžŽαŸ‚αž› αžœαžΆαž“αžΉαž„αžšαŸ†αž›αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸ’αž‘αžΆαž€αŸ‹αž…αžΆαž”αŸ‹αž‘αžΆαŸ†αž„αž˜αžΌαž›αŸ” αž‡αžΆαž€αžΆαžšαž–αž·αžαžŽαžΆαžŸαŸ‹ αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž‚αžΊαž’αžΆαžŸαŸ’αžšαŸαž™αž›αžΎαžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜ (x86_64) αžαŸ„αŸ‡αž–αŸ’αž™αžΆαž™αžΆαž˜αž’αž“αž»αžœαžαŸ’αžαžœαžΆαžŠαžΎαž˜αŸ’αž”αžΈαžšαž€αž˜αžΎαž›αž€αžΆαžšαž”αžΎαž€ ld.so.preload.

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUFFER_SIZE 256

int syscall_open(char *path, long oflag)
{
    int fd = -1;
    __asm__ (
             "mov $2, %%rax;" // Open syscall number
             "mov %1, %%rdi;" // Address of our string
             "mov %2, %%rsi;" // Open mode
             "mov $0, %%rdx;" // No create mode
             "syscall;"       // Straight to ring0
             "mov %%eax, %0;" // Returned file descriptor
             :"=r" (fd)
             :"m" (path), "m" (oflag)
             :"rax", "rdi", "rsi", "rdx"
             );
    return fd;
 }
int main()
{
    syscall_open("/etc/ld.so.preload", O_RDONLY) > 0 ?
      printf("LD_PRELOAD (open syscall) [+]n"):
      printf("LD_PRELOAD (open syscall) [-]n");
        
}

$ ./detect_syscall
LD_PRELOAD (open syscall) [+]

αž αžΎαž™αž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αž˜αžΆαž“αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αŸ” αžŠαž€αžŸαŸ’αžšαž„αŸ‹αž…αŸαž‰αž–αžΈ αž˜αž½αž™'A:

ptrace αž‚αžΊαž‡αžΆαž§αž”αž€αžšαžŽαŸαžŠαŸ‚αž›αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αŸαžŠαžΎαž˜αŸ’αž”αžΈαžŸαž„αŸ’αž€αŸαž αž“αž·αž„αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸƒαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αž½αž™αž•αŸ’αžŸαŸαž„αž‘αŸ€αž αž˜αžΎαž› αž“αž·αž„αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž‘αž·αž“αŸ’αž“αž“αŸαž™ αž“αž·αž„αž€αžΆαžšαž…αž»αŸ‡αžˆαŸ’αž˜αŸ„αŸ‡αžšαž”αžŸαŸ‹αžœαžΆαŸ” αž‡αžΆαž’αž˜αŸ’αž˜αžαžΆαž˜αž»αžαž„αžΆαžšαž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαžŠαžΎαž˜αŸ’αž”αžΈαž”αž„αŸ’αž€αžΎαžαž…αŸ†αžŽαž»αž…αžˆαž”αŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸ αž“αž·αž„αžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž€αžΆαžšαž αŸ…αžαžΆαž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’αŸ”

αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αŸαž’αžΆαž…αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžαžΆαž˜αžŠαžΆαž“αžŠαŸ„αž™αž€αžΆαžšαž αŸ…αž‘αžΌαžšαžŸαž–αŸ’αž‘αžŠαŸ†αž”αžΌαž„ fork(2) αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αžΌαž“αž›αž‘αŸ’αž’αž•αž›αž’αžΆαž…αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž· PTRACE_TRACEME αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžαžΆαž˜ (αž‡αžΆαž’αž˜αŸ’αž˜αžαžΆ) αžŠαŸ„αž™αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž· exec(3)αŸ” αž˜αŸ’αž™αŸ‰αžΆαž„αžœαž·αž‰αž‘αŸ€αž αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αŸαž’αžΆαž…αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ‚αž›αž˜αžΆαž“αžŸαŸ’αžšαžΆαž”αŸ‹αžŠαŸ„αž™αž”αŸ’αžšαžΎ PTRACE_ATTACH αŸ”

αž“αŸ…αž–αŸαž›αžαžΆαž˜αžŠαžΆαž“ αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž»αž˜αžΆαžšαžˆαž”αŸ‹αžšαžΆαž›αŸ‹αž–αŸαž›αžŠαŸ‚αž›αžœαžΆαž‘αž‘αž½αž›αž”αžΆαž“αžŸαž‰αŸ’αž‰αžΆ αž”αžΎαž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαžŸαž‰αŸ’αž‰αžΆαž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸαž˜αž·αž“αž’αžΎαž–αžΎαž€αŸαžŠαŸ„αž™αŸ” (αž€αžšαžŽαžΈαž›αžΎαž€αž›αŸ‚αž„αž‚αžΊ SIGKILL αžŠαŸ‚αž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‡αžΆαž’αž˜αŸ’αž˜αžαžΆαŸ”) αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αŸαž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‡αžΌαž“αžŠαŸ†αžŽαžΉαž„αž’αŸ†αž–αžΈαž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αžŠαŸ„αž™αž€αžΆαžšαž αŸ…αžšαž„αŸ‹αž…αžΆαŸ† (2) αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž“αŸ„αŸ‡αžœαžΆαž’αžΆαž…αž˜αžΎαž› αž“αž·αž„αž€αŸ‚αž”αŸ’αžšαŸ‚αžαŸ’αž›αžΉαž˜αžŸαžΆαžšαž“αŸƒαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž»αž˜αžΆαžš αž˜αž»αž“αž–αŸαž›αžœαžΆαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αŸαž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž€αžΌαž“αž”αž“αŸ’αžαžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαžαŸ’αž›αŸ‡αž˜αž·αž“αž’αžΎαž–αžΎαž“αžΉαž„αžŸαž‰αŸ’αž‰αžΆαžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‰αžΎαž‘αŸ…αžœαžΆ αž¬αž”αž‰αŸ’αž‡αžΌαž“αžŸαž‰αŸ’αž‰αžΆαž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž‡αŸ†αž“αž½αžŸαžœαž·αž‰)αŸ”

αžŠαžΌαž…αŸ’αž“αŸαŸ‡ αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž‚αžΊαžŠαžΎαž˜αŸ’αž”αžΈαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αžŠαŸ„αž™αž”αž‰αŸ’αžˆαž”αŸ‹αžœαžΆαž˜αž»αž“αž–αŸαž›αž€αžΆαžšαž αŸ…αžšαž”αžŸαŸ‹αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž“αžΈαž˜αž½αž™αŸ— αž αžΎαž™αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž…αžΆαŸ†αž”αžΆαž…αŸ‹ αž”αž„αŸ’αžœαŸ‚αžšαžαŸ’αžŸαŸ‚αžŸαŸ’αžšαž‘αžΆαž™αž‘αŸ…αž‡αžΆαž˜αž»αžαž„αžΆαžšαž‘αŸ†αž–αž€αŸ‹αŸ”

#define _GNU_SOURCE
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <asm/unistd.h>


#if defined(__x86_64__)
#define REG_SYSCALL ORIG_RAX
#define REG_SP rsp
#define REG_IP rip 
#endif

long NOHOOK = 0;

long evil_open(const char *path, long oflag, long cflag) 
{
    char real_path[PATH_MAX], maps_path[PATH_MAX];
    long ret;
    pid_t pid;
    pid = getpid();
    realpath(path, real_path);
    if(strcmp(real_path, "/etc/ld.so.preload") == 0)
    {
        errno = ENOENT;
        ret = -1;
    }
    else
    {
        NOHOOK = 1; // Entering NOHOOK section
        ret = open(path, oflag, cflag);
    }
    // Exiting NOHOOK section
    NOHOOK = 0;
    return ret;
}

void init()
{
    pid_t program;
    // Π€ΠΎΡ€ΠΊΠ°Π΅ΠΌ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ процСсс
    program = fork();
    if(program != 0) {
        int status;
        long syscall_nr;
        struct user_regs_struct regs;
        // ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌΡΡ ΠΊ Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅ΠΌΡƒ процСссу
        if(ptrace(PTRACE_ATTACH, program) != 0) {
            printf("Failed to attach to the program.n");
            exit(1);
        }
        waitpid(program, &status, 0);
        // ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π΅ΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ SYSCALLs
        ptrace(PTRACE_SETOPTIONS, program, 0, PTRACE_O_TRACESYSGOOD);
        while(1) {
            ptrace(PTRACE_SYSCALL, program, 0, 0);
            waitpid(program, &status, 0);
            if(WIFEXITED(status) || WIFSIGNALED(status)) break;
            else if(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP|0x80) {
                // ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π½ΠΎΠΌΠ΅Ρ€ систСмного Π²Ρ‹Π·ΠΎΠ²Π°
                syscall_nr = ptrace(PTRACE_PEEKUSER, program, sizeof(long)*REG_SYSCALL);
                if(syscall_nr == __NR_open) {
                    // Π§ΠΈΡ‚Π°Π΅ΠΌ слово ΠΈΠ· памяти Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ процСсса
                    NOHOOK = ptrace(PTRACE_PEEKDATA, program, (void*)&NOHOOK);
                    // ΠŸΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ Π²Ρ‹Π·ΠΎΠ²
                    if(!NOHOOK) {
                        
                        // ΠšΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ рСгистры Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ процСсса
                        // Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ regs Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ
                        ptrace(PTRACE_GETREGS, program, 0, &regs);
                        // Push return address on the stack
                        regs.REG_SP -= sizeof(long);
                        // ΠšΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ слово Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ процСсса
                        ptrace(PTRACE_POKEDATA, program, (void*)regs.REG_SP, regs.REG_IP);
                        // УстанавливаСм RIP ΠΏΠΎ адрСсу evil_open
                        regs.REG_IP = (unsigned long) evil_open;
                        // ЗаписываСм состояниС рСгистров процСсса
                        ptrace(PTRACE_SETREGS, program, 0, &regs);
                    }
                }
                ptrace(PTRACE_SYSCALL, program, 0, 0);
                waitpid(program, &status, 0);
            }
        }
        exit(0);
    }
    else {
        sleep(0);
    }
}

αž€αŸ†αž–αž»αž„αž–αž·αž“αž·αžαŸ’αž™:

$ ./detect_syscall
LD_PRELOAD (open syscall) [+]
$ LD_PRELOAD=./ld_undetect_syscall.so ./detect_syscall
LD_PRELOAD (open syscall) [-]

+0-0=5

αž’αžšαž‚αž»αžŽαž…αŸ’αžšαžΎαž“αŸ”

αž›αŸ„αž€ Charles Hubain
αž…αŸ†αžŽαž»αž…αž†αž€αŸ‹
αžœαŸ‰αžΆαž›αŸ‹αžŒαžΈαž€αž’αŸαžŸαž’αŸαžŸ
Philippe Teuwen
derhass

αžŠαŸ‚αž›αž’αžαŸ’αžαž”αž‘ αž”αŸ’αžšαž—αž– αž“αž·αž„αž˜αžαž·αž™αŸ„αž”αž›αŸ‹αž”αžΆαž“αž’αŸ’αžœαžΎαž…αŸ’αžšαžΎαž“αž‡αžΆαž„αž’αŸ’αžœαžΈαžŠαŸ‚αž›αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž’αŸ’αžœαžΎ αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαž±αŸ’αž™αž…αŸ†αžŽαžΆαŸ†αž“αŸαŸ‡αž›αŸαž…αž‘αžΎαž„αž“αŸ…αž‘αžΈαž“αŸαŸ‡αŸ”

αž”αŸ’αžšαž—αž–: www.habr.com

αž‘αž·αž‰αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αžŠαŸ‚αž›αž’αžΆαž…αž‘αž»αž€αž…αž·αžαŸ’αžαž”αžΆαž“αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αŸαž αž‘αŸ†αž–αŸαžšαžŠαŸ‚αž›αž˜αžΆαž“αž€αžΆαžšαž€αžΆαžšαž–αžΆαžš DDoS, αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ VPS VDS πŸ”₯ αž‘αž·αž‰αžŸαŸαžœαžΆαž”αž„αŸ’αž αŸ„αŸ‡αž‚αŸαž αž‘αŸ†αž–αŸαžšαžŠαŸ‚αž›αž’αžΆαž…αž‘αž»αž€αž…αž·αžαŸ’αžαž”αžΆαž“αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž€αžΆαžšαž–αžΆαžš DDoS αž“αž·αž„αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ VPS VDS | ProHoster