# NKCTF-2024 Writeup

# 前言

还是太菜了,re 磨磨蹭蹭就做出来两题 qwq,安卓那题不知道为什么 blutter 编译老是报错,无奈放弃,这里就简单放一下个人题解了

# Reverse[2/4]

# login_system

z3 解一下,得到 username

from z3 import *
s = Solver()
a1 = [Int('a1_%d' % i) for i in range(16)]
s.add(a1[2] + a1[1] + a1[0] + a1[3] == 447)
s.add(101 * a1[2] + a1[0] + 9 * a1[1] + 8 * a1[3] == 12265)
s.add(5 * a1[2] + 3 * a1[0] + 4 * a1[1] + 6 * a1[3] == 2000)
s.add(88 * a1[2] + 12 * a1[0] + 11 * a1[1] + 87 * a1[3] == 21475)
s.add(a1[6] + 59 * a1[5] + 100 * a1[4] + a1[7] == 7896)
s.add(443 * a1[4] + 200 * a1[5] + 10 * a1[6] + 16 * a1[7] == 33774)
s.add(556 * a1[5] + 333 * a1[4] + 8 * a1[6] + 7 * a1[7] == 44758)
s.add(a1[6] + a1[5] + 202 * a1[4] + a1[7] == 9950)
s.add(78 * a1[10] + 35 * a1[9] + 23 * a1[8] + 89 * a1[11] == 24052)
s.add(78 * a1[8] + 59 * a1[9] + 15 * a1[10] + 91 * a1[11] == 25209)
s.add(111 * a1[10] + 654 * a1[9] + 123 * a1[8] + 222 * a1[11] == 113427)
s.add(6 * a1[9] + 72 * a1[8] + 5 * a1[10] + 444 * a1[11] == 54166)
s.add(56 * a1[14] + 35 * a1[12] + 6 * a1[13] + 121 * a1[15] == 11130)
s.add(169 * a1[14] + 158 * a1[13] + 98 * a1[12] + 124 * a1[15] == 27382)
s.add(147 * a1[13] + 65 * a1[12] + 131 * a1[14] + 129 * a1[15] == 23564)
s.add(137 * a1[14] + 132 * a1[13] + 620 * a1[12] + 135 * a1[15] == 51206)
      
if s.check() == sat:
    model = s.model()
    for i in range(16):
        print(chr(model[a1[i]].as_long()), end="")
else:
    print("No solution found")
    
# user01_nkctf2024

password 前一半

enc = "~Znw:y5v|"
for i in range(len(enc)):
    print(chr((ord(enc[i]) - 9 + i) ^ i), end="")
# uSer1p4ss

剩下一半分析一下可以发现是魔改 AES,修改了 s_box,找个脚本推导一下逆盒然后解密就行了,key 就是 username

