ctfs
  • ๐Ÿ‘‹Hello!
  • ๐ŸดPractice
    • ๐ŸŒCryptohack
      • Introduction
      • General
        • Encoding
        • XOR
        • Mathematics
        • Data Formats
      • Symmetric Ciphers
        • How AES Works
        • Symmetric Starter
        • Block Ciphers 1
        • Stream Ciphers
      • Mathematics
        • Modular Math
        • Lattices
      • RSA
        • Starter
        • Primes Part 1
        • Public Exponent
    • ๐ŸŒPortSwigger
      • Path Traversal
      • File Upload
      • SSRF Attacks
    • ๐ŸŒTryHackMe
      • Basic Skills
      • Linux
      • Penetration Testing
      • Networking
      • OSINT
  • ๐ŸšฉCompetitions
    • 2025
      • ๐Ÿ‡ฎ๐Ÿ‡ฉGKSK#9 Osintathon
        • Mudik Lebaran (100 pts)
        • Foto Patung (100 pts)
        • Kolektor Komik (100 pts)
        • Tolong Aku (100 pts)
        • Kencan Pertama (100 pts)
        • Nama Si Pelaku (100 pts)
        • Cekidot (100 pts)
        • Ledakan! (100 pts)
        • ๐ŸŽน๐ŸŽถ (100 pts)
        • Batu Besar (100 pts)
        • Komentar (100 pts)
        • Ini dimana? (100 pts)
        • Koordinat Foto Misterius (100 pts)
        • Bianglalaaa (100 pts)
        • Aku Hacker (100 pts)
        • Anjazzz (100 pts)
        • Dikirim Kakakku (129 pts)
        • Ingfo Loker (154 pts)
        • MISSING 00 (100 pts)
        • MISSING 01 (154 pts)
        • Siapa Aku? (154 pts)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉIFEST 13
        • Ququerer (250 pts)
        • Silent Trace (370 pts)
        • Nugas (Solved After Event)
        • Free Flag (280 pts)
        • Brute (Solved After Event)
        • Web V1 (Solved After Event)
        • Bypass (Solved After Event)
        • Orbiter (Solved After Event)
      • ๐ŸŒOSINT Combine (Wildlife)
        • Getting Started (100 pts)
        • Proper Poppy (100 pts)
        • Legendary Beasts (200 pts)
        • Shadow Fleet (200 pts)
        • Proper Poppy II (200 pts)
        • Not So Smug Smuggler (200 pts)
        • Icy (200 pts)
        • Forest Pals (200 pts)
        • Safari Time II (200 pts)
        • Sneaky! (200 pts)
        • Hello Friend (300 pts)
        • Busy As A (300 pts)
        • Get Rotated! (300 pts)
        • High Seas (300 pts)
        • Nocturnal (300 pts)
        • Safari Time (400 pts)
        • Peak Weather (400 pts)
        • Singsong (400 pts)
        • Falling Fell (500 pts)
        • Kitty Cats (500 pts)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉRECURSION
        • let him cook
        • Basic Math
        • Favourite Number
        • Zarrar Cipher (100 pts)
        • paBlue Team (100 pts)
        • [๐Ÿฉธ] I wish I was there on December 21, 2024 (100 pts)
        • Small House (200 pts)
        • [๐Ÿฉธ] Mission Difference (456 pts)
    • 2024
      • ๐ŸŒSanta Claus CTF
        • Complete Picture
        • Day 1 - Big Bang
        • Day 2 - The Summer Job
        • Day 3 - The Visitors
        • Day 4 - Happy Birthday
        • Day 5 - Say My Name
        • Day 6 - Say "Cheese"
        • Day 7 - Revealing Pixels
        • Day 8 - Connecting The Dots
        • Day 9 - 404 Not Found
        • Day 10 - Breaking News
        • Day 11 - Ayrton Santa
        • Day 12 - Lost and Found
        • Day 13 - Planespotting
        • Day 14 - Santa Surveillance
        • Day 15 - Shaken, Not Stirred
        • Day 16 - Status Update
        • Day 17 - Waste ...of Time
        • Day 18 - Lost in Translation
        • Day 19 - Santa's Clones
        • Day 20 - Losing Tracks
        • Day 21 - Sing my Song
        • Day 22 - Eagle Eye
        • Day 23 - Distances Matters
        • Day 24 - Mastermind
      • ๐ŸŒCyber Jawara International
        • Stone Game (100 pts)
        • prepare the tools (176 pts)
        • Persona (484 pts)
      • ๐ŸŒOSMOSIS Precon CTF
        • 1 The art of espionage
        • # 2 The Hack
        • # 3 The rabbit hole
        • # 4 The Association
        • # 6 Where is number 5
        • # 5 Who is it
        • Too many Layers
        • The prize
      • ๐Ÿ‡ฎ๐Ÿ‡ฉIntechfest
        • Sanity Check (100 pts)
        • Alin (113 pts)
        • GerakSendiri (106 pts)
        • Details (100 pts)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉCOMPFEST 16
        • Let's Help John! (100 pts)
        • money gone, wallet also gone (100 pts)
        • headโ€™s up! (493 pts)
        • CaRd (304 pts)
        • Sanity Check (100 pts)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉGemastik
        • Baby AES (451 pts)
        • Baby Structured (100 pts)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉTechnofair 11
        • Kenangan
        • Xorban
        • Marsha
        • Siap Tempur!!
        • eftipi
        • kurang berarti
        • DUMPling
        • Malicious
      • ๐ŸŒDIVER OSINT
        • chiban
      • ๐Ÿ‡ฎ๐Ÿ‡ฉGKSK#8 Osintathon
        • Sport Location
        • Meklaren lu warna apa boss ?
        • Postcode
        • Rumah Minang
        • Latihan
        • Anak Misterius
        • Travelling Anywhere
        • The Thief
        • Danger Watch
        • Misteri Ruang Angkasa
        • Fun Walk
        • I am Late
        • My Oshi
        • Wellcome to my Youtube Channel
        • Pesan Tersembunyi Wingdings
        • Salah Fokus
        • Apa itu GKSK?
        • Foto Bersejarah
        • Picture
        • Nostalgia Child
        • oldschool
        • Summer Olympic
      • ๐Ÿ‡ฎ๐Ÿ‡ฉTechcomfest
        • pemanasan
        • crackable
        • Kuli-ah forensik
    • 2023
      • ๐Ÿ‡ฎ๐Ÿ‡ฉCyber Jawara
        • daruma
      • ๐Ÿ‡ฎ๐Ÿ‡ฉNCW
        • Simple (220 pts)
        • wangsaf (320 pts)
        • Sillyville Saga (220 pts)
        • Freminhelp (Solved after event)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉHology 6
      • ๐Ÿ‡ฎ๐Ÿ‡ฉSlashRoot 7
        • Summary (441 pts)
        • eeee (480 pts)
        • Zebra Cross (409 pts)
        • Waka Waka eh eh (185 pts)
        • ANABUL (250 pts)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉCOMPFEST 15
        • not simply corrupted (316 pts)
        • Artificial secret (356 pts)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉGemastik
        • easy AES
        • k-1
        • Gen Z
      • ๐Ÿ‡ฎ๐Ÿ‡ฉTechnoFair 10
        • RSA Bwang
        • Marsah
        • rapsodi
        • Pengen Merch JKT ๐Ÿ˜ข
        • space mono
        • file pemberian fans
        • bantu aku mencari sebuah rahasia
    • 2022
      • ๐Ÿ‡ฎ๐Ÿ‡ฉNCW
        • sabeb64 (331 pts)
        • cakemath (451 pts)
        • Downloader (244 pts)
        • 199 passcode (Solved after event)
      • ๐Ÿ‡ฎ๐Ÿ‡ฉTEDCTF
      • ๐Ÿ‡ฎ๐Ÿ‡ฉGemastik
      • ๐Ÿ‡ฎ๐Ÿ‡ฉOSCCTF
      • ๐Ÿ‡ฎ๐Ÿ‡ฉARA
  • ๐ŸชฆOld Hello
