LD_PRELOAD рдХреА рддрд▓рд╛рд╢ рд╣реИ

рдпрд╣ рдиреЛрдЯ 2014 рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдореИрдВ рдмрд╕ рд╣рдм рдкрд░ рджрдорди рдореЗрдВ рдЖ рдЧрдпрд╛ рдФрд░ рдЙрд╕рдиреЗ рдкреНрд░рдХрд╛рд╢ рдХреЛ рдирд╣реАрдВ рджреЗрдЦрд╛ред рдкреНрд░рддрд┐рдмрдВрдз рдХреЗ рджреМрд░рд╛рди, рдореИрдВ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреВрд▓ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЕрдм рдореИрдВрдиреЗ рдЗрд╕реЗ рдорд╕реМрджрд╛ рдкреНрд░рддрд┐рдпреЛрдВ рдореЗрдВ рдкрд╛рдпрд╛ред рд╕реЛрдЪрд╛ рдерд╛ рдХрд┐ рдЗрд╕реЗ рд╣рдЯрд╛рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╢рд╛рдпрдж рдХреЛрдИ рдХрд╛рдо рдЖрдПред



рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, "рд╢рд╛рдорд┐рд▓" LD_PRELOAD рдХреА рдЦреЛрдЬ рдХреЗ рд╡рд┐рд╖рдп рдкрд░ рдПрдХ рдЫреЛрдЯрд╛ рд╢реБрдХреНрд░рд╡рд╛рд░ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдкрдврд╝рддрд╛ рд╣реИред

1. рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯрд╛ рд╡рд┐рд╖рдпрд╛рдВрддрд░ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ


рдмрд╛рдХреА рдЪрд░рдг 2 рдкрд░ рд╕реАрдзреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред

рдЖрдЗрдП рдХреНрд▓рд╛рд╕рд┐рдХ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ:

#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { srand (time(NULL)); for(int i=0; i<5; i++){ printf ("%d\n", rand()%100); } } 

рдмрд┐рдирд╛ рдХрд┐рд╕реА рдЭрдВрдбреЗ рдХреЗ рд╕рдВрдХрд▓рди:

 $ gcc ./ld_rand.c -o ld_rand 

рдФрд░, рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ, рд╣рдо 100 рд╕реЗ рдХрдо 5 рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:

 $ ./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 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:

 # 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 рдлрд╝рд╛рдЗрд▓ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдпрд╣ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реИ рдЬреЛ рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдФрд░ рдмреБрдирд┐рдпрд╛рджреА рдХрд╛рд░реНрдп рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдУрдкрди , рдореЙрд▓реЛрдХ , рдкреНрд░рд┐рдВрдЯрдл , рдЖрджрд┐ред рд╣рдорд╛рд░реА рд░реИрдВрдб рднреА рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рд╣реИред рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ:

 # 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 code\n"); orig_rand_f_type orig_rand; orig_rand = (orig_rand_f_type)dlsym(RTLD_NEXT,"rand"); return orig_rand(); } 

рдпрд╣рд╛рдБ, рд╣рдорд╛рд░реЗ "additive" рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рдХреЗрд╡рд▓ рдкрд╛рда рдХреА рдПрдХ рдкрдВрдХреНрддрд┐ рдХреЛ рдкреНрд░рд┐рдВрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдореВрд▓ рд░реИрдВрдб рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдмрдирд╛рддреЗ рд╣реИрдВред рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ 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. рдЖрдЯрд╛ рдЦреЛрдЬ


рд╕рдВрднрд╛рд╡рд┐рдд рдЦрддрд░реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдпрд╣ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░реАрд▓реЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдЗрд╕реЗ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рдврд╛рд▓ рджреЗрдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдерд╛рди рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд░реБрдЪрд┐ рдереАред

рдЕрдЧрд▓рд╛, рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдФрд░ рдЙрдирдХреЗ рдкреНрд░рддрд┐рдирд┐рдпреБрдХреНрддрд┐ рдХреЗ рд╕рдорд╛рдзрд╛рди рдЬреЛрдбрд╝реЗ рдореЗрдВ рдЬрд╛рдПрдВрдЧреЗред

