الاثنين، 20 سبتمبر 2021

بايثون للشبكات : برنامج يستخدم برتوكول ARP لعرض جميع الأجهزة المتصلة على الشبكة المحلية

 بسم الله الرحمن الرحيم

الحصول على عنوان الأنترنت الخاص بالإجهزة على الشبكة هو الخطوة الأولى لكي تبدأ عملية اكتشاف نقاط الضعف في هذه الأجهزة , و في هذه التدوينة سوف نبني برنامج بايثون يقوم بهذه المهمة , و هنا يأتي السؤال لماذا ؟ , ألا يوجد برامج تقوم بهذا العمل و تغني عن هذا المجهود , الأجابة نعم  لكن افضل طريقة للتعلم هو التطبيق, سنبدأ أولا بشرح نظري للطريقة التي سنستخدمها مع نظرة لبرتوكول ARP , ثم تثبيت مكتبة Scapy في ويندوز و لينكس و أخيرا سوف نقوم بكتابة سكريبت يقوم باستخدام بروتوكول ARP لكشف الأجهزة المتصلة .


  • نظرة لبرتوكول ARP :

Address Resolution Protocol أو أختصاراً (ARP) , هو برتوكول يهدف لعرض العنوانين الفزيائية أو ما يسمى بعنوان MAC المرتبط بعنوان الأنترنت ( IP Address ) و العكس صحيح .

لنفترض بأنك تريد الاتصال بكمبيوتر يوجد على الشبكة المحلية و لديك عنوان الأنترنت (IP) فتحصل الخطوات التالية :
  1. سيبحث جهازك عن العنوان الفزيائي في جدول العناوين الموجود على النظام  والمسمى ARP Caching Table .
  2. في حالة وجود هذا العنوان في الجدول سوف يتم الأعتماد عليه بدون ارسال طلب ARP .
  3. في حالة عدم وجود العنوان سوف يرسل الجهاز طلب ARP Request لجميع الأجهزة المتصلة (Broadcast message).
  4. جهاز الــ"switch" سيقوم بأرسال هذه الرسالة لجميع المنافذ النشطة ما عدا المنفذ الذي تم منه الأرسال .
  5. عند وصول الرسالة إلى الجهاز الذي يحمل عنوان الأنترنت المطابق سوف يرد برسالة تحمل عنوانه الفيزيائي .
  6. في حالة عدم وجود جهاز يحمل عنوان الأنترنت على الشبكة المحلية سوف ينتهي وقت انتظار الرد و يفترض الجهاز المرسل بأنه لا وجود لهذا الجهاز .

هذه صورة لطلب ARP Request من برنامج wireshark , تلاحظ بساطة البروتوكول :


 الرد في برتوكول يكون العنوان البديل لعنوان البث (Broadcast ) و سوف تكون الرسالة موجهة بشكل  مباشر للمرسل (Unicast) ونوع الرسالة Opcode هو Reply .


هذا شرح مبسط جدا لهذا البرتوكول , و السبب لوجوده بأن الرسائل داخل الشبكة المحلية يتم تبدلها بواسطة برتوكول Ethernet  الذي يعمل في طبقة ربط البيانات (Data Link) والذي يستخدم العنوان الفيزيائي للاتصال  , كما يظهر لك نموذج OSI .


هنا قد تتساءل لماذا لا نستخدم برتوكول ICMP و اشهر تطبيقاته و هو الأمر Ping في انظمة ويندوز و لينكس , السبب هو أن الكثير من الأجهزة مثل الهواتف الذكية و جدران النار تحظر هذا البرتوكول و تقوم بمنع الرد على رسائله, أما في حالة برتوكول ARP فمن الصعب تعطيله لأنه اساسي لعملية الأتصال كما رأيت .


  • تثبيت مكتبة Scapy 

مكتبة Scapy هي مكتبة متخصصة في بناء و ارسال حزم شبكات معدلة و ارسالها عبر الشبكة , امكانيات هذه المكتبة كبيرة جداٌ و تعطي المبرمج امكانيات رائعة .

التثبيت في نظام لينكس :

لمستخدمي توزيعة Ubuntu أو اي توزيعة تستخدم مدير الحزم Apt فقط اكتب الأمر في موجه الأوامر :

sudo apt-get install scapy


التثبيت في نظام ويندوز :

لتثبيت في ويندوز سوف نستخدم توزيعة البايثون Anaconda , هذه التوزيعة من الأشهر في مجال علم البيانات ( Data sciences ) و ما يميزها هو سهولة تثبيت المكتبات و وجود محرر ممتاز لذا سوف نستخدمها في حالتنا .

  1. قم بتنزيل التوزيعة من الموقع الرسمي ( https://www.anaconda.com/products/individual-d ) .
     
    2. اتبع خطوات التثبيت 
     



    3. تأكد من تفعيل خيار أضافة مجلد التثبيت إلى متغير مسار البرامج ( PATH )


 4. بعد أنتهاء التثبيت قم بتشغيل برنامج Anconda من القائمة Start 




5. عندما ينتهي تحميل البرنامج ستظر لم نافذة كالتالي :



6. أختر من القائمة على اليمين Enviroments :





7. و لتحديث قائمة المكتبات أضغط "Update Index" و غير العرض إلى جميع المكتبات ثم أبحث عن المكتبة scapy و اضغط في اسفل المكتبة على الخيار Apply :

 
للتأكد من نجاح التثبيت قم بتشغيل موجه الأوامر الخاص بالمكتبة Scapy في نظام ويندوز من القائمة Start أكتب في مربع البحث أكتب "Cmd" و أختر "Run as Administrator" :
 

 اكتب في موجه الأوامر Scapy أذا ظهر لك موجه الأوامر كالتالي فيعني أننا نجحنا في التثبيت :


في نظام ليكنس فقط أكتب الأمر كالتالي , يجب أن يظهر لك موجه الأوامر مشابه لما في ويندوز :

sudo scapy


  • الموجه التفاعلي لمكتبة Scapy

    قبل أن نكتب السكريبت في بايثون سوف نستغل خاصية الموجه الأوامر في Scapy و الذي هو عبارة عن موجه python مع تفعيل المكتبة Scapy.
     
    هذه الخاصية اعتبرها من الأمكانيات الممتازة حيث يمكن تجريب و التعديل بشكل مباشر و سريع لكي تتأكد من نجاح برنامجك.

    لنبدأ أولا بأنشاء الاساس في أطار الشبكة الخاصة ببرتوكول ARP , البرتوكول مبنى و مضمن في أطار ايثرنت (Ethernet Frame) .
    * يجب أن أنوه بأن برتوكول ARP مستخدم في أكثر من أطار للشبكات , ولكن للشبكات المحلية الأطار المستخدم هو ايثرنت .
     
    و لكن قبل أن ننشىء هنا عرض مبسط لمكونات الإطار و شرح لها :

    المصدر :https://commons.wikimedia.org/wiki/File:Ethernet_II_Frame_Structure.png


    هذه الصورة لإطار ايثرنت ( اقصد بالإطار Frame و هي الكلمة المستخدمة للحزم في الطبقة الثانية من OSI للشبكات ) و الشرح ببساطة :

    1. Preamble : هو مجموعة 56 بايت تستخدم لمزامنة ساعة المستقبل على نفس ساعة المرسل ( Clock Sync )  و هنا لا نعني التوقيت كالوقت و التاريخ , هذا المصطلح يخص الإلكترونيات , و هذا النطاق يخص الطبقة الأولى من من OSI وسوف اتجنب شرحها لكي لا أعقد الموضوع .
    2. SFD : اختصار لــ  Start Frame Delimiter بداية البيانات الخاص بالإطار أيضا يقع في الطبقة الأولى من OSI .
    3. Destination Address : العنوان الفيزيائي للبطاقة الشبكة (Mac Address ) المرسل لها البيانات يتكون من 6 بايتات يتم عرضه بتمثيل Hexadecimal و فصل بين كل بايت بـ ":" .
    4.  Source Address : العنوان الفيزيائي للبطاقة الشبكة (Mac Address ) المرسل منها البيانات يتكون من 6 بايتات ايضا و يتبع نفس التمثيل كما في العنوان المرسل له .
    5. النوع : بحسب البرتوكول المستخدم في حالتنا سيكون ARP و سيحمل القيمة 0x0806.
    6.  البيانات : البيانات الفعلية
    7. FCS : هذه القيمة تمثل ناتج معادلة تأكد للمرسل أذا حدث خطأ في نقل البيانات , حيث يتم تنفيذ نفس المعادلة في المرسل و المستقبل و في حالة أختلاف القيمة في المرسل يتم أفتراض حصول خطأ .


    في Scapy يمكن الوصول إلى العنوان المرسل و المستقبل و البيانات و النوع , و FCS متروكين للنظام أما Preamble و SFD فهما متروكين لبطاقة الشبكة .
     
    لإنشاء أطار Ethernet في Scapy فقط استخدم الأمر التالي الذي سوف ينشأ أطار Ethernet و يسنده إلى المتغير الخاص بنا:
myFrame = Ether()

لعرض مجتويات هذا الأطار فقط أستخدم الدالة show كالتالي :

myFrame.show()

سيعرض لك القيم التي تستطيع تغيرها في الإطار كالتالي :
###[ Ethernet ]###
dst= ff:ff:ff:ff:ff:ff
src= 11:36:12:54:14:49
type= 0x9000


العنوان الذي في خانة dst و الخاص بإطار Ethernet هو عنوان broadcast و معناه أرسال هذه الرسالة لجميع المنافذ ما عدا المنفذ المرسل , في نظام ويندوز لن يكون هذا العنوان للمرسل , للتغيير فقط قم بدخل للمتغير dst في كائن (Object) الإيثرنت الذي إنشائنا :


myFrame.dst = "ff:ff:ff:ff:ff:ff"

أما عنوان المرسل فالمكتبة تستخدم عنوانك الفيزيائي للبطاقة المستخدمة , في حالة برنامجنا فهذا هو المطلوب .

و الأن قد تتساءل لماذا لم نغير نوع الاطار (Frame) لنوع أطار برتوكول ARP , لكي تعرف السبب سوف نضيف طبق برتوكول ARP للإطار الذي تم إنشائه :

myFrame = myFrame / ARP()

الأن قم بعرض الإطار بأستخدام الدالة show و لاحظ التغير :

>>> myFrame.show()
###[ Ethernet ]###
dst= ff:ff:ff:ff:ff:ff
src=
11:36:12:54:14:49 
  type= ARP
###[ ARP ]###
hwtype= 0x1
ptype= IPv4
hwlen= None
plen= None
op= who-has
hwsrc=
11:36:12:54:14:49 
     psrc= 192.168.1.148
hwdst= 00:00:00:00:00:00
pdst= 0.0.0.0

>>


هل لاحظت نوع إطار الإيثرنت , لقد تغير إلى ARP , بدون أي داعي من قبلك لتغيير أي شيء , كما أن طريقة العرض و الأضافة كطبقات تسهل عملية الأضافة و البرمجة .
نوع ARP هنا تجده في القيمة op هو who-has هو طلب استفسار عن العنوان الفيزيائي لعنوان أنترنت و هو المطلوب لبرنامجنا لذا لن نغير أي شيء , العنوان الفيزيائي للجهة المرسل إليها في الطبقة الخاصة ببرتوكول ARP هي 00:00:00:00:00:00 و هو ايضا عنوان خاص بالإرسال إلى الكل (broadcast) .

نحتاج فقط لوضع عنوان الأنترنت الذي نريد التأكد من وجوده في الشبكة المحلية , نستطيع أن نكتب عنوان واحد كالتالي :

myFrame.pdst = "192.168.1.114"

و لكن تذكر نريد أن نعرض جميع الأجهزة المتصلة , قد تقترح أن تقوم بعمل حلقة تكرارية (Loop) كالتالي :

for i in range(1,254):
    myFrame.pdst = "192.168.1." + str(i) 
    #الإرسال هنا و الاستقبال - سنضيف ذلك  
 
 هذا حل جيد و لكن هنالك طريقة أفضل فمكتبة Scapy توفر أمكانية استخدام المدى لعنوانين الأنترنت فنكتب كالتالي :


myFrame.pdst = "192.168.1.0/24"

 و الأن إلى الأرسال و عرض النتائج باستخدام الدالة srp التي تقوم لنا بعملية الأرسال و الأستقبال حرف p في نهاية اسم الدالة يدل على أنها ترسل و تستقبل في الطبقة الثانية ( Data Link ) من نموذج OSI , هذه الدالة ترجع Tuple يحتوي على الطلبات التي تم الأستجابة لها و التي تم رفضها , لكي تقوم بتجاهل الطلبات التي تم تجاهلها فقط أستبدل اسم المتغيرunanswered بـ _ :

answered , unanswered = srp(myFrame,timeout2)

وهنا الأمر بعد التعديل لتجاهل الطلبات التي لم يتم الرد عليها :
 


answered , _ = srp(myFrame,timeout2)
 
 لعرض النتائج تستطيع استخدام الدالة summary الموجودة في المكتبة كالتالي :

answered.summary()

لتقليل البيانات المعروضة استخدم هذا الحلقة التكرارية , سوف نقوم بدوران في القائمة التي لدينا و التي تحتوي على tuple يحتوي على البيانات المرسلة و المستقبلة   و سوف نقوم بتجاهل ما تم ارسالها و عرض فقط الردود :

for _ , recv in answered :
    print(recv.summary())
 

 
هذا الخطوات هي ببساطة ما سوف يقوم به السكريبت , الأن سوف نضع هذه الأوامر في سكريبت .
 
 
  • السكريبت النهائي :

 
#!/usr/bin/env python
import sys
from scapy.all import srp,Ether,ARP,conf

#الحصول على مدى عنوانين الشبكة او في حالة وجود عنوان واحد

if len(sys.argv) != 2:
    print("Usage:arping.py <Net or IP> Ex. 192.168.1.0/24 or 192.168.1.10")
    exit(1)
#ايقاف  عرض البيانات الأضافية الخاصة بعملية الأرسال 
conf.verb = 0

target = sys.argv[1]
pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=target)