s_box = [0x31, 0x52, 0x5A, 0xC8, 0x0B, 0xAC, 0xF3, 0x3A,
         0x8B, 0x54, 0x27, 0x9B, 0xAB, 0x95, 0xDE, 0x83,
         0x60, 0xCB, 0x53, 0x7F, 0xC4, 0xE3, 0x0A, 0x97,
         0xE0, 0x29, 0xD5, 0x68, 0xC5, 0xDF, 0xF4, 0x7B, 
         0xAA, 0xD6, 0x42, 0x78, 0x6C, 0xE9, 0x70, 0x17,
         0xD7, 0x37, 0x24, 0x49, 0x75, 0xA9, 0x89, 0x67,
         0x03, 0xFA, 0xD9, 0x91, 0xB4, 0x5B, 0xC2, 0x4E, 
         0x92, 0xFC, 0x46, 0xB1, 0x73, 0x08, 0xC7, 0x74, 
         0x09, 0xAF, 0xEC, 0xF5, 0x4D, 0x2D, 0xEA, 0xA5, 
         0xDA, 0xEF, 0xA6, 0x2B, 0x7E, 0x0C, 0x8F, 0xB0, 
         0x04, 0x06, 0x62, 0x84, 0x15, 0x8E, 0x12, 0x1D, 
         0x44, 0xC0, 0xE2, 0x38, 0xD4, 0x47, 0x28, 0x45, 
         0x6E, 0x9D, 0x63, 0xCF, 0xE6, 0x8C, 0x18, 0x82, 
         0x1B, 0x2C, 0xEE, 0x87, 0x94, 0x10, 0xC1, 0x20,
         0x07, 0x4A, 0xA4, 0xEB, 0x77, 0xBC, 0xD3, 0xE1, 
         0x66, 0x2A, 0x6B, 0xE7, 0x79, 0xCC, 0x86, 0x16,
         0xD0, 0xD1, 0x19, 0x55, 0x3C, 0x9F, 0xFB, 0x30, 
         0x98, 0xBD, 0xB8, 0xF1, 0x9E, 0x61, 0xCD, 0x90, 
         0xCE, 0x7C, 0x8D, 0x57, 0xAE, 0x6A, 0xB3, 0x3D, 
         0x76, 0xA7, 0x71, 0x88, 0xA2, 0xBA, 0x4F, 0x3E, 
         0x40, 0x64, 0x0F, 0x48, 0x21, 0x35, 0x36, 0x2F, 
         0xE8, 0x14, 0x5D, 0x51, 0xD8, 0xB5, 0xFE, 0xD2, 
         0x96, 0x93, 0xA1, 0xB6, 0x43, 0x0D, 0x4C, 0x80, 
         0xC9, 0xFF, 0xA3, 0xDD, 0x72, 0x05, 0x59, 0xBF, 
         0x0E, 0x26, 0x34, 0x1F, 0x13, 0xE5, 0xDC, 0xF2, 
         0xC6, 0x50, 0x1E, 0xE4, 0x85, 0xB7, 0x39, 0x8A, 
         0xCA, 0xED, 0x9C, 0xBB, 0x56, 0x23, 0x1A, 0xF0, 
         0x32, 0x58, 0xB2, 0x65, 0x33, 0x6F, 0x41, 0xBE, 
         0x3F, 0x6D, 0x11, 0x00, 0xAD, 0x5F, 0xC3, 0x81, 
         0x25, 0xA8, 0xA0, 0x9A, 0xF6, 0xF7, 0x5E, 0x99, 
         0x22, 0x2E, 0x4B, 0xF9, 0x3B, 0x02, 0x7A, 0xB9, 
         0x5C, 0x69, 0xF8, 0x1C, 0xDB, 0x01, 0x7D, 0xFD]
new_contrary_sbox = [0]*256
for i in range(256):
    line = (s_box[i] & 0xf0) >> 4
    rol = s_box[i] & 0xf
    new_contrary_sbox[(line * 16) + rol] = i
# 偷懒拿 AI 写的转换输出 (
def convert_to_hex_matrix(numbers):
    hex_matrix = []
    for i in range(0, len(numbers), 16):
        row = numbers[i:i+16]
        hex_row = ["0x" + hex(num)[2:].rjust(2, '0') for num in row]
        hex_matrix.append(hex_row)
    return hex_matrix
def print_hex_matrix(matrix):
    for row in matrix:
        print(", ".join(row))
        
print_hex_matrix(convert_to_hex_matrix(new_contrary_sbox))
# inv_s_box
# 0xe3, 0xfd, 0xf5, 0x30, 0x50, 0xbd, 0x51, 0x70, 0x3d, 0x40, 0x16, 0x04, 0x4d, 0xb5, 0xc0, 0xa2
# 0x6d, 0xe2, 0x56, 0xc4, 0xa9, 0x54, 0x7f, 0x27, 0x66, 0x82, 0xd6, 0x68, 0xfb, 0x57, 0xca, 0xc3
# 0x6f, 0xa4, 0xf0, 0xd5, 0x2a, 0xe8, 0xc1, 0x0a, 0x5e, 0x19, 0x79, 0x4b, 0x69, 0x45, 0xf1, 0xa7
# 0x87, 0x00, 0xd8, 0xdc, 0xc2, 0xa5, 0xa6, 0x29, 0x5b, 0xce, 0x07, 0xf4, 0x84, 0x97, 0x9f, 0xe0
# 0xa0, 0xde, 0x22, 0xb4, 0x58, 0x5f, 0x3a, 0x5d, 0xa3, 0x2b, 0x71, 0xf2, 0xb6, 0x44, 0x37, 0x9e
# 0xc9, 0xab, 0x01, 0x12, 0x09, 0x83, 0xd4, 0x93, 0xd9, 0xbe, 0x02, 0x35, 0xf8, 0xaa, 0xee, 0xe5
# 0x10, 0x8d, 0x52, 0x62, 0xa1, 0xdb, 0x78, 0x2f, 0x1b, 0xf9, 0x95, 0x7a, 0x24, 0xe1, 0x60, 0xdd
# 0x26, 0x9a, 0xbc, 0x3c, 0x3f, 0x2c, 0x98, 0x74, 0x23, 0x7c, 0xf6, 0x1f, 0x91, 0xfe, 0x4c, 0x13
# 0xb7, 0xe7, 0x67, 0x0f, 0x53, 0xcc, 0x7e, 0x6b, 0x9b, 0x2e, 0xcf, 0x08, 0x65, 0x92, 0x55, 0x4e
# 0x8f, 0x33, 0x38, 0xb1, 0x6c, 0x0d, 0xb0, 0x17, 0x88, 0xef, 0xeb, 0x0b, 0xd2, 0x61, 0x8c, 0x85
# 0xea, 0xb2, 0x9c, 0xba, 0x72, 0x47, 0x4a, 0x99, 0xe9, 0x2d, 0x20, 0x0c, 0x05, 0xe4, 0x94, 0x41
# 0x4f, 0x3b, 0xda, 0x96, 0x34, 0xad, 0xb3, 0xcd, 0x8a, 0xf7, 0x9d, 0xd3, 0x75, 0x89, 0xdf, 0xbf
# 0x59, 0x6e, 0x36, 0xe6, 0x14, 0x1c, 0xc8, 0x3e, 0x03, 0xb8, 0xd0, 0x11, 0x7d, 0x8e, 0x90, 0x63
# 0x80, 0x81, 0xaf, 0x76, 0x5c, 0x1a, 0x21, 0x28, 0xac, 0x32, 0x48, 0xfc, 0xc6, 0xbb, 0x0e, 0x1d
# 0x18, 0x77, 0x5a, 0x15, 0xcb, 0xc5, 0x64, 0x7b, 0xa8, 0x25, 0x46, 0x73, 0x42, 0xd1, 0x6a, 0x49
# 0xd7, 0x8b, 0xc7, 0x06, 0x1e, 0x43, 0xec, 0xed, 0xfa, 0xf3, 0x31, 0x86, 0x39, 0xff, 0xae, 0xb9

最后解得后半部分是 9ee779cd2abcde48,中间有一个 _,整合一下 flag 就是

MKCTF{md5(user01_nkctf2024uSer1p4ss_9ee779cd2abcde48)}

# REEZ

外面一层 ollvm 的壳,d810 去一下混淆,分析一下可以看出来是 rc4 解密了一个 elf 文件然后调用
img.png
分析一下解出来的一坨
img.png
好吧,原谅我太菜了,分析不了一点,看了一下逻辑应该可以直接上 angr

import angr
import sys
def main():
  path_to_binary = "outputfile"
  project = angr.Project(path_to_binary)
  initial_state = project.factory.entry_state(
    add_options = { angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY,
                    angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS}
  )
  simulation = project.factory.simgr(initial_state)
  def is_successful(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return stdout_output == b"D0_y0u_Like_What_You_See?\nWhat can I say? You are so great!"  # :boolean
  def should_abort(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return stdout_output == b"You are wrong!" 
  simulation.explore(find=is_successful, avoid=should_abort)
  if simulation.found:
    solution_state = simulation.found[0]
    print(solution_state.posix.dumps(sys.stdin.fileno()).decode())
  else:
    raise Exception('Could not find the solution')
if __name__ == '__main__':
  main()

解得 NKCTF{THut_1Ss_s@_eAsyhh}

# Forensics[1/3]

# cain_is_hacker

filescan 一下,搜 zip 发现了个 h4re.zip ,分析里面的 importfile 发现是 encfs

importfile 是 .encfs6.xml ,但是缺个 password,后面在一个 rtf 里发现有 base 字符串

6GMtDa2H7uy7mLLi75A9QqfwbwUSVGKDQW1ot41U1ptKr5MCoXscSRDWb9nSQZUYefiMWH99Xu7zaXejrp3A9fUdx5VWRjpypcUhCEgh3zgbsRmvWJjEnRMfosBxxwbXLc

base58 解得 key: welcome_to_NkCTF_and_this_is_the_enkey

github 上下个 EncFSMP,然后挂载
img.png

在里面发现个 ez.xslx,有宏代码

Function Base64Decode(ByVal base64String As String) As String
    Dim base64Decoded As Object
    Dim base64 As Object
    Set base64 = CreateObject("MSXML2.DOMDocument")
    Set base64Decoded = CreateObject("MSXML2.DOMDocument")
    
    If Not base64 Is Nothing And Not base64Decoded Is Nothing Then
        base64.DataType = "bin.base64"
        base64Decoded.DataType = "bin.base64"
        
        base64Decoded.LoadXML base64String
        Base64Decode = base64Decoded.NodeTypedValue
    Else
        Base64Decode = ""
    End If
End Function
Sub DecodeBase64()
    Dim base64String As String
    Dim decodedString As String
    
    base64String = "Q0IgRkMgM0IgRDUgM0QgRTkgQ0IgMjkgQzQgMTAgQ0EgM0QgOUQgREIgRjEgQTQNCkJEIEY4IDUzIDQyIDgwIERDIDkzIDUwIDA0IEM1IDhGIDA5IEREIEJFIDc0IEMzDQo5QiAzNCA0QyA3MSAwMyAwRiBBNCBFNCBGQSBFOCAwNiA5OCA2NCBGMSAxNSBDOA0KMTcgOTIgRTkgOEUgQjggM0EgQzcgQjMgRTIgRjAgMUIgQTUgNjggMzQgQzkgM0MNCjA3IDQ2IDYwIEZBIDc1IEZCIDFBIDBDIDUwIDNDIEU5IEFFIEEzIDdGIDlEIERFDQowQiBERiBBOCAzQyA4NyBEMSBGNiA5QyA0OSA3RCBGRiBBQyBCQSBFRiBFNiAzMQ=="
    
    decodedString = Base64Decode(base64String)
End Sub

解 base 得到几行 hex

CB FC 3B D5 3D E9 CB 29 C4 10 CA 3D 9D DB F1 A4
BD F8 53 42 80 DC 93 50 04 C5 8F 09 DD BE 74 C3
9B 34 4C 71 03 0F A4 E4 FA E8 06 98 64 F1 15 C8
17 92 E9 8E B8 3A C7 B3 E2 F0 1B A5 68 34 C9 3C
07 46 60 FA 75 FB 1A 0C 50 3C E9 AE A3 7F 9D DE
0B DF A8 3C 87 D1 F6 9C 49 7D FF AC BA EF E6 31

乍一看确实没看出来什么,但是前面在 Temp 目录下发现了一个 hidden-tear.exe,虽然是残缺的,不过在 github 上可以搜到,是一个开源的勒索软件

甚至解密器都给了,但是我们还缺个 key,后面在 Documents 目录下发现个奇妙文件,一番” 琢磨” 后得到了 key 是 nT0XoHBA2!Uc?
img.png
最后把解密器的代码抄过来,解一下就好了

using System;
using System.Security.Cryptography;
using System.Text;
public class Program
{
    public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
    {
        byte[] decryptedBytes = null;
        // Set your salt here, change it to meet your flavor:
        // The salt bytes must be at least 8 bytes.
        byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        using (MemoryStream ms = new MemoryStream())
        {
            using (RijndaelManaged AES = new RijndaelManaged())
            {
                AES.KeySize = 256;
                AES.BlockSize = 128;
                var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);
                AES.Mode = CipherMode.CBC;
                using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                    cs.Close();
                }
                decryptedBytes = ms.ToArray();
            }
        }
        return decryptedBytes;
    }
    public static void DecryptFile(string file, string password)
    {
        byte[] bytesToBeDecrypted = File.ReadAllBytes(file);
        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
        passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
        byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);
        File.WriteAllBytes(file, bytesDecrypted);
        string extension = System.IO.Path.GetExtension(file);
        string result = file.Substring(0, file.Length - extension.Length);
        System.IO.File.Move(file, result);
    }
    public static void Main(string[] args)
    {
        DecryptFile("encrypt.dat", "nT0*Xo*HBA2!Uc?");
    }
}

NKCTF{C0ngr@tu1atiOns_On_coMpleting_t3e_Fo3eNs1cs_Ch41lenge_I_wi1l_giv4_y0u_A_cain!!!!}