Geo-chat, bot berbahaya dan steganografi: memperkaya pengetahuan tentang Telegram


Apa yang Anda ketahui tentang telegram di Telegram? Dan bisakah Anda membedakan steganografi di VideoNote (populer - round-robin)? Kami menganalisis tugas NeoQUEST-2020 , yang menyebabkan sebagian besar pertanyaan dan seruan mendukung kami! Spoiler: ya, dan akan ada sedikit crypto di sini :)

Dalam legenda NeoQUEST-2020 , kami menemukan tautan ke profil robot bepergian di Instagram. Tidak ada yang luar biasa, bukan? Jadi kami memutuskan juga, tapi kami masih harus menyelesaikan masalah, jadi kami dengan hati-hati mempertimbangkan semua gambar di profil dan mencari setidaknya beberapa petunjuk. Sedikit meditasi pada gambar indah Danau Baikal, dan kita sampai pada kesadaran bahwa petunjuknya ada di pos terakhir:


Berkat gambarnya, kami memahami bahwa kami perlu menghubungkan entahal Baikal (Shaman Rock) dan Telegram (“Anda dapat bergabung dengan saya ...” - apakah itu tidak mengingatkan apa-apa?). Pada awalnya, kami memutuskan untuk tidak memberikan petunjuk langsung kepada geo-chat (yang persis seperti itu!), Dan banyak dari mereka berhasil mengatasi tugas menggunakan emulator atau perangkat seluler dengan kemampuan untuk mengubah lokasi geografis. Shamanim Kami menetapkan koordinat (53.20074, 107.349426) (Anda dapat dengan mata) di bidang batu Shamanka dan bersiap-siap untuk hal yang paling sulit - menunggu. Telegram anehnya bekerja dengan penentuan posisi geografis dan menarik kontak dan obrolan yang relevan selama satu jam. Atas ketekunan dan kesabaran kami, kami sepenuhnya dihargai - obrolan yang diinginkan muncul di bagian Kontak -> Temukan orang di sekitar -> Grup terdekat.


Voila, kita dalam bisnis!


Bot menemui kita dengan tugas dalam bentuk file some.bytes dengan konten yang tidak dikenal, di mana kita dapat membaca baris “Decrypt me” dan “Apocalypse Spares Nobody”.

Kami memahami baris pertama tanpa masalah, tetapi apa artinya yang kedua? .. Di sini, para peserta dibagi menjadi dua kubu: beberapa menulis kepada kami melalui surat, karena mereka menemui jalan buntu, sementara yang lain dengan hati-hati melihat frasa "Apocalypse Spares Nobody" dan mengetahui bahwa ? Baik! Format ASN.1 lama yang baik (di sini kita sudah menulis tentang cara menguraikannya).


Mari kita perbaiki. Di dalamnya ada 2 struktur. Dalam satu, kami menemukan satu set byte yang ditandai "Dekripsi saya", dari mana kami menganggap bahwa ini adalah ciphertext. Dalam struktur kedua, kita melihat dua angka. Tidak mungkin bahwa ini adalah kunci yang diberikan dengan murah hati oleh peserta bersama dengan ciphertext, yang berarti sangat mungkin. Kami berurusan dengan kunci publik. Semua informasi yang dikumpulkan membawa kita pada kesimpulan yang jelas - mengapa tidak mencoba RSA ?

Jadi, kami memiliki modul dan indikator terbuka, yang, omong-omong, cukup besar. Setelah studi kejang RSA untuk beberapa pemikiran, kami menyimpulkan bahwa indikator tertutup kecil, yang berarti apa? Bingo! Kami pasti bisa bermain penjahat dan menggunakan serangan Wiener .

Kami memikirkannya bahkan untuk mereka yang tidak menyukai kriptografi - Anda dapat menggunakan versi serangan yang sudah jadi, misalnya, ini .

