BeginCTF2024部分逆向

real_xor

给的python,一眼循环异或

xor-1

先脱壳

搜字符串找到密文

从start进入,找到code

复制数字和明文

异或数字

反向异或,其实伪c是很奇怪的i=0,下标为16,但是看汇编确实是这样

而且c用16来算就是对的

又来一整轮

ida7.5可以显示中文

当时就这样,直接乱序

我知道了,我写的脚本是一位一位的加到flag里,而现实是16位算完直接复制的,当然有点问题,第一个f没了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
fin = [ord(i) for i in "`agh{^bvuwTooahlYocPtmyiijj|ek'p"]

lst9 = fin[:16]
lst8 = fin[16:]

lst7 = [ord(i) for i in "3092606632787947"]
lst6 = [ord(i) for i in "4180387362590136"]

for i in range(1, 16):
lst8[i] ^= lst6[16-i]
lst9[i] ^= lst7[16-i]

for i in range(1, 16):
lst8[i] ^= lst7[16-i]
lst9[i] ^= lst6[16-i]

for i in range(16):
lst8[i] ^= lst6[i]
lst9[i] ^= lst7[i]

for i in range(16):
lst8[i] ^= lst7[i]
lst9[i] ^= lst6[i]

lst4 = lst8
lst3 = lst9

lst1 = [ord(i) for i in "6329079420771558"]
lst2 = [ord(i) for i in "7679621386735000"]

for i in range(1, 16):
lst3[i] ^= lst1[16-i]
lst4[i] ^= lst2[16-i]

for i in range(1, 16):
lst3[i] ^= lst2[16-i]
lst4[i] ^= lst1[16-i]

for i in range(16):
lst3[i] ^= lst1[i]
lst4[i] ^= lst2[i]

for i in range(16):
lst3[i] ^= lst2[i]
lst4[i] ^= lst1[i]

flag = "".join([chr(i) for i in lst3 + lst4])

print(flag)

下面用动调做:

椰奶师傅说是要去符号表,这里本来就去了符号,不过链接好的地址没有去

符号通常是变量或函数的名称,符号表可用于确定变量或函数在内存中的位置。

所以strip一下可以去掉,现在就只剩下偏移了,而且可以直接动调到密文比较处

imgimg

真的从0x7f开头变成0x14开头啦,而且直接出

红白机-1

6502汇编

找不到flag头

结果跟我说在线网站

https://itema-as.github.io/6502js/

俄语学习-1

直接乱输,然后修改zf绕过

伪rc4?

str复制有点奇怪,是0到strlen,后面密文比较也是少了一位

