TL ؛ DR: لقد صممنا برنامجًا معكوسًا لكتابة بنية وحدة المعالجة المركزية غير المعروفة تمامًا دون أي وثائق على وحدة المعالجة المركزية (بدون محاكي ، بدون ISA ، دون كل شيء) في غضون عشر ساعات فقط. من المقال سوف تتعلم كيف فعلنا ذلك ...
في نهاية الأسبوع الماضي ، شاركت أنا وفريق CMU PPP في فريق Dragon Sector Teaser CTF 2019 للاسترخاء والابتعاد عن الموعد النهائي الصعب
CHI 2020 . Dragon Sector هو فريق بولندي محترم
ولديه تاريخ من
CTFs مثيرة للاهتمام ، لذلك كنت أتساءل ما لديهم في الأوراق المالية.
بعد حل "ummmfpu" ، وهي المهمة التي تضمنت الهندسة العكسية لل bytecode لمعالج النقطة الفاصلة العائمة Micromega uM-FPU ، قررت المشاركة في مسابقة لحل مشكلة CPU Adventure ، والتي لم يتم حلها في ذلك الوقت من قبل أي من الفرق (نتيجة لذلك) كنا الوحيدين الذين أكملوا المهمة).
فيما يلي وصف لمهمة وحدة المعالجة المركزية Adventure:
كان جدي في الستينيات منخرطاً في تطوير أجهزة الكمبيوتر. من أجل وضع الأشياء في العلية ، وجدت سيارة غريبة. بجانب الآلة كان هناك مجموعة من البطاقات المثقوبة تحمل علامة "Dragon Adventure Game". بعد بعض الوقت ، تمكنت من توصيله بالمعدات الحديثة ، لكن اللعبة معقدة للغاية ولا يمكنني الوصول إلى النهاية دون الغش. هل يمكنك مساعدتي؟ أرفق نسخة من بطاقات اللكم المستخدمة في الجهاز. يزعم أن الجهاز يحتوي على 4 سجلات للأغراض العامة ، و 1 كيلوبايت من ذاكرة البيانات و 32 كيلوبايت من ذاكرة الأمر. لتشغيل اللعبة ، قم بالاتصال بالخادم كما يلي: socat tcp4-connect:cpuadventure.hackable.software:1234 fd:0,rawer
تلميح socat tcp4-connect:cpuadventure.hackable.software:1234 fd:0,rawer
: معالج الجهاز فريد من نوعه ، لا تحاول استخدام معلومات google على ذلك.
game.bin
بعد الاتصال بالخادم ، تلقينا المعلومات التالية:
THERE IS A TAVERN HERE. INSIDE THE TAVERN, YOU SEE VALIS.
SELECT AN OPTION:
- GO (N)ORTH
- GO (E)AST
- (T)ALK TO VALIS
- (D)RINK
- SHOW (I)NVENTORY
YOUR CHOICE:
ممتاز. هذه هي لعبة مغامرة المدرسة القديمة. بعد لعبها قليلاً ، أدركنا أنه يمكنك محاربة الأعداء والحصول على علم من شخصية Valis هذه إذا رضينا عنه:
YOUR CHOICE: T
YOU ENTER THE TAVERN AND APPROACH VALIS.
- HEY, I WAS WONDERING IF YOU COULD HELP ME FIND THE FLAG?
- THE FLAG? MAYBE, BUT FIRST, I NEED A REDBULL.
- I... I DON'T HAVE A REDBULL.
- WELL THEN, MAKE YOURSELF USEFUL AND FIND ONE.
THERE IS A TAVERN HERE. INSIDE THE TAVERN, YOU SEE VALIS.
SELECT AN OPTION:
- GO (N)ORTH
- GO (E)AST
- (T)ALK TO VALIS
- (D)RINK
- SHOW (I)NVENTORY
YOUR CHOICE:
الخطوات الأولى
لم ألعب اللعبة لفترة طويلة ،
game.bin
أنه على الأرجح أنه من الأفضل عكس هندسة ملف
game.bin
. فتحته في محرر سداسي عشرًا ، أتوقع أن أرى قيمًا ثنائية. تخيل دهشتي عندما رأيت هذا:
110011111101000000111100110010001110000011001101000000000000110010011101010000001101001111100001111111001100111000000011 ...
هذا
حرفيًا ملف ثنائي - ملف نصي لا يحتوي على أي شيء آخر غير الأحرف ASCII 1 و 0. نعلم أن هذا هو على الأرجح رمز الجهاز للمعالج ، ولكن بالإضافة إلى وجود 4 سجلات و 1 كيلوبايت من ذاكرة البيانات و 32 kibibyte من ذاكرة التعليمات ،
لا يعرف
شيء عن ذلك. لذلك ، ستكون أول مهمة جدية هي تحديد حجم وحدة هذا الملف الثنائي (على سبيل المثال ، هل له بعد 8 بت أم ربما له بعد 12 بت أو 18 بت ، كما هو الحال في بعض
البنى القديمة ؟)
لمعرفة حجم ملف غير معروف ، استخدمت خدعة قديمة - قمت بتغيير حجم مربع النص حتى يتوافق طول فاصل الأسطر مع المحاذاة. تعد هذه الطريقة رائعة بالنسبة لأشياء مثل العديد من نصوص XOR المشفرة وتنسيقات الملفات غير المعروفة (غير المضغوطة) ورمز وحدة المعالجة المركزية غير المعروفة:
تغيير حجم مربع النصمن هذا الفحص السريع ، اكتشفت أن حجم وحدة هذا الملف يجب أن يكون مقسومًا على 20 (عرض النافذة المتوافقة). لمعرفة الحجم الدقيق ، كتبت بسرعة نصًا يبحث عن خطوط مكررة طويلة (على افتراض أن أي رمز يحتوي على تكرار متواليات نمطية). كان خط التكرار الأطول عبارة عن كتلة 425 بت التالية ، وجدت في 43625 و 44510:
10000011111110000001010100011111110100000101100010111000001001000101000100001000100001010001011000101000000001111111111100010000011110010100100001010100111100000110000010100000101000101000011110001111001101111001010100001010000111110100001010000110010011011110011111000000111011101000000001100000110000111101011010111011000100100010100000111000100011100011000000000101010101100010111000001010000001101010010000000011000001100
بما أن المسافة بين التكرارات هي 885 ، توصلنا إلى استنتاج مفاده أن البعد يجب أن يكون 5 بت ، أي يجب أن تحتوي وحدة المعالجة المركزية غير المعروفة على 5 بايت. التقدم!
بحثنا عن ترميزات بطاقة لكمة 5 بت واستقرنا بسرعة على الترميز القديم
باستخدام كود Baudot . وفي الحقيقة - عندما استخدمنا وحدة فك الترميز عبر الإنترنت لفك تشفير بعض الأجزاء ، حصلنا على نص مقروء!
AGDRAGON⇩HERE⇧ ؛ HSHE⇩APPEARS⇩TO⇩BE⇩GUARDING⇩ SOME⇩KIND⇩OF⇩A⇩BOTTLE⇧؛ &. &. ⇩␀THERE⇩IS⇩A⇩B
LSB Baudot ITA المحسّن 425 بت رمز
ثم حاولنا فك تشفير الملف بأكمله باستخدام كود Bodo ، لكن في حوالي 20 ألف بت حصلنا على القمامة ، وبعد ذلك كان هناك نص مقروء تمامًا. هذا أوضح لنا أن الجزء الأول من الملف ينتمي إلى قسم "الشفرة" ، يليه قسم "البيانات" ، الذي يحتوي على خطوط ثابتة. افترضنا أن الجهاز ربما يستخدم كود Bodo لإدخال / إخراج ، وبالتالي يخزن الخطوط الثابتة في ترميز Bodo في الذاكرة أيضًا. لجعل مقطع التعليمات البرمجية أكثر قابلية للقراءة ، قررت ترميزه باستخدام تشفير base-32 ، على غرار التشفير السداسي عشري ، لكن مع توسيعه باستخدام الأبجدية 0-9a-v. إليك ما يبدو عليه ملف game.bin من خلال الجزء الأول الذي تم ترميزه بواسطة base-32 والجزء الثاني تم فك ترميزه بواسطة Bodo (يتم نشر الملف الكامل هنا:
game.b32 ):
pv83pi70pk00p7a0qfgvpjg3f0kf13f28p5f3pv10pk40pn60f0sf1sf24p5f3r9c11qad0f0sf1df26p5f39c21qad0f05f1ff26p5f39c41qad0f08f1df26p5f39c81qad0f0hf1ef26p5f3r1c00qaq15c20qcl0f01f1of27p5f3p3g3psf35c10qal0f02f1nf27p5f3p3g3psf3rf0hf1nf27p5f3f05f16f27p5f3rf84f95101311fl0f510f84907qa40b518447qa40b514f84f95k9m0k9m0k9m0907qa40b511447qa40b512ruougf10f20g0i9g0i910931b320u2u1u0ro9f0o9f0ojh0o9f0o9f0o9f0olj0o9f0o9f0o9f0o9f0o9f0o9f0o9f0o9k1onp0o9f0o9f0o9f0o9f0onf0ot82odi0o9f0o9f0o9f0o9f0o9f0o9f0o9f0olg0o9f0f0gf1df24p5f3r9c11qa835548755
[...]
93e9n59ka8fo87r85g8ui8ml8ed87b9h89u291u82333333333456789abcdb01234567892)%c3BOTTLE OF SOPLICA PIGWOWAENEMY HEALTH:
YOU ATTACK
YOU APPROACH REDFORD.
YOU ENTER THE TAVERN AND APPROACH VALIS.
[...]
من أجل البساطة ، سأدعو الوحدات ذات الخمس بتات "بايت" أدناه. بين بعضنا البعض في الفريق ، توصلنا إلى أسماء أخرى لهم - دعوتهم kibbles ، و Zak - hacks.
هندسة المعالج غير معروفة الهندسة العكسية
نصل الآن إلى الجزء الصعب - الهندسة العكسية 4000 بايت من التعليمات البرمجية التي تعمل على بنية وحدة المعالجة المركزية الفريدة غير معروفة تماما. من الكود ، من الواضح أن هذا يجب أن يكون مجموعة من الإرشادات
ذات الطول المتغير ، لأنه من المستحيل العثور على نمط تكرار ثابت ملحوظ فيه. قضيت بضع ساعات في هذا ، فيما بعد بدأ عضو فريقي زاكاري ويد (@ zwad3) بمساعدتي. بادئ ذي بدء ، لقد بدأت في البحث عن أجزاء مكررة من التعليمات البرمجية ، مما يشير إلى أنها غالباً ما تستخدم عددًا صغيرًا من التعليمات. بدأت في تقسيم الشفرة إلى تسلسلات متكررة أقصر كانت أكثر ملاءمة للتحليل. أود أن أقول إنها كانت عملية صارمة ، ولكن في الواقع ، استخدمت الخوارزمية الغامضة التالية بشكل أساسي:
- ننظر من خلال الكود ونبحث عما إذا كان هناك شيء يتكرر فيه كثيرًا
- قم بإجراء البحث واستبدال الإجراء لإدراج سطر جديد بجانب هذا التكرار
- استكشاف أوجه التشابه / الاختلافات بين خطوط الانقسام الناتجة.
- كرر هذه العملية لمدة ساعة تقريبًا ...
على سبيل المثال ، كان أحد الأنماط التي اكتشفتها هو "0f0.f" ، حيث "." يشير إلى شخصية غير معروفة. كسرت الخيط على هذا النمط وحصلت على ما يلي:
pv83pi70pk00p7a0qfgvpjg3f0kf13f28p5f3pv10pk40pn60f0sf
1sf24p5f3r9c11qad0f0sf
1df26p5f39c21qad0f05f
1ff26p5f39c41qad0f08f
1df26p5f39c81qad0f0hf
1ef26p5f3r1c00qaq15c20qcl0f01f
1of27p5f3p3g3psf35c10qal0f02f
مفيد جدا من السطور الثاني والثالث ، نرى أن هناك "... p5f3r9c ..." و "... p5f39c ..." ، وهذا يشير إلينا إلى أن "r" عبارة عن شفرة تشغيل واحدة البايت ، وهذا هو ، "... 5f3" هو نهاية شفرة تشغيل واحدة ، و " 9c .. "هي بداية أخرى. في الخطين الأخيرين ، نرى "p5f3r1c ..." وهذا يعني أن "1c .." هو شفرة تشغيل أخرى ، و "p3 ..." هو شفرة تشغيل أخرى.
واصلت تقسيم التعليمات مرارًا وتكرارًا بطريقة مماثلة ، باستخدام أوجه التشابه والاختلاف في الكتل المشابهة للعثور على الإرشادات المحتملة. في النهاية ، حصلت على شيء مثل هذا:
pv83
pi70
pk00
p7a0
qfgv
pjg3
f0k
f13
f28
p5f3
pv10
pk40
pn60
f0s
f1s
f24
p5f3
r
9c11
qad0
f0s
f1d
f26
p5f3
9c21
qad0
f05
f1f
افترضت أن "p" و "q" كانتا تعليمات بثلاثة بايتات للمعاملات ، و "f0" و "f1" و "f2" كانت تعليمات مع معامل واحد ، و "9c" كانت تعليمة مع اثنين من المعاملين. ومع ذلك ، لم أكن أعرف ما هو كل من هذه التعليمات.
لذا التفتت إلى دليل جميع الإرشادات "p" التي أبرزتها ، ووجدت أنه في الوقت الحالي ، كانت التعليمات الأكثر شيوعًا مع "p" هي "p5f3". علاوة على ذلك ، عند النظر إلى الأماكن التي يحدث فيها ، وجدت أنه يسبقها دائمًا التعليمات "f0" و "f1" و "f2". بالنظر إلى جميع المعامِلات "f0" و "f1" و "f2" ، لاحظت أن المعامِلات f2 موجودة دائمًا في النطاق 4-8. تذكر أن وحدة المعالجة المركزية تحتوي على 32 كيلوبايت من ذاكرة البرنامج للعنونة والتي تتطلب 15 بت ، افترضت أن "f0" و "f1" و "f2" قاموا بتحميل بعض العناوين مع f2 باعتبارها البايت العالي. عندما قمت بتوصيل بعض هذه العناوين معًا ، وجدت أنها تشير جميعها تمامًا إلى بداية السطور الثابتة في قسم البيانات. لقد وجدت وظيفة
print
! تبع ذلك على الفور أن "p5f3" هو في الواقع نوع من التعليمات لطباعة خط أو مكالمة ؛ إذا أخذت في الاعتبار المعامل ثلاثي البايت ، فمن المرجح أنه "مكالمة". مرة أخرى ، نظرًا إلى الإرشادات "p" ، أدركت أن البايتات الثلاث للمعامل تشير إلى العنوان
بالترتيب المباشر (end-little endian) ، أي أن البايت الأخير من المعامل هو البايت الأعلى من العنوان.
لقد كان إنجازا كبيرا! لقد حددنا تعليماتنا الأولى. بعد أن رأيت أنه يتم استخدام "f0" و "f1" في بعض الأماكن الأخرى ، افترضت أنهما لا يقومان بتحميل العناوين ، ولكن أحد السجلات الأربعة (على سبيل المثال ، f0 تحميلات تسجل 0) مع ثوابت ذات 5 بت مع عنونة مباشرة. هذا منطقي لـ p5f3 - يقوم بتحميل ثلاث وسائط تسجيل للدالة 3f5 ("print_string").
بدأت في كتابة أداة فك تجميع تتعرف على المصطلح "طباعة" (f0x ، f1x ، f2x ، p5f3) ، مع وضع استبدال الخط المطبوع في الشفرة المفككة. نظرًا للعدد الكبير من الأسطر الموجودة في البرنامج ، سرعان ما أصبحت الشفرة المفككة قابلة للقراءة للغاية ، وأصبح من السهل معرفة موقع كتل الوظائف (الرمز الكامل المفكك موجود
هنا ):
0: call 38v
4: call 7i
8: call k
c: call a7
g: q vgf
k: call 3gj
o: print 83k # 'SELECT AN OPTION\x0e:\r\n\r\n\x0f\x00'
15: call 1v
19: call 4k
1d: call 6n
1h: print 4ss # '\r\nYOUR CHOICE\x0e: \x0f\x00'
1u: ret
1v: unk 9
20: unk c
21: unk 1
22: unk 1
23: q 0da
27: print 6ds # '\x0e- \x0fGO \x0e(\x0fS\x0e)\x0fOUTH\r\n\x00'
2k: unk 9
2l: unk c
2m: unk 2
2n: unk 1
2o: q 0da
2s: print 6f5 # '\x0e- \x0fGO \x0e(\x0fN\x0e)\x0fORTH\r\n\x00'
39: unk 9
3a: unk c
3b: unk 4
3c: unk 1
3d: q 0da
3h: print 6d8 # '\x0e- \x0fGO \x0e(\x0fE\x0e)\x0fAST\r\n\x00'
3u: unk 9
3v: unk c
40: unk 8
41: unk 1
42: q 0da
46: print 6eh # '\x0e- \x0fGO \x0e(\x0fW\x0e)\x0fEST\r\n\x00'
4j: ret
من مقتطف الشفرة الصغير هذا ، تمكنت من تحديد عدة جوانب: يجب أن يشير تعليمة "q0" إلى بعض التفرعات الشرطية (لأنه يُستخدم لتخطي طباعة الاتجاهات غير الضرورية في الوظيفة 1v) ، والتعليمات "9c11" ، "9c21" ، "9c41" ، " يجب أن يشير 9c81 "إلى نوع ما من التعليمات AND - يتحققون من البتات المضبوطة لمعرفة ما إذا كانت هذه الاتجاهات مسموحًا بها (يتم التلميح إلى ذلك بوضوح باستخدام" 1 "و" 2 "و" 4 "و" 8 "في هذه التعليمات).
خلال الساعتين التاليتين ، قمت أنا وزاكاري واد (@ zwad3) بترتيب مختلف التعليمات ، وصنعنا وصقلنا افتراضاتنا حول ما كانا يفعلانه. وجود العديد من البيانات المطبوعة المقروءة جعل مهمتنا أسهل كثيرًا. قررنا أن يقوم كل واحد منا على حدة بكتابة مفكك تفكيكه الخاص حتى نتمكن من فحص التعليمات في وتيرنا وتبادل النتائج التي توصلنا إليها.
كود الهندسة العكسية
بعد بضع ساعات ، بدأت في إحراز تقدم كبير في تفكيكها. بعد فحص الشفرة التي عملت مع مخزون المستخدم (بشكل أكثر تحديدًا ، وظيفة "الشراب" وكل معالج مرتبط بها) ، وجدنا تعليمات للحفظ والتحميل من الذاكرة (لا تنس أن وحدة المعالجة المركزية تحتوي على 1 كيلوبايت من ذاكرة البيانات). ثم اكتشفنا أن بعض الإرشادات الحسابية / المنطقية (ALU) تأخذ معاملات ذاكرة (على سبيل المثال ، "9c41" تعني "تنفيذ AND بقيمة في عنوان البيانات 1 مع القيمة 4"). من هذا ، استطعنا إعادة إنشاء المتغيرات في ذاكرة البيانات ، على سبيل المثال ، في [0] يتم تخزين معرف NPC في الموقع الحالي ، وفي [6،7] يتم تخزين صحة اللاعب الحالية (أقل 5 بتات في [6] ، أقدم 5 بتات في [7] ]). في هذه المرحلة ، تحولت من تعليمات الهندسة العكسية إلى التعليق على التعليمات البرمجية المفككة وهندسة الهندسة العكسية للبرنامج نفسه. فيما يلي تدويني المضحك لقيم 5 بت:
_start:
call init
L4:
call check_moves
call print_menu
call handle_command
br 4
print_menu:
call print_itemname
print 83k # 'SELECT AN OPTION\x0e:\r\n\r\n\x0f\x00'
call print_moves
call print_npcmenu
call print_itemmenu
print 4ss # '\r\nYOUR CHOICE\x0e: \x0f\x00'
ret
print_moves:
and 0y1, [1]
brz 2k
print 6ds # '\x0e- \x0fGO \x0e(\x0fS\x0e)\x0fOUTH\r\n\x00'
2k: and 0y2, [1]
brz 39
print 6f5 # '\x0e- \x0fGO \x0e(\x0fN\x0e)\x0fORTH\r\n\x00'
39: and 0y4, [1]
brz 3u
print 6d8 # '\x0e- \x0fGO \x0e(\x0fE\x0e)\x0fAST\r\n\x00'
3u: and 0y8, [1]
brz 4j
print 6eh # '\x0e- \x0fGO \x0e(\x0fW\x0e)\x0fEST\r\n\x00'
4j: ret
print_npcmenu:
add 0y0, [0]
brz 6m
sub 0y2, [0]
br<c> 5p
print 7o1 # '\x0e- (\x0fT\x0e)\x0fALK TO \x00'
call print_npcname
call print_crlf
5p: sub 0y1, [0]
brz 6m
print 7n2 # '\x0e- (\x0fF\x0e)\x0fIGHT \x00'
call print_npcname
call print_crlf
6m: ret
print_itemmenu:
print 7nh # '\x0e- (\x0fD\x0e)\x0fRINK\r\n\x00'
print 765 # '\x0e- \x0fSHOW \x0e(\x0fI\x0e)\x0fNVENTORY\r\n\x00'
ret
لا يزال لدينا العديد من أكواد شفرة التشغيل غير المعروفة ، على سبيل المثال ، على الرغم من أننا اكتشفنا أن "qa" عبارة عن تفرع مشروط على الصفر (فرع على صفر ، brz) ، لم نتمكن من فهم معنى كلمة "qc" (المشار إليها أعلاه على أنها ر <c>). لكن ذلك كان كافيا للبدء في فهم منطق البرنامج.
في الواقع ، تسمح اللعبة للاعب بالتحرك حول خريطة 8 × 8 التي يتم فيها وضع NPCs (التنين ، الثيران الحمراء ، والبشر) بشكل عشوائي. يمكنك القتال مع أي NPC (حتى Valis ، على الرغم من عدم وجود عنصر قائمة المقابلة). أثناء المعركة ، يمكنك مهاجمة العدو ، مما يتسبب في حدوث ضرر عشوائي أو ضياع ، وبعد ذلك يهاجم العدو اللاعب ، مما يتسبب أيضًا في قدر عشوائي من الضرر أو الخسارة. يمكنك أيضا اختيار قفل الدرع ، وذلك بفضل أن العدو يفوت أو يضرب الدرع دون التسبب في أضرار. أخيرًا ، يمكنك الغش من خلال رفع صحتك إلى 1000 ، ولكن في هذه الحالة ، يتم تعيين المتغير المخفي ("خدع" ، العنوان 10) إلى 1. إذا قتل اللاعب العدو بنجاح ، يسقط كائن منه ، وعادة ما يكون زجاجة من الكحول (من الواضح ، هذه اللعبة ليست للأطفال).
يحتوي NPC Valis الرئيسي ، الذي يجب على اللاعب من خلاله استلام العلم ، على جهاز حكومي يسأل فيه اللاعب عن عدة عناصر - مجموعة من مشروبات الثور الأحمر (التي تم الحصول عليها بوضوح عند هزيمة أعداء الثور الأحمر) ، ومشروبات مختلطة متعددة (مثل الجن والتونيك) للحصول عليها ، تحتاج إلى هزيمة التنين الأزرق والتنين الرمادي ، ثم مزج الكائنات التي تم إسقاطها منها ، وقطاع الطاقة ، والذي يمكن الحصول عليه إذا هزمت شخصًا آخر من NPC في اللعبة (Redford) أو ساعدته. إذا استوفيت كل هذه السلسلة الطويلة من الطلبات ، فسوف يعطيك العلم ، ولكن
فقط إذا كان المتغير "خدع" لا يساوي 1. وهذا هو ، مهمتنا هي الفوز في اللعبة دون الغش. نظرًا لأننا نبدأ بـ 100 حصان فقط ، مثل كل الأعداء ، فمع مرور الوقت سيكون من المستحيل هزيمة جميع الأعداء (للحصول على جميع الأشياء الضرورية التي تحتاجها لهزيمة حوالي 20 معارضًا). من الضروري تعديل RNG بطريقة ما ، حتى لا يفوت العدو دائمًا.
يتم إنشاء أرقام عشوائية بواسطة دالة تشبه نوعًا ما من PRNG (العنوان 37 أ) ، لكنها تستخدم إرشادات فريدة لا تُستخدم في أي مكان آخر ، لذلك لا يمكننا عكس ذلك. ومع ذلك ، لاحظنا أنه يقوم بتحميل متجه الحالة الخاص به من ثلاثة عناوين في الذاكرة ([11] و [12] و [13]) ، أي أن حالته الكاملة لا تستغرق سوى 15 بت. هذا يعني أن RNG يجب أن يكون لها فترة قصيرة - لا يزيد طولها عن 2 ^ 15 = 32768.
بينما حاولنا (دون جدوى) عكس تطبيق RNG ، قام جاي بوساميا (@ jay_f0xtr0t) وماثيو سافاج (thebluepichu) بتنفيذ استغلال. ببساطة عن طريق إرسال أمر "الدرع" 100000 مرة على التوالي ، تمكنا من الحصول على سلسلة من "الزيارات" العدو و "يخطئ" المقابلة لإخراج بت من RNG. لقد تأكدنا من أن هذا التسلسل يتكرر مع فترة 32767. وبفضل هذا ، تمكنا من تجميع استغلالنا الرئيسي - عندما قاتلنا مع العدو الأول الذي قابلناه ، أغلقنا دروعنا 40 مرة لإعادة إنشاء سلسلة الضربات والمخططات ، وبحثنا عن هذا التسلسل في تسلسل دوري كبير ، ثم اكتشفنا متى يجب درع ومتى يهاجم العدو حتى يخطئ دائمًا. ثم ذهبنا للتو في جميع أنحاء الخريطة في وضع
killhobo ، وقتل الجميع وجمع نهبهم. في النهاية ، عدنا إلى فاليس وطلبنا بأدب علمنا ، الذي تلقيناه:
DrgnS{m4kin9-v4lis-happy-w1th-n4t1ve-b4ud0t-cpu}
تفو! في الواقع ، مغامرة حقيقية. ما زلت لا أؤمن تمامًا بأننا أتينا من سلسلة ثنائية ونقص تام في الوثائق الموجودة على المعالج إلى مفكرين شبه كاملين وكود نظيف مفكك في أقل من 10 ساعات! كل الشفرة متاحة على GitHub:
مفكِّك الخاص بي ،
مفكّك Zachary ،
الكود الخام المفكَّك ،
الكود المشروح المُفكَّك ،
عميل Matt's Exploit .