REVERSE
- ezr3
- BabySnake
- ez_cpp
- 3D_maze
- babythread
- gowhere
(还是太菜啦~,做题太慢了,有两道题赛后才出
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+=2v2=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+=1for 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)&0xffprint(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^4else:if opcode[i*4]==1:a=j^9else:a=j-2else:if opcode[i*4]==1:a=j^6else:a=j-5v2=0v3=0v4=7a2=8while v3<a2:v2|=((a>>v3)&1)<<v4v3+=1v4-=1a=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 = 0wddwwdddddDdwwwdddsdddddDwwWassaaaaaaaaAsssssssssSddwwdwwwwwWw
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 inputdef enc2(input):input[0]+=2input[1]-=28input[2]^=0x47input[3]+=input[4]input[5]+=73input[6]+=12input[7]-=input[8]input[8]^=0x5ainput[9]^=0x22input[10]+=20input[12]+=0x0FFFFFFACinput[13]^=4input[14]^=0x1cinput[17]-=1input[27]^=0x11input[28]^=3for i in range(len(input)):input[i]&=0xffreturn inputdef enc3(input):for i in range(len(input)//2):input[i],input[29-i]=input[29-i],input[i]return inputdef enc1_rev(input,x):for i in range(len(input)):input[i]=((input[i]^0x17)-x)return inputdef enc2_rev(input):input[0]-=2input[1]+=28input[2]^=0x47input[3]-=input[4]input[5]-=73input[6]-=12input[8]^=0x5ainput[7]+=input[8]input[9]^=0x22input[10]-=20input[12]-=0x0FFFFFFACinput[13]^=4input[14]^=0x1cinput[17]+=1input[27]^=0x11input[28]^=3for i in range(len(input)):input[i]&=0xffreturn inputdef 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}