Hello_re
提示010,点击查看,发现加了一层upx的壳,并且特征位UPX0被修改成SYC0
修改后进行脱壳,然后拖进IDA
可以推出加密函数就是
sub_140001408(v6, &v5, v4);
v6为输入的flag,v5为密钥,v4为输出并且后续会与已知的v7进行对比
得脚本
v7 = [
0, 1, 2, 52, 3, 96, 47, 28,
107, 15, 9, 24, 45, 62, 60, 2,
17, 123, 39, 58, 41, 48, 96, 26,
8, 52, 63, 100, 33, 106, 122, 48
]
# 密钥v5,转换为字节数组形式
v5 = 0x5245564F4C435953
v5_bytes = v5.to_bytes(8, 'little')
# 注意是小端序
v4 = [0] * 32
# XOR
for j in range(32):
v4[j] = v7[j] ^ (j ^ v5_bytes[j % 8])
# 将每个字符转换为字符串
flag = ''.join(chr(c) for c in v4)
print("The flag is:", flag)
# The flag is: SYC{H3lI0_@_new_R3vers3_Ctf3r!!}
先来一道签到题
拿到sssssssss.s文件,先拖进IDA看看是什么意思
这种未转成可读的exe有两种选择,要么是选中按a,把他转换成字符类型来阅读看看有没有什么信息,第二种是选中按c,转换成代码
这里我们按a转换成字符串
输入flag,判断长度
进行加密操作
脚本
temp = "TTDv^jrZu`Gg6tXfi+pZojpZSjXmbqbmt.&x"
flag = ""
times = 0
for i in temp:
if times % 2 == 0:
flag += chr(ord(i) ^ 7)
else:
flag += chr(ord(i) + 5)
times += 1
print(flag)
# SYC{You_re@l1y_kn0w_how_To_revers3!}
也许你也听jay
这个题给了一个c文件
#include <stdio.h>
int main() {
char URL[46];
char o00O0OO000OO0oooo0o0oo0O0oo000000O0O0OO0O0O00OO0OO0O[46];
strcpy(o00O0OO000OO0oooo0o0oo0O0oo000000O0O0OO0O0O00OO0OO0O, URL);
char o00O0OO000OO0oooo0o0oo0O0oo000000O0O0OO0O00000O0OO0O[] = {0x96, 0xa1, 0xa0, 0x9b, 0x9b, 0x5f, 0x49, 0x46, 0x85, 0x82, 0x53, 0x95, 0x7d, 0x36, 0x8d, 0x74, 0x82, 0x88, 0x46, 0x7a, 0x81, 0x65, 0x80, 0x6c, 0x78, 0x2f, 0x6b, 0x6a, 0x27, 0x50, 0x61, 0x38, 0x3f, 0x37, 0x33, 0xf1, 0x27, 0x32, 0x34, 0x1f, 0x39, 0x23, 0xde, 0x1c, 0x17, 0xd4};
int o00O0OO000OO0oooo0o0oo0O0000oooooooO0O0OO0O0O00OO0OO0O[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D};
int o00O0OO000OO0oooo0o0oo0O000O0OO0O0O00OO0OO0O00000[] = {0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
int o00O0OO000OO0oooo0o0oo0O000000O00O0O0OO0O0O00OO0OO0O[]={0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x00, 0x31, 0x30, 0x2F};
int len = strlen(URL);
for(int i = 0; i < len; i++) {
o00O0OO000OO0oooo0o0oo0O000000O00O0O0OO0O0O00OO0OO0O[i] ^= o00O0OO000OO0oooo0o0oo0O000O0OO0O0O00OO0OO0O00000[i+1];
}
for(int i = 0; i < len; i++) {
o00O0OO000OO0oooo0o0oo0O0oo000000O0O0OO0O0O00OO0OO0O[i] ^= o00O0OO000OO0oooo0o0oo0O0000oooooooO0O0OO0O0O00OO0OO0O[i];
}
for(int i = 0; i < len; i++) {
o00O0OO000OO0oooo0o0oo0O000000O00O0O0OO0O0O00OO0OO0O[i] -= o00O0OO000OO0oooo0o0oo0O0000oooooooO0O0OO0O0O00OO0OO0O[i];
}
for(int i = 0; i < len; i++) {
o00O0OO000OO0oooo0o0oo0O0oo000000O0O0OO0O0O00OO0OO0O[i] -= o00O0OO000OO0oooo0o0oo0O0000oooooooO0O0OO0O0O00OO0OO0O[47 + i];
o00O0OO000OO0oooo0o0oo0O0000oooooooO0O0OO0O0O00OO0OO0O[i]^=o00O0OO000OO0oooo0o0oo0O000000O00O0O0OO0O0O00OO0OO0O[51];
}
for(int i = 0; i < len; i++) {
o00O0OO000OO0oooo0o0oo0O0oo000000O0O0OO0O0O00OO0OO0O[i] += o00O0OO000OO0oooo0o0oo0O000O0OO0O0O00OO0OO0O00000[i];
}
for(int i=0;i<len;i++){
if(o00O0OO000OO0oooo0o0oo0O0oo000000O0O0OO0O0O00OO0OO0O[i] != o00O0OO000OO0oooo0o0oo0O0oo000000O0O0OO0O00000O0OO0O[i]){
printf("Error");
}
}
return 0;
}
先ctrl + r把易混淆的这几个变量换成a1,a2....
然后看一下逻辑,就是明文a1经过多轮加密,得到密文a2
a1 = [0] * 46
a2 = [0x96, 0xa1, 0xa0, 0x9b, 0x9b, 0x5f, 0x49, 0x46, 0x85, 0x82,
0x53, 0x95, 0x7d, 0x36, 0x8d, 0x74, 0x82, 0x88, 0x46, 0x7a,
0x81, 0x65, 0x80, 0x6c, 0x78, 0x2f, 0x6b, 0x6a, 0x27, 0x50,
0x61, 0x38, 0x3f, 0x37, 0x33, 0xf1, 0x27, 0x32, 0x34, 0x1f,
0x39, 0x23, 0xde, 0x1c, 0x17, 0xd4]
a3 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C,
0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82,
0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C,
0x8D]
a4 = [0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53,
0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48,
0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D,
0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
0x31, 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27,
0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C,
0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06,
0x05, 0x04, 0x03, 0x02, 0x01]
a5 = [0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5F, 0x5E, 0x5D, 0x5C,
0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52,
0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48,
0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E,
0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34,
0x33, 0x00, 0x31, 0x30, 0x2F]
for i in range(32):
a5[i] ^= a4[i + 1]
for i in range(32):
a1[i] ^= a3[i]
for i in range(32):
a5[i] -= a3[i]
for i in range(32):
a1[i] -= a3[47 + i]
a3[i] ^= a5[51]
for i in range(32):
a1[i] += a4[i]
for i in range(32):
if a1[i] != a2[i]:
print("Error")
else:
print("yes")
写成python代码,主要看一下这几轮加密
for i in range(32):
a5[i] ^= a4[i + 1]
for i in range(32):
a1[i] ^= a3[i]
for i in range(32):
a5[i] -= a3[i]
for i in range(32):
a1[i] -= a3[47 + i]
a3[i] ^= a5[51]
for i in range(32):
a1[i] += a4[i]
for i in range(32):
if a1[i] != a2[i]:
逆向从尾向头,那么先让
- a1 = a2
- 原本是a1每一位都加a4[i],现在就是a1[i] - a4[i]
- 原本是a1先减去a3[47+i],然后a3每一位(in range 32)和a5[51]进行异或,现在就是a1先加上a3[47+i],然后a3每一位(in range 32)和a5[51]进行异或
- 后面就是两个异或
得脚本
a1 = [0] * 46
a2 = [0x96, 0xa1, 0xa0, 0x9b, 0x9b, 0x5f, 0x49, 0x46, 0x85, 0x82,
0x53, 0x95, 0x7d, 0x36, 0x8d, 0x74, 0x82, 0x88, 0x46, 0x7a,
0x81, 0x65, 0x80, 0x6c, 0x78, 0x2f, 0x6b, 0x6a, 0x27, 0x50,
0x61, 0x38, 0x3f, 0x37, 0x33, 0xf1, 0x27, 0x32, 0x34, 0x1f,
0x39, 0x23, 0xde, 0x1c, 0x17, 0xd4]
a3 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C,
0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82,
0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C,
0x8D]
a4 = [0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53,
0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48,
0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D,
0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
0x31, 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27,
0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C,
0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06,
0x05, 0x04, 0x03, 0x02, 0x01]
a5 = [0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5F, 0x5E, 0x5D, 0x5C,
0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52,
0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48,
0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E,
0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34,
0x33, 0x00, 0x31, 0x30, 0x2F]
for i in range(46):
a1[i] = a2[i]
for i in range(46):
a1[i] -= a4[i]
for i in range(46):
a1[i] += a3[47 + i]
a3[i] ^= a5[51]
for i in range(46):
a5[i] += a3[i]
for i in range(46):
a1[i] ^= a3[i]
for i in range(46):
a5[i] ^= a4[i + 1]
for i in range(46):
print(chr(a1[i]),end="")
这里写的都是range(46),因为32解密不完全
得到https://am1re-sudo.github.io/CoisniĮgithubĮioį
后面几位解密稍微有些问题,但是可读字符串github和io还在,į其实是/
或者直接搜
点进可能你也听jay(声音好大)
这里还有一个RC4加密
)
找个在线网站即可解出
SYC{ILIKELISTENJAYSONG}
我勒个z3啊
打开IDA查看主函数
先输入key,再输入flag
我们先去看一下key检验处的逻辑
逻辑就是对输入的key中的每一个字符串在给定的字典中遍历,如果相匹配则那个字符被替换成被匹配的字符在字典中的相对序号,最后与已知的数列数组相比对
写个脚本
temp = [42, 14, 14, 20, 63, 63, 63, 38, 17, 10,
21, 21, 14, 23, 16, 14]
key = ""
dic = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ?_"
for i in temp:
key += dic[i]
print(key)
得到key是Geek___Challenge
继续往下看flag的逻辑
sub_401AAC(v6, v4);
if ( !sub_40179A(v6) )
{
puts("[~]NO,Something_gets_wrong. TT.TT");
exit(0);
}
第一个函数传进去的是flag和key,第二个函数检测的是加密后的flag。
我们先看第二个函数
写一个z3脚本解一下
from z3 import *
solver = Solver()
cal_flag = [Int(f'cal_flag{i}') for i in range(32)]
calculate = [0x19B, 0x113, 0x189, 0x1C9, 0x250, 0x536, 0x4DE, 0x1BC, 0x41B,
0x724, 0x6D0, 0x4A1, 0x645, 0x475, 0x4CA, 0x68C, 0x3E5, 0x1C7,
0x33D, 0x5B7, 0x28D, 0x244, 0x30E, 0x291, 0x271, 0x301, 0x45F,
0x46F, 0x517, 0x41E, 0x426, 0x4B5]
enc_flag = [0] * 32
for i in range(0, 32, 4):
solver.add(
cal_flag[i] + 8 * cal_flag[i + 1] + 6 * cal_flag[i + 2] + cal_flag[i + 3] == calculate[i],
cal_flag[i + 1] + 8 * cal_flag[i + 2] + 6 * cal_flag[i + 3] + cal_flag[i] == calculate[i + 1],
cal_flag[i + 2] + 8 * cal_flag[i + 3] + 6 * cal_flag[i] + cal_flag[i + 1] == calculate[i + 2],
cal_flag[i + 3] + 8 * cal_flag[i] + 6 * cal_flag[i + 1] + cal_flag[i + 2] == calculate[i + 3]
)
if solver.check() == sat:
model = solver.model()
enc_flag = [model[cal_flag[i]].as_long() for i in range(32)]
print(enc_flag)
# print("strlen =", len(enc_flag))
解出来加密的flag后,我们再来看一下第一个加密函数
这个函数对每个字符进行了两次异或加密
其中还有个函数,是对输入的flag进行重新排序
既然现在拿到的是加密后的数据,那么我们先要进行解密xor,然后再把顺序恢复
这里最主要的点就是对xor逻辑的理解
for ( i = 0; i <= 31; ++i )
{
a1[i] ^= a1[(v3 + i - 1) % v3];
a1[i] ^= a2[(47 - i) % 16] ^ i;
}
从第一位到最后一位,数据先与自己的前一位进行异或(第一位取模后实际上是与最后一位异或),然后再与key和i异或;
从逆向的角度来看,每一个数据与自己前一位异或后还要在key,i异或,那么就先和key与i异或,再与前一位异或;
并且,与前一位异或时,前一位已经是异或加密之后的状态了,所以循环要从后往前进行,同理,还原顺序时也要注意是同样的逻辑
写个脚本
flag = [0] * 32
for i in range(31, -1, -1):
enc_flag[i] ^= ord(key[(47 - i) % 16]) ^ i
enc_flag[i] ^= enc_flag[(32 + i - 1) % 32]
flag[i] = enc_flag[i]
for i in range(7, -1, -1):
for j in range(i - 1, -1, -1):
v2 = flag[4 * i + 3]
for k in range(2, -1, -1):
flag[4 * i + k + 1] = flag[4 * i + k]
flag[4 * i] = v2
for i in range(32):
print(chr(flag[i]), end="")
完整脚本
temp = [42, 14, 14, 20, 63, 63, 63, 38, 17, 10,
21, 21, 14, 23, 16, 14]
key = ""
dic = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ?_"
for i in temp:
key += dic[i]
print(key)
# print("strlen =", len(key))
from z3 import *
solver = Solver()
cal_flag = [Int(f'cal_flag{i}') for i in range(32)]
calculate = [0x19B, 0x113, 0x189, 0x1C9, 0x250, 0x536, 0x4DE, 0x1BC, 0x41B,
0x724, 0x6D0, 0x4A1, 0x645, 0x475, 0x4CA, 0x68C, 0x3E5, 0x1C7,
0x33D, 0x5B7, 0x28D, 0x244, 0x30E, 0x291, 0x271, 0x301, 0x45F,
0x46F, 0x517, 0x41E, 0x426, 0x4B5]
enc_flag = [0] * 32
for i in range(0, 32, 4):
solver.add(
cal_flag[i] + 8 * cal_flag[i + 1] + 6 * cal_flag[i + 2] + cal_flag[i + 3] == calculate[i],
cal_flag[i + 1] + 8 * cal_flag[i + 2] + 6 * cal_flag[i + 3] + cal_flag[i] == calculate[i + 1],
cal_flag[i + 2] + 8 * cal_flag[i + 3] + 6 * cal_flag[i] + cal_flag[i + 1] == calculate[i + 2],
cal_flag[i + 3] + 8 * cal_flag[i] + 6 * cal_flag[i + 1] + cal_flag[i + 2] == calculate[i + 3]
)
if solver.check() == sat:
model = solver.model()
enc_flag = [model[cal_flag[i]].as_long() for i in range(32)]
print(enc_flag)
# print("strlen =", len(enc_flag))
flag = [0] * 32
for i in range(31, -1, -1):
enc_flag[i] ^= ord(key[(47 - i) % 16]) ^ i
enc_flag[i] ^= enc_flag[(32 + i - 1) % 32]
flag[i] = enc_flag[i]
for i in range(7, -1, -1):
for j in range(i - 1, -1, -1):
v2 = flag[4 * i + 3]
for k in range(2, -1, -1):
flag[4 * i + k + 1] = flag[4 * i + k]
flag[4 * i] = v2
for i in range(32):
print(chr(flag[i]), end="")
得到flag:SYC{Wow!!_Y0u_4r3_9o0d_At_r3$!!}
好像是python?
先根据给的汇编,写一个python代码
def test2(s2):
key = 'SYC'
length = 18
cipher = []
for i in range(length):
cipher.append(ord(s2[i]) ^ i + ~ord(key[i % 3]) + 1)
return cipher
def test(s, R):
result = []
for i in s:
if ord('A') <= i <= ord('Z'):
result.append(chr((ord(i) - ord('A') + R) % 26 + ord('A')))
elif ord('a') <= i <= ord('z'):
result.append(chr((ord(i) - ord('a') + R) % 26 + ord('a')))
elif ord('0') <= i <= ord('9'):
result.append(chr((ord(i) - ord('0') + R) % 10 + ord('0')))
else:
result.append(i)
return result
input0 = input("plz input")
a = 13
b = 14
c = (a + b) ^ a
d = b * 100
e = a ^ b
m = (4 * c) - d + e - 1
r = m % 26
cipher1 = test(input0, r)
cipher2 = test2(cipher1)
num = [-1, -36, 26, -5, 14, 41, 6, -9, 60, 29, -28, 17, 21, 7, 35, 38, 26, 48]
for i in range(18):
if cipher2[i] != num[i]:
print("wrong!")
让我康康你的调试
观察main函数,能看出逻辑大概是
key = syclover
s2[0] = 0xA67A02C9047D5B94
s2[1] = 0x7EF9680DBC980739
s2[2] = 0x7104F81698BFBD08
s2[3] = 0x61DB8498B686155F
flag = input()
for i in flag:
xor_flag += i ^ 0x14
enc_flag = RC4(xor_flag, 33, key, 8)
if enc_flag == s2:
print("yes")
查看RC4函数逻辑
能看到先调用sub_55B7E1B161C9(v9, a3, a4)对key进行处理
然后进行RC4加密运算
题目提示使用动调,我们可以利用动调获得数据,更加方便我们进行逆向脚本的编写
我们在key加密后的地方设置断点,在输入flag之后程序会运行到断点处,这时我们查看key的数据
使用选项Debugger中的Locals查看数据
点击v9展开
选中v9的全部数据之后,使用shift+e获取
得到key
得到key之后,我们把下面的加密逻辑复现出来
for i in range(32):
v6 = (v6 + 1) % 256
v7 = (v7 + key[v6]) % 256
v5 = key[v6]
key[v6] = key[v7]
key[v7] = v5
flag[i] ^= key[(key[v6] + key[v7]) % 256]
在加密完成之后,还要和s2的值进行比对,我们在memcmp处下断点,提取s2的值
双击并选中s2,同样的办法提取,这里有大小端序的问题存在
由于输入的flag在加密前与0x14异或过,要注意这一步
写个脚本
key = [0x31, 0x50, 0x52, 0xC1, 0xCD, 0xA7, 0x07, 0x39, 0x3D, 0x04,
0xFD, 0xC4, 0x2A, 0x72, 0xDF, 0x60, 0xE3, 0xBD, 0xE2, 0x61,
0xE4, 0x63, 0xEA, 0xFF, 0xFE, 0x09, 0xF9, 0xC3, 0xCE, 0x9E,
0x25, 0x6A, 0x4C, 0xDC, 0x13, 0xF0, 0x83, 0x3B, 0x24, 0xDB,
0xDD, 0x7F, 0xEF, 0x8C, 0x3E, 0xE1, 0x26, 0x6F, 0x92, 0x06,
0xF7, 0x96, 0xD0, 0xB4, 0xE7, 0xF8, 0x5F, 0x78, 0xF2, 0xAA,
0x44, 0x32, 0x36, 0x5A, 0xEC, 0xA6, 0x7B, 0x08, 0xC0, 0x2E,
0x9B, 0x84, 0x55, 0x9C, 0xAE, 0x65, 0x0A, 0x10, 0x53, 0x88,
0x49, 0x46, 0xAB, 0x0C, 0x1F, 0x59, 0x7E, 0xE5, 0xB3, 0xF6,
0x48, 0x1A, 0xD1, 0xA4, 0x67, 0x6B, 0xBA, 0x87, 0x73, 0x4B,
0xA2, 0xCF, 0x1D, 0x18, 0xD4, 0xBB, 0x2C, 0x70, 0x93, 0xAC,
0x0F, 0x7A, 0x51, 0xB5, 0x21, 0x85, 0x45, 0x02, 0x1C, 0x9F,
0x81, 0x5C, 0x4A, 0x95, 0x1B, 0x16, 0xD2, 0xC7, 0xE0, 0xDA,
0x58, 0xA9, 0x1E, 0xD7, 0xC2, 0x69, 0x71, 0xD6, 0x2D, 0x75,
0xBC, 0x66, 0xFA, 0x30, 0xAD, 0x99, 0x8B, 0x77, 0x41, 0x97,
0x22, 0xB8, 0xB2, 0xD3, 0x47, 0xC6, 0x79, 0x14, 0x0B, 0xF4,
0x3F, 0x11, 0x2B, 0xDE, 0xEE, 0xF3, 0xF5, 0xAF, 0xA5, 0x86,
0x91, 0xBE, 0x8E, 0x8F, 0xE8, 0xE6, 0xB1, 0x4E, 0x37, 0xD5,
0xFC, 0x4D, 0x5E, 0x42, 0xCA, 0x35, 0xC8, 0x6E, 0xA3, 0x89,
0x15, 0x6D, 0x03, 0x8A, 0x8D, 0xD8, 0x76, 0xCB, 0xC5, 0xF1,
0x6C, 0xB9, 0x17, 0x64, 0x68, 0xE9, 0x56, 0x29, 0x90, 0xED,
0x74, 0x0D, 0xEB, 0xB0, 0xA1, 0x94, 0x80, 0xC9, 0x7C, 0xB7,
0x28, 0x05, 0x5B, 0x23, 0x9D, 0xA0, 0x27, 0x98, 0x43, 0x7D,
0xBF, 0x4F, 0x12, 0x34, 0xA8, 0xD9, 0x57, 0x33, 0x9A, 0x01,
0x54, 0x2F, 0x3C, 0x62, 0x38, 0xFB, 0x82, 0x0E, 0x3A, 0x19,
0x5D, 0xB6, 0x40, 0x20, 0xCC]
v6 = 0
v7 = 0
s2 = [0x94, 0x5B, 0x7D, 0x04, 0xC9, 0x02, 0x7A, 0xA6, 0x39, 0x07,
0x98, 0xBC, 0x0D, 0x68, 0xF9, 0x7E, 0x08, 0xBD, 0xBF, 0x98,
0x16, 0xF8, 0x04, 0x71, 0x5F, 0x15, 0x86, 0xB6, 0x98, 0x84,
0xDB, 0x61]
flag = [0] * 33
for i in range(32):
v6 = (v6 + 1) % 256
v7 = (v7 + key[v6]) % 256
v5 = key[v6]
key[v6] = key[v7]
key[v7] = v5
flag[i] = key[(key[v6] + key[v7]) % 256] ^ s2[i] ^ 0x14
print(chr(flag[i]),end="")
奇怪的RC4
先从exe反编译为pyc,再反编译为py文件
from Rc4 import *
def xor1(plaintext, xor_list):
try:
xor_list = (lambda .0: [ord(i) for i in .0])(xor_list)
finally:
pass
try:
plaintext = (lambda .0: [ord(i) for i in .0])(plaintext)
finally:
pass
for i in range(len(plaintext)):
plaintext[i] ^= xor_list[i]
return plaintext
def xor2(plaintext):
try:
plaintext = (lambda .0: [ord(i) for i in .0])(plaintext)
finally:
pass
for i in range(len(plaintext) - 1):
plaintext[i + 1] = plaintext[i] ^ plaintext[i + 1]
return plaintext
def enc(plaintext, key, xor_list):
plaintext = rc4(plaintext, key)
plaintext = xor1(plaintext, xor_list)
plaintext = xor2(plaintext)
return plaintext
plaintext = input('please give your input:')
key = 'SYCFOREVER'
xor_list = list(range(len(plaintext)))
cipher = [
158, 31, 205, 434, 354, 15, 383, 298, 304, 351,
465, 312, 261, 442, 397, 474, 310, 397, 31, 21,
78, 67, 47, 133, 168, 48, 153, 99, 103, 204,
137, 29, 22, 13, 228, 3, 136, 141, 248, 124,
26, 26, 65, 200, 7
]
plaintext = enc(plaintext, key, xor_list)
for i in range(len(cipher)):
if cipher[i] != plaintext[i]:
print('Wrong')
exit(1)
continue
print('You know the flag!!')
return None
看逻辑
cipher = [
158, 31, 205, 434, 354, 15, 383, 298, 304, 351,
465, 312, 261, 442, 397, 474, 310, 397, 31, 21,
78, 67, 47, 133, 168, 48, 153, 99, 103, 204,
137, 29, 22, 13, 228, 3, 136, 141, 248, 124,
26, 26, 65, 200, 7
]
xor_list = list(range(len(cipher)))
xor_plaintext = [0] * 45
xor_plaintext[0] = 158
for i in range(len(xor_plaintext) - 1):
xor_plaintext[i + 1] = cipher[i] ^ cipher[i + 1]
rc4_plaintext = [0] * 45
for i in range(len(rc4_plaintext)):
rc4_plaintext[i] = xor_list[i] ^ xor_plaintext[i]
def rc4_key_schedule(key1):
key_len = len(key1)
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key1[i % key_len]) % 256
S[i], S[j] = S[j], S[i] # 交换S[i]与S[j]
return S
key = [ord(c) for c in "SYCFOREVER"]
key = rc4_key_schedule(key)
def rc4(S, plaintext):
keystream = []
i = j = 0
for char in plaintext:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i] # 交换
keystream.append(S[(S[i] + S[j]) % 256])
return [c ^ k for c, k in zip(plaintext, keystream)]
rc4_decrypted = rc4(key, rc4_plaintext)
for i in range(45):
print(chr(rc4_decrypted[i] % 128), end="")
import hashlib
def decrypt_test2(cipher):
key = 'SYC'
length = 18
result = []
for i in range(length):
original = (cipher[i] - (~ord(key[i % 3]) + 1)) ^ i
result.append(chr(original))
return ''.join(result)
def decrypt_test(s, R):
result = []
for i in s:
if 'A' <= i <= 'Z':
result.append( chr(((ord(i) - ord('A') + R) % 26) + ord('A')) )
elif 'a' <= i <= 'z':
result.append( chr(((ord(i) - ord('a') + R) % 26) + ord('a')) )
elif '0' <= i <= '9':
result.append( chr(((ord(i) - ord('0') + R) % 10) + ord('0')) )
else:
result.append(i)
return ''.join(result)
num = [-1, -36, 26, -5, 14, 41, 6, -9, 60, 29, -28, 17, 21, 7, 35, 38, 26, 48]
str1 = decrypt_test2(num)
input_ = decrypt_test(str1, -14)
print(input_) print("SYC{" + hashlib.md5(input_.encode("UTF-8")).hexdigest()+"}")
得到D0_You_Iik3_python
玩就行了
得到一个黄金矿工程序,用CE改一下分数就通关了,或者010把"\玩就行了\玩就行了_Data\level0"
最后末尾的666改成一个很小的数字
提示有些东西被遗漏了,根据提示发现文件夹中生成了一个文件data.txt,根据文件大小怀疑这是一个16进制的文件
)
导入到010中,保存得到了exe文件
IDA打开
根据逻辑写出代码
flag = ["0"] * 20
second = [0] * 20
for i in range(20):
if ord(flag[i]) <= 96 or ord(flag[i]) > 122:
if ord(flag[i]) <= 64 or ord(flag[i]) > 90:
if 47 < ord(flag[i]) <= 57:
second[i] = (20 + ord(flag[i]) - 48) % 10 + 48
else:
second[i] = (ord(flag[i]) - 65 + 20) % 26 + 65
else:
second[i] = (ord(flag[i]) - 97 + 20) % 26 + 97
key = "GEEK"
v3 = len(key)
third = [0] * 20
for i in range(len(second)):
third[i] = ord(key[i % v3]) ^ second[i]
final = "0A161230300C2D0A2B303D2428233005242C2D26182206233E097F133A"
# 把最后得到的字符串转成十六进制数组
# answer = ""
# for i in range(58):
# if i % 2 == 0:
# answer += ", 0x"
# answer += final[i]
# else:
# answer += final[i]
# print(answer)
写个逆向脚本
final = "0A161230300C2D0A2B303D2428233005242C2D26182206233E097F133A"
flag = ["0"] * 29
second = [0] * 29
third = [0x0A, 0x16, 0x12, 0x30, 0x30, 0x0C, 0x2D, 0x0A, 0x2B, 0x30, 0x3D, 0x24, 0x28, 0x23, 0x30, 0x05, 0x24, 0x2C, 0x2D, 0x26, 0x18, 0x22, 0x06, 0x23, 0x3E, 0x09, 0x7F, 0x13, 0x3A]
key = "GEEK"
v3 = len(key)
for i in range(len(second)):
second[i] = ord(key[i % v3]) ^ third[i]
decrypted_char = [0] * 29
for i in range(29):
v3 = second[i]
if 97 <= v3 <= 122: # 小写字母
decrypted_char[i] = (v3 - 97 - 20) % 26 + 97
elif 65 <= v3 <= 90: # 大写字母
decrypted_char[i] = (v3 - 65 - 20) % 26 + 65
elif 48 <= v3 <= 57: # 数字
decrypted_char[i] = (v3 - 48 - 20) % 10 + 48
else: # 其他字符保持不变
decrypted_char[i] = v3
for i in range(29):
print(chr(decrypted_char[i]), end="")
得到flag为SYC{cOnGraduulaTions_mIneR:D}
没有评论