#في حالة وجود خطأ في عنوان الأنترنت أو المدى
try:
    answerd, _ = srp(pkt,timeout=4)
except Exception as e:
    print("Error: " + e.__class__, " occurred.")
    exit(2)



for _ , recv in answerd :
    #عرض فقط عنوان الانترنت الخاص بالمرسل
    #أذا اردت معلومات أكثر استخدم summary 
    print("IP:" + recv.psrc) 
 
 
 
 
 لتشغيل السكريبت في ويندوز , افنح موجه أوامر خاص بمدير النظام ثم أكتب python متبوعا بمسار الملف الذي حفظته :

python C:\Users\abgoor\Desktop\arping.py 192.168.1.0/24

 أما في نظام لينكس فيجب أن تحول الملف لملف تنفيذي باستخدام الأمر chmod ثم لتنفيذ الأمر استخدم النقطة "." ثم مسار الملف :
 
 
chmod +x /home/abgoor/script/arping.py

. /home/abgoor/script/arping.py 192.168.1.0/24
 
 
  • الخاتمة

    احساس الإنجاز شعور جميل , رغم بساطة برنامجنا إلا أنه يعمل و بشكل جيد , طبعا أريد منك أنك تحاول تطور البرنامج و في الأخير هذا لن يكون الموضوع الأخير عن مكتبة Scapy , هذه المكتبة تعطيك اختيارات غير محدودة في برمجة الشبكات, و أن شاء الله سوف نحاول نغطي هذه الإمكانيات في أكثر من موضوع .
    أذا اعجبك الموضوع طلب بسيط دعوة طيبة منك تكفي :-) .
     

الأحد، 12 سبتمبر 2021

برمجة سكريبت بالبايثون يعرض المنافذ المتاحة ببرتوكول TCP

   بسم الله الرحمن الرحيم

في هذا الشرح البسيط ستتعلم كيف تبرمج برنامج بسيط بالبايثون يظهر لك المنافذ المفتوحة على اي جهاز مشبوك على الشبكة الخاصة ببرتوكول TCP , لكن قبل ان ابدأ يجب ان انبه ان هذا البرنامج للأغراض التعليمية و يجب الا تستخدمه الا على انظمة يحق لك الوصول له .

 

  •  كيف يعمل البرنامج ؟
البرنامج يستخدم عملية handshake في برتوكول TCP في حالة اتمام الاتصال يقوم البرنامج بأنذار المستخدم برقم المنفذ (Port).
 
هذه الصورة تبين عملية اتصال ناجحة لبرتوكول TCP
مصدر الصورة :https://commons.wikimedia.org/wiki/File:Tcp_normal_2.png
 
1. يرسل الجهاز للسيرفر رسالة TCP -SYN 
2. في حالة توافر المنفذ يرد السيرفر برسالة SYN-ACK
3. لتأكيد الاتصال يرسل الجهاز للسيرفر رسالة ACK لتأكيد الاتصال 