2.1ред рдПрдХ рд╕рд░рд▓ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ


рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЖрдк рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ 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 рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдЙрдиреНрд╣реЗрдВ рдзреЛрдЦрд╛ рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред

2.2ред рдЪрд▓ рд░рд╣рд╛ рд╣реИ


рдКрдкрд░ рд╣рдордиреЗ LD_PRELOAD рдХрд╛ рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП getenv () рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ , рд▓реЗрдХрд┐рди ENV рд╡реИрд░рд┐рдПрдмрд▓реНрд╕ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдзрд┐рдХ "рдирд┐рдореНрди рд╕реНрддрд░" рддрд░реАрдХрд╛ рд╣реИред рд╣рдо рдордзреНрдпрд╡рд░реНрддреА рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди ** environ рд╕рд░рдгреА рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреА рдПрдХ рдкреНрд░рддрд┐ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИ:

 #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 рдЪрд░ рдХрд╛ рдорд╛рди рдЕрдм рдкрдЯрд╛рдЦреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ, рдЕрд░реНрдерд╛рдд, рдЖрдк рдЗрд╕реЗ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдХрд┐рд╕реА рднреА рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЗрд╕реЗ рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдмреЗрд╢рдХ, рд╕реНрдореГрддрд┐ рдореЗрдВ рдХрд┐рд╕реА рд╕рд░рдгреА рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдХрдо рд╕реЗ рдХрдо рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╢реИрд▓реА рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд┐рд╕реА рдХреЛ рд░реЛрдХ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдорд╛рд░реА рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдордирд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ?

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдирдХрд▓реА рдлрд╝рдВрдХреНрд╢рди init () рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╣рдо рд╕реНрдерд╛рдкрд┐рдд 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) [-] 

2.3ред / рдЦрд░реАрдж / рд╕реНрд╡ /


рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореЗрдореЛрд░реА рдЕрдВрддрд┐рдо рд╕реНрдерд╛рди рдирд╣реАрдВ рд╣реИ рдЬрд╣рд╛рдБ рдЖрдк LD_PRELOAD рд╕реНрдкреВрдлрд┐рдВрдЧ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд╡рд╣рд╛рдБ рднреА / proc / рд╣реИ ред рдЪрд▓реЛ рд╕реНрдкрд╖реНрдЯ / proc / {PID} / environ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ ред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ undetect ** environ рдФрд░ / proc / self / environ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд╕рдорд╛рдзрд╛рди рд╣реИред рд╕рдорд╕реНрдпрд╛ рдЕрд╕рддреНрд╕реЗрд╡ (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] != '\0'; j++) environ[i][j] = '\0'; 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 "\000" "\n" | grep -F LD_PRELOAD $ 


рд▓реЗрдХрд┐рди рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдореЗрдВ рдпрд╣ рдирд╣реАрдВ рдорд┐рд▓рд╛ рдФрд░ / proc / self / environ рдореЗрдВ "рд╕рдорд╕реНрдпрд╛рдЧреНрд░рд╕реНрдд" рдбреЗрдЯрд╛ рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдорд╛рд░реЗ рдкрд┐рдЫрд▓реЗ "рднреЗрд╕" рдХреЗ рд╕рд╛рде рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ:

 $ (LD_PRELOAD=./ld_undetect_environ.so cat /proc/self/environ; echo) | tr "\000" "\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 != '\0'; ptr++) { found = 1; for(i = 0; found == 1 && sub[i] != '\0'; 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 == '\0') { //printf("\n"); if(!sstrstr(buffer, "LD_PRELOAD")) { if((wbytes = write(fh,buffer,k))==-1) { //printf("write error\n"); } else { //printf("writed %d\n", 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 "\000" "\n" | grep -F LD_PRELOAD $ 

