# some_RE 题目
# ez_z3
一道来自 NSSCTF 举办的逆向专题比赛 round#x 的题目
(NSSCTF 和 NKCTF 时间重复了 两边都在看题 = =)
在 IDA 中看很明显看到加了壳 直接脱 UPX 不行 魔改了 010 中查看发现就是改了字节头的加壳 直接在 010 中搜索 XYU1 改成 UPX! 就行了
成功脱壳后在 IDA 中看到主程序 2 次输入 其中在第二个输入后越过循环看到一个需要 z3 解的函数
直接解就行了
上脚本
from z3 import * | |
a1 = [BitVec('x%d' % i, 32) for i in range(20)] | |
s = Solver() | |
for i in range(20): | |
s.add(a1[i] < 127) # 添加约束条件①因为输入的肯定是可见字符 | |
s.add(a1[i] >= 32) | |
s.add( | |
20 * a1[19] * 19 * a1[18] | |
+ 14 * a1[13] | |
+ 13 * a1[12] | |
+ 11 * a1[10] * 10 * a1[9] | |
+ 30 * a1[5] | |
+ 5 * a1[4] | |
+ a1[0] | |
+ 2 * a1[1] | |
- 3 * a1[2] | |
- 4 * a1[3] | |
- 7 * a1[6] | |
+ 8 * a1[7] | |
- 9 * a1[8] | |
- 12 * a1[11] | |
- 16 * a1[15] * 15 * a1[14] | |
- 17 * a1[16] | |
- 18 * a1[17] == 2582239) | |
s.add( | |
20 * a1[19] * 19 * a1[18] | |
+ 14 * a1[13] | |
+ 13 * a1[12] | |
+ 11 * a1[10] * 10 * a1[9] | |
+ 30 * a1[5] | |
- 7 * a1[6] | |
+ 8 * a1[7] | |
- 9 * a1[8] | |
+ 5 * a1[4] | |
+ 3 * a1[2] | |
+ 2 * a1[1] * a1[0] | |
- 4 * a1[3] | |
- 12 * a1[11] | |
- 16 * a1[15] * 15 * a1[14] | |
- (18 * a1[17] | |
+ 17 * a1[16]) == 2602741) | |
s.add(19 * a1[18] | |
+ 18 * a1[17] | |
+ 14 * a1[13] * 13 * a1[12] | |
+ 12 * a1[11] * 11 * a1[10] | |
+ 9 * a1[8] | |
+ 7 * a1[6] * 30 * a1[5] | |
+ a1[0] | |
- 2 * a1[1] | |
- 4 * a1[3] * 3 * a1[2] | |
- 5 * a1[4] | |
+ 8 * a1[7] | |
- 10 * a1[9] | |
- 15 * a1[14] | |
- 17 * a1[16] * 16 * a1[15] | |
- 20 * a1[19] == 2668123) | |
s.add(20 * a1[19] * 19 * a1[18] | |
+ 14 * a1[13] | |
+ (13 * a1[12] + 11 * a1[10] - 12 * a1[11]) * 10 * a1[9] | |
+ 30 * a1[5] | |
+ 5 * a1[4] | |
+ a1[0] | |
+ 2 * a1[1] | |
- 3 * a1[2] | |
- 4 * a1[3] | |
- 7 * a1[6] | |
+ 8 * a1[7] | |
- 9 * a1[8] | |
- 16 * a1[15] * 15 * a1[14] | |
- 17 * a1[16] | |
- 18 * a1[17] == 2520193) | |
s.add( | |
18 * a1[17] | |
+ 17 * a1[16] | |
+ 15 * a1[14] | |
+ 13 * a1[12] * 12 * a1[11] | |
+ 10 * a1[9] | |
+ 9 * a1[8] * 8 * a1[7] | |
+ 3 * a1[2] * 2 * a1[1] * a1[0] | |
- 4 * a1[3] | |
- 5 * a1[4] | |
- 30 * a1[5] | |
- 7 * a1[6] | |
- 11 * a1[10] | |
- 14 * a1[13] | |
- 16 * a1[15] | |
- 19 * a1[18] | |
- 20 * a1[19] == 8904587) | |
s.add( | |
18 * a1[17] | |
+ 7 * a1[6] * 30 * a1[5] * 5 * a1[4] | |
+ 4 * a1[3] | |
+ 8 * a1[7] | |
+ a1[0] | |
- 2 * a1[1] | |
- 3 * a1[2] | |
- 9 * a1[8] | |
- 11 * a1[10] * 10 * a1[9] | |
- 16 * a1[15] * (13 * a1[12] + 12 * a1[11] - 14 * a1[13] - 15 * a1[14]) | |
- 17 * a1[16] | |
- 19 * a1[18] | |
- 20 * a1[19] == 1227620874) | |
s.add(20 * a1[19] * 19 * a1[18] | |
+ 17 * a1[16] | |
+ 14 * a1[13] | |
+ 13 * a1[12] | |
+ 12 * a1[11] * 11 * a1[10] * 10 * a1[9] | |
+ 7 * a1[6] * 30 * a1[5] | |
+ 5 * a1[4] | |
+ 3 * a1[2] | |
+ a1[0] | |
+ 2 * a1[1] | |
+ 4 * a1[3] | |
+ 8 * a1[7] | |
- 9 * a1[8] | |
- 16 * a1[15] * 15 * a1[14] | |
- 18 * a1[17] == 1836606059) | |
s.add( | |
20 * a1[19] * 19 * a1[18] | |
+ 16 * a1[15] * 15 * a1[14] | |
+ 14 * a1[13] | |
+ 13 * a1[12] | |
+ 12 * a1[11] | |
+ 7 * a1[6] * 30 * a1[5] | |
+ 5 * a1[4] | |
+ 2 * a1[1] * a1[0] | |
- 3 * a1[2] | |
+ 4 * a1[3] | |
+ 8 * a1[7] | |
- 9 * a1[8] | |
- 10 * a1[9] | |
- 11 * a1[10] | |
- 17 * a1[16] | |
- 18 * a1[17] == 8720560) | |
s.add(20 * a1[19] * 19 * a1[18] | |
+ 14 * a1[13] | |
+ 13 * a1[12] | |
+ 11 * a1[10] * (10 * a1[9] + 30 * a1[5] + 5 * a1[4] + 4 * a1[3] - 7 * a1[6] + 8 * a1[7] - 9 * a1[8]) | |
+ a1[0] | |
+ 2 * a1[1] | |
- 3 * a1[2] | |
- 12 * a1[11] | |
- (16 * a1[15] - 17 * a1[16] - 18 * a1[17]) * 15 * a1[14] == 11387045) | |
s.add( | |
20 * a1[19] * 19 * a1[18] | |
+ 16 * a1[15] * 15 * a1[14] | |
+ 14 * a1[13] | |
+ 11 * a1[10] * 10 * a1[9] | |
+ 9 * a1[8] | |
+ 3 * a1[2] | |
+ a1[0] | |
- 2 * a1[1] | |
+ 4 * a1[3] | |
- 5 * a1[4] | |
- 30 * a1[5] | |
- 7 * a1[6] | |
+ 8 * a1[7] | |
- 12 * a1[11] | |
- 13 * a1[12] | |
- 17 * a1[16] | |
- 18 * a1[17] == 7660269) | |
s.add(20 * a1[19] * 19 * a1[18] | |
+ 14 * a1[13] | |
+ 13 * a1[12] | |
+ 11 * a1[10] * 10 * a1[9] | |
- 12 * a1[11] | |
+ a1[0] | |
+ 2 * a1[1] | |
- (4 * a1[3] * 3 * a1[2] | |
- 5 * a1[4] | |
- 30 * a1[5]) | |
- 7 * a1[6] | |
+ 8 * a1[7] | |
- 9 * a1[8] | |
- 16 * a1[15] * 15 * a1[14] | |
- 17 * a1[16] | |
- 18 * a1[17] == 2461883) | |
s.add( | |
14 * a1[13] | |
+ 11 * a1[10] * 10 * a1[9] | |
+ 9 * a1[8] * 8 * a1[7] | |
+ 7 * a1[6] | |
+ 2 * a1[1] * a1[0] | |
- 4 * a1[3] * 3 * a1[2] | |
- 5 * a1[4] | |
- 30 * a1[5] | |
- 12 * a1[11] | |
- 13 * a1[12] | |
- 15 * a1[14] | |
- 17 * a1[16] * 16 * a1[15] | |
- 18 * a1[17] | |
- 19 * a1[18] | |
- 20 * a1[19] == -966296) | |
s.add( | |
14 * a1[13] | |
+ 13 * a1[12] | |
+ (11 * a1[10] * 10 * a1[9] + 30 * a1[5] + 5 * a1[4] + 3 * a1[2] + 4 * a1[3] - 7 * a1[6] + 8 * a1[7] - 9 * a1[8]) | |
* 2 | |
* a1[1] | |
+ a1[0] | |
- 12 * a1[11] | |
- 15 * a1[14] | |
- 16 * a1[15] | |
- 17 * a1[16] | |
- 18 * a1[17] | |
- 20 * a1[19] * 19 * a1[18] == 254500223 | |
) | |
s.add( | |
16 * a1[15] * 15 * a1[14] | |
+ 14 * a1[13] | |
+ 11 * a1[10] * 10 * a1[9] | |
+ 7 * a1[6] * 30 * a1[5] | |
+ a1[0] | |
- 2 * a1[1] | |
- 3 * a1[2] | |
- 5 * a1[4] * 4 * a1[3] | |
+ 8 * a1[7] | |
- 9 * a1[8] | |
- 12 * a1[11] | |
- 13 * a1[12] | |
- 17 * a1[16] | |
- 18 * a1[17] | |
- 19 * a1[18] | |
- 20 * a1[19] == 6022286 | |
) | |
s.add( | |
18 * a1[17] | |
+ 16 * a1[15] | |
- 17 * a1[16] | |
+ 14 * a1[13] | |
+ 12 * a1[11] | |
+ 11 * a1[10] * 10 * a1[9] | |
+ 30 * a1[5] | |
+ 5 * a1[4] | |
+ 4 * a1[3] * 3 * a1[2] | |
+ 2 * a1[1] * a1[0] | |
- 9 * a1[8] * 8 * a1[7] * 7 * a1[6] | |
- 13 * a1[12] | |
- 15 * a1[14] | |
- 19 * a1[18] | |
- 20 * a1[19] == -636956022 | |
) | |
s.add( | |
20 * a1[19] * 19 * a1[18] | |
+ 13 * a1[12] | |
+ 12 * a1[11] | |
+ 11 * a1[10] * 10 * a1[9] | |
+ 7 * a1[6] | |
+ 30 * a1[5] | |
+ 5 * a1[4] | |
+ 3 * a1[2] * 2 * a1[1] * a1[0] | |
- 4 * a1[3] | |
- 9 * a1[8] * 8 * a1[7] | |
- 14 * a1[13] | |
- 15 * a1[14] | |
- 16 * a1[15] | |
- 17 * a1[16] | |
- 18 * a1[17] == 10631829 | |
) | |
s.add( | |
20 * a1[19] * 19 * a1[18] | |
+ 16 * a1[15] | |
- 17 * a1[16] | |
- 18 * a1[17] | |
+ 15 * a1[14] * 14 * a1[13] | |
+ 13 * a1[12] | |
+ 11 * a1[10] * 10 * a1[9] | |
- 12 * a1[11] | |
+ 7 * a1[6] | |
+ (4 * a1[3] - 5 * a1[4] - 30 * a1[5]) * 3 * a1[2] | |
+ a1[0] | |
+ 2 * a1[1] | |
+ 8 * a1[7] | |
- 9 * a1[8] == 6191333 | |
) | |
s.add( | |
14 * a1[13] | |
+ 10 * a1[9] * 9 * a1[8] * 8 * a1[7] | |
+ 5 * a1[4] | |
+ 4 * a1[3] * 3 * a1[2] | |
+ 2 * a1[1] * a1[0] | |
- 7 * a1[6] * 30 * a1[5] | |
- 11 * a1[10] | |
- 13 * a1[12] * 12 * a1[11] | |
- 16 * a1[15] * 15 * a1[14] | |
- 18 * a1[17] * 17 * a1[16] | |
- 20 * a1[19] * 19 * a1[18] == 890415359 | |
) | |
s.add( | |
20 * a1[19] | |
+ 19 * a1[18] | |
+ 18 * a1[17] | |
+ 16 * a1[15] | |
- 17 * a1[16] | |
+ 12 * a1[11] | |
+ 11 * a1[10] | |
+ 10 * a1[9] | |
+ 9 * a1[8] | |
+ 30 * a1[5] | |
+ a1[0] | |
+ 4 * a1[3] * 3 * a1[2] * 2 * a1[1] | |
- 5 * a1[4] | |
- 7 * a1[6] | |
+ 8 * a1[7] | |
- 13 * a1[12] | |
- 14 * a1[13] | |
- 15 * a1[14] == 23493664 | |
) | |
s.add( | |
20 * a1[19] * 19 * a1[18] | |
+ 13 * a1[12] | |
+ 12 * a1[11] | |
+ 10 * a1[9] | |
+ 3 * a1[2] * 2 * a1[1] | |
+ a1[0] | |
- 4 * a1[3] | |
- 5 * a1[4] | |
+ 8 * a1[7] * 7 * a1[6] * 30 * a1[5] | |
- 9 * a1[8] | |
- 11 * a1[10] | |
- 14 * a1[13] | |
- 16 * a1[15] * 15 * a1[14] | |
- 17 * a1[16] | |
- 18 * a1[17] == 1967260144 | |
) | |
flag = [] | |
strflag = '' | |
if s.check() == sat: # 检测是否有解 | |
result = s.model() | |
for i in a1: # 因为最后得出的是等式,先遍历 a1,把 a1 的每个依次赋给 i | |
flag.append(result[i]) # 然后找到每个 a1 对应的解,附加到空列表的后面 | |
print(flag) | |
else: | |
print('无解') | |
#得 [104, 97, 104, 97, 104, 97, 116, 104, 105, 115, 105, 115, 102, 97, 99, 107, 102, 108, 97, 103] |
注意 Z3 约束求解器 - 初始化序列时选择正确的格式 比如这里就是 int 型序列
得第二次输入为 [104, 97, 104, 97, 104, 97, 116, 104, 105, 115, 105, 115, 102, 97, 99, 107, 102, 108, 97, 103]
z3 的数据在这里用到,又 weneed 比较数据已知 可求出数组 tempp
cp=[0x00001207, 0x00004CA0, 0x00004F21, 0x00000039, 0x0001A523, 0x0000023A, 0x00000926, 0x00004CA7, 0x00006560, 0x00000036, 0x0001A99B, 0x00004CA8, 0x0001BBE0, 0x00003705, 0x00000926, 0x000077D3, 0x00009A98, 0x0000657B, 0x00000018, 0x00000B11] | |
z33=[104, 97, 104, 97, 104, 97, 116, 104, 105, 115, 105, 115, 102, 97, 99, 107, 102, 108, 97, 103] | |
for i in range(len(cp)): | |
cp[i]^=z33[len(cp)-i-1] | |
print(cp) |
cp (比较数据) 与倒过来的 z33 数据异或得 tempp 数组 [4704, 19649, 20301, 95, 107848, 601, 2375, 19649, 25875, 95, 109032, 19649, 113544, 14193, 2375, 30651, 39673, 25875, 121, 2937]
最后的关键在这一步函数,又因为函数的第二个参数是 int 数组 somenum 已知,tempp 已知,直接爆破 flag
C 语言爆破脚本如下
#include <stdio.h>
#include <string.h>
int baopo(int a1, int a2){
{
unsigned int v3;
v3 = 1;
while ( a2 )
{
if ( (a2 & 1) != 0 )
v3 *= a1;
a1 = a1 * a1 % 1000;
a2 >>= 2;
}
return v3;
}
}
int main(){
unsigned int somenum[20] = {
0x00000007, 0x00000007, 0x00000007, 0x00000009, 0x00000005, 0x00000006, 0x00000007, 0x00000007,
0x00000007, 0x00000009, 0x00000007, 0x00000007, 0x00000005, 0x00000007, 0x00000007, 0x00000007,
0x00000005, 0x00000007, 0x00000009, 0x00000007
};
int cp[20]={4704, 19649, 20301, 95, 107848, 601, 2375, 19649, 25875, 95, 109032, 19649, 113544, 14193, 2375, 30651, 39673, 25875, 121, 2937};
int flag[20]={0};
for(int i=0; i<20; i++){
while (baopo(flag[i],somenum[i]) != cp[i])
{
flag[i]++;
};
printf("%d ",flag[i]);
}
}
运行结果 84 49 101 95 122 51 95 49 115 95 118 49 114 57 95 51 97 115 121 33
转字符即为 flag: T1e_z3_1s_v1r9_3asy! 把 flag 用给定的格式包起来提交就行了
# ctfshow 愚人杯 RE
除了一道抽象谜语题 其他挺简单的 我都能一眼丁真
# easy_pyc
先解 pyc 发现很简单 不过就 114514 有点迷惑性 其实可以直接去掉 我直接 z3 解出
# 脚本及 flag
from z3 import * | |
code = [ 0x16, 0x1d, 0x1e, 0x1a, 0x18, 0x09, 0xff, 0xd0, 0x2c, 0x03, 0x02, 0x14, 0x38, 0x6d, 0x01, 0x43, 0x44, 0xbd, 0xf7, | |
0x2a, 0x0d, 0xda, 0xf9, 0x1c, 0x26, 0x35, 0x27, 0xda, 0xd4, 0xd1, 0x0b, 0xc7, 0xc7, 0x1a, 0x90, 0x44, 0xa1] | |
l = len(code) | |
codec=[] | |
a1 = [BitVec('x%d' % i, 32) for i in range(l)] | |
s = Solver() | |
for i in range(l): | |
num = ((a1[i] + i) ) | |
codec.append(num) | |
for i in range((l - 4) + 1): | |
codec[i] = codec[i] ^ codec[i + 1] | |
for i in range(l): | |
s.add(codec[i]==code[i]) | |
flag = [] | |
if s.check() == sat: # 检测是否有解 | |
result = s.model() | |
for i in a1: # 因为最后得出的是等式,先遍历 a1,把 a1 的每个依次赋给 i | |
flag.append(result[i]) # 然后找到每个 a1 对应的解,附加到空列表的后面 | |
print(flag) | |
else: | |
print('无解') | |
str='' | |
flag=[99, 116, 102, 115, 104, 111, 119, 123, 74, 117, 115, 116, 95, 70, 48, 48, 108, 39, 115, 95, 68, 64, 121, 95, 82, 51, 95, 67, 104, 51, 99, 107, 45, 105, 110, 33, 125] | |
for i in range(len(flag)): | |
str+=chr(flag[i]) | |
print(str) |
ctfshow
# easy_cc
32 位 IDA 打开 程序逻辑很简单 直接解 上脚本
eee=[0x08,0x11,0x1f,0x42,0x5a,0x5c,0x1c,0x1e,0x1a,0x52,0x6d,0x41,0x0e,0x3a,0x1e,0x5e,0x5d,0x57,0x34,0x02,0x16,0x5e,0x56,0x12,0x16] | |
key='key123' | |
key=list(key) | |
v17=[] | |
for i in range(len(eee)): | |
v17.append((eee[i])^ord(key[i%len(key)])) | |
print(v17) | |
strr='' | |
for i in range(len(v17)): | |
strr+=chr(v17[i]) | |
print(strr) |
ctfshow
# babyre
动调
提取的比较数据 [0x79, 0x8F, 0xAA, 0xEE, 0x69, 0x6A, 0x65, 0x53, 0x2B, 0xEE, 0x7B, 0x80, 0x9B, 0xD7, 0x7D, 0x9B, 0xD0, 0x2B, 0xE8, 0x71, 0x7E, 0x9B, 0xBD, 0xFD]
看看加密函数
我直接开爆 (其实是 z3)
from z3 import * | |
temp = [BitVec('x%d' % i, 8) for i in range(24)] # 初始化序列 | |
s = Solver() # 创建约束求解器 | |
cp=[0x79, 0x8F, 0xAA, 0xEE, 0x69, 0x6A, 0x65, 0x53, 0x2B, 0xEE, 0x7B, 0x80, 0x9B, 0xD7, 0x7D, 0x9B, 0xD0, 0x2B, 0xE8, 0x71, 0x7E, 0x9B, 0xBD, 0xFD] | |
l=len(cp) | |
sum=0 | |
for i in range(l): | |
sum=0 | |
for j in range(l): | |
sum=temp[j]+sum | |
temp[i]=sum | |
for i in range(l): | |
s.add(cp[i]==temp[i]) | |
print(s.check()) | |
flag=[] | |
result = s.model() | |
print(result) | |
-----------------get flag------------------- | |
flag=[99,116,102,115,104,111,119,123,104,97,118,101, 95,49,95,102,117,110,95,100,97,121,125] | |
strr='' | |
for i in range(len(flag)): | |
strr+=chr(flag[i]) | |
print(strr) | |
#ctfshow{have_1_fun_day} |
弗拉格为 ctfshow
# easy_re
32 位直接 IDA
逻辑也很清晰 问题是获取 key 可以通过爆破?后面怎么办 做不来摆烂了 等 wp
# not_a_like
NKCTF 一道题,和前面的 ez_z3 类似 魔改的 UPX 壳,不同的是它不是修改了区段头名字而是直接抹去了
和正常的一对比就能补充上头部了
(其实位置没有规定的那么固定)
直接解 upx 然后放进 IDA 中看 可判断为 py 打包 (也可从程序的大小很大看出)
直接 python pyinstxtractor.py not_a_like.exe (这里其实警告说是 python3.8 我是 3.10 但发现没影响后面)
直接找在线工具解密 pyc 得以下 py 脚本
#!/usr/bin/env python | |
# visit https://tool.lu/pyc/ for more information | |
# Version: Python 3.8 | |
import libnum | |
import base64 | |
import hashlib | |
from ctypes import * | |
def encrypt(text): | |
data_xor_iv = bytearray() | |
sbox = [] | |
j = 0 | |
x = y = k = 0 | |
key = '911dcd09ad021d68780e3efed1aa8549' | |
for i in range(256): | |
sbox.append(i) | |
for i in range(256): | |
j = j + sbox[i] + ord(key[i % len(key)]) & 255 | |
sbox[i] = sbox[j] | |
sbox[j] = sbox[i] | |
for idx in text: | |
x = x + 1 & 255 | |
y = y + sbox[x] & 255 | |
sbox[x] = sbox[y] | |
sbox[y] = sbox[x] | |
k = sbox[sbox[x] + sbox[y] & 255] | |
data_xor_iv.append(idx ^ k) | |
return data_xor_iv | |
if __name__ == '__main__': | |
flag = input('%e8%af%b7%e8%be%93%e5%85%a5flag> ') | |
pub_key = [ | |
0x1B6A7561D99E6FC35BA3C241159424698BF3CAC017CFCE8BB325CC9AF9CBCBDB3997B08D922C8705FC3EEAEF50D60ADAB2757A7204715483A1D612502970595358BCFE9CD11C98CAD293EB921D777F4F910905D79CDCA5C1EC1FBA5DA74DB165F82BBE29EA0B2E597860FC6D2C51C12D46BF11AFA5018496DDFC3474B10B4457L, | |
0x6C8E1CC5B384DE3B3316C22CF72D9895406298E172B5F4D890BDC04889BB43CD4892689DE701C84ED68B4CBC7193926BCCB0A4F259D2E752FAEF3CD590A793F120D15424AEB3CD53F5D59B5D41D699694ABF4F01532F0F1CE127B07958FB874982E757EF97643335376790BC990CEE9D7F0D05DA90AD62084C88BFA9C9BEB683L] | |
m = libnum.s2n(flag) | |
c = str(pow(m, pub_key[0], pub_key[1])) | |
q = b'EeJWrgtF+5ue9MRiq7drUAFPtrLATlBZMBW2CdWHRN73Hek7DPVIYDHtMIAfTcYiEV87W7poChqpyUXYI3+/zf5yyDOyE9ARLfa5qilXggu60lmQzFqvFv+1uOaeI2hs2wx+QZtxqGZzC0VCVWvbTQ52nA2UdUtnk8VezRMPMfmf7rOqPxDTv/aacLnI3RdLG2TbT52qtN4+naejI7Xe8HLOL765OZKdDBERKwd5ARQ3UL6YPbuOKOQahIFddnIX6rZ7dTNqCUDOjfJbMdrzJVDNjmNlkLNtYFo7M65Wfwj6PV5vvtT33FsmH50/YLEasnlCiJujYOgi2KCdf5msz1dPEvrXDDL6Csnjo+6m/44RzlluzcqMS5ZJFdrHEh68LIqtu+HCO+69Dyq4e22APq8wgN9kU6R8kikXSn/Ej0N/jOvomFCbkHskRl8xP1KgWFW0SMVDlaDCM4EKG812VgDWgSYOUnVhVpz65uOtg4Z8PrPI+BW4398dQYhD24D9EIPgvtmhNrHiEHouB46ElTGQgZBhtn6y9tL1sw==' | |
v = encrypt(base64.b64encode(c.encode('utf-8'))) | |
v = base64.b64encode(v) | |
if v == q: | |
print('You are right!') | |
input('') | |
else: | |
print('winer winer winnie dinner') | |
print('Do you think the encryption and decryption are the same?') |
分析逻辑知输入 flag 后先是 RSA 加密,再 base64 加密,再 RC4 加密,再 base64 加密 又比较数据已知直接找脚本或工具解就行了
附上一个包括了所有解密的完整脚本
import base64, gmpy2, libnum | |
def continuedFra(x, y): | |
cf = [] | |
while y: | |
cf.append(x // y) | |
x, y = y, x % y | |
return cf | |
def gradualFra(cf): | |
numerator = 0 | |
denominator = 1 | |
for x in cf[::-1]: | |
numerator, denominator = denominator, x * denominator + numerator | |
return numerator, denominator | |
def solve_pq(a, b, c): | |
par = gmpy2.isqrt(b * b - 4 * a * c) | |
return (-b + par) // (2 * a), (-b - par) // (2 * a) | |
def getGradualFra(cf): | |
gf = [] | |
for i in range(1, len(cf) + 1): | |
gf.append(gradualFra(cf[:i])) | |
return gf | |
def wienerAttack(e, n): | |
cf = continuedFra(e, n) | |
gf = getGradualFra(cf) | |
for d, k in gf: | |
if k == 0: continue | |
if (e * d - 1) % k != 0: | |
continue | |
phi = (e * d - 1) // k | |
p, q = solve_pq(1, n - phi + 1, n) | |
if p * q == n: | |
return d | |
c = bytearray() | |
pub_key = [ | |
19252067118061066631831653736874168743759225404757996498452383337816071866700225650384181012362739758314516273574942119597579042209488383895276825193118297972030907899188520426741919737573230050112614350868516818112742663713344658825493377512886311960823584992531185444207705213109184076273376878524090762327, | |
76230002233243117494160925838103007078059987783012242668154928419914737829063294895922280964326704163760912076151634681903538211391318232043295054505369037037489356790665952040424073700340441976087746298068796807069622346676856605244662923296325332812844754859450419515772460413762564695491785275009170060931] | |
q = b'EeJWrgtF+5ue9MRiq7drUAFPtrLATlBZMBW2CdWHRN73Hek7DPVIYDHtMIAfTcYiEV87W7poChqpyUXYI3+/zf5yyDOyE9ARLfa5qilXggu60lmQzFqvFv+1uOaeI2hs2wx+QZtxqGZzC0VCVWvbTQ52nA2UdUtnk8VezRMPMfmf7rOqPxDTv/aacLnI3RdLG2TbT52qtN4+naejI7Xe8HLOL765OZKdDBERKwd5ARQ3UL6YPbuOKOQahIFddnIX6rZ7dTNqCUDOjfJbMdrzJVDNjmNlkLNtYFo7M65Wfwj6PV5vvtT33FsmH50/YLEasnlCiJujYOgi2KCdf5msz1dPEvrXDDL6Csnjo+6m/44RzlluzcqMS5ZJFdrHEh68LIqtu+HCO+69Dyq4e22APq8wgN9kU6R8kikXSn/Ej0N/jOvomFCbkHskRl8xP1KgWFW0SMVDlaDCM4EKG812VgDWgSYOUnVhVpz65uOtg4Z8PrPI+BW4398dQYhD24D9EIPgvtmhNrHiEHouB46ElTGQgZBhtn6y9tL1sw==' | |
e = pub_key[0] | |
n = pub_key[1] | |
# 恢复 c | |
v = base64.b64decode(q) | |
data_xor_iv = bytearray() | |
sbox = [] | |
j = 0 | |
x = y = k = 0 | |
key = '911dcd09ad021d68780e3efed1aa8549' | |
for i in range(256): | |
sbox.append(i) | |
for i in range(256): | |
j = j + sbox[i] + ord(key[(i % len(key))]) & 255 | |
sbox[i], sbox[j] = sbox[j], sbox[i] | |
for idx in v: | |
x = x + 1 & 255 | |
y = y + sbox[x] & 255 | |
sbox[x], sbox[y] = sbox[y], sbox[x] | |
k = sbox[(sbox[x] + sbox[y] & 255)] | |
c.append(idx ^ k) | |
c = int(base64.b64decode(bytes(c))) | |
# 维纳攻击 | |
d = wienerAttack(e, n) | |
m = pow(c, d, n) | |
print(libnum.n2s(m).decode()) |