إكتشاف العمليات والمنافذ المخفية ال rootkit في أنظمة التشغيل اليونكس واللينكس بواسطة لغة C,C++

عام 0 geek4arab
Spread the love

في هذا الموضوع سنأخذ مثال لإكتشاف العمليات المخفية Hidden processes
في الأنظمة مفتوحة المصدر وسنطبق المثال على نظامي Linux RedHat و Unix OpenBSD
والإختلاف بسيط . يفيدنا هذا الموضوع في إكتشاف الملفات الخبيثة التي تستخدم تقنيات الاخفاء

نبدأ الموضوع
أولاً: إستخدام مجلد proc في إكتشاف العمليات
العمليات بإختصار هي البرامج والملفات التنفيذية التي تعمل في الذاكرة
فعندما تقوم بتشغيل برنامج ما يقوم النظام بتعريفه في الذاكرة وإعطائه رقم عمليه

في الأنظمة مفتوحة المصدر يعمل النظام على توفير مجلد proc في الجذر /
هذا المجلد يعمل على ترتيب كل العمليات وتخزين اهم المعلومات عنها
مثلاً لو فتحت المجلد proc لوجدت مجلدات كثيرة عبارةعن ارقام هذه الارقام
تمثل PID او معرف العملية , لاحظ الصورة

لو دخلت مجلد اي عمليه لوجدت تفاصيل عنها.
مثل الحاله والمسار وحيز الذاكرة stat و cmdline و mem
وكأنك بداخل ال task manager في نظام وندوز
لاحظ العملية 3033 :

والآن سنأخذ مشروع او برنامج مفتوح المصدر كتب بواسطة security-projects.com
هذا البرنامج يقوم بعرض العمليات المخفية
تجد الكود هنا
unhide.c

في البداية سنقوم بتحليل كود البرنامج وكيف يظهر العمليات
توجد طريقتين يستخدمها البرنامج
الاولى طريقه proc ,, تبدأ بالداله checkproc لعرض العمليات ثم checkps لإظهار معلومات pid

طريقة عمل داله سرد العمليات checkproc

int maxpid= 999999;