直接逆向跑出来这个鬼东西

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
s1='m5d5w5d5b5n5m5d5w5d5b5n5m5d5w5d5b5n'
s2='+i&[@Y:g8[&l$f8S8v$Y&e>{'
#s2=[0x2b, 0x69, 0x26, 0x5b, 0x40, 0x59, 0x3a, 0x67, 0x38, 0x5b, 0x26, 0x6c, 0x24, 0x66, 0x38, 0x53, 0x38, 0x76, 0x24, 0x59, 0x26, 0x65, 0x3e, 0x7b]
print(len(s2))
a=[0x38, 0x9A, 0xFA, 0xC3, 0x5B, 0x89, 0xA5, 0xE6, 0xD0, 0xAB,
0x42, 0x58, 0x57, 0x09, 0x42, 0xAB, 0x33, 0x2F, 0x98, 0x42,
0x2E, 0x59, 0x6D]
print(len(a))
s_ni=[0x35, 0x8E, 0x0B, 0x19, 0x7A, 0xF6, 0x31, 0x9C, 0xD9, 0x2C,
0xC1, 0xFC, 0xE2, 0xD8, 0x1D, 0x8D, 0x4F, 0x97, 0x81, 0x26,
0xC0, 0xB8, 0x96, 0x27, 0xD5, 0x5B, 0xAA, 0x18, 0x85, 0xFA,
0x61, 0xE4, 0xA1, 0xBC, 0xF8, 0xA4, 0x56, 0x37, 0x43, 0x58,
0x2B, 0xC9, 0x77, 0x64, 0xCC, 0x6B, 0x98, 0x65, 0x75, 0x38,
0x80, 0x09, 0x11, 0x3D, 0xD0, 0xE6, 0x8F, 0xA9, 0x57, 0x99,
0x06, 0x10, 0x5D, 0xC5, 0x69, 0xBD, 0x2D, 0x68, 0x7E, 0xE3,
0x67, 0xD1, 0xFF, 0x5E, 0xF9, 0xF5, 0x41, 0x8C, 0xDD, 0x21,
0x4B, 0xA7, 0x47, 0x86, 0x6D, 0xC3, 0x2A, 0x9A, 0x9F, 0x20,
0x48, 0xBB, 0x94, 0xB9, 0xB4, 0x92, 0x02, 0x74, 0x7D, 0x1B,
0x1E, 0x5F, 0xBA, 0x49, 0xD6, 0xE7, 0x53, 0x04, 0xCB, 0x28,
0x3F, 0xE8, 0x33, 0x3E, 0x00, 0x9B, 0x6A, 0xFD, 0xBE, 0x1C,
0x90, 0xED, 0xDF, 0x4D, 0x25, 0x6F, 0xB5, 0x13, 0x70, 0x3C,
0x9E, 0x16, 0x0C, 0x05, 0x4A, 0x73, 0xDE, 0xB1, 0x8A, 0x51,
0x3B, 0x54, 0x14, 0xE0, 0x5A, 0xDC, 0x91, 0x62, 0xA3, 0x95,
0xD3, 0x3A, 0x17, 0xEE, 0x32, 0xF2, 0x7C, 0xAF, 0xB3, 0x88,
0xEC, 0x0E, 0xAE, 0x9D, 0x5C, 0x0D, 0x55, 0x4E, 0xFB, 0x46,
0x22, 0x44, 0x45, 0xBF, 0x52, 0x12, 0x66, 0x07, 0xD2, 0x36,
0x93, 0x6E, 0x42, 0x1A, 0x0F, 0xE9, 0x60, 0xCA, 0xB2, 0x6C,
0x83, 0xF0, 0x03, 0x76, 0xA8, 0x1F, 0x63, 0xEF, 0xA5, 0xCD,
0x79, 0x7B, 0x0A, 0xDA, 0xAB, 0xDB, 0xD4, 0x7F, 0x01, 0x34,
0x23, 0x59, 0xE1, 0x29, 0xC6, 0xAC, 0xA2, 0x40, 0xC8, 0xAD,
0xC4, 0x89, 0xC2, 0xB6, 0x71, 0xA0, 0xEB, 0x2F, 0x78, 0xF3,
0xB0, 0xFE, 0xCE, 0xF7, 0x84, 0x72, 0xF4, 0xCF, 0xC7, 0xD7,
0xB7, 0xF1, 0x4C, 0x82, 0x30, 0x50, 0x2E, 0x24, 0x87, 0x08,
0x39, 0xE5, 0xEA, 0xA6, 0x8B, 0x15]
s=[0x35, 0x8E, 0x0B, 0x78, 0xB4, 0x6D, 0x05, 0xBC, 0x39, 0x27,
0xFE, 0x2F, 0xEF, 0xAF, 0x60, 0xD1, 0xD3, 0x6B, 0x52, 0xE1,
0xA3, 0x41, 0xEB, 0x43, 0xC2, 0x5B, 0xAA, 0x18, 0x85, 0xFA,
0x61, 0xE4, 0xA1, 0x9C, 0xF8, 0xA4, 0x56, 0x37, 0x2C, 0x58,
0x2B, 0xC9, 0x77, 0x64, 0xCC, 0x97, 0x98, 0x65, 0x75, 0x38,
0x80, 0x09, 0x11, 0x3D, 0xD0, 0xE6, 0x8F, 0xA9, 0x57, 0x99,
0x06, 0x10, 0x5D, 0xC5, 0x69, 0xBD, 0x2D, 0x68, 0x7E, 0xE3,
0x67, 0x8D, 0xFF, 0x5E, 0xF9, 0xF5, 0xB8, 0x8C, 0xDD, 0x21,
0x4B, 0xA7, 0x47, 0x86, 0xF6, 0xC3, 0x2A, 0x9A, 0x9F, 0x20,
0x48, 0xBB, 0x94, 0xB9, 0x7A, 0x92, 0x02, 0x74, 0x7D, 0x1B,
0x1E, 0x5F, 0xBA, 0x49, 0xD6, 0xE7, 0x53, 0x04, 0xCB, 0x28,
0x3F, 0xE8, 0x33, 0x3E, 0x00, 0x9B, 0x6A, 0xFD, 0xBE, 0x1C,
0x90, 0xED, 0xDF, 0x4D, 0x25, 0x6F, 0xB5, 0x13, 0x70, 0x3C,
0x9E, 0x16, 0x0C, 0x31, 0x4A, 0x73, 0xDE, 0xB1, 0x8A, 0x51,
0x3B, 0x54, 0x14, 0xE0, 0x5A, 0xDC, 0x91, 0x62, 0xC0, 0x95,
0x4F, 0x3A, 0x17, 0xEE, 0x32, 0xF2, 0x7C, 0xD8, 0xB3, 0x88,
0xEC, 0x0E, 0xAE, 0x9D, 0x5C, 0x0D, 0x55, 0x4E, 0xFB, 0x46,
0x22, 0x44, 0x45, 0xBF, 0x81, 0x12, 0x66, 0x07, 0xD2, 0x36,
0x93, 0x6E, 0x42, 0x1A, 0x0F, 0xE9, 0x1D, 0xCA, 0xB2, 0x6C,
0x83, 0xF0, 0x03, 0x76, 0xA8, 0x1F, 0x63, 0xE2, 0xA5, 0xCD,
0x79, 0x7B, 0x0A, 0xDA, 0xAB, 0xDB, 0xD4, 0x7F, 0x01, 0x34,
0x23, 0x59, 0x26, 0x29, 0xC6, 0xAC, 0xA2, 0x40, 0xC8, 0xAD,
0xC4, 0x89, 0xD5, 0xB6, 0x71, 0xA0, 0x96, 0xFC, 0x19, 0xF3,
0xB0, 0xC1, 0xCE, 0xF7, 0x84, 0x72, 0xF4, 0xCF, 0xC7, 0xD7,
0xB7, 0xF1, 0x4C, 0x82, 0x30, 0x50, 0x2E, 0x24, 0x87, 0x08,
0xD9, 0xE5, 0xEA, 0xA6, 0x8B, 0x15]
print(len(s))
flag=''

