admin管理员组文章数量:1565800
REVERSE-COMPETITION-GeekChallenge2021
- Re0
- 刘壮桌面美化大师
- 买Activity
- Re1
- 调试
- 珍惜生命
- new_language
- easypyc
- Brute_force
- win32
- wasm
- 猜拳
- have_a_tea
Re0
64位exe,ida打开,main函数中没发现什么重要的逻辑
Shift+F12打开字符串窗口,直接找到flag明文
刘壮桌面美化大师
apk文件,jadx-gui打开,MainActivity中什么都没有,于是查看与MainActivity在同一目录下的其它类
在DesktopbeautifierConfigureActivityKt类里面找到一个好像和flag相关的方法loadTitlePref
loadTitlePref要获取R.string.flag,我们跟过去发现只是一个整型,实际上是一个资源id
在android中,一个资源id和一个实际的资源绑定,而这个实际的资源在资源文件res中
于是在如下位置找到flag
买Activity
apk文件,加载了buyactivity库,MainActivity大概作用是保存输入到一个msgList里,没什么大用,于是Msg和MsgAdapter这两个类就不用看了
查看ExportedActivity这个类,发现可以直接在一个文本框打印flag
来到Decode类,从本地获取一个字符串,然后对这个字符串顺序异或16即为flag
这个时候可以直接用jeb调试smali,指定启动ExportedActivity即可获得flag
这里我们按照getDecodedFlag方法的逻辑计算flag
ida打开libbuyactivity.so,来到Java_com_sorrowrain_buyactivity_Decode_stringFromNative
可以看到两个字符串和一些操作,下面的操作一时看不懂,直接将两个字符串拼接,然后顺序异或16
可以看到两个字符串拼接顺序异或16后,得到的字符串中含有"{}",说明这个字符串大概率就是flag,但是顺序不对
s="CSD!Os!yiyO#|iU`bu1Ikxc$dFdOCBq!Oh dtm"
flag=""
for c in s:
flag+=chr(ord(c)^16)
print(flag)
# SCT1_c1iyi_3lyEpre!Y{hs4tVt_SRa1_x0td}
看着像栅栏,直接用工具,栏数为2,得到flag
解栅栏前:
解栅栏后:
Re1
64位的exe,ida打开
主要的逻辑在main函数中,输入的长度为44,输入经标准base64变换后与0x40异或,最后与data比较
取出data的数据,写逆脚本即可
import base64
res=[21,113,44,4,37,113,40,16,21,44,121,40,34,45,18,38,25,45,6,58,26,20,
25,112,24,114,6,57,26,22,121,112,33,7,22,38,25,45,6,58,33,24,14,38,
34,114,26,38,35,45,22,114,26,24,10,58,26,24,112,125]
for i in range(len(res)):
res[i]^=0x40
flag="".join(chr(i) for i in res)
print(base64.b64decode(flag))
# SYC{XOR_and_base64_are_the_basis_of_reverse}
调试
64位elf,反编译main函数后就只有一个字符串拷贝
查看main函数的汇编代码,在偏移0x144C处有一条jnz条件跳转指令,如果[rbp+var_144]非零则跳转到loc_1455,但是在偏移0x1382处给[rbp+var_144]赋值为0,所以ida反编译到jnz就判定为不跳转,进而jmp到loc_14A0即main函数结束处
我们看到loc_1455中偏移为0x146B处调用了sub_11C8函数,根据函数调用约定可知上面拷贝来的字符串作为参数传入了sub_11C8函数进行处理
于是可以猜测出题人就是想通过上述不执行jnz条件跳转的方式来隐藏flag
这里我们先去看一下sub_11C8函数,ida分析sub_11C8失败,先在偏移0x11C8处右键->undefine
我们知道函数的开头一般是push rbp,机器码为0x55,于是在偏移0x11CD处,按c将数据转为代码,再按p创建函数,反编译后得到
sub_11CD没看懂什么逻辑,实际上也不需要看懂
出题人通过不执行sub_11CD的方式来隐藏flag,于是我们可以patch程序,将jnz改写成jz,如图
保存后,直接运行elf,即可得到flag
或者不patch程序,根据题目的提示,用ida远程调试elf的时候,在执行jnz之前将零标志位的值修改为0即可将程序流引向执行sub_11CD,进而获得flag
珍惜生命
.pyc文件,用uncompyle6来反编译
输入flag和key,flag长度为51,key长度为8
验证key经过多元方程组运算后是否与"Syclover"相同,然后输入的flag中{}中包含的内容与key做循环异或,结果与一个给定的flag元组比较,验证输入的flag是否正确
def Challenge():
import sys
print("Welcome to py's world")
S = input('plz give me your flag:')
Key = input('plz give me your key(string):')
if len(S) != 51 or len(Key) != 8:
print("the flag's or key's strlen...")
sys.exit()
else:
tmp = S[4:50]
KEY_cmp = 'Syclover'
key = []
key_cmp = ''
for i in Key:
key.append(ord(i))
try:
key_cmp += chr((key[1] * key[2] - key[5] * 72 - key[4] * 3 - key[3] ^ key[1] + (key[3] << 2) + key[2] * 6 - key[7] & key[6] - 1000) - 14)
key_cmp += chr((key[5] * 7 + key[3] * 3 + key[2] + key[6] - (key[2] >> 2) - key[1] ^ key[0] + key[7] + (key[4] ^ key[1]) + (key[4] | key[7])) - 801)
key_cmp += chr((key[6] * 5 + key[2] * 6 - key[3] * 7 + key[4] | key[5] + key[4] * 10 + key[0] ^ key[1] * 3 - key[7] + key[0] + key[1]) - 924)
key_cmp += chr(key[1] * 3 + key[5] * 9 + key[0] + key[2] * 2 + key[3] * 5 - key[4] * (key[6] ^ key[7]) + 321 - 16)
key_cmp += chr((key[5] * 12 - key[0] ^ key[6] - key[3] * 23 + key[4] * 3 + key[2] * 8 + key[1] - key[7] * 2 + key[6] * 4 + 1324) + 1)
key_cmp += chr(key[3] * 54 - key[1] * 3 + key[2] * 3 + key[4] * 11 - key[5] * 2 + key[0] + key[7] * 3 - key[6] - 6298 + 40)
key_cmp += chr(key[7] - key[6] * key[3] + key[2] * key[2] - key[4] * 32 + key[5] * (key[0] >> 2) - key[1] * key[1] - 6689 + 41)
key_cmp += chr((key[5] - key[3] * 41 + key[6] * 41 + key[5] ^ (key[4] & key[6] | key[0]) - (key[7] * 24 | key[2]) + key[1] - 589) - 36)
except ValueError:
print("You know what I'm going to say...")
sys.exit()
if key_cmp != KEY_cmp:
print("You know what I'm going to say...")
sys.exit()
flag = [
113, 74, 71, 35, 29, 91, 29, 12, 114, 73, 60, 52, 69, 5, 113, 35, 95, 38, 20, 112, 95, 7, 74, 12, 102, 23, 7, 31, 87, 5, 113, 98, 85, 38, 16, 112, 29, 6, 30, 12, 65, 73, 83, 36, 12, 23]
for i in range(46):
if ord(tmp[i]) ^ key[((i + 1) % len(key))] != flag[i]:
print("You know what I'm going to say...")
sys.exit()
print('Yeah!Submit your flag in a hurry~')
Challenge()
核心在求解key,用z3解多元方程组即可,需要注意两个地方
1、用BitVec定义变量时需要是16位,笔者开始用8位,一直解不出来
2、此方程组多解,要用while s.check()==sat来输出多组解,需要的是key的8个值都小于128的一组解
from z3 import *
key=[BitVec("key[%d]"%i,16) for i in range(8)]
KEY_cmp="Syclover"
KEY_num=[ord(c) for c in KEY_cmp]
s=Solver()
s.add(((key[1] * key[2] - key[5] * 72 - key[4] * 3 - key[3] ^ key[1] + (key[3] << 2) + key[2] * 6 - key[7] & key[6] - 1000) - 14)==KEY_num[0])
s.add(((key[5] * 7 + key[3] * 3 + key[2] + key[6] - (key[2] >> 2) - key[1] ^ key[0] + key[7] + (key[4] ^ key[1]) + (key[4] | key[7])) - 801)==KEY_num[1])
s.add(((key[6] * 5 + key[2] * 6 - key[3] * 7 + key[4] | key[5] + key[4] * 10 + key[0] ^ key[1] * 3 - key[7] + key[0] + key[1]) - 924)==KEY_num[2])
s.add((key[1] * 3 + key[5] * 9 + key[0] + key[2] * 2 + key[3] * 5 - key[4] * (key[6] ^ key[7]) + 321 - 16)==KEY_num[3])
s.add(((key[5] * 12 - key[0] ^ key[6] - key[3] * 23 + key[4] * 3 + key[2] * 8 + key[1] - key[7] * 2 + key[6] * 4 + 1324) + 1)==KEY_num[4])
s.add((key[3] * 54 - key[1] * 3 + key[2] * 3 + key[4] * 11 - key[5] * 2 + key[0] + key[7] * 3 - key[6] - 6298 + 40)==KEY_num[5])
s.add((key[7] - key[6] * key[3] + key[2] * key[2] - key[4] * 32 + key[5] * (key[0] >> 2) - key[1] * key[1] - 6689 + 41)==KEY_num[6])
s.add(((key[5] - key[3] * 41 + key[6] * 41 + key[5] ^ (key[4] & key[6] | key[0]) - (key[7] * 24 | key[2]) + key[1] - 589) - 36)==KEY_num[7])
while s.check():
print(s.model())
# [key[6] = 54,
# key[1] = 38,
# key[3] = 99,
# key[0] = 83,
# key[7] = 46,
# key[2] = 121,
# key[5] = 45,
# key[4] = 64]
最后key与flag循环异或即可得到flag
flag = [113, 74, 71, 35, 29, 91, 29, 12, 114, 73, 60, 52, 69, 5, 113, 35, 95, 38, 20, 112, 95, 7, 74, 12, 102, 23, 7, 31, 87, 5, 113, 98, 85, 38, 16, 112, 29, 6, 30, 12, 65, 73, 83, 36, 12, 23]
key=[0]*8
key[6] = 54
key[1] = 38
key[3] = 99
key[0] = 83
key[7] = 46
key[2] = 121
key[5] = 45
key[4] = 64
for i in range(len(flag)):
flag[i]^=key[(i+1)%len(key)]
print("SYC{"+"".join(chr(i) for i in flag)+"}")
# SYC{W3$c0m3_T0_th3_py_w0r1d_@nd_z3_1s_s0000_g00d!!}
new_language
32位.Net程序,dnSpy打开,来到Main
text为输入,长度为38,将输入作为下标从sbox中取值,保存到array中,然后array与已知的array2比较
取出sbox和array2,写逆运算脚本即可得到flag
sbox=[99,
124,
119,
123,
242,
107,
111,
197,
48,
1,
103,
43,
254,
215,
171,
118,
202,
130,
201,
125,
250,
89,
71,
240,
173,
212,
162,
175,
156,
164,
114,
192,
183,
253,
147,
38,
54,
63,
247,
204,
52,
165,
229,
241,
113,
216,
49,
21,
4,
199,
35,
195,
24,
150,
5,
154,
7,
18,
128,
226,
235,
39,
178,
117,
9,
131,
44,
26,
27,
110,
90,
160,
82,
59,
214,
179,
41,
227,
47,
132,
83,
209,
0,
237,
32,
252,
177,
91,
106,
203,
190,
57,
74,
76,
88,
207,
208,
239,
170,
251,
67,
77,
51,
133,
69,
249,
2,
127,
80,
60,
159,
168,
81,
163,
64,
143,
146,
157,
56,
245,
188,
182,
218,
33,
16,
255,
243,
210,
205,
12,
19,
236,
95,
151,
68,
23,
196,
167,
126,
61,
100,
93,
25,
115,
96,
129,
79,
220,
34,
42,
144,
136,
70,
238,
184,
20,
222,
94,
11,
219,
224,
50,
58,
10,
73,
6,
36,
92,
194,
211,
172,
98,
145,
149,
228,
121,
231,
200,
55,
109,
141,
213,
78,
169,
108,
86,
244,
234,
101,
122,
174,
8,
186,
120,
37,
46,
28,
166,
180,
198,
232,
221,
116,
31,
75,
189,
139,
138,
112,
62,
181,
102,
72,
3,
246,
14,
97,
53,
87,
185,
134,
193,
29,
158,
225,
248,
152,
17,
105,
217,
142,
148,
155,
30,
135,
233,
206,
85,
40,
223,
140,
161,
137,
13,
191,
230,
66,
104,
65,
153,
45,
15,
176,
84,
187,
22]
array2=[64,
249,
133,
69,
146,
253,
253,
207,
182,
4,
157,
207,
251,
4,
60,
81,
59,
77,
146,
77,
207,
26,
38,
207,
64,
77,
177,
77,
64,
195,
77,
253,
253]
flag=[]
for i in range(len(array2)):
for j in range(len(sbox)):
if sbox[j]==array2[i]:
flag.append(j)
break
print("SYC{"+"".join(chr(i) for i in flag)+"}")
# SYC{right!!_y0u_c0mpIete_C#_reVer3e!!}
easypyc
python打包成的exe,用pyinstxtractor脚本解包
uncompyle6反编译easypyc.pyc失败,原因是解包后的easypyc.pyc文件魔数被破坏,需要修正正确
此为被破坏的easypyc.pyc文件
想要修正easypyc.pyc需要对照同目录下的struct.pyc进行修正,如图
此为修正后的easypyc.pyc文件
保存后再用uncompyle6反编译
whatbox = [
0] * 256
def aaaaaaa(a, b):
k = [
0] * 256
t = 0
for m in range(256):
whatbox[m] = m
k[m] = ord(a[(m % b)])
else:
for i in range(256):
t = (t + whatbox[i] + k[i]) % 256
temp = whatbox[i]
whatbox[i] = whatbox[t]
whatbox[t] = temp
def bbbbbbbbbb(a, b):
q = 0
w = 0
e = 0
for k in range(b):
q = (q + 1) % 256
w = (w + whatbox[q]) % 256
temp = whatbox[q]
whatbox[q] = whatbox[w]
whatbox[w] = temp
e = (whatbox[q] + whatbox[w]) % 256
a[k] = a[k] ^ whatbox[e] ^ 102 #魔改,多异或了一个102
def ccccccccc(a, b):
for i in range(b):
a[i] ^= a[((i + 1) % b)]
else:
for j in range(1, b):
a[j] ^= a[(j - 1)]
if __name__ == '__main__':
kkkkkkk = 'Geek2021'
tttttt = [117, 62, 240, 152, 195, 117, 103, 74, 240, 151, 173, 162, 17, 75, 141, 165, 136, 117, 113, 33, 98, 151, 174, 4, 48, 25, 254, 101, 185, 127, 131, 87]
ssss = input('Please input your flag:')
inp = [0] * len(ssss)
if len(ssss) != 32:
print('Length Error!!!!')
exit(0)
for i in range(len(ssss)):
inp[i] = ord(ssss[i])
else:
aaaaaaa(kkkkkkk, len(kkkkkkk))
bbbbbbbbbb(inp, 32)
ccccccccc(inp, 32)
for m in range(32):
if tttttt[m] != inp[m]:
raise Exception('sorry your flag is wrong')
print('success!!!!!!')
print('your flag is {}'.format(ssss))
aaaaaaa和bbbbbbbbbb是魔改了一点的RC4,最后异或的时候多异或了一个102,解RC4的时候要加上,密钥为"Geek2021"
ccccccccc对RC4加密后的密文进行异或运算,结果与tttttt比较
先逆ccccccccc解得正确的RC4密文
tttttt = [117, 62, 240, 152, 195, 117, 103, 74, 240, 151, 173, 162, 17, 75, 141, 165, 136, 117, 113, 33, 98, 151, 174, 4, 48, 25, 254, 101, 185, 127, 131, 87]
for i in range(len(tttttt)-1,0,-1):
tttttt[i]^=tttttt[i-1]
tttttt[len(tttttt)-1]^=tttttt[0]
for i in range(len(tttttt)-2,-1,-1):
tttttt[i]^=tttttt[i+1]
print(tttttt)
# [34, 87, 28, 210, 186, 225, 87, 69, 104, 210, 181, 143, 128, 51, 105, 175, 135, 170, 87, 83, 3, 64, 181, 140, 38, 18, 59, 220, 71, 155, 93, 161]
再解魔改RC4即可得到flag
#include<stdio.h>
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
k[i] = key[i % Len_k];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
/*
RC4加解密函数
unsigned char* Data 加解密的数据
unsigned long Len_D 加解密数据的长度
unsigned char* key 密钥
unsigned long Len_k 密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
unsigned char s[256];
rc4_init(s, key, Len_k);
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k < Len_D; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] = Data[k] ^ s[t]^102; //这里加一个异或102
}
}
void main()
{
//密钥
unsigned char key[] = "Geek2021";
unsigned long key_len = sizeof(key) - 1;
//密钥
//unsigned char key[] = {};
//unsigned long key_len = sizeof(key);
//密文
unsigned char data[] = { 34, 87, 28, 210, 186, 225, 87, 69, 104, 210, 181, 143, 128, 51, 105, 175, 135, 170, 87, 83, 3, 64, 181, 140, 38, 18, 59, 220, 71, 155, 93, 161 };
//解密
rc4_crypt(data, sizeof(data), key, key_len);
for (int i = 0; i < sizeof(data); i++)
{
printf("%c", data[i]);
}
printf("\n");
return;
}
//SYC{Just_a_Eeeeeeasy_Rc4_right?}
Brute_force
64位exe,ida打开,go语言,左侧函数窗找到main_main
要求运行时加参数,且参数的长度为24
进入main_unnamed630函数,第40行有一个main_encode函数,做了md5散列,返回十六进制摘要
直接在ida中调试一下,断点下在main_unnamed630函数第49行调用runtime_memequal函数前
参数设置为一段长度为24的字符串,如图
程序运行后在此处断下
v15指向我们的输入经main_encode函数处理返回的十六进制摘要,此时为"e2fc714c4727ee9395f324cd2e7f331f"
v19指向要去比较的长度为32的md5十六进制摘要,此时为"957a3926d4ff16d0d3bac4ed3044537b"
通过在线网站查询到v15指向的字符串就是我们输入的前四个字符"abcd"的md5十六进制摘要
那么这题的流程就是将长度为24的输入分成6组,每组4个字符,对每组进行md5散列,返回散列值的十六进制摘要,与已知的长度为32的md5十六进制摘要比较,从而验证输入
每组4个字符,每个字符的ascii码范围为[48,128),可爆破,和题目名称呼应
"957a3926d4ff16d0d3bac4ed3044537b"只是第1组要去比较的md5十六进制摘要,其他5组可通过调试得到
最后全部6组md5十六进制摘要和爆破脚本如下
# -*- coding:utf-8 -*-
import hashlib
s="957a3926d4ff16d0d3bac4ed3044537b"
#s="d7bf94ada03842f20934c5605728fbc5"
#s="5781f597ce91fb5f66057f35846bcb78"
#s="ae4b9b5b2468a3d15b6b8690b761e160"
#s="4ad50c4af2c5beda7aca217afbac9bd6"
#s="f40b339be4c5898741b8a0d2a8007bd5"
for i0 in range(48,128):
for i1 in range(48, 128):
for i2 in range(48, 128):
for i3 in range(48, 128):
flag=chr(i0)+chr(i1)+chr(i2)+chr(i3)
h=hashlib.md5()
h.update(flag.encode(encoding='utf-8'))
if h.hexdigest()==s:
print(flag)
exit()
# 7h3_g0_pr0g@rm_13_slgned
win32
题目名为win32,实际是个64位的exe,upx脱壳,ida打开
题目描述中提到了base64,猜测可能是变表base64
交叉引用Str2来到sub_140011B80函数,主要逻辑在case 0x111处
输入传入sub_1400110F5函数处理,结果放入变量Str1中,与已知的Str2比较,验证输入
进入sub_1400110F5->sub_140011F90
sub_140011F90函数构造了一个表,和标准的base64表是一样的,下面就是正常的base64算法
直接解Str2的base64即可得到flag
wasm
wasm逆向参考:一种Wasm逆向静态分析方法
使用wasm2c将.wasm文件转为.c文件,对.c文件用gcc只编译不链接得到.o文件
ida分析.o文件,w2c_main->w2c_f11
大概的逻辑如下图,判断输入的长度是否等于22,w2c_f10对输入进行变换,w2c_f9对变换后的输入进行比较验证
进入w2c_f10函数,唯一的参数就是我们的输入
看到循环体里有一个异或0x66的运算,结合题目文件名xorwasm,这个异或0x66的运算可能有很大作用
之前猜测w2c_f9是对变换后的输入进行比较验证的函数,但是跟进去分析并没有找到最后要去比较的数据
参考博客里写道,“对于wasm,所有的字符串会被存放在二进制文件的末尾,以此能获取一些关键的信息”
而且在ida字符串窗口中也能找到一些明文字符串
在Hex View中找到这些明文字符串,可以看到在"infinity"这个有意义的单词前正好有22个数据,猜测这些数据就是最后要去比较的数据
直接取出这22个数据,异或0x66后即可得到flag
arr=[0x35, 0x3f, 0x25, 0x1d, 0x11, 0x07, 0x15, 0x0b, 0x39, 0x2f, 0x15, 0x39,
0x35, 0x56, 0x39, 0x21, 0x09, 0x56, 0x02, 0x47, 0x47, 0x1b]
for i in range(len(arr)):
arr[i]^=0x66
print("".join(chr(i) for i in arr))
# SYC{wasm_Is_S0_Go0d!!}
猜拳
64位exe,加了upx壳,但是工具脱不掉壳
根据提示"API断点"猜测可能是通过调试器对按钮相关的API下断点,程序停下来后修改寄存器的值,从而改变程序执行流,得到flag
程序直接扔进x64dbg,然后F9会被程序检测到调试器从而结束进程
这时我们先运行程序,然后让x64dbg去附加(attach)到运行中的程序
附加成功后,右键->搜索->所有模块->字符串
可以发现一些明文字符串
双击字符串"Congratulations on getting the flag"(相当于ida中的交叉引用),找到引用该字符串的指令
我们看到该字符串的上方有一条"Sycl0v3r"的字符串,还有一条"call re.7FF7A77E13D8"的指令
多次调试发现,程序将"Sycl0v3r"作为密钥传入0x7FF7A77E13D8处的函数,对密文进行解密,返回flag
在上图标红处,即"00007FF7A77E1567"处,右键->设置新的运行点,将rip设置到此处
随后F8单步步过,在"call re.7FF7A77E13D8"这条指令执行后即可得到flag
have_a_tea
64位ELF,start函数中存在SMC,在偏移0x1A2F处下断点
启动调试,程序断下来后,F8来到偏移0x0870处
再多按几次F8,来到偏移0x1361处
之后可以不用按F8,往下走,来到偏移0x14C6处,可以看到"db 55h"
我们知道"push rbp"的机器码为0x55,于是这里就是一个函数的起始地址
在偏移0x14C6处按c,将数据转成代码,再按p创建函数,然后F5反编译
sub_55C97B2014C6->sub_55C97B2012BD,可以看到程序正常运行时会打印的字符串
进入sub_55C97B2010B7函数,分析可知
程序对输入进行CBC模式的TEA加密,已知iv和key,密文为res
笔者没有CBC模式的TEA解密脚本,只能先对密文解TEA,然后按CBC模式加密思路来逆CBC
对密文解TEA:
#include <stdio.h>
#include <stdint.h>
//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
} /* end cycle */
v[0] = v0; v[1] = v1;
}
//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i<32; i++) { /* basic cycle start */
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
} /* end cycle */
v[0] = v0; v[1] = v1;
}
int main()
{
uint32_t v[2] = { 0xc9fa3b95,0x7cfd0735 };//0x243a2b27,0x1d133211
//uint32_t v[2] = { 0x958c7c9f,0xc143b59e };//0x8d945ac6,0x2393665c
//uint32_t v[2] = { 0x61741e89,0xf47dcdc4 };//0xfbbc14c5,0x9e22f9c1
//uint32_t v[2] = { 0xd6e2a1f2,0x6a38e9ad };//0x3e1a2ff0,0xab1ca587
//uint32_t v[2] = { 0xc2c16feb,0x8c0ee999 };//0xb883e88a,0x683ae9d0
uint32_t k[4] = { 0x65766967,0x756f795f,0x7075635f,0x6165745f };
int n = sizeof(v) / sizeof(uint32_t);
decrypt(v, k);
for (int i = 0; i < n; i++)
{
printf("0x%x,", v[i]);
}
printf("\n");
return 0;
}
按CBC模式加密思路来逆CBC
from Crypto.Util.number import long_to_bytes
res=[0xc9fa3b95,0x7cfd0735,0x958c7c9f,0xc143b59e,0x61741e89,0xf47dcdc4,0xd6e2a1f2,0x6a38e9ad,0xc2c16feb,0x8c0ee999]
iv=[0]*10
iv[0]=0x5f797274
iv[1]=0x64726168
for i in range(8):
iv[i+2]=res[i]
plain=[0x243a2b27,0x1d133211,0x8d945ac6,0x2393665c,0xfbbc14c5,0x9e22f9c1,0x3e1a2ff0,0xab1ca587,0xb883e88a,0x683ae9d0]
flag=""
for i in range(10):
flag+=long_to_bytes(plain[i]^iv[i])[::-1]
print(flag)
# SYC{ySaySanDian_Zh0n_La_y1n_Cha_xIan}
本文标签: REVERSEcompetition
版权声明:本文标题:REVERSE-COMPETITION-GeekChallenge2021 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dongtai/1726694076a1081000.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论