طبعا هذا الشرح مبسط جدا  , لغاية عدم تعقيد الموضوع , يمكن في المستقبل اخصص موضوع خاص ببرتوكول TCP .

في حالة عدم نجاح عملية الاتصال سوف يتم اعتبار المنفذ مغلق , و الأن لشرح بسيط لبرمجة الشبكات في البايثون قبل ان نبدأ , بشكل عام جميع لغات البرمجة تتشابه في الخطوات التالية :


 طبعا لمثالنا سوف يكون برنامجنا هو Client لكن من دون ارسال اي بيانات فقط سيحاول الاتصال و سيقوم بعرض النتيجة للاتصال ثم اغلاق الاتصال .

و الأن للنص البرمجي الكامل لمثالنا :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/python3
import sys
import socket

if len(sys.argv) == 2:
    print("Start Scanning : {}".format(sys.argv[1]))
    target = sys.argv[1]
else:
    print(("Usage:{} target".format(sys.argv[0])))
    exit(2)
    
    
try:
    for port in range(1,65535):
        sos = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        result = sos.connect_ex((target,port))
        if result == 0 :
            print ( "{} is Open".format(port))
        sos.close()
        
except KeyboardInterrupt:
    print("\nExiting the program")
    exit(0)
except socket.gaierror:
    print("Host couldn't be reslove")
    exit(1)
except socket.error:
    print("Couldn't connect to {}".format(target))
    exit(2)


بندأ بشرح برنامجنا بالتفصيل , أولا نبدأ في السطرين الأولين  :

1
2
import socket 
import sys   
 
المكتبة البرمجة socket بنستخدمها لعملية الاتصال , هذه المكتبة تستخدم لجميع عمليات الشبكات الاساسية , و مكتبة sys التي بنحتاجها لمعالجة المعطيات من سطر الاوامر .


و الان الى السطر الذي يعالج معطيات سطر الأوامر :


1
2
3
4
5
6
if len(sys.argv) == 2: #اذا طول معطيات سطر الاوامر يساوي 2 
    print("Start Scanning : {}".format(sys.argv[1])) #اطبع اسم الهدف 
    target = sys.argv[1] #احفظ اسم الهدف في المتغير target
else:
    print(("Usage:{} target".format(sys.argv[0]))) #في حال عدم تطابق الشرط اطبع رسالة الاستخدام و اخرج من البرنامج
    exit(2)

هذا مثال على استخدام برنامجنا , في بايثون يكون معاملات البرنامج (program parameters)  تبدأ دائما باسم ملف البرنامج , و يتم تخزين المعاملات في مصفوفة (array) يمكن الوصول لها باستخدام sys.argv

kh@DESKTOP-3444:~$ ./myscript target
 
و الأن إلى الجزء الذي يقوم بالعمل الفعلي :

1
2
3
4
5
6
7
for port in range(1,65535): # المدى يمثل جميع منافذ برتوكول TCP
        sos = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #انشاء مقبس الشبكة
        result = sos.connect_ex((target,port)) # محاولة الاتصال 
        if result == 0 : #اذا كانت نتيجة الاتصال صفر فالاتصال ناجح
            print ( "{} is Open".format(port)) #طباعة رسالة للمستخدم
        sos.close() #اغلاق الاتصال

قمت بوضع هذه الأوامر في كتلة Try-Except للتعامل مع الإستثاءات التي قد تواجه التنفيذ , والأن لشرح هذه الاسطر بتفصيل اكثر:


1
sos = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

هذا السطر الذي ينشيء المقبس (socket) , و يخبر النظام لحجز الموارد كما يحدد نوع نظام العناوين و نوع الاتصال :
 
  • AF_INET : نظام عناوين الانترنت النسخة الرابعة Internet protocol version 4 أو اختصارا IPv4 , هو النظام الحالي المستخدم لعنونة الاجهزة على شبكة الانترنت
  • SOCK_STREAM : استخدام برتوكول TCP كنوع البرتوكول المستخدم لتوصيل البيانات .
للعلم يمكنك كتابة امر تحديد المقبس (socket) من دون تحديد نظام العناوين و نوع الاتصال حيث انه القيم الافتراضية .
 
1
sos = socket.socket()

و الأن بعد انشاء الاتصال سنحاول اجراء الاتصال باستخدام connect_ex , في حالة نجاح الاتصال سنحصل على القيمة صفر , و في هذه الحالة فقط سيتم طباعة رقم المنفذ :

1
2
3
result = sos.connect_ex((target,port))  
        if result == 0 : 
            print ( "{} is Open".format(port)) 

و في الاخير سنقوم بأغلاق المنفذ :

1
sos.close()

و للتعامل مع جميع الاستثناءات (exceptions) قمنا باستخدام try..except :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
try:



except KeyboardInterrupt:
    print("\nExiting the program")
    exit(0)
except socket.gaierror:
    print("Host couldn't be reslove")
    exit(1)
except socket.error:
    print("Couldn't connect to {}".format(target))
    exit(2)

و هذا شرح للاستثناءات :
  • KeyboardInterrupt : في حالة ضغط المستخدم Ctrl+C سيتم اغلاق البرنامج
  • socket.gaierror :  في حالة فشل البرنامج بتحويل النطاق (Domain) إلى عنوان رقمي IP
  • socket.error : في حالة فشل انشاء مقبس (socket) 

هذا شرح مبسط لهذا البرنامج البسيط , لكن هل هذا البرنامج يعمل , اذا اردت تجربة البرنامج تستطيع استخدام جهازك مباشرة باستخدام العنوان localhost .
لكن هل هذا البرنامج عملي ؟ , بصراحة هذا البرنامج يعمل و لكن هنالك الكثير من الامور الذي يجب توضيحها 
  • اولا هذا البرنامج سيكون بطيء بشكل كبير حيث يتم تنفيذه بشكل خطي و اذا اردنا تسريعه يجب ان يتم التنفيذ بأستخدام التنفيذ متزامن (concurrent execution ) .
  • عملية مسح المنافذ (port scan ) باستخدام جميع المنافذ و بالتسلسل و بدون وجود وقت انتظار سيجعل ابسط برنامج جدار نار (Firewall) ينذر المستخدم .
  • عملية المسح باستخدام عملية الاتصال كاملة , "مصافحة برتوكول TCP" الكاملة بطيئة و مكشوفة للبرامج جدران النار.
