(没报名,赛后在NSSCTF上找到相关题目来做
CSGO
一道go语言题目,主要是base64换表加密
可以在runtime_intstring->runtime_encoderune函数里找到base64相应算法
本来想IDA动调找表的,但有反调试,于是用x64dbg+SharpOD 反反调试插件来绕过反调试找表
SharpOD 反反调试插件
先设置一下
先在IDA里找到表赋值处,然后在x64dbg里找到0x93B161地址处下断点
对比的密文
cPQebAcRp+n+ZeP+YePEWfP7bej4YefCYd/7cuP7WfcPb/URYeMRbesObi/=
接着x64dbg动调来到0x93B161地址处
反复按F9
即可大致猜出更换后的表了,就是把原本的表前11个字符放到末尾
然后base64解密即可
Blast
先放IDA看看,代码有点长,就不细看了,先看看最后对比的是什么
先在main->sub_402370函数里找到对比的地方
有点像md5加密后的字符串
于是随便拿一串字符串出来尝试md5在线解密下
发现就是用单个字符进行两次md5加密
然后用python脚本爆一下即可得到flag
from hashlib import *
cmp=['14d89c38cd0fb23a14be2798d449c182', 'a94837b18f8f43f29448b40a6e7386ba', 'af85d512594fc84a5c65ec9970956ea5', 'af85d512594fc84a5c65ec9970956ea5', '10e21da237a4a1491e769df6f4c3b419', 'a705e8280082f93f07e3486636f3827a', '297e7ca127d2eef674c119331fe30dff', 'b5d2099e49bdb07b8176dff5e23b3c14', '83be264eb452fcf0a1c322f2c7cbf987', 'a94837b18f8f43f29448b40a6e7386ba', '71b0438bf46aa26928c7f5a371d619e1', 'a705e8280082f93f07e3486636f3827a', 'ac49073a7165f41c57eb2c1806a7092e', 'a94837b18f8f43f29448b40a6e7386ba', 'af85d512594fc84a5c65ec9970956ea5', 'ed108f6919ebadc8e809f8b86ef40b05', '10e21da237a4a1491e769df6f4c3b419', '3cfd436919bc3107d68b912ee647f341', 'a705e8280082f93f07e3486636f3827a', '65c162f7c43612ba1bdf4d0f2912bbc0', '10e21da237a4a1491e769df6f4c3b419', 'a705e8280082f93f07e3486636f3827a', '3cfd436919bc3107d68b912ee647f341', '557460d317ae874c924e9be336a83cbe', 'a705e8280082f93f07e3486636f3827a', '9203d8a26e241e63e4b35b3527440998', '10e21da237a4a1491e769df6f4c3b419', 'f91b2663febba8a884487f7de5e1d249', 'a705e8280082f93f07e3486636f3827a', 'd7afde3e7059cd0a0fe09eec4b0008cd', '488c428cd4a8d916deee7c1613c8b2fd', '39abe4bca904bca5a11121955a2996bf', 'a705e8280082f93f07e3486636f3827a', '3cfd436919bc3107d68b912ee647f341', '39abe4bca904bca5a11121955a2996bf', '4e44f1ac85cd60e3caa56bfd4afb675e', '45cf8ddfae1d78741d8f1c622689e4af', '3cfd436919bc3107d68b912ee647f341', '39abe4bca904bca5a11121955a2996bf', '4e44f1ac85cd60e3caa56bfd4afb675e', '37327bb06c83cb29cefde1963ea588aa', 'a705e8280082f93f07e3486636f3827a', '23e65a679105b85c5dc7034fded4fb5f', '10e21da237a4a1491e769df6f4c3b419', '71b0438bf46aa26928c7f5a371d619e1', 'af85d512594fc84a5c65ec9970956ea5', '39abe4bca904bca5a11121955a2996bf']
table=[]
table_md5=[]
for i in range(33,127):
table.append(chr(i))
table_md5.append(md5((md5(chr(i).encode()).hexdigest()).encode()).hexdigest())
for i in range(len(cmp)):
print(table[table_md5.index(cmp[i])],end='')#Hello_Ctfer_Velcom_To_my_Mov_and_md5(md5)_world
vm_wo
一个Mach-O ARM64程序,其中通过VM来实现加密
没有条件调试,于是用qiling模拟执行下
通过输入两组数据
可以猜出是挨个字符依次加密的,那思路就很清晰了,直接爆每个可见字符,然后取出结果,最后通过密文找相应的字符即可
直接上qiling脚本
from qiling import Qiling
from qiling.const import QL_VERBOSE
instructions_skip_list = [0x100003DC8, 0x100003DFC, 0x100003E10, 0x100003a08]
inp=''
for i in range(33,127):
inp+=chr(i)
def hook_code(ql, address, size, user_data):
# print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' % (address, size))
if ql.arch.regs.arch_pc in instructions_skip_list:
ql.arch.regs.arch_pc += 4
elif ql.arch.regs.arch_pc == 0x100003DB0:
ql.arch.regs.x8 = 0x100000001
elif ql.arch.regs.arch_pc == 0x1000039DC:
ql.arch.regs.x8 = 0x100000001
elif ql.arch.regs.arch_pc == 0x100003B00:
ql.arch.regs.x9 = 0x100000001
elif ql.arch.regs.arch_pc == 0x100003E2C:#对循环长度进行patch,确保输入的字符都能进行加密
ql.arch.regs.w1 = len(inp)
elif ql.arch.regs.arch_pc == 0x100003E44:
# if ql.arch.regs.w10 == ql.arch.regs.w11:
# print('%d is Right!'%ql.arch.regs.x8)
# print(hex(ql.arch.regs.w10), hex(ql.arch.regs.w11))
result=ql.mem.read(ql.arch.regs.x19, len(inp))#提取加密后的字符串
cmp=ql.mem.read(ql.arch.regs.x9, 29)#提取对比的字符串
print(result)
print(cmp)
for i in range(len(cmp)):
print(inp[result.index(cmp[i])],end='')
elif ql.arch.regs.arch_pc == 0x100003E18:
ql.mem.write(ql.arch.regs.x0, inp.encode())#将输入的字符串写入相应地址
ql.arch.regs.arch_pc += 4
ql.arch.regs.x0 = 0x1D#将长度的值修改为0x1D
ql = Qiling(["./vm_wo"], "./qiling/examples/rootfs/arm64_ios", verbose=QL_VERBOSE.OFF)
ql.arch.disassembler.detail = True
ql.mem.map(0x10000, 0x10000)
ql.hook_code(hook_code, user_data=ql.arch.disassembler)
ql.run(0x100003D98, 0x100003E8C)
Ez加密器
主要逻辑就是先输入6位字符密钥和40位字符flag
然后base64换表加密密钥,再用密钥对flag进行DES加密
base64换表后
abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+/
在des_encode->sub_7FF6103F1A20函数里找到byte_7FF610406100数组(变换数组PC1)
在des_encode->sub_7FF6103F2180函数里找到byte_7FF6104063C0数组(置换表)
可以猜测下这是DES算法
最后来到strcmp处找对比的密文,发现有点问题
交叉引用发现在程序运行中密文和7进行了异或
得到密文后,直接上python脚本进行爆破
from Crypto.Util.number import *
from Crypto.Cipher import DES
from base64 import *
ciphertext=long_to_bytes(0x0723105D5C12217DCDC3601F5ECB54DA9CCEC2279F1684A13A0D716D17217F4C9EA85FF1A42795731CA3C55D3A4D7BEA)
table='1234567890'
for i1 in table:
for i2 in table:
for i3 in table:
for i4 in table:
for i5 in table:
for i6 in table:
key_ = i1+i2+i3+i4+i5+i6
string1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
string2 = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+/'
key=b64encode(key_.encode()).decode().translate(str.maketrans(string1,string2)).encode()
des = DES.new(key, DES.MODE_ECB)
decrypted = des.decrypt(ciphertext) # 解密
if b'DASCTF' in decrypted:
print(key_)
print("解密后的结果:", decrypted)#DASCTF{f771b96b71514bb6bc20f3275fa9404e}