Assembly Interrupts/System Calls list for Linux Kernel

السلام عليكم ورحمة الله وبركاته

لي فترة أصارع مع Assembly على بيئة جنو/لينوكس … أنا لست خبير في هذه اللغة ولكن الحمد لله عندي صديق خبير فيها بشكل مميز للغاية (عمل ألعاب عليها ::22 الله يوفقه، لكن هو يعرف أسمبلي على الويندوز وليس جنو/لينوكس) وجالس يساعدني في تعلمها وإتقانها الى حد ما … الأمر الوحيد الذي وقف عائق في وجهنا أنا وهو هي لم نصل الى أرقام الـ Interrupts أو الـ System Calls الخاصة بـ Kernel جنو/لينوكس … عندي Reference ممتاز لـ Interrupts الخاصة بالـ BIOS ولكن للنواة لا … بحثت كثيراً أنا وإياه الجمعة الماضية ولكن كل الذي وجدناه هو الـ System Call على شكل دالة C … أي كلهم يعطونني HLA … وأنا أريد قائمة الـ Interrupts مع كل متغيير يستطيع أن يأخذها هذا الـ Interrupt … فكما يعرف الأخوة الذين يبرمجون في أسمبلي بإن كل Interrupt له قائمة من القييم التي يقبلها الـ registers أو الذاكرة … وكل واحد من هذه القييم لها دوور ووظيفة … سأواصل البحث وأحاول أشوف طريقة للحصول على هذه القوائم …

راسلت الأخ مؤيد السعدي وأفادني ببعض الأمور منها بإنني عند حصولي على الدالة مثلاً mknod والتي بالـ C تبدأ هكذا:

int mknod(const char *pathname, mode_t mode, dev_t dev);

أخبرني بإنه

pathname —> ebx

mode —> ecx

dev —> edx

سأقوم بالتجربة وأشوف … إن شاء الله تكون حل لما أبحث عنه …

ملاحظة: للحصول على هذه الدالة وغيرها أبحث في المصدر للنواة نفسها … يعني هنا:

/usr/src/$(uname -r)/include/asm-x86/

حالياً أنا استعمل NASM ولكننا وجدنا مؤخراً بإنه لا يدعم الـ Registers الجديدة مثل eex و efx و egx وربما حتى التي تخص الـ Multimedia … لا أعلم إن كان كلامنا 100% سليم أم لا … وربما يستطيع أحد أن يصححني في هذه الناحية … سأحاول تجربة GAS والذي هو لجماعة GNU نفسهم والذي أعتقد يفترض يدعم كل المعالجات الجديدة بما فيها جميع إمكانيات البانتيوم وما بعدها … أيضاً كبداية أنصح بقراءة الكتاب Linux Assembly Language Programming بسيط للغاية ويعطيك زبدة بداية الإستعمال للأسمبلي على جنو/لينوكس … موقع وجدته الحين وأنا أبحث عن رابط للكتاب الذي ذكرته بالأعلى Which Assembler is the Best? سأقوم بقرائته أيضاً إن شاء الله وإن شاء الله يفيدكم …

ودمتم بود …