في النهاية هذا رابط لموضوع عن برمجة الشبكات ببايثون بالتفصيل :



الاثنين، 6 سبتمبر 2021

حالة الطقس في موجه الأوامر

 بسم الله الرحمن الرحيم

موقع wttr.in مصمم لعرض حالة الطقس في موجه الأوامر في نظامي ويندوز و لينكس  في نظام لينكس أكتب الأمر :

curl wttr.in

 و في نظام موجه powershell استخدام الأمر التالي :

Invoke-RestMethod wttr.in

لتحديد المدينة فقط أضف :

Invoke-RestMethod wttr.in/london

في حالة عدم التحديد سيعرض المعلومات بحسب موقعك ( عبر عنوان الأنترنت IP address) .
 




دورة تعلم Bash (الأذونات) : الجزء الثاني

 بسم الله الرحمن الرحيم

الأذونات (Permissions):

نظام لينكس صمم منذ البداية في بيئة يتعدد فيها المستخدمين , لذا فأن النظام يمنحك القدرة على التحكم بكل ملف و مجلد و من يستطيع الوصول له , فتستطيع جعل المستخدم يتمكن من الكتابة في ملف و لكن لا يستطيع قراءته و العكس صحيح , و تستطيع منح مجموعة من المستخدمين صلاحية القراءة و التنفيذ بدون التعديل .

  • كيف اعرف الأذونات على أي ملف أو مجلد :

بواسطة الأمر ls فقط ارفق الأمر ls بعلامة -l :

abgoor@DESKTOP:~$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1183448 Jun 18  2020 /bin/bash

لنبدأ من بداية سطر المعطيات أول حرف في السطر هو - , هذا الحرف يدل على نوع الملف كما في الصورة التالية :

و الأن لتقسيم الصلاحيات :

مالك الملف و المجموعة موجودة في معطيات الأمر ls :


شرح الصلاحيات :


في نظام لينكس تستطيع تعديل هذه الأذونات بواسطة الأمر chmod , و سوف نستخدمه لتطبيق الأمثلة لفهم أكبر للأذونات في نظام لينكس , و لمثالنا قم بأنشاء المجلد test و الملف test.txt بداخل المجلد ( أذا لم تقرأ الجزء الأول من هذه التدوينة فأنصحك بذلك على هذا الرابط ) .

abgoor@DESKTOP:~$ mkdir test
abgoor@DESKTOP:~$ cd test
abgoor@DESKTOP:~$ touch test.txt

لنعرض أولا الأذونات على الملف test.txt باستخدام الأمر ls :

abgoor@DESKTOP:~$ ls -l test.txt
-rw_r--r-- 1 abgoor abgoor 1183448 Jun 18  2020 test.txt

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

لنفترض بأنك تريد بأن تسمح للمجموعة بالكتابة باستخدام الأمر chmod :

abgoor@DESKTOP:~$ chmod g+w test.txt


الحرف g يرمز للمجموعة (group) و الأشارة + تدل على أنك ستضيف أذن الكتابة , و لنفترض بأنك تريد بأن تمنع الأخرين من قراءة الملف فقط نفذ الأمر كالتالي :

abgoor@DESKTOP:~$ chmod o-w test.txt

و هذه الصورة تحمل الرموز الخاصة الحرفية :

طبعا هناك الطريقة باستخدام القيم الرقمية لتعديل الأذونات , كل أذن له قيمة و لكي تحصل على القيمة النهائية أجمع القيم و ستحصل على القيمة الخاصة بالأذن , في هذا الجدول ستحصل على جميع القيم :


لنفترض بأنك تريد أن تعطي نفسك جميع الأذونات سنجمع 1 + 2 + 5 = 7 , و لنعطي المجموعة حق التنفيذ و القراءة 4 + 1 = 5 , أما الباقية فلن نعطيهم أي أذن :

abgoor@DESKTOP:~$ chmod 750 test.txt


تذكر الترتيب في الأرقام في رقم الأذونات , من اليسار لليمين المالك للملف ثم المجموعة و أخيرا باقي المستخدمين .

حاول أن تغير الأذونات للمالك الملف و جرب أن تحاول حذف الملف أو قراءة محتوياته , و الأن الى نقطة تختلف في المجلدات كما ترى لا يمكن تنفيذ المجلد (execute) , لكن هذا الأذن يمكنك من الوصول لملف بداخل مجلد حتى لو لم تكن لديك الصلاحية لقراءة محتويات المجلد أو التعديل على محتوياته

abgoor@DESKTOP:~$ date > test.txt
abgoor@DESKTOP:~$ cd ..
abgoor@DESKTOP:~$ chmod 111 test/ 

 في السطر الأول قمنا بحفظ معطيات الأمر date في ملفنا test.txt ثم غيرنا المجلد الحالي الى المجلد الأعلى في المسار , و غيرنا تصريح مجلدنا test إلى التنفيذ فقط , جرب أن تنفذ الأمر ls على المجلد test :

abgoor@DESKTOP:~$ ls test/
ls: cannot open directory 'test/': Permission denied 

 و اﻷن جرب الأمر cat لعرض محتويات الملف test.txt بداخل المجلد test :

abgoor@DESKTOP:~$ cat test/test.txt
Tue  7 Sep 01:58:17 +04 2021 
 

