因为太菜了所以才打了全国第九...
不过半小时AK了crypto是真的【呲牙】
Dawn_whisper_解题报告
MISC
调查问卷
随便填一填就能搞到flag了…
HiddenImage
Look "through" the image and get the flag.
看到题目说明猜测可能是文件捆绑
拿到ubuntu下binwalk一下:
发现的确存在zip文件:
Foremost一下,拿到gotflag.jpg
打开之后发现flag并不是以图片形式显示的,那就用010 Editor打开查看文件尾部,
看到这样可疑的编码
OK,得到flag。
Crypto
RSA
下载文件
Interesting-RSA! You could finish it step by step and please use the search engine appropriately!
看到提示和代码发现这个题是分步给出,所以我们需要一步步的解密。
Part1:
提示很贴心,c1是用p1加密得到的,看到e=3,而且n比c要大得多,就直接将c开3次方得到p。
Part2:
看了半天不知道这个部分对p和q有什么影响,所以直接跳过。
Prat3:
和Part1一样c3是用q加密得到的,所以掏出我们的神器分解一下n顺便求一下d:
如图,该有的数据都有了。
Part4:
一样,flag_c是由flag加密的,所以写可以写出脚本并运行:
直接转成ascii码
Flag到手!
Decrypt it!
说实话拿到题目代码我吃了一惊(逃
165行的代码我也是惊了
不过出题人真的良心,所有的注释写的很详细(还把答案的计算方式写的很清楚),不然我觉得我也得做个半个小时左右。
废话不多说,先分析代码:
上面一大堆奇奇怪怪的代码不用太懂,重要的部分出题人标的很清楚(太良心了啊喂)
其中一个函数,矩阵乘法(比赛的时候我还准备自己写后来发现已经有了2333)
接着往下看:
这么明显的格式基本就能猜到left和right矩阵互为逆矩阵,然而出题人在最后给了提示(太良心了啊喂):
好了不扯这些没用的,接下来我们就看到了整个算法的核心:
加密函数encrypt
(这个注释也太详细了吧,这把难度降了多少啊)
我们一句句分析:
检查长度,不管,跳过,
规定了随机数的种子(因为计算机生成的是伪随机数,所以规定了种子之后后续得到的随机数都是相同的)。
随机生成16个数作为候选key,
乱序,
转为bytes,
把明文和key异或一下
将这时的plaintext(下文简称P)转为二维:
我们将P[0:1]记为P[0],P[1:2]记为P[1]…以此类推,
我们就能得到它将P转为二维的对应表格:
P0 |
P1 |
P2 |
P3 |
P5 |
P6 |
P7 |
P4 |
P10 |
P11 |
P8 |
P9 |
P15 |
P12 |
P13 |
P14 |
接下来继续看:
将这个矩阵和left相乘然后压成一维(这个地方要是没有提示我可能要卡半天)
再把key乱序一下,
再次和plaintext异或一下然后输出,
解密函数,…显然是要我们自己写的。
这里有flag加密后的密文,然而没多大用处,你要是不看的话下面出题人也很贴心:
Flag的获得方式写的清清楚楚♂。
所以分析完,这道题的关键就是写出加密函数的逆函数:
为了方便,下午将cipher_text简称为c,第一次乱序得到的key记为key1,第二次乱序得到的key记为key2,
先提前处理处key1和key2方便后面使用,
我们逆着加密算法倒着进行,首先将c和key2进行异或
然后将一维的c扩展成二维,
将得到的矩阵乘以加密时用到的加密矩阵的逆矩阵,
根据上面加密时对应的表格
我们可以得到返回时所对应的表格:
P0 |
P1 |
P2 |
P3 |
P7 |
P4 |
P5 |
P6 |
P10 |
P11 |
P8 |
P9 |
P13 |
P14 |
P15 |
P12 |
再把key1异或掉,就可以得到加密前的flag
然后运行这个214行的代码(是真的累2333),就可以拿到flag:
Reverse
maze
下载文件放进ubuntu用file看一下:
ELF文件,看来是linux下的逆向,不过我们也可以拖进ida,找到main函数按F5
程序使用了一个参数来表示整个map,其中找到了这么一句话:
得知该map是50个一行。
然后寻找map:
在这个位置找到了map,提取出来之后如图:
wasd顺着!走迷宫
打开文件试一下:
WTF?不对?
再返回ida康康:
map中间有两个奇怪的函数function,点开康康:
发现这个function对map的两个位置进行了修改,根据地址找到位置,手动修改地图,wasd再来一遍,再打开试试:
OK,得到flag。
Programming
死锁
题目很简单,用edge连接事件,bfs即可
代码如下:
1 #include2 3 #include 4 5 #include 6 7 #include 8 9 #include 10 11 using namespace std; 12 13 bool vis[1010]; 14 15 int ru[1010],nex[1010],len,n; 16 17 queue<int> q; 18 19 struct node 20 21 { 22 23 int v,nxt; 24 25 }edge[1010*1010]; 26 27 void add(int u,int v) 28 29 { 30 31 edge[++len]=(node) {v,nex[u]},nex[u]=len; 32 33 } 34 35 void bfs() 36 37 { 38 39 while(!q.empty()) 40 41 { 42 43 int x=q.front(); 44 45 q.pop(); 46 47 vis[x]=1; 48 49 for(int i=nex[x];i;i=edge[i].nxt) 50 51 { 52 53 int v=edge[i].v; 54 55 ru[v]--; 56 57 if(!ru[v]) 58 59 q.push(v); 60 61 } 62 63 } 64 65 } 66 67 int main() 68 69 { 70 71 scanf("%d",&n); 72 73 for(int i=0;i ) 74 75 { 76 77 scanf("%d",&ru[i]); 78 79 if(!ru[i]) 80 81 q.push(i); 82 83 for(int j=1;j<=ru[i];j++) 84 85 { 86 87 int v; 88 89 scanf("%d",&v); 90 91 add(v,i); 92 93 } 94 95 } 96 97 bfs(); 98 99 for(int i=0;i i) 100 101 if(!vis[i]) 102 103 { 104 105 printf("Y\n"); 106 107 return 0; 108 109 } 110 111 printf("N\n"); 112 113 return 0; 114 115 }