def rc4(s,a):
i=0
j=0
for k in range(23):
i=(i+1)%256
j=(j+s[i])%256
s[i],s[j]=s[j],s[i]
a[k]^=s[(s[i]+s[j])%256]
print(a)

if __name__== '__main__':
rc4(s_ni,a)
for i in range(len(a)):
flag+=chr(a[i]+112-ord(s1[i]))
print(flag)

后面显示说上面每答对一个问题,就填充一部分s盒,所以我的绕过会使s盒有问题,怪不得说正向加密也会不对

正确的s盒,果然和我的有差别

也可以直接猜是rc4,因为我找不到rc4的初始化过程

1
2
3
4
5
6
7
8
9
10
11
t = b"5m5d5w5d5b5n5m5d5w5d5b5n5m5d5w5d5b5n\x8e"
# tmp[i] = flag[i] + t[i]-112
from Crypto.Cipher.ARC4 import *
enc = bytes([0x38, 0x9A, 0xFA, 0xC3, 0x5B, 0x89, 0xA5, 0xE6, 0xD0, 0xAB, 0x42, 0x58, 0x57, 0x09, 0x42, 0xAB, 0x33, 0x2F, 0x98, 0x42, 0x2E, 0x59, 0x6D, 0x41])
rc4 = new(t)
p = rc4.decrypt(enc)
print(p)
p = list(p)
for i in range(len(p)):
p[i] = (p[i]+112-t[i])&0xff
print(bytes(p))