5 thoughts on “Assembly Interrupts/System Calls list for Linux Kernel

  1. اهلا وسهلا مره اخرى
    كنت استخدم ال system calls احيانا عندما كنت اتعلم كتابة ال shell code

    وكنت استخدم هذا الجدول
    http://foosec.pl/pub/info/syscalls_linux_2_2.html

    طبعا كما واضح هو للكرنل 2.2 لكن اغلب الارقام لم تتغير، وللعلم بتحصل بعض الفروقات بين سولاريز وBSD بأرقام الـ system calls واعدادها،
    وعملهن بسيط جدا وليس صعب

    تحط رقم الـ system call بالـ EAX وتعمل int 0x80
    وبحالة تريد تمرر argument فتقدر تعملها بطريقتين

    في حالة اللينكس تقدر تستخدم الregisters الاخرى مثل EBX,ECX,EDX

    او تقدر تحطها على الstack
    عموما كرنل اللينكس تتوقع انك تحط الـ argument بالمسجلات

    بينما الـ BSD تتوقع الـ argument تكون بالمكدس

    هذا والله اعلم

    تحياتي

  2. المعتصم @ هلا والله أخي الكريم …
    أشكرك جزيل الشكر على الإضافة … هذا الموقع نعم وجدته ولكنه يا خوي لو تفتح كتاب Using Assembly Language سترى كيف يتم وصف كل Interrupt وكل خيار من خياراته وبأي مسجل تضعه حتى … يعني شرح مفصل ودقيق للغاية بصراحة … وهذا ما أحاول البحث عنه وهو كتاب أو مصدر بديل لهذا الذي هو للويندوز والـ BIOS …

    الطريقة التي ذكرتها حول وضع القيمة للـ Call في Register ومن ثم تناديها صحيحة ولكن هذه حالة واحدة ويوجد حالات أخرى وهذه من ظمن ما أبحث عنه … يعني ممكن يكون int 0x80 لعمل قراءة … وأريد معرفة باقي الـ 256 syscall الموجودين للنواة حق لينوكس …

    وجدت بالمناسبة هذول ممكن تفيدك أيضاً:
    http://www.linfo.org/int_0x80.html
    http://tldp.org/LDP/khg/HyperNews/get/syscall/syscall86.html
    http://www.digilife.be/quickreferences/QRC/LINUX%20System%20Call%20Quick%20Reference.pdf

    إن شاء الله تفيدك … وإن شاء الله نتبادل الأفكار والحلول بهذا المجال …
    شكراً لك أخوي المعتصم على المرور والإضافة … نورت الزون ::20
    دمت بود …

  3. السلام عليكم ورحمة الله وبركاتة

    في كتاب Shellcoder’s الشرح بالتفصيل وهنا جزء قد ترجمت أن شاء الله يفيدك :: ::207

    في الواقع ..Syscalls فهي مجموعة قوية من الدوال التي تسمح للدخول الى نظام تشغيل معين فمثلاً للحصول على الدخل ، وناتج الخرج ،وعملية exit ، وتنفيذات الملف الثنائي ، اذاً فهي تسمح للوصول المباشر الى النواه التي تعطيك الوصول الى الدوال المتندية المستوي ،وهذة الدوال (إستدعاءت النظام) للتفاعل بين protected kernel mode and user mode ، وتعين النمط المحمي للنواه نظرياً لكي يمنع برنامج المستخدم من التفاعل مع نظام التشغيل ، وبمحاول نمط المستخدم الى الوصول الى فضاء عنوان النواه ، فالوصول الاستثناي access exception هو عموماًُ من يمنع نمط المستخدم للوصول المباشر الى فضاء العنوان للنواه ، وبسبب أن بعضها تشتغل على خدمات معينة وهي مطلوبة لكي يتمكن البرامج من الإشتغال ، لذا يجب ان تضمن استدعاءات النظام للتفاعل بين regular user mode و kernel mode.

    هناك طرقتين مشتركة وموحدة للتنفيذ syscall في الينكس ، فيمكن بإستخدام مكتبة السي (libc فهذة الطريقة تستعمل بشكل غير مباشر ) أو عن طريق تنفيذ syscall مباشرتاً بالاسمبلي عن طريق شحن الوسطاء الملائمه الى المسجلات ثم استدعاء software interrupt ،إنشاءت ملفوفات الLibc لكي يتمكن البرنامج من المواصلة للإشتغال اذا تغيرت syscall وكذلك لتزويد ببعض الدوال المفيدة ( مثل malloc )ويمكن القول ان أغلب libc syscalls هي مغلقة لإستدعاءات النظام للنواه الحقيقية .

    أستدعاءات النظام في الينكس تتم عن طريق مقاطعات البرنامج software interrupts وتسمى بالامر int 0x80 ،وعندما int 0x80 تنفذ بواسطة برنامج نمط المستخدم ، فأن المعالج CPU يفتح نمط النواه وينفذ دالة syscall ، ويختلف الينكس عن syscall اليونكس الاخرى باستدعاء الدوال او methods بحيث يتميز بسرعة الاستدعاء fastcall المتعارفة لإستدعاءات النظام ، التي تجعل من إستعمال المسجلات باعلى أداء للعمل ،وتعمل العملية كالتالي :

    [code]
    1. The specific syscall function is loaded into EAX.
    2. Arguments to the syscall function are placed in other registers.
    3. The instruction int 0x80 is executed.
    4. The CPU switches to kernel mode.
    5. The syscall function is executed.

    [/code]

    فالعداد الصحيح يربط مع كل syscall فهذة القيمة يجب ان توضع الى EAX ، ويمكن ان تأخذ syscall وسيط أو أكثر شئ سته arguments و تعبئ الى EBX, ECX, EDX, ESI, EDI, and EPB على التوالي . وفي حالة كانت مطلوبة للدالة syscall اكثر من ستة وسطاء فأن الوسطاء سيمرون من خلال ال data structure الى اول وسيط ،الان بعد معرفة لكيفية عمل syscall من الاسمبلي دعنا نعمل الاخطوات التالية ونصنع syscall في السي ثم نقوم بفك التجميع للبرنامج ونراي اوامر الاسمبلي الفعلية ،والبداية ستكون مع استدعاء النظام التي هي exit() ،وكما هي فستقوم بخروج وتقوم بانهاء العملية .

    [code]
    main()
    {
    exit(0);
    }
    [/code]
    نجمع البرنامج بستعمال خيار static وذلك لمنع dynamic linking ، التي سحتفظ باستدعاء النظام exit .
    [code]
    gcc –static –o exit exit.c
    [/code]

    نقوم بافك disassemble

    [code]
    [[email protected] root] gdb exit
    GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
    Copyright 2003 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you
    are welcome to change it and/or distribute copies of it under certain
    conditions. Type “show copying” to see the conditions.
    There is absolutely no warranty for GDB. Type “show warranty” for details.
    This GDB was configured as “i386-redhat-linux-gnu”…
    (gdb) disas _exit
    Dump of assembler code for function _exit:
    0x0804d9bc : mov 0x4(%esp,1),%ebx
    0x0804d9c0 : mov $0xfc,%eax
    0x0804d9c5 : int $0x80
    0x0804d9c7 : mov $0x1,%eax
    0x0804d9cc : int $0x80
    0x0804d9ce : hlt
    0x0804d9cf : nop
    End of assembler dump.
    [/code]

    نشاهد من عملية الفك 2 من syscalls ، وتخزن قيمة syscall في EAX لكي تكون مستدعاءة في السطر exit+4 و exit+11

    [code]
    0x0804d9c0 : mov $0xfc,%eax
    0x0804d9c7 : mov $0x1,%eax
    [/code]

    والتي تقابل لإستدعاء النظام رقم 252 التي هي exit_group() وأيضاً syscall 1 التي هي exit() ،وايضاً نرى الامر يقوم بشحن وسيط إستدعاء النظام exit الى EBX ، وهذا الوسيط يدفع في السبق الى المكدس التي لديها القيمة صفر .

    [code]
    0x0804d9bc : mov 0x4(%esp,1),%ebx
    [/code]

    وفي الاخير لدينا 2 من الاوامر int 0x80 الذي يفتح الCPU على نمط النواة لتنفيذ استدعاء النظام بتاعنا

    [code]
    0x0804d9c5 : int $0x80
    0x0804d9cc : int $0x80

    ….تابع باقية الصفحةالتالية

    يمكن الرجوع الى ارقام قائمة syscalls في الاسمبلي التي توضع الى مسجل eax وباقي المسجلات تعبئ EBX, ECX, EDX, ESI, EDI, and EPB بوسطاء الدالة :

    [code]
    $ head -n 80 /usr/include/asm-i386/unistd.h
    #ifndef _ASM_I386_UNISTD_H_
    #define _ASM_I386_UNISTD_H_

    /*
    * This file contains the system call numbers.
    */

    #define __NR_restart_syscall 0
    #define __NR_exit 1
    #define __NR_fork 2
    #define __NR_read 3
    #define __NR_write 4
    #define __NR_open 5
    #define __NR_close 6
    #define __NR_waitpid 7
    #define __NR_creat 8
    #define __NR_link 9
    #define __NR_unlink 10
    #define __NR_execve 11
    #define __NR_chdir 12
    #define __NR_time 13
    #define __NR_mknod 14
    #define __NR_chmod 15
    #define __NR_lchown 16
    #define __NR_break 17
    #define __NR_oldstat 18
    #define __NR_lseek 19
    #define __NR_getpid 20
    #define __NR_mount 21
    #define __NR_umount 22
    #define __NR_setuid 23
    #define __NR_getuid 24
    #define __NR_stime 25
    #define __NR_ptrace 26
    #define __NR_alarm 27
    #define __NR_oldfstat 28
    #define __NR_pause 29
    #define __NR_utime 30
    #define __NR_stty 31
    #define __NR_gtty 32
    #define __NR_access 33
    #define __NR_nice 34
    #define __NR_ftime 35
    #define __NR_sync 36
    #define __NR_kill 37
    #define __NR_rename 38
    #define __NR_mkdir 39

    [/code]

    فمثلاً للكتابة أستدعاء exit(0)

    [code]
    Section .text

    global _start

    _start:

    mov ebx,0
    mov eax,1
    int 0x80
    [/code]

    ثم بالتجميع بواسطة الاسمبلير nasm مع الخيار -f elf للتجميع البرنامج ليصبح ملف object جاهز لكي يربط ، ثم إستخدام GNU linker لربط ملف object بواسطة ld ليصبح برنامج قابل للتنفيذ .

    [code]
    [[email protected] root] nasm -f elf exit_shellcode.asm
    [[email protected] root] ld -o exit_shellcode exit_shellcode.o
    [[email protected] root] ./exit_shellcode
    [/code]

    وهنا برنامج اخر مقتبس helloworld.asm

    [code]
    section .data ; Data segment
    msg db “Hello, world!”, 0x0a ; The string and newline char

    section .text ; Text segment
    global _start ; Default entry point for ELF linking

    _start:

    ; SYSCALL: write(1, msg, 14)
    mov eax, 4 ; Put 4 into eax, since write is syscall #4.
    mov ebx, 1 ; Put 1 into ebx, since stdout is 1.
    mov ecx, msg ; Put the address of the string into ecx.
    mov edx, 14 ; Put 14 into edx, since our string is 14 bytes.
    int 0x80 ; Call the kernel to make the system call happen.

    ; SYSCALL: exit(0)
    mov eax, 1 ; Put 1 into eax, since exit is syscall #1.
    mov ebx, 0 ; Exit with success.
    int 0x80 ; Do the syscall.
    [/code]

    والتنفيذ

    [code]
    [email protected]:~/booksrc $ nasm -f elf helloworld.asm
    [email protected]:~/booksrc $ ld helloworld.o
    [email protected]:~/booksrc $ ./a.out
    Hello, world!
    [email protected]:~/booksrc $
    [/code]

  4. عمر الدليمي @ هلا أخوي عمر … مو شغلة C تكفي أو لا …
    ولكن حالياً جالس أتعلم الأسمبلي للأغراض الأمنية بصراحة …
    كنت أعرف شوية فيها ولكن الآن حان وقت التعمق أكثر بهل مجال …
    أشكرك جزيل الشكر على المرور والدعوات الطيبة وإن شاء الله توضح السبب لك ::20

Comments are closed.