
محلل بايت كود جافا قابل للتخصيص عبر قواعد JSON
محلل كود بايت (Bytecode) لجافا قابل للتخصيص عبر قواعد JSON. أداة سطر أوامر تستقبل مسارًا يحتوي على ملف Jar أو War واحد أو أكثر، وتحللها باستخدام القواعد المقدمة وتنشئ تقارير HTML بالنتائج.
usage: java -jar cba-cli.jar [OPTIONS] -a DIRECTORY_TO_ANALYZE
-a,--analyze <pathToAnalyze> مسار الدليل المراد تحليله.
-c,--checks <checks...> قائمة مفصولة بمسافات من الفحوصات المخصصة
التي سيتم تشغيلها في التحليل.
-f,--custom-file <customFile> حدد ملفًا بتنسيق JSON لتشغيل قواعد مخصصة.
اقرأ المزيد على
https://github.com/fergarrui/custom-bytecode-analyzer.
-h,--help طباعة هذه الرسالة.
-i,--items-report <maxItems> أقصى عدد من العناصر لكل تقرير. إذا تجاوز
عدد المشكلات التي تم العثور عليها هذه القيمة،
سيتم تقسيم التقرير إلى ملفات مختلفة. مفيد إذا كنت
تتوقع عددًا كبيرًا من المشكلات في التقرير. القيمة الافتراضية: 50.
-o,--output <outputDir> الدليل لحفظ التقرير. تحذير -
إذا كانت هناك تقارير محفوظة بالفعل في هذا
الدليل فسيتم استبدالها.
الافتراضي هو "report".
-v,--verbose-debug زيادة مستوى التفاصيل إلى وضع التصحيح.
-vv,--verbose-trace زيادة مستوى التفاصيل إلى وضع التتبع - يجعله أبطأ، استخدمه فقط عند الحاجة.
يمكن تحديد ملف القواعد باستخدام الوسيطة -f,--custom-file. الملف بتنسيق JSON وله الهيكل التالي:
finalيمكنك أيضًا مراجعة net.nandgr.cba.custom.model.Rules.java للاطلاع على الهيكل في كود Java.
توجد بالفعل عدة قواعد ضمن الدليل examples. على أي حال، فيما يلي أمثلة لكل قاعدة.
إذا احتجنا إلى العثور على الفئات التي تحتوي على إلغاء تسلسل مخصص، يمكننا القيام بذلك بسهولة. تحدد الفئة إلغاء التسلسل المخصص من خلال تنفيذ private void readObject(ObjectInputStream in). لذلك نحتاج فقط إلى العثور على جميع الفئات التي تم تعريف هذه الطريقة فيها. سيكون كافيًا تعريف قاعدة كما يلي:
{
"rules": [{
"name": "Custom deserialization",
"methods": [{
"name": "readObject",
"visibility": "private",
"parameters" : [{
"type" : "java.io.ObjectInputStream"
}]
}]
}]
}
سيُبلغ عن الطرق ذات الرؤية private، والاسم readObject ومعامل من النوع java.io.ObjectOutputStream. المعاملات عبارة عن مصفوفة، إذا تم تحديد أكثر من واحد، يجب أن تتطابق جميعها للإبلاغ. نظرًا لأن لدينا قاعدة واحدة فقط، سيتم إنشاء تقرير باسم: custom-deserialization-0.html.
في هذه الحالة، يجب تعريف قاعدة واحدة بطريقتين. نفس القاعدة كما في المثال السابق لإلغاء التسلسل، وقاعدة جديدة لمطابقة private void writeObject(ObjectOutputStream out). كما هو موضح في هيكل JSON أعلاه، الخاصية rules.rule.methods هي مصفوفة من الطرق، لذا يمكن كتابة قاعدة مثل هذه:
{
"rules": [{
"name": "Custom serialization and deserialization",
"methods": [{
"name": "readObject",
"visibility": "private",
"parameters" : [{
"type" : "java.io.ObjectInputStream"
}]
},{
"name": "writeObject",
"report": "false",
"visibility": "private",
"parameters" : [{
"type" : "java.io.ObjectOutputStream"
}]
}]
}]
}
تم تعيين الخاصية report إلى false لتجنب الإبلاغ مرتين لنفس القاعدة. نحن نستخدم الطريقة الثانية كشرط فقط، ولكن الإبلاغ عن طرق readObject فقط يجب أن يكون كافيًا للغرض من هذه القاعدة.
إذا لم يتم تعريف خاصية، فسوف تتطابق دائمًا على أنها true. على سبيل المثال، هذه القاعدة ستعيد جميع تعريفات الطرق:
{
"rules": [{
"name": "Method definitions",
"methods": [{
}]
}]
}
يمكن أيضًا العثور على استدعاءات الطرق. سيكون JSON في هذه الحالة:
{
"rules": [{
"name": "String equals",
"invocations": [{
"owner": "java.lang.String",
"method": {
"name": "equals"
}
}]
}]
}
الخاصية owner تحدد الفئة التي تحتوي على الطريقة.
مثال آخر لاستدعاء طريقة أكثر فائدة قليلاً من السابق:
{
"rules": [{
"name": "Method invocation by reflection",
"invocations": [{
"owner": "java.lang.reflect.Method",
"method": {
"name": "invoke"
}
}]
}]
}
هو نفسه أي استدعاء طريقة، ولكن اسم الطريقة في هذه الحالة يجب أن يكون <init>.
{
"rules": [{
"name" : "String instantiation",
"invocations" : [{
"owner" : "java.lang.String",
"method" : {
"name" : "<init>"
}
}]
}]
}
ستجد هذه القاعدة حالات مثل:
[...]
String s = new String("foo");
[...]
في هذا المثال، نريد العثور على استخدامات إلغاء التسلسل (وليس الفئات التي تحدد سلوكيات التسلسل كما في الأمثلة السابقة). يحدث إلغاء التسلسل عندما يتم استدعاء ObjectInputStream.readObject(). على سبيل المثال في مقتطف الكود هذا:
ObjectInputStream in = new ObjectInputStream(fileInputStream);
Object o = in.readObject();
لذا نحتاج إلى العثور على استدعاءات طرق من ObjectInputStream بالاسم readObject. لكنها ستجد الكثير من النتائج الإيجابية الخاطئة في سياق البحث، لأنه عندما تحدد فئة إلغاء تسلسل مخصص، فإنها تقوم باستدعاء لهذه الطريقة داخل طريقة private void readObject(ObjectInputStream in)، وهذا سيلوث التقرير كثيرًا. إذا أردنا استبعاد هذه الحالات والاحتفاظ فقط بإلغاء التسلسل الحقيقي، يمكن استخدام الخاصية notFrom: