Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
metasm — This is the main repository for metasm, a free assembler / disassembler / compiler written in ruby | Kitploit
أدوات/GitHubGitHub/jjyg/metasm
Code AnalysisReverse EngineeringShellcodeDebuggersBinary Analysis
GitHubjjyg/metasm

metasm

This is the main repository for metasm, a free assembler / disassembler / compiler written in ruby

عرض المستودع
475821منذ 5 أشهرتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة
الموقع الإلكتروني

Metasm، مجموعة أدوات معالجة لغة التجميع Ruby

  • نماذج سكربتات في samples/ -- اقرأ التعليقات في بداية الملفات
  • جميع الملفات مرخّصة بموجب شروط LGPL

المؤلف: Yoann Guillot

نظرة عامة أساسية:

تتيح لك Metasm التعامل مع تنسيقات الملفات التنفيذية (ExeFormat): PE وELF وMach-O وShellcode وغيرها. هناك ثلاث طرق للتعامل مع ExeFormat:

  • إنشاء واحد من الصفر
  • فك تجميع تنسيق موجود
  • معالجة بنية الملف

يمكن العثور على سكربتات جاهزة للاستخدام في المجلد الفرعي samples/، تحقق من التعليقات في ترويسات السكربتات. يمكنك أيضًا تجربة وسيط --help إذا كنت تشعر أنك محظوظ.

لمزيد من المعلومات، راجع المجلد الفرعي doc/. يمكن تحويل الملفات النصية إلى html باستخدام سكربت misc/txt2html.rb.

فيما يلي نظرة عامة مختصرة على مكونات Metasm الداخلية.

التجميع:

عند التجميع، تبدأ من نص مصدري (String في Ruby، يتكون غالبًا من سلسلة من التعليمات/البيانات/توجيهات الحشو)، ويتم تحليله.