Kemudian kita mendapatkan nilai sosok yang tertutup d=40553818206320299896275948250950248823966726834704013657854904761789429403771dan ciphertext mendekripsi: key=nq2020faAeFeGUCBjYf7UDrH9FapFCdFPa4u;pass=passCxws3jzYhp0HD5Fy84.

Kami mendapatkan kunci "nq2020faAeFeGUCBjYf7UDrH9FapFCdFPa4u" ke bagian pertama dari pekerjaan dan kata sandi "passCxws3jzYhp0HD5Fy84", yang Anda butuhkan untuk memberi makan perwakilan bot. Ini dapat ditemukan di antara peserta obrolan dengan nama @neoquestbot.

Berada di gelombang positif dari menerima kunci pertama, kami tidak segera menyadari bahwa bot itu pilih-pilih dalam komunikasi dan sepanjang waktu mengatakan bahwa itu tidak melihat lawan bicara:


Tetapi bot dengan senang hati menerima pesan putaran VideoNote dan bahkan menjawabnya ... dalam bentuk putaran yang sama:


Tampaknya video dan suaranya sama, tetapi ini hanya sekilas. Bagaimana jika bot kami memberi kami beberapa tanda rahasia? Untuk mengetahuinya, kami akan menyimpan dan membandingkan video asli dengan respons bot. Untuk ini dan untuk langkah selanjutnya, paket FFmpeg sangat cocok untuk kami . Jadi, mari kita lihat apa yang ada di sana:



Format aac -> flac, frekuensi 44100 Hz -> 98000 Hz. Mereka tahu, kami terus bekerja lebih jauh dengan audio.

Dengan gerakan tangan yang cekatan kami menariknya keluar dari video:


Hal yang sama dapat dilakukan dengan pesan asli kami, sehingga kami dapat membandingkannya nanti. Untuk kejelasan, buka kedua trek di Audacity .


Lompatan amplitudo dalam respons audio bot segera menarik perhatian Anda (terutama aneh jika kami diam sama sekali). Pada pemeriksaan lebih dekat, kami mencatat batas interval yang jelas selama pergantian "gelombang-keheningan":


Kami menyarankan untuk mengesampingkan semua hal dan menghitung sedikit. Kami menganalisis dengan fragmen:

0 - 0,005 - diam
0,005 - 0,01 - gelombang
0, 01 - 0,0225 - diam
0,025 - 0,04 - gelombang
0,04 - 0,045 - diam

Interval terkecil adalah 0,005, dan yang lainnya interval adalah kelipatan 0,005.
Kami mengambil kehadiran gelombang 0,005 untuk 1, dan diam untuk 0. Kami mendapatkan tidak lebih dari kode biner!
Kami ingat bahwa frekuensinya telah berubah, dan mencoba melihat grafik spektrum (Analisis -> Grafik spektrum):


Kita melihat bahwa sinyal yang paling kuat adalah pada frekuensi ~ 44100 Hz, yaitu ultrasound.
Jadi, maka Anda harus bekerja hanya dengan frekuensi tinggi.

Faktanya, bot menempatkan sinyal pada audio asli dalam spektrum yang dapat didengar. Dan para peserta yang memiliki suara dalam video asli memperhatikan ini di Audacity.

Kami memotong frekuensi tinggi dengan filter high-pass baik di Audacity, atau di ffmpeg yang sama:


Jadi, kami memiliki file mono wav 16-bit. Terdiri dari header, stream audio yang tidak terkompresi, dan metadata. Aliran audio itu sendiri dibagi menjadi bingkai (dan bingkai dapat menyimpan beberapa sampel, tetapi ini adalah cerita yang sama sekali berbeda), dalam kasus kami masing-masing 16 bit (ini ditunjukkan oleh huruf pcm_s16 di tangkapan layar). Frame adalah urutan bit yang menggambarkan amplitudo gelombang pada satu waktu untuk satu saluran atau lebih (dalam kasus kami, untuk satu). Frekuensi pengambilan sampel dari aliran audio adalah 98000 frame (yaitu, 98000 frame per satu detik), 490 frame per 0,005 interval kedua.