Powered by GitBook
On this page
  1. Competitions
  2. 2024
  3. Technofair 11

Marsha

PreviousXorbanNextSiap Tempur!!

Last updated 11 months ago

Description

Seseorang berhasil melakukan serangan terhadap ruang chat antara marsha dan pacarnya!!!

Author: AnYujin

nc 103.185.53.181 4254

Kita diberikan sebuah service dan soal.py yang berisikan source code dari service tersebut.

Berikut adalah soal.py yang sudah saya annotate untuk menjelaskan alurnya.

from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from secret import flag
import hashlib
import os
import random
import string

charset=string.printable


class dh():
    def __init__(self,p,g):
        self.p=p
        self.g=g
        self.privatekey=random.randrange(2,p-1)
        self.pubkey=pow(g,self.privatekey,p)
        self.BLOCK_SIZE=16

    def get_pubkey(self):
        return self.pubkey

    def bytes_to_bin(self,val):
        return "{:08b}".format(bytes_to_long(val))

    def mult_mat(self,a,b,m):
        assert len(a[0]) == len(b)
        return [[sum([int(a[k][i]) * int(b[i][j]) for i in range(len(b))]) % m for j in range(len(a))] for k in range(len(a))]

    def add_mat(self,a,b,m):
        assert len(a[0]) == len(b[0]) and len(a) == len(b)
        return [[(int(a[i][j]) + int(b[i][j])) % m for j in range(len(a[0]))] for i in range(len(a))]

    def hex_to_bytes(self,msg):
        return long_to_bytes(int(msg,16))
    
    def bits_to_matrix(self,val):
        temp=[list(val[i:i+16]) for i in range(0, 256, 16)]
        return temp
    
    def matrix_to_bits(self,val):
        return ''.join(str(i) for j in val for i in j)

    def bytes_to_hex(self,msg):
        return "{0:x}".format(bytes_to_long(msg))


    def generate_secret(self,pub):
        self.sharedsecret=pow(pub,self.privatekey,self.p)
        temp=("{0:b}".format(self.sharedsecret)).rjust(768,'0')
        self.A,self.B,self.C=[temp[i:i+256] for i in range(0,768,256)]
        self.A=self.bits_to_matrix(self.A)
        self.B=self.bits_to_matrix(self.B)
        self.C=self.bits_to_matrix(self.C)

    
    def encrypt(self,msg):
        msg=pad(msg,self.BLOCK_SIZE)
        iv=os.urandom(self.BLOCK_SIZE)
        cipher=AES.new(hashlib.sha256(long_to_bytes(self.sharedsecret)).digest(),AES.MODE_CBC,iv=iv)
        ct=cipher.encrypt(msg)
        return self.bytes_to_hex(ct),self.bytes_to_hex(iv)

    def decrypt(self,enc,iv,sig):
        cipher=AES.new(hashlib.sha256(long_to_bytes(self.sharedsecret)).digest(),AES.MODE_CBC,iv=self.hex_to_bytes(iv))
        try:
            pt=unpad(cipher.decrypt(self.hex_to_bytes(enc)),self.BLOCK_SIZE)
            verif=(self.hash(pt)==sig)
            return verif,pt.decode()
        except:
            return False,''

    def hash(self,msg):
        len_msg=len(msg)
        msg=self.bytes_to_bin(msg)
        if(msg[0]=='0'):
            val=self.mult_mat(self.A,self.C,2)
        else:
            val=self.mult_mat(self.B,self.C,2)
        msg=msg[1:]
        for i in msg:
            if int(i)==0:
                val=self.mult_mat(self.mult_mat(val,self.A,2),self.C,2)
            else:
                val=self.mult_mat(self.mult_mat(val,self.B,2),self.C,2)
        val=self.add_mat(val,self.C,2)
        sig=self.matrix_to_bits(val)
        return "{:x}".format(int(sig))

    def kirim(self,msg):
        sig=self.hash(msg)
        enc,iv=self.encrypt(msg)
        return enc,iv,sig
        
if __name__=='__main__':
    p=getPrime(768)
    g=8
    print('Yujin sending modulo and base')
    print(f'Modulo  : {p}')
    print(f'g       : {g}')
    print('Able to change modulo')
    try:
        inp=input("> ")
        temp=len("{:08b}".format(int(p)))
        if(temp>=512 and temp<=768):
            pass
        else:
            print('Invalid value sending as it is')
        p=int(inp)
    except:
        pass

    # DH setup for Marsha
    B=dh(p,g)
    print("Marsha sending public key...")
    print(f"Sucessfully intercepted Marsha's public key")
    print(f"Marsha's public key : {B.get_pubkey()}")

    # DH setup for Yujin
    A=dh(p,g)

    # Yujin generate pubkey
    A.generate_secret(B.get_pubkey())
    print("Yujin sending public key...")
    print(f"Sucessfully intercepted Yujin's public key")
    print(f"Yujin's public key : {A.get_pubkey()}")

    # Marsha generate pubkey
    B.generate_secret(A.get_pubkey())

    # [ == shared secret is calculated == ]

    # Marsha send message
    enc,iv,sig=B.kirim(b"Halo, kamu apa kabar?")

    # WE intercept the message
    print(f"Successfully intercepted Marsha's message")
    print(f'enc          : {enc}')
    print(f'iv           : {iv}')
    print(f'signature    : {sig}')

    # WE tamper message, system check that the message is 
    # ...valid hex (already encrypted)
    try:
        print("Able to change Marsha's encrypted message")
        inp1=input("> ")
        enc=int(inp1,16)
        enc="{:x}".format(enc)
    except:
        print('Invalid value sending as it is')
        pass
    
    # Yujin will verify the message
    verif,pt=A.decrypt(enc,iv,sig)

    # Yujin must receive valid message
    try:
        assert all(i in charset for i in list(pt))
    except:
        print('Yujin left the chat...')
        exit()

    # to get flag, try to send something other than 
    # ..."halo kamu apa kabar"
    if(not verif):
        print('Yujin left the chat...')
    elif pt!="Halo, kamu apa kabar?":
        if verif:
            enc,iv,sig=A.kirim(flag)
            print(f"Successfully intercepted Yujin's message")
            print(f'enc          : {enc}')
            print(f'iv           : {iv}')
            print(f'signature    : {sig}')
        else:
            print('Yujin left the chat...')

    # if you just forward Marsha's message, Yujin will not give flag
    else:
        enc,iv,sig=A.kirim(b"Aku baik, bentar ya aku tidur dulu...")
        print(f"Successfully intercepted Yujin's message")
        print(f'enc          : {enc}')
        print(f'iv           : {iv}')
        print(f'signature    : {sig}')
        print(f"Yujin left the chat...")

