ماذا تعرف عن البرقيات في برقية؟ وهل يمكنك التمييز بين إخفاء المعلومات في VideoNote (شعبي - مستدير - روبن)؟ نحن نحلل المهمة NeoQUEST-2020 ، التي تسببت في معظم الأسئلة والتعجب لدعمنا ! المفسد: نعم ، وسيكون هناك أيضًا القليل من التشفير هنا :)في أسطورة NeoQUEST-2020 ، نجد رابطًا إلى الملف الشخصي لروبوت متنقل على Instagram. لا شيء خارج عن المألوف ، أليس كذلك؟ لذلك قررنا ذلك أيضًا ، ولكننا ما زلنا بحاجة إلى حل المشكلة ، لذلك نحن نفكر بعناية في جميع الصور في الملف الشخصي ونبحث عن بعض القرائن على الأقل. القليل من التأمل في صورة جميلة لبحيرة بايكال ، ونصل إلى إدراك أن الدليل موجود في آخر مشاركة:بفضل الصورة ، نتفهم أننا بحاجة إلى ربط بايكال (شامان روك) وتليجرام بطريقة ما ("يمكنك الانضمام إلى ..." - ألا تذكر أي شيء؟). في البداية ، قررنا عدم إعطاء المشاركين تلميحًا مباشرًا للدردشة الجغرافية (وهذا كل شيء!) ، وقد تعامل العديد منهم بنجاح مع المهمة باستخدام محاكي أو جهاز محمول مع القدرة على تغيير الموقع الجغرافي. Shamanim قمنا بتعيين الإحداثيات (53.20074 ، 107.349426) (يمكنك بالعين) في منطقة صخرة شامانكا والاستعداد لأصعب شيء - الانتظار. يعمل Telegram بشكل غريب مع تحديد الموقع الجغرافي ويسحب جهات الاتصال والدردشات ذات الصلة لمدة ساعة. بالنسبة لجهدنا وصبرنا ، فإننا نكافأ تمامًا - تظهر الدردشة المطلوبة في قسم جهات الاتصال -> البحث عن الأشخاص القريبين -> المجموعات القريبة.فويلا ، نحن في العمل!يقابلنا البوت بمهمة في شكل ملف some.bytes بمحتويات غير محددة ، حيث يمكننا قراءة السطور "فك تشفير لي" و "نهاية العالم قطع الغيار لا أحد".نحن نفهم السطر الأول دون أي مشاكل ، ولكن ماذا يعني الثاني؟ .. هنا ، انقسم المشاركون إلى معسكرين: كتب إلينا البعض عن طريق البريد ، لأنهم وصلوا إلى طريق مسدود ، بينما نظر البعض الآخر بعناية في عبارة "نهاية العالم قطع الغيار لا أحد" ووجدوا أن ؟؟؟ حق! تنسيق ASN.1 قديم جيد ( كتبنا هنا بالفعل حول كيفية تحليله).دعنا نحصل على حق. في الداخل هيكلين. في واحدة ، نجد مجموعة من وحدات البايت المميزة بعلامة "فك تشفير لي" ، والتي نفترض منها أن هذا نص مشفر. في الهيكل الثاني ، نرى رقمين. من غير المحتمل أن يكون هذا هو المفتاح الذي قدمه المشاركون بسخاء مع نص مشفر ، وهو ما يعني على الأرجح. نحن نتعامل مع مفتاح عام. جميع المعلومات التي تم جمعها تقودنا إلى استنتاج واضح - لماذا لا تجرب RSA ؟لذلك ، لدينا وحدة نمطية ومؤشر مفتوح ، بالمناسبة ، كبير جدًا. بعد دراسة متشنجة لـ RSA لبعض الفكر ، نستنتج أن المؤشر المغلق صغير ، مما يعني ماذا؟ البنغو! يمكننا بالتأكيد لعب الأشرار واستخدام هجوم Wiener .لقد فكرنا في ذلك حتى بالنسبة لأولئك الذين لا يحبون التشفير - يمكنك استخدام نسخة جاهزة من الهجوم ، على سبيل المثال ، هذا .ثم نحصل على قيمة الرقم مغلق d=40553818206320299896275948250950248823966726834704013657854904761789429403771
وفك تشفير النص المشفر: key=nq2020faAeFeGUCBjYf7UDrH9FapFCdFPa4u;pass=passCxws3jzYhp0HD5Fy84
.نحصل على المفتاح "nq2020faAeFeGUCBjYf7UDrH9FapFCdFPa4u" للجزء الأول من المهمة وكلمة المرور "passCxws3jzYhp0HD5Fy84" ، التي تحتاجها لإطعام ممثل برنامج الروبوت. يمكن العثور عليه بين المشاركين في الدردشة تحت اسمneoquestbot.كوننا على الموجة الإيجابية من تلقي المفتاح الأول ، فإننا لا ندرك على الفور أن البوت صعب الإرضاء في التواصل ويقول دائمًا أنه لا يرى المحاور:لكن البوت يتلقى بسعادة رسائل جولة VideoNote وحتى يجيبها ... في نفس شكل الجولة:يبدو أن الفيديو والصوت متشابهان ، ولكن هذا فقط للوهلة الأولى. ماذا لو أعطانا البوت بعض العلامات السرية؟ لمعرفة ذلك ، سنقوم بحفظ ومقارنة الفيديو الأصلي مع استجابة الروبوت. لهذا وللخطوات التالية ، فإن حزمة FFmpeg رائعة بالنسبة لنا . لذا ، دعنا نرى ما هو موجود:تنسيق aac -> flac ، تردد 44100 هرتز -> 98000 هرتز. اكتشفوا أننا نواصل العمل مع الصوت.بحركة بارعة للأيدي ، نخرجه من الفيديو:يمكن فعل الشيء نفسه مع رسالتنا الأصلية ، حتى نتمكن من مقارنتها لاحقًا. للتوضيح ، افتح كلا المسارين في Audacity .القفزة في السعة في الاستجابة الصوتية للبوت تجذب انتباهك على الفور (غريب بشكل خاص إذا كنا صامتين على الإطلاق). عند الفحص الدقيق ، نلاحظ الحدود الواضحة للفترات أثناء تناوب "صمت الموجة":نقترح وضع كل الأشياء جانبا والعد قليلا. نقوم بتحليل الشظايا:0 - 0.005 - الصمت0.005 - 0.01 - الموجة0 ، 01 - 0.0225 - الصمت0.025 - 0.04 - الموجة0.04 - 0.045 - الصمتأصغر فاصل 0.005 ، وجميع الآخرين الفترات هي مضاعفات 0.005.نأخذ وجود موجة 0.005 لـ 1 ، والصمت عند 0. لا نحصل على أكثر من رمز ثنائي!نذكر أن التردد قد تغير ، ونحاول إلقاء نظرة على الرسم البياني للطيف (التحليل -> الرسم البياني للطيف):نرى أن أقوى إشارة على تردد ~ 44100 هرتز ، وهو الموجات فوق الصوتية.لذا ، يجب أن تعمل فقط بترددات عالية.في الواقع ، يضاعف البوت إشارته على الصوت الأصلي في الطيف المسموع. وقد لاحظ هؤلاء المشاركون الذين ظهروا في الفيديو الأصلي ذلك في الجرأة.نقطع الترددات العالية باستخدام مرشح تمرير عالي إما في Audacity ، أو في نفس ffmpeg:لذلك ، لدينا ملف WAV أحادي 16 بت. يتكون من رأس ، دفق صوتي غير مضغوط ، وبيانات تعريف. ينقسم دفق الصوت نفسه إلى إطارات (ويمكن للإطارات تخزين عدة عينات ، ولكن هذه قصة مختلفة تمامًا) ، في حالتنا 16 بت لكل منها (يشار إلى ذلك بالحروف pcm_s16 في لقطات الشاشة). الإطارات هي تسلسلات من البتات التي تصف اتساع الموجة في وقت واحد لقناة أو أكثر (في حالتنا ، لقناة واحدة). تردد أخذ العينات لدفق الصوت هو 98000 إطارًا (أي 98000 إطارًا لكل ثانية واحدة) ، 490 إطارًا لكل 0.005 ثانية.لذلك ، نعمل أيضًا وفقًا لخوارزمية بسيطة: نقرأ 490 إطارًا ، ونحدد ما إذا كانت موجة أم صمتًا ، واعتمادًا على ذلك ، قم بتعيين البت إلى 0 أو 1.سنستخدم python وحزمةموجة لتحليل ملفات WAV.إذا حدث الخطأ "wave.Error: unknown format: 65534" عند فتح الملف ، فاستبدل "wFormatTag" في الرأس من "FE FF" إلى "01 00":fh = open(input_file, "r+b")
fh.seek(20)
fh.write(b'\x01\x00')
fh.close()
لذا ، افتح الملف ، وقم بمعالجة 490 إطارًا واحسب متوسط القيمة:file = wave.open(input_file,"r")
for i in range (1, int(file.getnframes()/490)+1):
frames = file.readframes(490)
bit = 0
sum = 0
for k in range(0, 246):
frame_bytes = frames[k*2:k*2+2]
sum += int.from_bytes(frame_bytes, "big")
if sum/490 > 16000:
bit = 1
bits.append(bit)
من الممكن أنه عندما يكون هناك صمت (مقارنة بالصورة في الجرأة) ، فقد تبقى الضوضاء. لذلك ، قمنا بتعيين العتبة (فليكن 16000) ، وعند تجاوزها نعتبر الإشارة هي 1.ثم نجمع البتات في بايت:bytes = []
for i in range (1, int(len(bits)/8)+1):
b1 = bits[i*8-8]
b2 = bits[i*8-7]
b3 = bits[i*8-6]
b4 = bits[i*8-5]
b5 = bits[i*8-4]
b6 = bits[i*8-3]
b7 = bits[i*8-2]
b8 = bits[i*8-1]
byte = (b1 << 7) | (b2 << 6) | (b3 << 5) | (b4 << 4) | (b5 << 3) | (b6 << 2) | (b7 << 1) | b8
bytes.append(byte.to_bytes(1, byteorder='big'))
إذا كان كل شيء يتم بشكل صحيح ، فإن النتيجة هي سلسلة "Givemethepassword". نظرًا لأن البوت يتواصل في دوائر باستخدام طريقة إخفاء المعلومات ، فسيكون من المنطقي أن ننقل كلمة مرور له (وقد استلمناها مع المفتاح نتيجة فك التشفير) بنفس التنسيق.للبدء ، أنشئ مسارًا صوتيًا بكلمة مرور. للقيام بذلك ، نستخدم البيانات التي تم الحصول عليها أثناء تحليل الرسالة من البوت: تردد أخذ العينات 98000 هرتز ؛ مدة الإشارة التي تصف كل بتة 5 ms ؛ تردد الإشارة المقابل لقيمة البتات "1" - كما رأينا من الرسوم البيانية ، 44100 هرتز.الآن نحن بحاجة إلى "توليد" الصمت. نقوم بذلك عن طريق تحييد:sample_rate = 98000.0
def generate_silence(duration_milliseconds=5):
fragment = []
num_samples = duration_milliseconds * (sample_rate / 1000.0)
for x in range(int(num_samples)):
fragment.append(0.0)
return fragment
لتوليد الصوت ، سنستخدم موجة جيبية (يمكن قراءة المعلومات هنا ):def generate_sinewave(
freq=41000.0,
duration_milliseconds=5,
volume=0.5):
fragment = []
amplitude = volume * 32767.0
num_samples = duration_milliseconds * (sample_rate / 1000.0)
for x in range(int(num_samples)):
fragment.append(amplitude * math.sin(2 * math.pi * freq * ( x / sample_rate )))
return fragment
الآن الشيء صغير: يبقى تحويل كلمة المرور إلى أجزاء ، ثم إلى صوت.ملاحظة: يستخدم الروبوت مسار الفيديو الأصلي المدخل لتراكب رسالته ، كما ذكرنا سابقًا. لذلك ، تحتاج إلى إضافة عدد قليل من وحدات البايت صفر بعد كلمة المرور من أجل التخلص من المفتاح بالكامل من البوت ، وليس فقط بدايته (كان طول المفتاح 36 بايت).توليد الصوت audio = []
f = open(input_file, 'rb')
for character in f.read():
a = character
b8 = a & 0b00000001
b7 = (a & 0b00000010) >> 1
b6 = (a & 0b00000100) >> 2
b5 = (a & 0b00001000) >> 3
b4 = (a & 0b00010000) >> 4
b3 = (a & 0b00100000) >> 5
b2 = (a & 0b01000000) >> 6
b1 = (a & 0b10000000) >> 7
if b1 == 1:
audio += generate_sinewave()
else:
audio += generate_silence()
if b2 == 1:
audio += generate_sinewave()
else:
audio += generate_silence()
if b3 == 1:
audio += generate_sinewave()
else:
audio += generate_silence()
if b4 == 1:
audio += generate_sinewave()
else:
audio += generate_silence()
if b5 == 1:
audio += generate_sinewave()
else:
audio += generate_silence()
if b6 == 1:
audio += generate_sinewave()
else:
audio += generate_silence()
if b7 == 1:
audio += generate_sinewave()
else:
audio += generate_silence()
if b8 == 1:
audio += generate_sinewave()
else:
audio += generate_silence()
الآن سنقوم بإنشاء ملف الموجة النهائي:wav_file=wave.open(file_name,"w")
nchannels = 1
sampwidth = 2
nframes = len(audio)
comptype = "NONE"
compname = "not compressed"
wav_file.setparams((nchannels, sampwidth, sample_rate, nframes, comptype, compname))
for sample in audio:
wav_file.writeframes(struct.pack('h', int(sample)))
wav_file.close()
نقوم بحفظ مسارنا ، على سبيل المثال ، في pass.wav. على طول الطريق ، نتحقق من وحدة فك ترميز stego الخاصة بنا لمعرفة ما إذا كان يتم التعرف على كلمة المرور. إذا كان كل شيء على ما يرام ، فإننا نحصل على فيديو جديد بكلمة مرور من الفيديو الأصلي my_video.mp4 ، ليحل محل المسار الصوتي:الآن نحن بحاجة إلى جعل VideoNote خارج هذا. يمكنك محاولة البحث عن العاملين (على سبيل المثال ، وجد بعض المشاركينTelescopyBot) ، أو يمكنك كتابة برنامج الروبوت الخاص بك باستخدام TelegramAPI.على أي حال ، إلى الأمام لدينا الروبوت:لقد حصلنا على جولة جديدة وتهنئة (كنا سنقوم بمثل هذا العمل!) ، وقمنا بفك تشفير الصوت وفقًا للسيناريو الذي تم وضعهبالفعل ، وحصلنا على المفتاح: "nq2020SyOMK7SnnJP1sNlvbTs8zt35vUrrsD" في الواقع ، يعتبر إخفاء المعلومات أحد أصعب مجالات الأمن السيبراني دون أي سبب هنا - حاول تخمين ذلك! لكن المشاركين في NeoQUEST أظهروا براعة ممتازة وإحساسًا بالفكاهة خلال هذه المهمة ، لذلك نحن نتحدث عن إعجابنا الصادق (من تهنئة البوت)!