AIS3 Pre-Exam 2023

AIS3 Pre-Exam 2023

tags: CTF EOF2023

:::spoiler TOC [TOC] :::

Web

E-Portfolio baby

Recon

直接用Burp Suite可以繞過reCAPTCHA,而且About Guest的內容會被完整的render出來達到XSS

Login Panel

Recon

Reverse

Pwn

Simply Pwn

Recon

  1. checksec
     $ checksec pwn
     [*] Checking for new versions of pwntools
         To disable this functionality, set the contents of /home/sbk6401/.cache/.pwntools-cache-3.7/update to 'never' (old way).
         Or add the following lines to ~/.pwn.conf or ~/.config/pwn.conf (or /etc/pwn.conf system-wide):
             [update]
             interval=never
     [*] You have the latest version of Pwntools (4.9.0)
     [*] '/home/sbk6401/CTF/AIS3-Pre-Exam/PWN/Simply Pwn/pwn'
         Arch:     amd64-64-little
         RELRO:    Partial RELRO
         Stack:    Canary found
         NX:       NX disabled
         PIE:      No PIE (0x400000)
         RWX:      Has RWX segments
    

Misc

Welcome

縮小檔案就看的到flag了 Flag: AIS3{WELCOME-TO-2023-PRE-EXAM-&-MY-FIRST-CTF}

Robot

簡單的Script,但是題目敘述太不直覺了吧 :::spoiler Script

from pwn import *

context.arch = 'amd64'
r = remote("chals1.ais3.org", 12348)

r.recvline()
r.recvline()

for i in range(30):
    question = r.recvline().decode().strip()
    ans = eval(question)
    sleep(1)
    r.sendline(str(ans).encode())

print(r.recvline())
r.interactive()

::: Flag: AIS3{don't_eval_unknown_code_or_pipe_curl_to_sh}

Crypto

Fernet

就直接按照decrypt的流程跑一次就好了 :::spoiler Source Code

import os
import base64
from cryptography.fernet import Fernet
from Crypto.Hash import SHA256
from Crypto.Protocol.KDF import PBKDF2
from pwn import *

def decrypt(ciphertext, password, salt):
    key = PBKDF2(password.encode(), salt, 32, count=1000, hmac_hash_module=SHA256)  
    f = Fernet(base64.urlsafe_b64encode(key))  
    plaintext = f.decrypt(ciphertext)  
    return plaintext

leak_password = 'mysecretpassword'
ciphertext = 'iAkZMT9sfXIjD3yIpw0ldGdBQUFBQUJrVzAwb0pUTUdFbzJYeU0tTGQ4OUUzQXZhaU9HMmlOaC1PcnFqRUIzX0xtZXg0MTh1TXFNYjBLXzVBOVA3a0FaenZqOU1sNGhBcHR3Z21RTTdmN1dQUkcxZ1JaOGZLQ0E0WmVMSjZQTXN3Z252VWRtdXlaVW1fZ0pzV0xsaUM5VjR1ZHdj'
tmp = base64.b64decode(ciphertext)
salt = tmp[:16]
ciphertext = tmp[16:]
print(decrypt(ciphertext, leak_password, salt))

::: Flag: FLAG{W3lc0m3_t0_th3_CTF_W0rld_!!_!!!_!}

2DES

  • meet in the middle attack 這一題沒有解出來,兩個exploit source code都有點問題導致無法實踐,但邏輯應該是對的 :::spoiler JS Source Code
      const crypto = require('crypto')
      const assert = require('assert')
    
    
      const hint_pt = Buffer.from('AIS3{??????????}', 'utf8')
      let hint = '118cd68957ac93b269335416afda70e6d79ad65a09b0c0c6c50917e0cee18c93'
      const iv = Buffer.concat([Buffer.from('AIS3 三')])
      console.log(iv)
    
      function encrypt(msg, key, iv) {
          const cipher = crypto.createCipheriv('des-cbc', key, iv)
          let encrypted = cipher.update(msg)
          encrypted = Buffer.concat([encrypted, cipher.final()])
          return encrypted
      }
    
      function decrypt(msg, key, iv) {
          const decipher = crypto.createDecipheriv('des-cbc', key, iv)
          let decrypted = decipher.update(msg, 'nyan~')
          decrypted = Buffer.concat([decrypted, decipher.final()])
          return decrypted
      }
    
      function intToHexStr(num) {
          var hexString = '';
          for (var i = 0; i < 8; i++) {
            var byte = num & 0xff; // 获取低8位
            var hex = byte.toString(16).padStart(2, '0'); // 转换为两位的十六进制字符串
            hexString = hex + hexString; // 将转换后的字符串拼接到结果中
            num = num >> 8; // 右移8位,处理下一个字节
          }
          return hexString;
      }
    
      var key1_table = []
      var key2_table = []
      var key1 = key2 = Buffer.from(intToHexStr(256), 'hex')
    
      for (let idx = 0; idx < 2**32; idx++)
      {
          tmp = encrypt(hint_pt, key1, iv)
          key1_table.push(tmp)
          key2_table.push(decrypt(hint, key2, iv))
    
          var key1 = key2 = Buffer.from(intToHexStr(idx + 1), 'hex')
      }
    
      for (let i = 0; i < 2**32; i++)
      {
          for (let j = 0; j < 2**32; j++)
          {
              if (key1_table[i] == key2_table[j])
              {
                  console.log("key1 = ", i, "\nkey2 = ", j)
                  break
              }
          }
      }
    

    :::

    :::spoiler Python Source Code

      # from Crypto.Cipher import DES
      from tqdm import trange
      from pyDes import des, CBC, PAD_PKCS5
    
    
      hint_pt = 'AIS3{??????????}'
      hint = '118cd68957ac93b269335416afda70e6d79ad65a09b0c0c6c50917e0cee18c93'
      iv = b'4149533320e4b889'
      key1_table = []
      key2_table = []
    
      def encrypt(m, key, iv):
          # des = DES.new(key, DES.MODE_CBC, iv)
          k = des("0" * 8, CBC, "0"*8, pad=None, padmode=PAD_PKCS5)
          k.setKey(key)
          k.setIV(iv)
          return k.encrypt(m, padmode=PAD_PKCS5)
    
      def decrypt(c, key, iv):
          # des = DES.new(key, DES.MODE_CBC, iv)
          k = des("0" * 8, CBC, "0"*8, pad=None, padmode=PAD_PKCS5)
          k.setKey(key)
          k.setIV(iv)
          return k.decrypt(c, padmode=PAD_PKCS5)
    
      key1 = key2 = '{0:0>16x}'.format(0).encode()
      for idx in range(2**32):
          key1_table.append(encrypt(hint_pt, key1, iv))
          key2_table.append(decrypt(hint, key2, iv))
    
          key1 = key2 = '{0:0>16x}'.format(idx + 1).encode()
    
      for i in range(len(key1)):
          for j in range(len(key2_table)):
              if key1_table[i] == key2_table[j]:
                  print("key1 = {}\nkey2 = {}".format(i, j))
    
    

    :::