还可以直接交叉引用(x)找资源

superguesser-1

有很多这样的花指令,反编译错误在数据后面

转化为数据之后无法创建函数

可能用脚本去花指令?

加了XObf混淆器

下硬件断点可以在这些字符串被引用的时候断下来

可以看到停在了输入

不断ctrl+f7(找函数调用关系)

直接猜异或

ezpython-1

找不到key和enc,要去secret.pyc里找

这就要求必须用python3.8反编译

也可以直接大厨

stick game-1

类似于跳一跳

有obfus混淆

用网站去混淆

Obfuscator.io Deobfuscator

一开始let score=0,后面会resetGame

直接去改关键词score,发现分数好像没变

要么去case6score+=99999999

要么去改scoreElement,本质上还是score

死了才能获得flag

在html界面找到元素下断点,然后玩游戏立刻就能找到真正的score

arc-1

大致来说就是字典太多,pydc反编译不了,我这里用python3.8.3编译,用anconda默认的3.8.13不行

一行行运行,得到类似结果

最终是list里又是list

替换之后发现是3维列表

最后也就是这个样子,不懂的可以问gpt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
print
(
all
(
[
[data][a][d] == e
for a, b in enumerate
(
[
[int(a) for a in bin(sum((ord(b) << 6 ^ 4102 - a ^ c for c in b'beginCTF'))).replace('0b', '')]
for a, b in enumerate
(
input('[+]Flag: ')
)
]
)
for d,e in iter #迭代器
(
(enumerate(b))
)
]
)

写脚本爆破

1
2
3
4
5
6
7
8
9
data = [[1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0], [1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0], [1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0], [1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0], [1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0], [1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0], [1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0], [1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0], [1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0], [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0], [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0], [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0], [1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0], [1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0], [1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0], [1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0], [1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0], [1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0], [1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0], [1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0], [1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0], [1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0], [1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0], [1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0]]

for i, lst in enumerate(data): #i是索引,lst是子序列(每一行)
for j in range(32, 128): #爆破有效字符
n = int("".join([str(x) for x in lst]), 2) #把每一行的数字连起来变成二进制,再转换为十进制
if sum((j << 6 ^ 4102 - i ^ key for key in b'beginCTF')) == n:
print(chr(j), end="")
break
#begin{Y@u_aRe_g00d_aT_play1ng_witH_sNake3}

not_main-1

main函数有个tea

有veh反调试

本题通过实现一个全局类让程序在main函数之前就执行类的构造函数,在main函数结束后执行类的析构函数

构造函数中veh定义了int 3断点和除0异常的处理方法

int3断点的处理逻辑是,当前程序在main函数中会执行事先放置的int3,此时如果在未调试的情况下,程序将异常交给veh处理,将一个dword_405038赋值为0. 如果是调试情况下将异常交给调试器处理,如果此时调试器处理异常则不会交给veh,则dword_405038为1.main函数接下来会对输入进行虚假的判断。在判断后进入到析构函数中

析构函数会根据先前的dword_405038即图中的is_debug变量的值判断是否除零。除零进入到veh handler的除零异常处理块中

后面是标准的xxtea

在start里找到关键函数

第三个参数可以看到两个疑似密文的地址

unk_485018引用分别在Handler和main,有可能是main里的假密文

第四个则会触发Handler

Handler内的unk_485018引用则再次进行了这个操作,也就是说等于没异或

所以如果真逻辑在Handler内,unk_485018就是没用的数据,真正的密文就是unk_48503C

可以以这种方式取数据

发现调用Handler在main之前

可以看到main当中的明文是从Handler中引用的,可能XXTEA之后又进行了TEA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2)+(y>>3^z<<4))^((sum^y)+(key[(p&3)^e]^z)))
void btea(uint32_t* v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1)
{
rounds = 6 + 52 / n; //这里可以说是预定义值,n=2是rounds=32
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1)
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
void detea(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0; v[1] = v1;
}
int main()
{
uint32_t v[8] = { 0xCFBE0F1B, 0x05F3083F, 0x4220E43B, 0x3383AFEE, 0xFA3237CE, 0xECADA66E, 0xA8D47CA7, 0xEFC51077 };
uint32_t k[4] = { 116,114,117,101 };//true
uint32_t fk[4] = { 0x66,0x61,0x6B,0x65 };//fake
int i, n = 8;
btea(v, -n, k);//负号是解密
for (i = 0; i < 8; i += 2)
detea(v + i, fk);
printf("%s", v);
return 0;
}
//begin{not_main_is_matter!}