void checkproc()
{
int procpids ;
char sendto[100];
int statusproc;

struct stat buffer;
printf (“[*]Searching for Hidden processes trougth /proc scanning\n\n”) ;

//بداية دورة للبحث عن PID تبدأ ب 1 إلى 999999
for ( procpids = 1; procpids <= maxpid; procpids = procpids +1 ) {
char directory[100] ;
//
بناء المسار /proc/pid = مأخوذ من الدورة
sprintf(directory,”/proc/%d”,procpids);

// إختبار إذا كان مجلد رقم العملية موجود
statusproc = stat(directory, &buffer) ;

if (statusproc == 0) {
// إذا كان موجود نكون قد إستخرجنا رقم عملية تعمل في الذاكرة
checkps(procpids);
}
}

تلاحظ ان الطريقة بسيطة بداية بتنفيذ دورة من 1 إلى 9999
في كل دورة يعمل البرنامج على إضافة الرقم للمسار proc
فتنتج المسارات بهذا الشكل

/proc/1
/proc/2
/proc/3
/proc/4
….
إلى 9999

بعد ان يقوم ببناء مسار يعتقد انها رقم عملية ينفذ داله stat وهي داله لجلب معلومات الملف
هذه الداله تعيد قيمتين إما 0 إذا نفذت بنجاح بمعنى الملف المحدد موجود و-1 إذا حدث خطأ في الدالة

وفي النهاية المعنى واضح إذا نفذت الداله stat بنجاح في دورة معنى ذلك ان المسار عباره عن عمليه مقيمه في الذاكرة
وبهذا نكون إستخرجنا pid ,, بعد إستخراجه يمرر إلى الداله checkps لقرائة معلوماته الاضافيه لمعرفه إذا كان مخفي ام لا

الآن سنأخذ الطريقة التي يقوم بهاالبرنامج لإظهار معلومات pid وهي الداله checkps

// Linux
#define COMMAND “ps -eLf | awk ‘{ print $2 }’ | grep -v PID”

//OpenBSD
// #define COMMAND “ps -axk | awk ‘{ print $1 }’ | grep -v PID”

void checkps(int tmppid)
{
int statusfile;
int statcommand;
int ok = 0;
char pids[30];

char compare[100];
FILE *fich_tmp ;

// تنفيذ ps وهو برنامج command line في نظام لينكس
fich_tmp=popen (COMMAND, “r”) ;

// قرائة النتائج التي اظهرها الامر ps
while (!feof(fich_tmp) && ok == 0) {

fgets(pids, 30, fich_tmp);
sprintf(compare,”%i\n”,tmppid);
// مقارنة رقم العملية التي إسخرجناها مسبقا مع العمليات التي يظهرها ps
// إذا كانت موجودة معنى ذلك انها ليست مخفية وإذا لم تظهر معنى ذلك انها مخفية
if (strcmp(pids, compare) == 0) {ok = 1;}
}

pclose(fich_tmp);
if ( ok == 0 ) {
int statuscmd ;
int posicion;
char cmd[100] ;
struct stat buffer;

printf (“Found HIDDEN PID: %i\n”, tmppid) ;
sprintf(cmd,”/proc/%i/cmdline”,tmppid);
statuscmd = stat(cmd, &buffer);

if (statuscmd == 0) {

FILE *cmdfile ;
char cmdcont[1000];

// قرائة ملف cmdline للبرنامج وإظهار المسار
cmdfile=fopen (cmd, “r”) ;

while (!feof (cmdfile)) {

fgets (cmdcont, 1000, cmdfile);
printf (“Command: %s\n\n”, cmdcont);
}
}
}
}

يبدأ البرنامج بتنفيذ برنامج نظام وهو ps وهو الخاص بالعمليات
وينفذ برامج إظافية للتنسيق مثل awk و grep لاحظ الامر
fich_tmp=popen (COMMAND, “r”) ;

عبارة عن كتابه ps -eLf | awk ‘{ print $2 }’ | grep -v PID في سطر الاوامر لنظام لينكس
لاحظ الصورة توضح لك برامج سطر الاوامر وإستخدام ps -elf

تلاحظ ظهور اكثر من جدول لخصائص العملية ونحن بدورنا نريد جدول واحد وهو PID
ولذلك إستخدمنا الامرين awk ‘{ print $2 }’ | grep -v PID

بعد ذلك ينفذ البرنامج امر قرائة المخرجات او قرائة الذي يظهر في سطر الاوامر
بواسطة داله fgets(pids, 30, fich_tmp);
ويتم مقارنة معرف العملية للتأكد من وجودة
إذا كان غير موجود يقوم برنامجنا بإظهاره على انه عملية مخفية.

=======================================

الطريقة الثانية بإستخدام دوال وخدمات العمليات
1- بإستخدام getpriority

void checkgetpriority() {

int syspids ;
char sendto[100];

printf (“[*]Searching for Hidden processes trougth getpriority() scanning\n\n”) ;
for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

int ret;
errno= 0 ;
ret = getpriority(PRIO_PROCESS, syspids);

if ( errno == 0) {
checkps(syspids);
}
}
}

لاحظ البرنامج مشابه لماسبق ,, يبدأ بدورة من 1 إلى 9999
ولتحقق من وجود العملية يستخدم الداله getpriority
النقطة الي تبالها توضيح هنا المتغير errno ولماذا قارناه ب الصفر

هذا المتغير يعرف بحاله الأخطاء إذا كنت مبرمج سي على نظام وندوز أكيد مرت
عليك داله GetLastError وتستخدم لمعرفه إذا كان قد حدث خطأ في آخر داله
وهنا الموضوع مشابه وبنفس الطريقة إذا كان errno =0 معنا ذلك انه لم يحدث اي خطأ والنتيجة ان
معرف العملية PID الذي مرر للدالة موجود .

2- بإستخدام getpgid