рдЕрдЧрд▓рд╛ рд╕реНрдкрд╖реНрдЯ рд╕реНрдерд╛рди / рдЦрд░реАрдж / рд╕реНрд╡ / рдорд╛рдирдЪрд┐рддреНрд░ рд╣реИ ред рдЗрд╕ рдкрд░ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред рд╕рдорд╛рдзрд╛рди рдкрд┐рдЫрд▓реЗ рдПрдХ рдХреЗ рд╕рдорд╛рди рд╣реИ: рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдбреЗрдЯрд╛ рдХреЛ рдХреЙрдкреА рдХрд░реЗрдВ libsso рдФрд░ ld.so рдХреЗ рдмреАрдЪ рдХреА рд░реЗрдЦрд╛рдПрдВред

2.4ред рдЪреЛрдХрдкреЙрдЗрдВрдЯ рд╕реЗ рд╡рд┐рдХрд▓реНрдк


рдореБрдЭреЗ рдпрд╣ рд╕рдорд╛рдзрд╛рди рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЕрдкрдиреА рд╕рд╛рджрдЧреА рдХреЗ рдХрд╛рд░рдг рдкрд╕рдВрдж рдЖрдпрд╛ред рд╕реАрдзреЗ libc рдФрд░ "NEXT" рдкрддреЗ рд╕реЗ рд▓реЛрдб рдХрд┐рдП рдЧрдП рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкрддреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВред

 #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: %p\n", libc_func); printf("Next address: %p\n", 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) [-] 

2.5ред Syscalls


рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рднреА, рд▓реЗрдХрд┐рди рдЕрднреА рднреА flounder рд╣реИред рдЕрдЧрд░ рд╣рдо рд╕реАрдзреЗ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рдПрдХ рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХреЛ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕рдВрдкреВрд░реНрдг рдЕрд╡рд░реЛрдзрди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░реЗрдЧрд╛ред рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рд╕рдорд╛рдзрд╛рди, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рд╡рд╛рд╕реНрддреБрдХрд▓рд╛- рдирд┐рд░реНрднрд░ ( 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) [+] 

рдФрд░ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдПрдХ рд╣рд▓ рд╣реИред рдЖрджрдореА рд╕реЗ рдЕрдВрд╢:
ptrace рдПрдХ рдРрд╕рд╛ рдЙрдкрдХрд░рдг рд╣реИ рдЬреЛ рдПрдХ рдкреЗрд░реЗрдВрдЯ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдкреНрд░рд╡рд╛рд╣ рдХреЛ рджреЗрдЦрдиреЗ рдФрд░ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ, рдЙрд╕рдХреЗ рдбреЗрдЯрд╛ рдФрд░ рд░рдЬрд┐рд╕реНрдЯрд░ рдХреЛ рджреЗрдЦрдиреЗ рдФрд░ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЖрдорддреМрд░ рдкрд░, рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдбрд┐рдмрдЧрд┐рдВрдЧ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдФрд░ рдЯреНрд░реИрдХ рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдореЗрдВ рдмреНрд░реЗрдХрдкреНрд╡рд╛рдЗрдВрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдкреИрд░реЗрдВрдЯ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд╣рд▓реЗ рдХрд╛рдВрдЯреЗ (2) рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдЯреНрд░реЗрд╕рд┐рдВрдЧ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреА рд╣реИ, рдФрд░ рдлрд┐рд░ рдкрд░рд┐рдгрд╛рдореА рдЪрд╛рдЗрд▓реНрдб рдкреНрд░рдХреНрд░рд┐рдпрд╛ PTRACE_TRACEME рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреА рд╣реИ, рдЙрд╕рдХреЗ рдмрд╛рдж (рдЖрдорддреМрд░ рдкрд░) рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрди (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

рдЖрдкрдХрд╛ рдмрд╣реБрдд-рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж

рдЪрд╛рд░реНрд▓реНрд╕ рд╣реБрдмреИрди
Chokepoint
ValdikSS
рдлрд┐рд▓рд┐рдк рдЯреЗрдЙрд╡реЗрди
derhass

рдЬрд┐рдирдХреЗ рд▓реЗрдЦ, рд╕реНрд░реЛрдд рдХреЛрдб рдФрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдпрд╣рд╛рдБ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭрд╕реЗ рдХрд╣реАрдВ рдЕрдзрд┐рдХ рдереЗред

Source: https://habr.com/ru/post/hi479858/


All Articles