Oleh karena itu, selanjutnya kami bekerja sesuai dengan algoritma sederhana: kami membaca 490 frame, menentukan apakah itu gelombang atau keheningan, dan, tergantung pada ini, atur bit ke 0 atau 1. Kami akan

menggunakan python dan paketwave untuk parsing file wav.
Jika kesalahan "wave.Error: format tidak diketahui: 65534" terjadi saat membuka file, lalu ganti "wFormatTag" di header dari 'FE FF' ke '01 00 ':

fh = open(input_file, "r+b")
fh.seek(20)
fh.write(b'\x01\x00')
fh.close()

Jadi, buka file, proses 490 frame dan hitung nilai rata-rata:

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)

Ada kemungkinan bahwa di mana harus ada keheningan (bandingkan dengan gambar di Audacity), noise mungkin tetap ada. Oleh karena itu, kami menetapkan ambang batas (biarlah 16000), setelah melebihi yang kami anggap sebagai sinyal 1.

Kemudian kami mengelompokkan bit menjadi byte:

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')) 

Jika semuanya dilakukan dengan benar, hasilnya adalah string “Givemethepassword”. Karena bot berkomunikasi dalam lingkaran menggunakan steganografi, masuk akal untuk memasukkan kata sandi (dan kami menerimanya bersama dengan kunci sebagai hasil dekripsi) dalam format yang sama.

Untuk memulai, buat lagu audio dengan kata sandi. Untuk melakukan ini, kami menggunakan data yang diperoleh selama analisis pesan dari bot: frekuensi sampling 98000 Hz; durasi sinyal yang menggambarkan setiap bit adalah 5 ms; frekuensi sinyal yang sesuai dengan nilai bit "1" - seperti yang kita lihat dari grafik, 44100 Hz.

Sekarang kita perlu "membangkitkan" keheningan. Kami melakukan ini dengan menetralkan:

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

Untuk menghasilkan suara, kami akan menggunakan gelombang sinus (informasi dapat dibaca di sini ):

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

Sekarang masalahnya kecil: tetap mengubah kata sandi menjadi bit, dan kemudian menjadi suara.

Catatan: Bot menggunakan trek video input asli untuk menampilkan pesannya, seperti yang disebutkan sebelumnya. Oleh karena itu, Anda perlu menambahkan beberapa nol byte setelah kata sandi untuk menghilangkan seluruh kunci dari bot, dan bukan hanya permulaannya (panjang kuncinya adalah 36 byte).

Generasi suara
    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()


Sekarang kita akan membuat file gelombang selesai:

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()

Kami menyimpan trek kami, misalnya, di pass.wav. Sepanjang jalan, kami memeriksa dengan decoder stego kami apakah kata sandi dikenali. Jika semuanya baik-baik saja, maka kami mendapatkan video baru dengan kata sandi dari video asli my_video.mp4, menggantikan trek audio:


Sekarang kita perlu membuat VideoNote dari ini. Anda dapat mencoba mencari yang berfungsi (beberapa peserta, misalnya, menemukan @TelescopyBot), atau Anda dapat menulis bot Anda menggunakan TelegramAPI.


Bagaimanapun, teruskan ke bot kami:


Kami mendapatkan babak baru dan selamat (kami akan melakukan pekerjaan seperti itu!), Mendekodekan audio sesuai dengan skenario yang sudah berhasil, dan mendapatkan kuncinya: “nq2020SyOMK7SnnJP1sNlvbTs8zt35vUrrsD”

Memang, steganografi dianggap sebagai salah satu area yang paling sulit di sini karena tidak ada alasan untuk mencoba keamanan ini tanpa alasan! Tetapi peserta NeoQUEST menunjukkan ketangkasan yang sangat baik dan rasa humor selama tugas ini, jadi kami menyapa kekaguman tulus kami (dari bot selamat)!

All Articles