
ارتباطات Python لـ VEX IR الخاص بـ Valgrind.
PyVEX هو ارتباطات Python لـ VEX IR.
مستودع المشروع: https://github.com/angr/pyvex
التوثيق: https://api.angr.io/projects/pyvex/en/latest/
يمكن تثبيت PyVEX عبر pip:
pip install pyvex
import pyvex
import archinfo
# translate an AMD64 basic block (of nops) at 0x400400 into VEX
irsb = pyvex.lift(b"\x90\x90\x90\x90\x90", 0x400400, archinfo.ArchAMD64())
# pretty-print the basic block
irsb.pp()
# this is the IR Expression of the jump target of the unconditional exit at the end of the basic block
print(irsb.next)
# this is the type of the unconditional exit (i.e., a call, ret, syscall, etc)
print(irsb.jumpkind)
# you can also pretty-print it
irsb.next.pp()
# iterate through each statement and print all the statements
for stmt in irsb.statements:
stmt.pp()
# pretty-print the IR expression representing the data, and the *type* of that IR expression written by every store statement
import pyvex
for stmt in irsb.statements:
if isinstance(stmt, pyvex.IRStmt.Store):
print("Data:", end="")
stmt.data.pp()
print("")
print("Type:", end="")
print(stmt.data.result_type)
print("")
# pretty-print the condition and jump target of every conditional exit from the basic block
for stmt in irsb.statements:
if isinstance(stmt, pyvex.IRStmt.Exit):
print("Condition:", end="")
stmt.guard.pp()
print("")
print("Target:", end="")
stmt.dst.pp()
print("")
# these are the types of every temp in the IRSB
print(irsb.tyenv.types)
# here is one way to get the type of temp 0
print(irsb.tyenv.types[0])
ضع في اعتبارك أن هذا تمثيل نحوي لكتلة أساسية. أي أنه سيخبرك بما تعنيه الكتلة، لكن ليس لديك أي سياق لتقول، على سبيل المثال، ما هي البيانات الفعلية التي تكتبها تعليمة تخزين.
للتعامل مع معماريات متنوعة على نطاق واسع، من المفيد إجراء التحليلات على تمثيل وسيط. يجرد التمثيل الوسيط (IR) عدة اختلافات في المعماريات عند التعامل مع معماريات مختلفة، مما يسمح بتشغيل تحليل واحد على جميعها:
rax في AMD64 يُخزَّن بدءاً من العنوان 16 في مساحة الذاكرة هذه).هناك العديد من الخيارات للتمثيل الوسيط. نستخدم VEX، لأن رفع الكود الثنائي إلى VEX مدعوم جيداً. VEX هو تمثيل مستقل عن المعمارية وخالٍ من الآثار الجانبية لعدد من لغات الآلات المستهدفة. يجرد كود الآلة إلى تمثيل مصمم لتسهيل تحليل البرامج. يحتوي هذا التمثيل على خمس فئات رئيسية من الكائنات:
t0. هذه المتغيرات المؤقتة ذات أنواع قوية (أي "عدد صحيح 64-بت" أو "عدد عشري 32-بت").تمثيل VEX IR موثق جيداً في ملف libvex_ir.h (https://github.com/angr/vex/blob/dev/pub/libvex_ir.h) في مستودع VEX. للكسالى، سنفصّل بعض أجزاء VEX التي من المحتمل أن تتفاعل معها بشكل متكرر. للبدء، إليك بعض تعبيرات التمثيل الوسيط:
| تعبير التمثيل الوسيط | القيمة المُقيَّمة | مثال مخرجات VEX |
|---|---|---|
| Constant | قيمة ثابتة. | 0x4:I32 |
| Read Temp | القيمة المخزنة في متغير مؤقت VEX. | RdTmp(t10) |
| Get Register | القيمة المخزنة في سجل. | GET:I32(16) |
| Load Memory | القيمة المخزنة في عنوان ذاكرة، مع تحديد العنوان بتعبير تمثيل وسيط آخر. | LDle:I32 / LDbe:I64 |
| Operation | نتيجة عملية تمثيل وسيط محددة، مطبقة على وسائط تعبير تمثيل وسيط محددة. | Add32 |
| If-Then-Else | إذا قُيِّم تعبير تمثيل وسيط معين إلى 0، أعد تعبير تمثيل وسيط واحد. وإلا، أعد آخر. | ITE |
| Helper Function | يستخدم VEX دوال مساعدة بلغة C لعمليات معينة، مثل حساب سجلات الأعلام الشرطية لمعماريات معينة. تعيد هذه الدوال تعبيرات التمثيل الوسيط. | function_name() |
ثم تُستخدم هذه التعبيرات، بدورها، في عبارات التمثيل الوسيط. إليك بعض العبارات الشائعة:
| عبارة التمثيل الوسيط | المعنى | مثال مخرجات VEX |
|---|---|---|
| Write Temp | اضبط متغيراً مؤقتاً في VEX على قيمة تعبير التمثيل الوسيط المعطى. | WrTmp(t1) = (IR Expression) |
| Put Register | حدّث سجلاً بقيمة تعبير التمثيل الوسيط المعطى. | PUT(16) = (IR Expression) |
| Store Memory | حدّث موقعاً في الذاكرة، معطى كتعبير تمثيل وسيط، بقيمة، معطاة أيضاً كتعبير تمثيل وسيط. | STle(0x1000) = (IR Expression) |
| Exit | مخرج شرطي من كتلة أساسية، مع تحديد هدف القفز بتعبير تمثيل وسيط. يُحدَّد الشرط بتعبير تمثيل وسيط. | if (condition) goto (Boring) 0x4000A00:I32 |
يُنتَج مثال لترجمة تمثيل وسيط، على ARM، أدناه. في المثال، تُترجم عملية الطرح إلى كتلة تمثيل وسيط واحدة تتألف من 5 عبارات تمثيل وسيط، كل منها يحتوي على تعبير تمثيل وسيط واحد على الأقل (على الرغم من أن كتلة التمثيل الوسيط في الواقع العملي تتكون عادةً من أكثر من تعليمة واحدة). تُترجم أسماء السجلات إلى فهارس رقمية تُعطى لتعبير GET وعبارة PUT.
سيلاحظ القارئ الذكي أن الطرح الفعلي يُنمذَج بواسطة أول 4 عبارات تمثيل وسيط في الكتلة، وأن زيادة عداد البرنامج للإشارة إلى التعليمة التالية (التي تقع، في هذه الحالة، عند 0x59FC8) تُنمذَج بواسطة العبارة الأخيرة.
التعليمة ARM التالية:
subs R2, R2, #8
تصبح تمثيل VEX IR هذا:
t0 = GET:I32(16)
t1 = 0x8:I32
t3 = Sub32(t0,t1)
PUT(16) = t3
PUT(68) = 0x59FC8:I32
أشياء رائعة!
إذا استخدمت PyVEX في عمل أكاديمي، يرجى الاستشهاد بالورقة البحثية التي طُوِّر من أجلها: