(还是太菜啦~,做题太慢了,有两道题赛后才出
ezr3
(赛后出的)
首先010查看下文件
发现有HCK字眼,猜测是UPX加壳,搜索下HCK
确认是UPX4.02版本加的壳,将HCK替换为UPX,然后UPX脱壳即可
IDA分析代码,在main函数中可以找到两个关键函数,v()和p()函数
在v()函数中,对程序中的一些数据进行异或操作
在p()函数中,首先对输入的数据以字节为单位进行操作,将前四位和后四位进行交换,例如0x7b变为0xb7,然后进行异或操作,最后验证flag是否正确
memStore=[3361, 0, 157, 0, 2379, 0, 969, 0, 3135, 0, 6121, 0, 4878, 0, 136, 0, 1158, 0, 8239, 0, 8752, 0, 9396, 0, 2225, 0, 2719, 0, 6866, 0, 9195, 0, 3198, 0, 1067, 0, 1471, 0, 4412, 0, 1097, 0, 5969, 0, 2766, 0, 6292, 0, 8330, 0, 3714, 0, 1725, 0, 3310, 0, 9094, 0, 5076, 0, 273, 0, 3356, 0, 9102, 0, 5977, 0, 299, 0, 8525, 0, 46656, 0]
auth=[244841, 868256, 239946, 281343, 283220, 52689, 6165, 15112, 460904, 812384, 415330, 546248, 56566, 19686, 1371842, 184278, 206694, 1373882, 155241, 436643, 1187517, 366876, 327702, 19005, 619653, 577696, 243990, 347224, 618388, 66356, 896290, 307764, 196246, 996300, 1229288, 1347486]
flag=[]
v2=0
for i in range(0,len(auth),6):
for j in range(6):
auth[i+j]^=memStore[v2+j*12]
v2+=2
v2=0
for i in range(0,len(auth),6):
for j in range(6):
flag.append(auth[i+j]//memStore[(v2+j*6)*2])
v2+=1
for i in range(len(flag)):
flag[len(flag)-1-i]^=flag[i]
flag[len(flag)-1-i]=(flag[len(flag)-1-i]>>4|flag[len(flag)-1-i]<<4)&0xff
print(bytes(flag))#SYC{1_w4Nn4_buy_4_c4R_G1V3_M3_50w_$}
BabySnake
(赛后出的)
刚开始看还以为很简单,以为patch个值就能出,刚开始直接改了判断是否吃到金币的逻辑,让其不管在哪都当作吃到金币来执行
由于地图不够大,即便吃满整个屏幕分数也不够,所以还要把这里的判断nop掉,开启无敌模式(x
没想到还是太年轻了,每次跑出的flag都不一样,原来是出题人加了逻辑验证,以此来生成随机数,先看看主要函数
sub_401E40函数判断是否吃到金币
sub_401B90函数按照我的理解是,先判断了蛇头部的位置是否在生成的金币位置上,如果是,则按照正常执行,否则获取当前时间并将其作为随机数种子
于是我将这三处函数逻辑改了下,不过得在调试中进行修改,得先让程序执行一遍,让数值正常定义
开始patch程序,先将以下代码nop掉,让其无论是撞墙还是碰到身子都能继续运行
patch前:
patch后:
将此处改为jnz判断,让其即使没吃到金币,也正常加分,将84改为85即可
在判断位置是否和金币位置一样的地方,把逻辑改为直接跳转到正常吃到金币后执行的代码
将前五个字节patch成E8 3D 00 00 00 ,然后运行
在调试中吃到金币会报异常,改为以下接着运行即可
然后等分数自己加就好
分数够后,得到flag
ez_cpp
关键函数
调试跟进函数看看,第一处sub_CD1136函数是做凯撒加密,key为13
第二处sub_CD1136函数根据opcode值做异或或者减法操作
sub_CD1177函数做以下操作
于是先爆破出凯撒加密后的密文
result=[]
opcode=[0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
cmp=[0x22, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0x72, 0x00,
0x00, 0x00, 0xE6, 0xFF, 0xFF, 0xFF, 0x52, 0x00, 0x00, 0x00,
0x8C, 0xFF, 0xFF, 0xFF, 0xF2, 0xFF, 0xFF, 0xFF, 0xD4, 0xFF,
0xFF, 0xFF, 0xA6, 0xFF, 0xFF, 0xFF, 0x0A, 0x00, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0xA6, 0xFF,
0xFF, 0xFF, 0x9C, 0xFF, 0xFF, 0xFF, 0x86, 0xFF, 0xFF, 0xFF,
0x24, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0xD4, 0xFF,
0xFF, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xB6, 0xFF, 0xFF, 0xFF,
0x14, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0xCE, 0xFF,
0xFF, 0xFF, 0xAC, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x00, 0x00,
0x6A, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xE4, 0xFF, 0xFF, 0xFF,
0xE4, 0xFF, 0xFF, 0xFF, 0x1E, 0x00, 0x00, 0x00]
for i in range(32):
for j in range(0x100):
if i<=16:
if i>=16:
a=j^4
else:
if opcode[i*4]==1:
a=j^9
else:
a=j-2
else:
if opcode[i*4]==1:
a=j^6
else:
a=j-5
v2=0
v3=0
v4=7
a2=8
while v3<a2:
v2|=((a>>v3)&1)<<v4
v3+=1
v4-=1
a=1^(v2+1)
if a==cmp[i*4]:
result.append(j)
print(bytes(result))#b'FLPnL3F-lR5-l0h-F0Ir-Gu3-P9C!!!}'
接着凯撒解密
把a改为{,即为flag
3D_maze
一道迷宫题,首先根据迷宫规律打印出迷宫
#迷宫数据
a=[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00...]
maze=[]
for i in range(0,len(a),4):
maze.append(a[i])
for i in range(len(maze)):
if i!=0 and i%10==0:
print()
print(maze[i],end='')
接着手搓路径
#0
0010000000 v4 = 9
0010000100
0010111100
0010100000
0010111111
0010100000
0011111111
0050100000
0003000000 v3 = 1
0001000000 D
#1
0000000000
0111100000
0100111111
0100000000
1100000000
0000000000
1111100000
0000000000 v3 = 2
0000000000 D
0000000000 v5=0
#2
1000000000
1000000000
1001010001
0010101010
0010000100
0001000100
0000100100
0010100100 v5=0
0001000100 W
0000000000 v3=4
#3
0010000000
0010000000
0010110000
0011001000
0011000000
0011000000
0011001000 v3 = 5
0010110000 S
0010000000 v4 = 0
0010000000 v5 = 2
#4
0000000011
0000000010
1111111110
0000000000
0000000000
0000000000
0000000000
0000000000 v3 = 3
0000000000 A
0000000000 v5=9
#5
0001000000
0001000000
0001000000
0001000000
0001000000
0011000000
0010000000 W
1110000000 v3 = 0
0000000000 v4 = 7
0000000000 v5 = 0
wddwwdddddDdwwwdddsdddddDwwWassaaaaaaaaAsssssssssSddwwdwwwwwWw
SYCTF{wddwwdddddDdwwwdddsdddddDwwWassaaaaaaaaAsssssssssSddwwdwwwwwWw}
babythread
RC4加密
先随便输入字符,取出rc4加密后的字符,再进行异或操作还原flag
cmp=[0xDE, 0x1C, 0x22, 0x27, 0x1D, 0xAE, 0xAD, 0x65, 0xAD, 0xEF,
0x6E, 0x41, 0x4C, 0x34, 0x75, 0xF1, 0x16, 0x50, 0x50, 0xD4,
0x48, 0x69, 0x6D, 0x93, 0x36, 0x1C, 0x86, 0x3B, 0xBB, 0xD0,
0x4C, 0x91]
input='1'*32
result=[0xBC, 0x74, 0x50, 0x6D, 0x78, 0xF7, 0xAD, 0x27, 0xC3, 0xB7,
0x2C, 0x2F, 0x3D, 0x5A, 0x01, 0xA1, 0x54, 0x38, 0x3E, 0xD6,
0x17, 0x3B, 0x2E, 0xDB, 0x77, 0x59, 0xF8, 0x2B, 0xAB, 0xC0,
0x5C, 0xDD]
flag=[]
for i in range(len(result)):
flag.append(ord(input[i])^result[i]^cmp[i])
print(bytes(flag))#SYC{Th1s_is_@_EasY_3ncryptO!!!!}
gowhere
一道go去符号题,先用GolangHelper还原符号
在main_main函数中找到主要对比逻辑
byte_55D1D0数组存放的是根据输入的字符串进行加密后得到的数组
unk_517E60数组存放的是密文
通过交叉引用,观察byte_55D1D0数组在哪被用到
分别跳转到相应位置下断点,然后调试理清代码逻辑
最后编写解密脚本
def enc1(input,x):
for i in range(len(input)):
input[i]=((input[i]+x)^0x17)
return input
def enc2(input):
input[0]+=2
input[1]-=28
input[2]^=0x47
input[3]+=input[4]
input[5]+=73
input[6]+=12
input[7]-=input[8]
input[8]^=0x5a
input[9]^=0x22
input[10]+=20
input[12]+=0x0FFFFFFAC
input[13]^=4
input[14]^=0x1c
input[17]-=1
input[27]^=0x11
input[28]^=3
for i in range(len(input)):
input[i]&=0xff
return input
def enc3(input):
for i in range(len(input)//2):
input[i],input[29-i]=input[29-i],input[i]
return input
def enc1_rev(input,x):
for i in range(len(input)):
input[i]=((input[i]^0x17)-x)
return input
def enc2_rev(input):
input[0]-=2
input[1]+=28
input[2]^=0x47
input[3]-=input[4]
input[5]-=73
input[6]-=12
input[8]^=0x5a
input[7]+=input[8]
input[9]^=0x22
input[10]-=20
input[12]-=0x0FFFFFFAC
input[13]^=4
input[14]^=0x1c
input[17]+=1
input[27]^=0x11
input[28]^=3
for i in range(len(input)):
input[i]&=0xff
return input
def enc3_rev(input):
for i in range(len(input)//2):
input[i],input[29-i]=input[29-i],input[i]
return input
#encode
# input=[]
# for i in '123456789012345678901234567890':
# input.append(ord(i))
# input=enc1(input,0xa)
# input=enc2(input)
# input=enc3(input)
# input=enc2(input)
# input=enc3(input)
# input=enc1(input,0x10)
# input=enc2(input)
# input=enc3(input)
# input=enc2(input)
# input=enc3(input)
# print(input)
#decode
result=[0x4D, 0x63, 0x5D, 0x34, 0x43, 0x09, 0xA2, 0x77, 0x0A, 0xBF,
0xC9, 0xB3, 0xE9, 0x6F, 0x79, 0x7D, 0x7B, 0xE8, 0x99, 0x90,
0x43, 0x08, 0xBB, 0x99, 0x0E, 0x2E, 0xD4, 0x7B, 0x27, 0xB7]
result=enc3_rev(result)
result=enc2_rev(result)
result=enc3_rev(result)
result=enc2_rev(result)
result=enc1_rev(result,0x10)
result=enc3_rev(result)
result=enc2_rev(result)
result=enc3_rev(result)
result=enc2_rev(result)
result=enc1_rev(result,0xa)
print(bytes(result))#SYC{I_h0pE_you_cAn_FInd_d4eam}