void checkgetpgid() {

int syspids ;
char sendto[100];

printf (“[*]Searching for Hidden processes trougth getpgid() scanning\n\n”) ;
for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

int ret;
errno= 0 ;
ret = getpgid(syspids);

if ( errno == 0) {
checkps(syspids);
}

}
}

3 بإستخدام getsid

void checkgetsid() {

int syspids ;
char sendto[100];
printf (“[*]Searching for Hidden processes trougth getsid() scanning\n\n”) ;

for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

int ret;
errno= 0 ;
ret = getsid(syspids);

if ( errno == 0) {
checkps(syspids);
}
}
}


وبهذا نكون قد تعرفنا على طرق وأساليب إظهار العمليات المخفية في أنظمة لينكس ويونكس
بقي ان اضيف مثال آخر عن إظهار المنافذة المخفية

هذا المثال مشابة لماسبق ويعمل على Linux و OpenBSD و Solaris
unhide-tcp.c

فكرة البرنامج بسيطة جدا ,, يبدأ بدورة من 1 إلى 65535 وهو مجال المنافذ لبروتوكولات TCP و UDP
المهم بعد ذلك يمسك البرنامج اي منفذ ويحاول فتحه بداله listen
إذا اعطت الداله خطأ معنى ذلك ان المنفذ محجوز ومعناه انه مفتوح ,, هذه هي فكرة عمل برامج ال port scanner
او مسح المنافذ ,, بهذا الشكل

printf (“Starting TCP checking\n\n”) ;

for (i =1; i < 65535; i++) {

int socket_desc;
struct sockaddr_in address;
socket_desc=socket(AF_INET,SOCK_STREAM,0);

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(i);

errno= 0 ;
bind(socket_desc,(struct sockaddr *)&address,sizeof(address));
listen(socket_desc,1);

if ( errno != 0) {
close(socket_desc);
checkport(i, tcpcommand);
}
close(socket_desc);
}

وبعد أن يظهر البرامج المنافذ المفتوحة يتأكد من ان النظام يعرفها او لا عن طريق الامرالمعروف في كل الانظمة netstat
وإذا لم يظهرها برنامج النظام يستنتج برنامجنا انه منفذ مخفي

// Linux

char tcpcommand[]= “netstat -tan | sed -e ‘/[\\.:][0-9]/!d’ -e ‘s/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'” ;

char udpcommand[]= “netstat -uan | sed -e ‘/[\\.:][0-9]/!d’ -e ‘s/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'” ;

// OpenBSD

// char tcpcommand[]= “netstat -an -p tcp | sed -e ‘/[\\.:][0-9]/!d’ -e ‘s/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'” ;

// char udpcommand[]= “netstat -an | -p udp| sed -e ‘/[\\.:][0-9]/!d’ -e ‘s/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'” ;

// Solaris

// char tcpcommand[]= “netstat -an -P tcp | sed -e ‘/[\\.:][0-9]/!d’ -e ‘s/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'” ;

// char udpcommand[]= “netstat -an | -P udp| sed -e ‘/[\\.:][0-9]/!d’ -e ‘s/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'” ;

void checkport(int port, char command[]) {

int statusfile;

int statcommand;

int ok = 0;
char ports[30];

char compare[100];

FILE *fich_tmp ;

fich_tmp=popen (command, “r”) ;

while (!feof(fich_tmp) && ok == 0) {

fgets(ports, 30, fich_tmp);

sprintf(compare,”%i\n”,port);

if (strcmp(ports, compare) == 0) {ok = 1;}
}

pclose(fich_tmp);

if ( ok == 0 ) {

printf (“Found Hidden port that not appears in netstat: %i\n”, port) ;

}
}

وكذلك نفس الطريقة مع بروتوكول UDP

وبهذا نكون قد أخذنا أساسيات عن عمليات الأخفاء في أنظمة لينكس ويونكس
في المواضيع القادمة سنحاول مناقشة تفاصيل اكثر

بالتوفيق ,,,

الكاتب geek4arab

geek4arab

مواضيع متعلقة

التعليقات مغلقة