Intinya adalah sebagai berikut:

  • Di awal, kita bisa mengubah parameter โ€œmoduloโ€ atau p dari protokol Diffie-Hellman pada komunikasi ini

  • Kedua pihak (Marsha dan Yujin) akan saling mengirimkan public key, dan menghitung shared secret

  • Dengan shared secret, Marsha mengirim pesan โ€œHalo, kamu apa kabar?โ€. Pesan ini bisa kita ganti.

  • Yujin akan membalas pesan berdasarkan pesan yang dikirimkan. Jika seperti yang di atas (tidak diubah), Yujin akan membalas dengan โ€œAku baik, bentar ya aku tidur dulu...โ€. Selain pesan di atas (kita ubah) maka Yujin akan membalas dengan flag.

  • Awalnya saya mengira bahwa signature-nya juga perlu diatur supaya pesannya verified. Rupanya, di sini kita tidak perlu memperhatikan signature karena pesan akan selalu verified, jadi cukup pesannya saja.

Jadi sudah cukup jelas bahwa tujuan kita adalah mengetahui shared secret mereka berdua supaya bisa mengganti pesan Marsha dengan pesan lain yang bisa didekripsi oleh Yujin.

Celah utama dari protokol Diffie-Hellman adalah serangan discrete log, yang disebabkan oleh pemilihan modulo atau p yang tidak kuat. Pada soal ini, p bisa kita ubah, dan saya memasukkan p yang smooth, artinya p-1 memiliki banyak faktor. Nilai p seperti ini rentan akan serangan discrete log. Berikut adalah kode solver yang saya gunakan.

from sage.all import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Util.number import *
import hashlib
from pwn import *

r = remote('103.185.53.181', 4254)

def encrypt(msg, shared_secret, iv):
	key = hashlib.sha256(long_to_bytes(shared_secret)).digest()
	cipher = AES.new(key, AES.MODE_CBC, iv)
	ciphertext = cipher.encrypt(pad(msg,16))
	return ciphertext

def decrypt(msg, shared_secret, iv):
	key = hashlib.sha256(long_to_bytes(shared_secret)).digest()
	cipher = AES.new(key, AES.MODE_CBC, iv)
	plaintext = cipher.decrypt(msg)
	plaintext = unpad(plaintext,16)
	return plaintext

# get g
r.recvuntil(b'g       : ')
g = int(r.readline()[:-1])	# g = 8

# generate smooth p
p = 2
k = 3
while (p < 2**512) or not isPrime(2*int(p) + 1):
	p *= k
	k = next_prime(k)
p = 2*p + 1

# send smooth p
r.recvuntil(b'> ')
r.sendline(str(p).encode())

# get A (Yujin's PK) and B (Marsha's PK) from service
r.recvuntil(b"Marsha's public key : ")
A = int(r.recvline()[:-1])
r.recvuntil(b"Yujin's public key : ")
B = int(r.recvline()[:-1])

# calculate shared secret
F = IntegerModRing(p)
a = discrete_log(F(A), F(g))
s = int(pow(B,a,p))

# get Marsha's message
r.recvuntil(b"enc          : ")
enc = bytes.fromhex(r.readline()[:-1].decode())
r.recvuntil(b"iv           : ")
iv = bytes.fromhex(r.readline()[:-1].decode())
marsha_msg = decrypt(enc,s,iv).decode()
print("Marsha's original message:", marsha_msg)

# send tampered message
tampered_msg = marsha_msg + 'a'		# 'a' can be replaced with anything
tampered_msg = encrypt(tampered_msg.encode(),s,iv).hex().encode()
r.recvuntil(b'> ')
r.sendline(tampered_msg)

# get Yujin's reply
r.recvuntil(b"enc          : ")
enc = bytes.fromhex(r.readline()[:-1].decode())
r.recvuntil(b"iv           : ")
iv = bytes.fromhex(r.readline()[:-1].decode())
yujin_msg = decrypt(enc,s,iv).decode()
print("Yujin's message:", yujin_msg)

Flag: TechnoFair11{4Ku_4d4lAH_R4J4_M3ks1Ko_El_M4r5hal3}

๐Ÿšฉ
๐Ÿ‡ฎ๐Ÿ‡ฉ