في النهاية هذا الجزء نصيحة حاول ألا تقوم بتغير أذونات الملفات الخاصة بالنظام فهذا قد يؤثر على عمل نظامك , في الجزء القادم سنبدأ في كتابة أو برامجنا .

 

الاثنين، 23 أغسطس 2021

دورة تعلم Bash : الجزء الاول

 بسم الله الرحمن الرحيم

يعتبر تعلم التحكم بالطرفية (Terminal) في نظام لينكس من الأمور المهمة جداً , خاصة للمهتمين بالأمن الأكتروني بخاصة , لكون معظم الأدوات المستخدمة في هذا المجال تعمل على هذا نظام لينكس , و كون التعامل مع هذه الأدوات يتم بالغالب باستخدام الواجهة النصية .


  • ما هو الـــ"Bash" ؟
  •  

    Bash   هو برنامج يعمل كواجهة نصية للمستخدم لتوجيه الأوامر لنظام لينكس  أو ما يسمى بشيل لينكس (Linux Shell), كما يعمل كمترجم للبرنامج المكتوبة باللغة الأوامر الخاصة به , تم تصميمه كبديل لـــ (Bourne Shell) في نظام يونكس المملوك لشركة AT&T  الامريكية , حتى أن الاسم هو أختر لــــ (Borune Again Shell)  كبديل لبرنامج Bourne Shell  الذي كان يتم توزيعه بترخيص من شركة AT&T , و تم من فترة تم جعل برنامج Bourne Shell أو كما في موجه الاوامر sh مجاني و مفتوح المصدر , لكن لا يضاهي برنامج Bash و خصائص المتطورة مثال :

    1. القدرة على انشاء المصفوفات و التعامل معها .
    2. وجود بنى التحكم في سير البرنامج
    3. هنالك متغيرات خاصة في باش مثل RANDOM$  و FUNCNAME$
    4. وجود الأمر history الذي يسجل جميع الأوامر التي تم تنفيذها .

     يعود تاريخ Bash إلى ما قبل الواجهة الرسومية حيث كانت الواجهة النصية تعد الطريقة المعتمدة للتعامل مع جهاز الكمبيوتر، وما تزال هذه الطريقة إلى يومنا الأفضل في التعامل مع الأنظمة من منظور مدير النظام.

    يعتبر هو البرنامج الافتراضي في معظم توزيعات لينكس، ويحتوي على العديد من المميزات مثل:

    1.        التحكم في العمليات (Jobs control).

    2.       عرض الأوامر السابقة وإمكانية استدعاءها بحسب التسلسل.

    3.        المصفوفات (Array)

    4.        العمليات الحسابية (Shell Arithmetic).

    5.        إمكانية انشاء اختصارات للأوامر (Aliases).

     

    رغم كون برنامج Bash هو البرنامج الافتراضي في معظم توزيعات لينكس , لكن يوجد برامج متعددة تعتبر منافسة لهذا البرنامج و منها

    1.   sh : أو الاسم البديل (Borune Shell) مسمى على اسم مطوره Stephen Borune  , هذا هو برنامج الأصلي .

    2. csh  : اختصار لي (C Shell)

     

  • كيف أحصل على الــ"Bash" ؟
مع كل توزيعة لينكس تحصل على Bash بشكل افتراضي , و هنا في توزيعة يوبتو Ubuntu طريقة التشغيل ببساطة 
 

في التوزيعات الأخرى ابحث عن برنامج بالأسم Terminal , و للمستخدمي نظام ويندوز قم بتنزيل نظام لينكس الفرعي باتباع الشرح في هذه التدوينة على هذا الرابط .

  • ما معنى هذه الشاشة  ؟

تراه في الشاشة مؤشر يومض هذا المؤشر في انتظار ادخال الأوامر , سنطبع أول امر لنا اكتب التالي :

whoami

هذا الأمر سيطبع لك اسم المستخدم الذي يستخدم قام بتشغيل الأمر :

يجب أن تنتبه نظام لينكس حساس لحالة الأحرف جرب الأن أن تكتب الامر السابق كالتالي Whoami :


ستطبع لك رسالة تبين لك عدم وجود الأمر , لذا انتبه عند طباعة الاوامر , لك ما هو هذا الأمر , الأمر whoami هو مجرد برنامج يتواجد في نظامك لكي تعرف اين يتواجد اطبع الأمر التالي :

whereis whoami

 سيطبع لك سطر الأوامر مسار الملف و أين يوجد في الملف التنفيذي اولا ثم مسار ملف التعليمات (manual)  :


  • المجلد الحالي (Current working directory) : أين أنا ؟
عندما يبدأ موجه الأوامر الخاص بك يكون في مجلد افتراضي , في الغالب يكون المجلد الخاص بالمستخدم في المسار home/username/ , لمعرفة المجلد الحالي فقط اكتب الأمر pwd و اضغط  Enter  , الأمر pwd اختصار للجملة (print working directory) اطبع المجلد العامل .

pwd

 

  • عرض محتويات المجلدات : ماذا يوجد هنا ؟
في الأنظمة ذات الواجهه الرسوميه يجود برنامج يعرض لك الملفات و المجلدات بشكل رسومي سهل و تتفاعل مع الملفات و المجلدات بأستخدام الماوس في الغالب , و لكن كيف يمكن أن تعرض قائمة الملفات و المجلدات في الواجهة النصية الخاصة بــBash .
 
صورة للواجهة الخاصة بمستعرض الملفات في نظام يبنتو لينكس

يتوافر في نظام لينكس الأمر ls أختصار لكلمة list , اطبع في موجه الأوامر الأمر ls فقط و اضغط Enter :

ls
 