出题人的密码-1

有花指令,按官方wp的方法去花指令

call指令按u,下一行按c,再nop call,把90转为数据,再按c变为nop

密文

搜Buffer的引用就可以快速找到加密函数

直接逆向,但是v2不知道

直接下断点会有反调试,回到主函数,下断点判断反调试在一开始的地方

修改zf绕过

发现下面还有一个,再次改zf

直接得到的key是不对的,因为还有时间反调试

nop掉然后apply,输入账号的时候记得输入群号612995005

交叉引用输入的字符串

先+5 ^0x25,然后传给比较的密文

主要加密是一个魔改的crc64,通过和零比较,从而进行不同的加密,实际上是比较最高位

可以直接逆

高位溢出到了最低位,所以看密文最低位,根据最低位判断这个数在加密前最高位是1还是0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
key = 0x33077d

def decrypt(value, key):
for i in range(64):
if value & 1:
value = (value ^ key) >> 1
value |= 0x8000000000000000 #还原最高位
else:
value = value >> 1
return value

out = bytes.fromhex('B4BBD8EBD06EABCA658E4BE94DD44AF37D29C2F99589A4859DCDDF77FD45CB5D7DFD934BBCF67CF32442F5D2DDE356AE')
out = [((i ^ 0x25) - 5) & 0xff for i in out]
print(out)

flag = b''
for i in range(0, len(out), 8):
v = int.from_bytes(out[i: i + 8], 'little')
flag += decrypt(v, key).to_bytes(8, 'little')

print(flag.decode())

goforfun-2

和big库有关

rc4部分很难辨别,同时key也找不到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def big_int_to_byte_array(big_int):
ans=[]
while big_int :
ans.append(big_int&0xff)
big_int>>=8
return ans[::-1]


cmpString = "HZ0sMJXqxHgUb2b9RNg+1xw"

str1 = "8G+cazk2jqb7w01CtoKH4FsrgR3vVmQ9pPhXLAleOd/nB6DfIxMWYiUZ5SEJyNuT"

cmpString = list(cmpString)

str1 = list(str1)

tmp=[]

for i in cmpString:
tmp.append(str1.index(i))

print('index:')
print(tmp)

bignum = 0

for i in range(len(tmp)-1,-1,-1):
bignum = bignum*0x40 + tmp[i]

#print('bignum:')
#print((bignum))

bytea = big_int_to_byte_array(bignum)

#print(bytea)

def rc4_crypt(key, data):
S = list(range(255,-1,-1))
j = 0
out = []

# 初始化S盒
for i in range(256):
j = (j + S[i] + ord(key[i % len(key)]) ) % 256
S[i], S[j] = S[j], S[i]

# 生成密钥流并加解密
i = j = 0
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
out.append(((char) ^ S[(S[i] + S[j]) % 256]^0x2f))

return out


key1='happynewyear'

key1 = list(key1)

flag=rc4_crypt(key1,bytea)
for i in flag:
print(chr(i),end='')

BeginCTF2024部分逆向
https://j1ya-22.github.io/2024/03/13/BeginCTF2024部分逆向/
作者
j1ya
发布于
2024年3月13日
许可协议