SCU2022新生赛 签到
Tower_of_Hanoi 1 2 3 4 5 6 7 8 9 10 11 int x[35 ]={ 0x1BF21 , 0x1BF31 , 0x1BF27 , 0x1BF31 , 0x1BF26 , 0x1BF34 , 0x1BF29 , 0x1BF20 , 0x1BF37 , 0x1BF24 , 0x1BF37 , 0x1BF20 , 0x1BF21 , 0x1BF37 , 0x1BF0D , 0x1BF3B , 0x1BF21 , 0x1BF0D , 0x1BF24 , 0x1BF37 , 0x1BF20 , 0x1BF2B , 0x1BF0D , 0x1BF3B , 0x1BF3C , 0x1BF26 , 0x1BF37 , 0x1BF20 , 0x1BF37 , 0x1BF21 , 0x1BF26 , 0x1BF3B , 0x1BF3C , 0x1BF35 , 0x1BF2F , }; int i;for (i=0 ;i<35 ;i++){ putchar (x[i]^0x1bf52 ); }
ez_Android 主体逻辑
即要获取一串0与1组成的字符串,使用check函数检查。
check函数 将apk解压从lib文件夹中找到so文件,check函数就在里面。
根据点击得到的10序列变化基数1,从而得到数组f的下标,再从而得到某特定的值,该值应该对应 likeAndroid字符串的对应位的ASCII值
解题脚本 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 b = [ 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , ... 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ] c = [] d = [] for i in range (len (b)): if b[i] != 0 : c.append(b[i]) d.append(i) a = "even if i only have seven seconds of memory, even if i forget the world, i still love android" total = [] for i in a: num = 0 frq = [] for j in range (len (c)): if ord (i) == c[j]: num = d[j] break if num == 0 : print ("wrong" ) break while num != 1 : if num % 2 == 0 : num = num // 2 frq.append(0 ) else : num = (num - 1 ) // 2 frq.append(1 ) frq.reverse() for t in frq: total.append(t) for i in total: if i == 1 : print ("1" , end="" ) elif i == 0 : print ("0" , end="" ) else : print ("wrong" ) break
最终得到01字符串
DEGUB 调试过程 当执行到除0异常时,更改eip,跳过除0异常。
由调试可发现,程序只是对Input字符串进行位置变换处理。
故,可以根据输入的字符串a变换后的结果b,去获取这个变换的过程。
解题脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 a = "0123456789abcdefghijklmnopqrstuv" b = [0x35 , 0x67 , 0x64 , 0x33 , 0x69 , 0x75 , 0x71 , 0x68 , 0x72 , 0x6B , 0x6A , 0x74 , 0x30 , 0x34 , 0x37 , 0x31 , 0x38 , 0x65 , 0x36 , 0x70 , 0x63 , 0x6C , 0x39 , 0x6E , 0x6F , 0x61 , 0x6D , 0x73 , 0x32 , 0x62 , 0x76 , 0x66 ] c = "fa+cmRG25L5Cst5cqO{CLmy6YigZu6}5" d = [0 ] * 32 for i in range (32 ): for j in range (32 ): if b[i] == ord (a[j]): d[j] = ord (c[i]) for i in d: print (chr (i), end="" )
base 程序逻辑 类似走迷宫,dword_4D7258不能进行变换,因此走的位置在maze中不能为0。
go_way_1和go_way_2是走迷宫的方式,目标是x、y都为29
解题脚本 使用DFS方法走迷宫
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 a = [ 0x20 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , ... 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 ] b = [] for i in range (len (a) // 4 ): b.append(a[i * 4 ]) for i in range (len (b)): if i % 30 == 0 : print () if b[i] != 0 : print ('0' , end=", " ) else : print ('-' , end=", " ) print ()b[0 ] = 0 def gomaze (x, y, flag, maze ): newflag = flag newmaze = [] for t in maze: newmaze.append(t) if x == 29 and y == 29 : print (newflag) if 30 > x + 2 >= 0 and 30 > y - 1 >= 0 and b[x + 2 + 30 * (y - 1 )] != 0 : b[x + 2 + 30 * (y - 1 )] = 0 gomaze(x + 2 , y - 1 , flag + '0' , newmaze) b[x + 2 + 30 * (y - 1 )] = 1 if 30 > x + 1 >= 0 and 30 > y - 2 >= 0 and b[x + 1 + 30 * (y - 2 )] != 0 : b[x + 1 + 30 * (y - 2 )] = 0 gomaze(x + 1 , y - 2 , flag + '1' , newmaze) b[x + 1 + 30 * (y - 2 )] = 1 if 30 > x - 1 >= 0 and 30 > y - 2 >= 0 and b[x - 1 + 30 * (y - 2 )] != 0 : b[x - 1 + 30 * (y - 2 )] = 0 gomaze(x - 1 , y - 2 , flag + '2' , newmaze) b[x - 1 + 30 * (y - 2 )] = 1 if 30 > x - 2 >= 0 and 30 > y - 1 >= 0 and b[x - 2 + 30 * (y - 1 )] != 0 : b[x - 2 + 30 * (y - 1 )] = 0 gomaze(x - 2 , y - 1 , flag + '3' , newmaze) b[x - 2 + 30 * (y - 1 )] = 1 if 30 > x + 2 >= 0 and 30 > y + 1 >= 0 and b[x + 2 + 30 * (y + 1 )] != 0 : b[x + 2 + 30 * (y + 1 )] = 0 gomaze(x + 2 , y + 1 , flag + '4' , newmaze) b[x + 2 + 30 * (y + 1 )] = 1 if 30 > x + 1 >= 0 and 30 > y + 2 >= 0 and b[x + 1 + 30 * (y + 2 )] != 0 : b[x + 1 + 30 * (y + 2 )] = 0 gomaze(x + 1 , y + 2 , flag + '5' , newmaze) b[x + 1 + 30 * (y + 2 )] = 1 if 30 > x - 1 >= 0 and 30 > y + 2 >= 0 and b[x - 1 + 30 * (y + 2 )] != 0 : b[x - 1 + 30 * (y + 2 )] = 0 gomaze(x - 1 , y + 2 , flag + '6' , newmaze) b[x - 1 + 30 * (y + 2 )] = 1 if 30 > x - 2 >= 0 and 30 > y + 1 >= 0 and b[x - 2 + 30 * (y + 1 )] != 0 : b[x - 2 + 30 * (y + 1 )] = 0 gomaze(x - 2 , y + 1 , flag + '7' , newmaze) b[x - 2 + 30 * (y + 1 )] = 1 gomaze(0 , 0 , '' , b)
dp 解题过程 使用pyinstxtractor将exe转化回py,得到的t4文件,在其文件头加入pyc文件头,然后使用uncompyle6将pyc转化为py,得到程序逻辑。
该程序需要点击一定次数后开始运行flag字符串生成,其生成逻辑如下:
1 2 3 4 5 6 7 8 9 10 def gogogo (self, x ): if x >= 5 : self.flag += 1 return self.gogogo(x + 1 ) self.gogogo(x + 2 ) def get_flag (self ): self.gogogo(0 ) return self.flag
举几个例子,可以看出是斐波拉契数列,flag是第102项,在网上直接搜索可得到。
flower 解题过程 动态调试程序,程序报错。
由上图发现,ida提示try,猜测是异常抛出,程序会执行下面的过程,因此更改eip直接执行下面的语句,程序开始正常运行。
程序的逻辑:
判定 input[i] ^ (i%7) == someStr[i]
someStr为程序的数组。
解题脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 Str = [0x73 , 0x62 , 0x77 , 0x60 , 0x70 , 0x63 , 0x7D , 0x4F , 0x74 , 0x70 , 0x5C , 0x70 , 0x60 , 0x67 , 0x6D , 0x5E , 0x6B , 0x70 , 0x5B , 0x6C , 0x68 , 0x5F , 0x74 , 0x70 , 0x64 , 0x61 , 0x6B , 0x72 , 0x5F , 0x6F , 0x67 , 0x66 , 0x60 , 0x5A , 0x69 , 0x66 , 0x5E , 0x70 , 0x66 , 0x72 , 0x60 , 0x74 , 0x73 , 0x64 , 0x5D , 0x73 , 0x68 , 0x64 , 0x7F , 0x65 , 0x73 , 0x71 , 0x7E ] myinput = [] for i in range (len (Str)): myinput.append(Str[i] ^ (i % 7 )) for i in myinput: print (chr (i), end="" )
go 解题思路 看程序的main_main、main_main_func1、main_main_func2、main_main_func3、main_main_func4、main_main_func5函数
后面五个func函数是分别处理访问url的参数的不同所执行的。
其中func2函数中包含scuctf字段,猜测其为提交flag,并且检测flag的地方。
不断调试该程序可以发现变换flag的过程,通过动态调试可以发现flag的转换只是位置上的转换,因此,可以根据输入的字符串a变换后的结果b,去获取这个变换的过程
解题脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 change = [0x30 , 0x35 , 0x61 , 0x66 , 0x6B , 0x70 , 0x75 , 0x31 , 0x36 , 0x62 , 0x67 , 0x6C , 0x71 , 0x76 , 0x32 , 0x37 , 0x63 , 0x68 , 0x6D , 0x72 , 0x33 , 0x38 , 0x64 , 0x69 , 0x6E , 0x73 , 0x34 , 0x39 , 0x65 , 0x6A , 0x6F , 0x74 ] ch = "0123456789abcdefghijklmnopqrstuv" re = "5r+cR6AoCc503=i45q/oR6Zyoq5LairI" flag = [0 ] * 32 for i in range (32 ): for j in range (32 ): if ord (ch[i]) == change[j]: flag[i] = ord (re[j]) break for i in flag: print (chr (i), end="" )
logic 解题过程 查询setjmp、longjmp函数理清程序流程,一共有三个函数。
第一个函数逻辑为:检查输入字符串每两位组合,前一个组合组成的数小于后一个组合组成的数;
第二个函数逻辑为:根据输入字符串对一个数组进行操作;
第三个函数逻辑为:其逻辑相当于检查被操作数组的每一个值。
由于被操作数组的结果正的相加为101,为输入字符串的一半,而负的相加为96,可以推断出每个组合的第一个数其对应数组的地方只加不减,而第二个数其对应数组的地方只减不加,且倒数五个组合的第二个数必须为Z。
解题脚本 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 def changenum (num ): if 0 <= num <= 9 : return chr (num + 48 ) elif 10 <= num <= 35 : return chr (num + 87 ) elif 36 <= num <= 62 : return chr (num + 29 ) def changestr (ch ): num = ord (ch) if 48 <= num <= 57 : return num - 48 elif 97 <= num <= 122 : return num - 87 elif 65 <= num <= 90 : return num - 29 a = [0x1 ...0 x5] frequencyOfNum = [0 ] * 62 for i in range (62 ): if i == 0 : frequencyOfNum[i] = a[i] else : frequencyOfNum[i] = a[i] - a[i - 1 ] print (frequencyOfNum[i], end=", " ) result = [-1 ] * 202 index1 = 0 index2 = 0 for i in range (62 ): if frequencyOfNum[i] > 0 : for j in range (frequencyOfNum[i]): result[index1 * 2 ] = i index1 += 1 if frequencyOfNum[i] < 0 : for j in range (-frequencyOfNum[i]): result[index2 * 2 + 1 ] = i - 1 index2 += 1 for j in range (5 ): result[index2 * 2 + 1 ] = 61 index2 += 1 print ("\n" , result)flag = "" for i in result: flag += changenum(i) print (flag)
pyc 将pyc转换为py,可以看出类似矩阵计算。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 sss = "99 ... 121674" // 条件等式 ss = sss.split(" and " ) num = [] r = [] for i in ss: s = i.split(" " ) x = [] for i in range (25 ): x.append(int (s[i * 4 ])) num.append(x) r.append(int (s[100 ])) import numpy as npb = np.array(num) a = np.array(r) flag = np.linalg.solve(b, a) print (flag)for i in flag: print (chr (round (i)), end="" )
xxx 程序一开始为检查函数解密出来,运行完解密函数,就可以知道检查函数了,
故使用动态调试,然后看汇编代码知道检查函数的流程,大概是(input + 4) ^ 0x28,然后进行比较。
解题脚本 1 2 3 b = [0x7E ... 0x00 ] for i in range (len (b) // 4 ): print (chr ((b[i * 4 ] ^ 0x28 ) - 4 ), end="" )
VM 解题过程 case0对应add,case1对应sub,case2对应xor,case3对应cmp,case456对应各类jmp,case7对应获取input,case8对应赋值input,case9对应获取具体操作。
三个数组分别为input、stack、operation,index被放在了input[0x32]
然后就是动态调试看程序的逻辑:
input[i] = input[i] ^ input[i+1]
input[i+1] = (input[i] - i) + input[i+1]
进行结果比较
解题脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 d = [0x3d , 0x56 , 0x80 , 0xb3 , 0xc9 , 0xf0 , 0x128 , 0x15f , 0x180 , 0x196 , 0x1a7 , 0x1a2 , 0x197 , 0x19e , 0x19d , 0x1c1 , 0x1e3 , 0x1de , 0x1ce , 0x1c6 , 0x1b3 , 0x1a5 , 0x19a , 0x1e8 ] c = [0 ] * 25 d.reverse() for i in range (23 ): c[i] = d[i] - d[i + 1 ] + (24 - i - 1 ) for i in range (23 ): c[i + 1 ] = c[i] ^ c[i + 1 ] c.reverse() for i in c: print (chr (i), end="" )
unity dnspy打开Assembly-CSharp.dll,找到其方法、函数等,发现其中有个GameManger,应该是管理游戏的类,再在其中发现Update方法,应该是判定游戏是否可以继续以及画面更新的方法。
在其中发现了Gameover变量,猜测是判定游戏是否可以继续的值,将赋值为true的地方更改为false,打开游戏,我不死了。