سيتم طباعة محتويات المجلد الحالي , الذي تعرفنا عليه باستخدام الأمر pwd :
 

 تلاحظ بأن الأمر طبع لنا الملفات و المجلدات الموجود و تم تميز المجلدات باللون الأزرق , لكن تستطيع اضافة / في نهاية المجلد كتميز للمجلدات :

ls -F
 
انتبه للمسافة مابين ls و F- , سيطبع لك كالتالي :
 

 الملفات و المجلدات المخفية في نظام لينكس يبدأ اسمها بالنقطة . , و لعرضها فقط أكتب الأمر ls كالتالي :

ls -a
 
 



تستطيع دمج المعاملين a- و F-  كالتالي :

ls -aF
 
أو كالتالي :

ls -Fa
 
لا يهم الترتيب في المعاملات (parameters) , لكن في بعض الحالات يجب ان تراعي الترتيب ,  سيكون مخرجات الأمر كالتالي :


تلاحظ وجود مجلدين في بداية القائمة هما :
.  : المجلد الذي يحمل اسم بالنقطة فقط هو المجلد الحالي .
.. : المجلد الذي يحمل النقطتين هو المجلد الاعلى من المجلد الحالي , في مسار المجلد , كمثال اذا كنت في المجلد  home/abgoor/ سيكون المجلد الاعلى هو home/  .

و لعرض محتويات أي مجلد فقط اضف مسار المجلد بعد الأمر ls و معاملاته كهذا المثال التالي الذي يعرض محتويات المجلد الجذر / :

ls -F /
 


تلاحظ وجود رموز بعد اسماء بعض الملفات :

@ : يدل على أن هذا الملف أو المجلد هو رابط (link) أو ما يسمى في ويندوز باختصار (shortcut) .
*   : يدل على ان الملف تنفيذي , يمكن تشغيله كبرنامج 

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

  • التحرك بين المجلدات 
لتغير المجلد الحالي تستطيع تنفيذ الأمر cd  مع مسار المجلد الذي تريد الذهاب إليه , كمثالنا التالي , قبل تنفيذ الأمر نفذ الأمر pwd


pwd
cd ..
pwd
 
نفذه هذه الأوامر بتتابع و لاحظ التغير لديك , ستلاحظ بأنك المجلد الحالي تغير للمجلد الأعلى في المسار كالتالي :
 

كما ذكرنا سابقا المجلد بالاسم ".." دائما يشير للمجلد الأعلى في مسار المجلد الحالي , "." يشير للمجلد الحالي . , و الأن للنتقل للمجلد tmp/ الخاص بالملفات المؤقتة في نظام لينكس فقط اكتب الأمر cd ثم مسافة ثم مسار المجلد :


cd /tmp
 
و الأن لنعد لمجلد المستخدم الحالي و الذي يسمى في نظام لينكس بالمجلد البيت "Home folder" , فقط اكتب الامر cd ثم مسافة و الرمز ~ كالتالي :

cd ~
 
تذكر أذا اردت ان تعرف المجلد الحالي نفذ الأمر pwd .
 
  • التعامل مع الملفات و المجلدات 

1. أنشاء المجلدات 

للانشاء المجلدات سوف نستخدم الأمر mkdir فقط اكتب الامر قم اسم المجلد :

mkdir test
 
قم بالدخول لهذا المجلد عبر الأمر cd سوف يكون هو مكان تجاربنا .

cd test
 
و لإنشاء مجلد يحتوي على مجلد فقط استخدام المعامل p- كالتالي :

mkdir -p test1/test
 
و لإنشاء عدد من المجلد في سطر واحد فقط اكتب اسماء المجلدات و تذكر وضع المسافة:

mkdir test1 test2 test3 test4
 
و لكن ماذا لو اردت أنشاء مجلد بأسم يوجد فيه اكثر من كلمة يفصل ما بينها مسافة فقط ضع الأسم بين " " علامتي التنصيص :

mkdir "This is test folder"
 
 و الأن إلى بعض الابداع , لنفترض بأنك تريد أنشاء مجلدات بالاسم A متبوعا برقم من 1 إلى 10 فقط ضع المجال في بين القوسين كالتالي {10..1} :

mkdir A{1..10}

ماذا لو اردت أن يكون بدل الارقام تكون حروف , تستطيع فقد ضع بدل الارقام مدى بالحروف , طبعا راعي ترتيب الحروف الإنجليزية و ان تكون حالة الأحرف مطابقة :

mkdir {B..Z}2
 
لنفترض بأنك تريد أن تنشأ مدى خاص بك ببساطة ضع المدى بين قوسين كالتالي :

mkdir test{"A","B","C"}
 
سيتنتج لك مجلدات بالاسم testA , testB , testC .

2. أنشاء الملفات 

 لإنشاء ملف يوجد الأمر touch , هذا الأمر ينشىء ملف فارغ فقط اكتب الأمر كالتالي :

touch myfile
 
 كما في الأمر mkdir تستطيع استخدام المدى و الأنماط كالتالي :

touch A{1..10}{A..C}
 
3. حذف الملفات و المجلدات 
 
لنبدأ بحذف أحد الملف الذي قمنا بأنشاءه في مثالنا السابق "myfile" :

rm myfile
 
في حالة ملفات متعددة تستطيع كتابتها في نفس السطر مع وجود مسافة:

rm A1A A2A A3A
  
كما في الأوامر السابقة تستطيع حذف باستخدام المدى , سنتخدم المدى الذي استخدمنها في السابق :

rm A{1..10}{A..C}
 
ستحصل على خطأ كالتالي :

rm: cannot remove 'A1A': No such file or directory
rm: cannot remove 'A2A': No such file or directory
rm: cannot remove 'A3A': No such file or directory
 
تذكر بأننا قد قمنا بحذف هذه الملفات في المثال السابق , لكي تجعل الأمر يتجاهل الملفات الغير الموجودة فقط أضف المعامل f- كالتالي:

rm -f A{1..10}{A..C}
 
و الأن لحذف المجلدات في حالة حذف المجلدات فتستطيع ذلك و لكن يجب عليك أضافة المعامل r- كما تستطيع دمجه مع المعامل f- كالتالي:

rm -fr {B..Z}2
 
هنالك الرمز * الذي تستطيع أما تحديد ملفات أو مجلدات تبدأ بحرف معين أو كلمة كــ "*A1" أو تحديد الكل فقط أكتب النجمة كالتالي (قبل تنفيذ هذا الأمر تأكد من أنك في المجلد الذي قمنا بإنشاءه من أجل هذه تجاربنا بأستخدام الأمر pwd ) :

rm *
 
4. قراءة الملفات النصية :

لقراءة الملفات النصية تستطيع استخدام الأمر cat , في مثالنا سوف تقرأ الملف hosts في المجلد etc/ , هذا المجلد يحتوي اعدادات النظام و البرامج :

cat /etc/hosts
 
5. معرفة نوع الملف 

بدون الامتداد تستطيع معرفة نوع الملف بواسطة الأمر file , الذي يعتمد على قيمة في بداية الملف تعتبر كتوقيع للأنواع الملف :

file /bin/echo
 

  • الأنابيب (pipeline) و تحويل سير البيانات (redirect)

كل شيء في نظام لينكس عبارة عن ملف , عندما يطبع برنامج رسالة على الطرفية (Terminal) , فهو يستخدم رقم يسمى file descriptor في حالة إدخال البيانات يكون القيمة 0 أو stdin , لطباعة البيانات يستخدم stdout و لرسائل الخطأ يستخدم stderr .

pipeline هي طريقة نظام لينكس في نقل البيانات التي ترسل للملف stdout و تحويلها ما بين العمليات (Process) .

و الأن لمثال عملي :

ls | cat -n
 
سينفذ الأمر ls و يحول البيانات الناتجة إلى الأمر cat -n الذي سيطبع كل سطر مع رقمه .
 
و الأن إلى مثالنا التالي سنحاول عرض محتويات مجلد غير موجود , لنرى طريقة تصرف النظام :

ls not_existing | cat -n
 
سيطبع لك النظام رسالة خطأ من الأمر ls و لن يحول هذه الرسالة إلى البرنامج cat :

ls: cannot access 'not_existing': No such file or directory
 
السبب لهذا السلوك من النظام أن رسائل الخطأ يتم تحويلها إلى stderr و pipeline تحول فقط مخرجات stdout .

طبعا هنالك طريقة لتعديل هذا السلوك , ستتعرف له في بعد أن نطبق عملية تحويل سير البيانات , لنفترض أنك تريد أن تغير من ملف المخرجات الافتراضي stdout , الأمر بكل بساطة أستخدم < كالتالي:

ls > test.txt
 
كما تستطيع تنفيذ هذه العملية بشكل عكسي فقط استخدم > :

cat -n < test.txt
 
سيتم في تلك الحالة اعتبار الملف كبديل لــstdin , وقراءة البيانات الموجودة في الملف و ارسالها إلى الأمر cat .
 
و لنعد لمثالنا السابق الخاص بالمجلد الغير موجود , و الذي ادى لطبع رسالة الخطأ :

ls not_existing | cat -n
 
للارسال البيانات الخاصة برسالة الخطأ يجب أن تعيد توجيه دفق البيانات (data stream) من الملف الخاص stderr إلى stdout بواسطة 1&<2 كالتالي :

ls not_existing 2>&1 | cat -n
 
ستطبع لك الطرفية كالتالي ,  لاحظ بأن الأمر cat قام بترقيم السطر الخاص بالخطأ مما يدل على أن سيل البيانات (Stream) الخاص بالخطأ تم أرساله إلى اﻷمر  :

     1    ls: cannot access 'not_existing': No such file or directory
 
لكن لماذا نضع قبل الرقم واحد الخاص بالملف stdout الرمز & , لنجرب :

ls not_existing 1 | cat -n
 
الأن قم بتنفيذ الأمر ls , ستلاحظ وجود ملف يحمل الرقم 1 , أستخدم اﻷمر cat لعرض محتويات الملف :


يم اضافة الرمز & كتميز بين اسم ملف عادي و ملف stdout , و الأن لنقوم باستخدام الأمر cat في كتابة أول سكريبت لنا :

cat > hello
 
اضغط Enter ثم أكتب الأمر echo متبوعا بالجملة "Hello,World" بين علامتي تنصيص, واضغط Enter بعد انتهاءك ثم أضغط Ctrl + C (الزر Ctrl مع الحرف C ) .
 

و لتحويل الملف لملف تنفيذي استخدم الأمر chmod كالتالي :

chmod +x hello
 
و في الاخير لتنفيذ الملف أكتب قبل اسم الملف /. كالتالي :

./hello
 

و لنفترض انك تريد أن تضيف للملف hello أمر اخر , في هذه الحالة لا تستخدم < لأنك سوف تمسح جميع محتويات الملف و للأضافة أستخدم << (append) :

cat >> hello
 
و بنفس الطريقة اكتب سطر الأوامر و اضغط Enter ثم في Ctrl + C , اضف سطرا ينفذ الأمر pwd كمثال :



هذه نهاية الجزء الاول , في الجزء الثاني سوف نتعلم الأذونات الخاصة بالملفات و تعديلها بواسطة اﻷمر chmod .

في النهاية هذا الجزء اسأل الله العزيز الحكيم , أن يكون هذا المجهود المتواضع قد سهل وصول المعلومة عن اهم الأساسيات في نظام لينكس و هي الطرفية . و طلب لكل من يقرأ هذه الكلمات أذا صادفت أي خطأ أو أردت أضافت معلومة فلا تتردد .