يُمرَّر النص إلى كائن Preprocessor (الذي يتعامل مع #if و#ifdef و#include و#define و/* */ وغيرها، وينبغي أن يكون متوافقًا 100% مع gcc -E)، وهو مغلف في AsmPreprocessor لمصادر لغة التجميع (للتعامل مع تعريفات الماكرو في asm، و'equ' وتعليقات asm ';'). الواجهة للقيام بذلك هي ExeFormat#parse(text[, filename, lineno]) أو ExeFormat.assemble (والتي تستدعي .new و#parse و#assemble).

يعيد (Asm)Preprocessor الرموز tokens إلى ExeFormat، الذي يحللها كبيانات Data أو حشو Padding أو تسميات Labels أو توجيهات محلل parser directives. تبدأ توجيهات المحلل دائمًا بنقطة. يمكن أن تكون عامة (.pad، .offset...) أو خاصة بـ ExeFormat (.section، .import، .entrypoint...). يتم معالجتها بواسطة #parse_parser_instruction(). إذا لم يتعرف ExeFormat على كلمة، فإنه يمررها إلى كائن CPU الخاص به، المسؤول عن تحليل التعليمات Instructions (أو إلقاء استثناء). تُخزَّن كل هذه الرموز في مصفوفة واحدة أو أكثر في خاصية @source لكائن ExeFormat (مصدر Shellcode هو Array، وبالنسبة لـ PE/ELF فهو hash [section name] => [Array of parsed data]) يمكن أن تكون كل قيمة فورية Expression عشوائيًا (انظر لاحقًا).

يمكنك بعد ذلك تجميع المصدر إلى مقاطع ثنائية باستخدام ExeFormat#assemble.

بمجرد توفر المقاطع الثنائية، يمكن كتابة الملف التنفيذي الثنائي الكامل على القرص باستخدام ExeFormat#encode_file(filename[, format]).

يتضمن PE وELF ميزة استيراد تلقائي تسمح بإنشاء تلقائي للبيانات المتعلقة بالاستيراد للدوال المعروفة الخاصة بنظام التشغيل (مثلًا، الاستدعاءات غير المحلولة إلى 'strcpy' ستُنشئ بيانات بحيث يتم ربط الملف الثنائي بمكتبة libc وقت التشغيل).

يمكن لـ samples/{exe,pe,elf}encode.rb أن تأخذ ملف مصدر asm كوسيط وتجميعه إلى ملف تنفيذي يعمل.

فئات CPU مسؤولة عن تحليل وترميز التعليمات الفردية. محلل Ia32 الحالي يستخدم صيغة Intel (مثل mov eax, 42). المحلل العام يتعرف على التسميات كسلسلة في بداية السطر متبوعة بنقطتين (مثل 'some_label:'). يمكن استخدام التسميات المحلية بنمط GCC (مثل '1:'، يُشار إليها باستخدام '1b' (للخلف) أو '1f' (للأمام)؛ ويمكن إعادة تعريفها عدة مرات حسب الحاجة.) تُحدد البيانات باستخدام ترميز من نمط 'db' (مثل 'dd 42h', 'db "blabla", 0') انظر samples/asmsyntax.rb

البيانات المشفرة EncodedData:

في Metasm، تُخزَّن جميع البيانات الثنائية ككائن EncodedData. يملك EncodedData ثلاث خصائص رئيسية:

  • #data الذي يحمل البيانات الثنائية الخام (غالبًا String في Ruby، ولكن انظر VirtualString)
  • #export وهو hash يربط اسم التصدير (اسم التسمية) بإزاحة داخل #data
  • #reloc وهو hash مفاتيحه إزاحات داخل #data، وقيمه كائنات Relocation. يملك كائن Relocation ترتيب بايتات endianness (:little/:big)، ونوعًا (:u32 للعدد الصحيح غير الموقّع 32 بت) وهدفًا (القيمة المقصودة المخزنة هنا). الهدف هو Expression حسابي/منطقي عشوائي.

لدى EncodedData أيضًا #virtsize (مثلًا لمقاطع .bss)، و#ptr (إزاحة داخلية تُستخدم عند فك ترميز الأشياء).

يمكنك تنفيذ fixup على EncodedData باستخدام hash اسم متغير => قيمة (يجب أن تكون القيمة Expression أو قيمة رقمية). عند القيام بذلك، يتم ربط هدف كل relocation باستخدام الربط binding، وإذا كانت النتيجة قابلة للحساب (لا يوجد اسم متغير خارجي مستخدم في Expression)، يتم ترميز النتيجة باستخدام معلومات الحجم/الإشارة/ترتيب البايتات الخاصة بالـ relocation. إذا حدث تجاوز (حاول تخزين 128 في relocation موقّع 8 بت)، يتم إلقاء استثناء EncodeError. استخدم النوع :a32 للسماح بقطع silent overflow. إذا لم يكن هدف relocation رقميًا، يبقى الهدف دون تغيير إذا استخدمت EncodedData#fixup، أو يُستبدل بالهدف المرتبط مع #fixup!.

التفكيك:

هذا الكود موجود في ملف المصدر metasm/decode.rb، الذي يعرّف الكلاس Disassembler.

يحتاج المفكك إلى ExeFormat مفكوك الترميز (ليتمكن من تحديد البيانات الموجودة عند أي عنوان افتراضي) ونقطة دخول entrypoint (عنوان افتراضي أو اسم تصدير). يمكنه بعد ذلك البدء في تفكيك التعليمات. عندما يصادف Opcode مُعلَّمًا بـ :setip، يطلب من CPU وجهة القفزة (Expression قد يتضمن قيم سجلات، مثل jmp eax)، ويتتبع التعليمات بشكل عكسي backtraces حتى يعثر على القيمة الرقمية.

أثناء فك الترميز، يحتفظ المفكك بـ hash #decoded يربط العناوين (expressions/أعداد صحيحة بعد #normalize()) بالتعليمات المفكوكة DecodedInstructions.

يولّد التفكيك رسمًا بيانيًا InstructionBlock. يحتوي كل block على قائمة من DecodedInstruction، ومؤشرات إلى الكتلة التالية/السابقة (بالعنوان).

كما يتتبع المفكك عمليات وصول البيانات التي تقوم بها التعليمات، ويخزن Xrefs لها. يمكن تعديل معاملات التتبع العكسي backtrace، ويمكن تغيير أقصى عمق يتم أخذه في الاعتبار تحديدًا لتتبعات :r/:w (مراجع تعليمات الذاكرة) باستخدام #backtrace_maxblocks_data. عند تتبع Expression بشكل عكسي، يتم تعليم كل block يتم المرور عليه بحيث يتم اكتشاف الحلقات، وبحيث إذا تم العثور على مسار كود جديد إلى block موجود، يمكن استئناف التتبعات العكسية باستخدام هذا المسار الجديد.

المفكك يضع افتراضات قليلة جدًا، ولا يفترض بشكل خاص أن الدوال ستعود؛ لن تعود إلا إذا كان التتبع العكسي لتعليمات 'ret' حاسمًا. هذا أمر قوي جدًا، ولكنه يعني أيضًا أن أي خطأ في عملية التتبع العكسي يمكن أن يؤدي إلى توقف كامل؛ ويعني أيضًا أن المفكك بطيء جدًا.

يمكن استخدام الطريقة الخاصة #disassemble_fast للالتفاف حول هذا عندما يكون الكود معروفًا بأنه سليم البنية (أي أنها تفترض أن جميع الاستدعاءات تعود)

عند العثور على دالة فرعية subfunction، يتم إنشاء DecodedFunction خاص، يحمل ملخصًا لتأثيرات الدالة (مثل DecodedInstruction معزّزة). وهذا يسمح للمتتبع العكسي بـ 'تخطي' الدوال الفرعية، مما يحسّن السرعة بشكل كبير. قد تكون DecodedFunctions مبنية على الاستدعاءات callback، للسماح بسلوك ديناميكي للغاية. استدعاءات الدوال الخارجية تنشئ DecodedFunctions مخصصة، تحمل بعض معلومات API (مثل معلومات إصلاح المكدس stack fixup، ووصولات المعاملات الأساسية...) قد تُشتق هذه المعلومات من ترويسة C تم تحليلها مسبقًا. إذا لم يتوفر نموذج أولي لدالة C، يتم استخدام إدخال خاص 'default'، يفترض أن الدالة تتبع ABI قياسي.

Ia32 ينفذ إدخالًا خاصًا :default، يعالج حل إصلاح المكدس تلقائيًا، بافتراض أن تعليمة 'call' الأخيرة تعود. قد يؤدي هذا إلى نتائج غير متوقعة؛ للحصول على أقصى دقة، يُنصح بترويسة C تحمل معلومات لجميع الدوال الخارجية (انظر samples/factorize-headers-peimports للحصول على سكربت لتوليد مثل هذه الترويسة من تثبيت Visual Studio كامل والملف الثنائي الهدف).

كما ينفذ Ia32 استدعاءً خاصًا GetProcAddress/dlsym، يعطي قيمة الإرجاع الصحيحة إذا أمكن تتبع المعاملات backtrace.

السكربتات التي تنفذ مفككًا كاملاً هي samples/disassemble{-gui}.rb انظر التعليقات لمعرفة اختصارات لوحة المفاتيح في الواجهة الرسومية GUI.

التعامل مع ExeFormat:

يمكنك ترميز/فك ترميز ExeFormat (أي فك ترميز المقاطع والاستيرادات والترويسات إلخ)

المنشئ: ExeFormat.decode_file(str), ExeFormat.decode_file_header(str) الطرق: ExeFormat#encode_file(filename), ExeFormat#encode_string

ملفات PE وELF لها نظير LoadedPE/LoadedELF، قادر على العمل مع نسخ معيّنة في الذاكرة memory-mmaped من تلك التنسيقات (مثلًا لتصحيح أخطاء العمليات الجارية)

السلاسل الافتراضية VirtualString:

VirtualString هو كائن شبيه بـ String: يمكنك قراءة مقاطع منه وربما إعادة كتابتها. يمكن استخدامه كـ EncodedData#data، وبالتالي يسمح بجعل معظم خوارزميات Metasm افتراضية virtualization. لا يمكنك تغيير طول VirtualString. أخذ مقطع من VirtualString سيعيد إما String (للأحجام الصغيرة) أو VirtualString آخر (نافذة إلى الآخر). يمكنك إجبار الحصول على VirtualString صغير باستخدام طريقة #dup(offset, length). أي طريقة غير منفذة تُستدعى عليه تُمرَّر إلى String مجمّد وهو نسخة كاملة من VirtualString (يجب تجنب ذلك إن أمكن، فقد تكون السلسلة الأساسية كبيرة جدًا وبطيئة الوصول).

يوجد حاليًا 3 VirtualStrings منفذة:

  • VirtualFile، الذي يحمّل ملفًا بقطع بحجم صفحة عند الطلب،
  • WindowsRemoteString، الذي يعيّن الذاكرة الافتراضية لعملية أخرى (يستخدم واجهة برمجة تصحيح أخطاء ويندوز من خلال WinDbgAPI)
  • LinuxRemoteString، الذي يعيّن الذاكرة الافتراضية لعملية أخرى (يتطلب صلاحيات ptrace، وتتم قراءة الذاكرة باستخدام /proc/pid/mem)

نسختا Win/Lin قويتان جدًا، وتسمحان بأشياء مثل تفكيك/ترقيع عملية حية بسهولة (باستخدام LoadedPE/LoadedELF كـ ExeFormat)

التصحيح:

تتضمن Metasm بعض الواجهات للتعامل مع التصحيح. تقدم الكلاسات WinOS وLinOS وصولًا إلى عمليات نظام التشغيل الأساسية (مثلًا: OS.current.find_process('foobar') سيسترجع عملية قيد التشغيل يحتوي اسم ملفها على foobar؛ ثم يمكن استخدام process.mem للوصول إلى ذاكرتها.)

واجهتا التصحيح منخفضتا المستوى في ويندوز ولينكس لهما واجهة روبي أساسية (PTrace وWinAPI)؛ وتُستخدم من قبل الكلاس الموحّد عالي المستوى Debugger. يتم دعم التصحيح عن بُعد عبر بروتوكول GDB server wire.

يمكن إنشاء مصححات عالية المستوى بسطر الروبي التالي: Metasm::OS.current.create_debugger('foo')

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

الخلفيات backend منخفضة المستوى معرّفة في المجلد الفرعي os/، والواجهة الأمامية معرّفة في debug.rb.

واجهة تصحيح أخطاء لوحدة التحكم في لينكس متوفرة في samples/lindebug.rb؛ وتستخدم مظهرًا وإحساسًا مشابهًا لـ SoftICE (مبسطًا). يمكنها التحدث مع مقبس gdb-server؛ استخدم هدفًا [udp:]host:port.

تسمح عينة disassembler-gui بالتفاعل المباشر مع العملية عند استخدام هدف 'live:'.

محلل C:

تتضمن Metasm محلل C مكتوبًا يدويًا. يتعامل مع جميع الإنشاءات التي أعرفها، باستثناء أرقام الفاصلة العائمة السداسية hex floats:

  • static const L"bla"
  • وسيطات متغيرة variable arguments
  • أنواع غير مكتملة
  • attributes(()), __declspec()
  • #pragma once
  • #pragma pack()
  • مُصرِّحات C99 - type bla = { [ 2 ... 14 ].toto = 28 };
  • دوال متداخلة
  • __int8 وأنواع أصلية أخرى
  • عناوين التسميات (&&label) لاحظ أيضًا أن كل هذه الأشياء يتم تحليلها، لكن معظمها سيفشل في الترجمة على الخلفية Ia32/X64 (الوحيدة المنفذة حتى الآن).

يجب تحليل ملفات C باستخدام ExeFormat موجود، عبر طريقة parse_c_file. يضمن ذلك تعريف وحدات الماكرو/ABI الخاصة بالتنسيق بشكل صحيح (مثلًا: حجم النوع 'long'، وABI لتمرير المعاملات إلى الدوال، إلخ)

عند تحليل نص C باستخدام C::Parser.parse(text)، تستلم كائن Parser. يحمل حقل #toplevel، وهو C::Block، يحمل #structs و#symbols و#statements. توجد الدوال عالية المستوى في hash #symbol الذي تكون مفاتيحه أسماء الرموز، مرتبطة بكائن C::Variable يحمل الدوال. يمكن الوصول إلى معاملات/سمات الدالة عبر func.type، والكود موجود في func.initializer، وهو نفسه C::Block. وتحته ستجد بنية شجرية من C::Statements (If وWhile وAsm وCExpressions...)

يمكن تحويل C::Parser مسبقًا #precompiled إلى نسخة مبسطة يسهل ترجمتها: تتم إزالة typedefs، وتُحوَّل تسلسلات التحكم إلى 'if (XX) goto YY;' إلخ.

لتجميع برنامج C، استخدم PE/ELF.compile_c، الذي سينشئ C::Parser مع تعريف وحدات ماكرو خاصة بالملفات التنفيذية (مثل PE أو ELF).

قد تحتاج ترويسات البائعين الخاصة إلى استخدام إما #pragma prepare_visualstudio (لتحليل ترويسات Microsoft Visual Studio) أو prepare_gcc (لـ gcc)، وقد يتم اكتشاف الأخير تلقائيًا (أو لا يتم). الترويسات الخاصة بالبائعين التي تم اختبارها هي VS2003 (بما في ذلك DDK) وgcc4؛ والنتائج قد تختلف (ymmv).

حاليًا، تولّد CPU#compilation لشفرة C مصدر asm (نص)، والذي يمكن بعد ذلك تحليله وتجميعه إلى كود ثنائي.

انظر ExeFormat#compile_c، وsamples/exeencode.rb

تنزيل الأداة