2021-0xGame第⼀周WriteUp(AK)
⽬录
Web
1. Robots
Robots协议了解⼀下,会被放在⽹站根⽬录下,告诉爬⾍哪些不能爬,哪些能爬。
直接访问.../得到提⽰4ll.html,之后直接访问…/4ll.html,F12查看⽹页源代码,即可得到flag.
0xGame{Rob0t_le4ks_seCr3t}
2. 爱ping才会赢
⾸先发现带有Ping字样的按钮是不可点击的,F12后将对应处的disabled="disabled"删除即可点中。
PHP中实现Ping的功能⼀般是通过类似于exec system的函数调⽤外部命令,在linux中;||&&等连接符可连接两个独⽴语句并执⾏。
输⼊;ls /可查看根⽬录下的⽂件(相当于执⾏了Ping;ls /),到flag后直接输⼊;cat /flag即可。
0xGame{L1nux_cmd_1s_3a5y_t0_you}
3. 你看你能登录吗?
先进⾏⽬录扫描(可⽤的⼯具很多),得到.../admin/进⼊后台,根据提⽰密码是个4位纯数字,也就是说0233也是合法的,之后直接爆破就好了(可⽤Burp Suite或⾃⼰写Python脚本,⽐较简单),账号根据常识,肯定是admin,密码通过爆破得到,为0310,进⼊后台即可拿到flag.
0xGame{y0u_brut3_f0rc3_successfully}
4. 看看我的头
题⽬的名字中就带有提⽰,这⾥的“头”是指“请求头或响应头”,可以拿Burp Suite抓包查看,或者直接在F12后在Network中也可以看见。
点开题⽬后提⽰“打开⽅式不对”,这⾥的⽅式是指“请求⽅式”,我们抓包后发现此题是GET⽅式,我们改成POST⽅式再放包即可发现页⾯有了变化,提⽰需要⽤“N1k0la浏览器”访问,所以,我们修改请求头中User-Agent的内容为N1k0la,即可发现页⾯⼜有了变化,提⽰“必须从本地来”,因此在请求头中添加X-Forwarded-For内容为本地IP地
址127.0.0.1即可。
之后,得到⼀串编码后的字符:
JGE9JF9HRVRbJzB4R2FtZTIwMjEnXTskYj0kX1BPU1RbJ1gxY1QzNG0nXTskZD0kX1BPU1RbJ1B1cGkxJ107JGM9J3dlbGNvbWUgdG8gdGhlIDB 4R2FtZTIwMjEnO2lmKG1kNSgkYik9PW1kNSgkZCkmJiRhPT09JGMpe2VjaG8gJGZsYWc7fQ==
显然是通过了Base64编码,解码后,得到:
$a=$_GET['0xGame2021'];$b=$_POST['X1cT34m'];$d=$_POST['Pupi1'];$c='welcome to the 0xGame2021';if(md5($b)==md5($d)&&$a===$c){ech o $flag;}
可以看到这个就是此题的PHP源代码,是个“弱类型”判断(MD5碰撞)。
其中,md5()返回32位字符串,若均为0e开头可被认为是科学计数法表⽰的数字0.
因此可提交:
0xGame2021=welcome to the 0xGame2021 //GET
X1cT34m=aabg7XSs&Pupi1=aabC9RqS //POST
aabg7XSs => md5: '0e087386482136013740957780965295'
aabC9RqS => md5: '0e041022518165728065344349536299'
当然,md5()也可以⽤数组绕过:当md5函数的参数为⼀个数组时,会报错并返回NULL值。
因此还可以提交:
0xGame2021=welcome to the 0xGame2021 //GET
X1cT34m[]=2333&Pupi1[]=2333 //POST
注意:⽤BurpSuite进⾏POST在最后要保留两⾏“空⾏”。
最终,得到flag:
0xGame{http_pr0t0c0l_1s_int3r3sting:-)}
Misc
1. Sign in
0xGame{Welc0m_to_0xGame2021}
2. A translate draft
附件是⼀个加密了的zip,这是zip伪加密,使⽤010⼗六进制编辑器打开,将80F0h⾏的09改为00即可解密。
压缩包内的word中有⽂字被隐写了,将⽂字全选,改为⿊体字,即可看到被隐写的内容:GB4EOYLNMV5W4MLDMVPXK===,使⽤Base32解密得到flag的前半
段:0xGame{n1ce_u。
打开压缩包,选中word,右击 => 查看⽂件,可看到该word也是⼀个压缩⽂件,其中word⽂件夹内有,其中内容是_s0haq_zr},但这并不是最终的flag,根据⽂件名
的提⽰,我们⽤Rot13或凯撒密码位移13,即可得到另⼀半:_f0und_me}。
0xGame{n1ce_u_f0und_me}
3. Kakurennbo
使⽤vim打开,有蓝⾊的零宽度字符,零宽度字符隐写,将⽂本⽂档内的内容解码,得到被隐藏的内容:0xGame{k}kT_hnG0it4_7rs4_i7nubB0_w,使⽤栅栏W型密码解密,栏
数21,解密后,得到flag:0xGame{kk_n0t_r4inb0w_Bu7_s74iGhT}.
4. 认真的⾎
先使⽤ WinRAR解压(其他压缩软件,如Bandizip好像不⾏),使⽤检测到有NTFS数据流在⾳频⽂件中,在命令⾏中执⾏notepad 认真的雪. 即可提取到内容(或者直接⽤NTFS Streams Editor提取):
He comes and leaves with no survival. HIS CODENAME: 47
_Iv2>6L}%u$0qcD:40Df68N
根据提⽰,使⽤Rot47解码,得到flag:0xGame{NTFS_B4sic_s7eg}
5. ezAlgorithm
⼀个基础得不能再基础的算法题,考虑动态规划。
状态转移⽅程:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
参考代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
const int mod=1435756429;
set<int> bad;
long long dp[4000005];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&k);
bad.insert(k);
}
for(int i=1;i<=n;i++)
{
if(bad.find(i)!=d())continue;
if(i==1){dp[i]=1;continue;}
else if(i==2){dp[i]=dp[i-1]+1;continue;}
else if(i==3){dp[i]=dp[i-1]+dp[i-2]+1;continue;}
dp[i]=((dp[i-1]+dp[i-2])%mod+dp[i-3])%mod;
}
printf("%lld\n",dp[n]);
return 0;
}
得到flag:0xGame{651977145}
Crypto
1. Crypto Sign in
0xGame{Welcom_to_Cryptogrphy_World_!}
2. CuteCaesar
先进⾏兽语解码,得到:0aJdph{fdhvdu_1v_q0w_fxwh},使⽤凯撒密码解密,得到flag:0xGame{caesar_1s_n0t_cute}.
3. manycode
看到颜⽂字,⾸先AAencode解码,得:
4A5645475153435A4B345957595A4A524B4A3347454D4A5A4F5249554F4E4A564C415A453235323249524844533D3D3D
观察到,最⼤的也就F,因此想到Base16解码,得:
JVEGQSCZK4YWYZJRKJ3GEMJZORIUONJVLAZE2522IRHDS===
观察到,最末尾有三个等号(占位符),因此想到Base32解码,得:
MHhHYW1le1Rvb19tQG55X2MwZDN9
最后,再Base64解码,得到flag:
0xGame{Too_m@ny_c0d3}
4. MyFunction
本质就是个解⽅程的问题:已知xlnx,求x。
我很暴⼒,直接先打表,把x为65~122再加上左右⼩括号的ASCII码4041(这些常⽤字符ASCII码)的时候,xlnx的值打出来,再写个程序到⾥查值对⽐即可。(更加暴⼒的)参考脚本:
from math import log
def get_ans(num):
for x in range(1, 200):
if x * log(x) == num:
print(chr(x), end='')
f = open('./')
ans = f.readlines()
for i in range(len(ans)):
ans[i] = float(ans[i].replace('\n', ''))
get_ans(ans[i])
0xGame{YouH4veKn0wedPy7honL081s<y=ln(x)>InM47hs}
5. Class8
第⼀⾏,从左⾄右,依次为:盲⽂,跳舞的⼩⼈,猪圈密码,⼿机九宫格按键加密,摩斯电码
解密的结果是:CLASS
第⼆⾏,从左⾄右,依次为:盲⽂,跳舞的⼩⼈,银河密码,摩斯电码,培根密码
解密的结果是:LNRDD
第三⾏,从左⾄右,依次为:⼿机九宫格按键加密,银河密码,键盘图形码,摩斯电码,培根密码
解密的结果是:LDVTN
最后⼀⾏是⼿机九宫格按键加密,解密为B
合起来,flag为0xGame{CLASSLNRDDLDVTNB}.
6. ABC Of RSA
⼀个基础RSA加密算法:已知p,q,e,求d.
0xGame{39982249}
7. ezVigenère
维吉尼亚密码⽆密钥破解,可以写个程序爆破密钥,最终得到密钥为:abc.
0xGame{interest1ng_Vigenere}
8. BlackGiveRSA
求出d = 1540111621310965943
有性质:m = (c ^ d) % n,其中m是明⽂,c是密⽂。
由给出的密⽂,求出对应的明⽂(⼤数据,防⽌溢出,要⽤⾼精度,可以⽤Python的gmpy2扩展库或者Java的BigInteger或者上⼤数计算的⽹站算),再反过来写个脚本:
from Crypto.Util.number import *
print(long_to_bytes(13643046854681979),end="")
print(long_to_bytes(18973676576264805),end="")
print(long_to_bytes(31037449384842088),end="")
print(long_to_bytes(29636688785989998),end="")
print(long_to_bytes(29073739401619561),end="")
print(long_to_bytes(22874675212740989),end="")
0xGame{ChuTiRenDeQQShiJiShangJiuShiQDeZhi}
Reverse
1. Signin: User Friendly
甚⾄不⽤IDA,直接拿Notepad之类的打开,查即可。
0xGame{we1c0me_2_Rever5e_egin44ring}
2. Packet
先查壳,发现有upx壳,再脱壳即可(我是⽤,命令执⾏.\ -d ⽂件路径)
(a&~b)|(b&~a)等价于a ^ b,位运算异或有⾃反性,即A ^ B ^ B = A ^ ( B ^ B ) = A ^ 0 = A
根据此性质,可写出如下代码:
enc = [0x91, 0x77, 0x0FB, 0x0E, 0x0B7, 0x0CC, 0x0E4, 0x38, 0x11, 0x94, 0x0FD, 0x85, 0x5C, 0x91, 0x84, 0x5C, 0x7D, 0x67, 0x27, 0x134, 0x135 , 0x0A, 0x0D8, 0x23, 0x0D, 0x30, 0x65, 0x3E, 0x13, 0x45, 0x54, 0x52, 0x51, 0x3E, 0x0B0, 0x0D9, 0x13, 0x33, 0x0C3, 0x0FF]
check = [0x0A1, 0x0F, 0x0BC, 0x6F, 0x0DA, 0x0A9, 0x9F, 0x5E, 0x29, 0x0F6, 0x0C5, 0x0E4, 0x6E, 0x0F2, 0x0B1, 0x38, 0x1B, 1 , 0x11, 0x100 , 0 x100 , 0x32, 0x0E9, 0x41, 0x68, 2, 4, 6, 0x2A, 0x70, 0x37, 0x6B, 0x30, 0x5D, 0x82, 0x0E8, 0x25, 0x57, 0x0F2, 0x82]
for i in range(40):
print(chr(enc[i]^check[i]), end="")
0xGame{f8b8a2c5dff64581be2a895c9ac216d1}
3. Our Compilation Story
根据异或的⾃反性,写出如下代码:
k = [21,44,45,104,31,30,26,121,65,125,23,112,77,46,47,126,89,112,7,109,7,88,10,105,104,59,54,91,83,98,32,54,15,65,113,119,113]
k = k[::-1]float up
for i in range(3,37):
print(chr(k[i]^k[i-3]),end="")
0xGame{Th3_10ng_w4y_w3_901ng_fr33}
4. Random Chaos
伪随机数,即如果系统提供的随机种⼦没有变化,每次调⽤rand函数⽣成的伪随机数序列都是⼀样的。
通常可以利⽤系统时间来改变系统的种⼦值,即srand(time(NULL)),可以为rand函数提供不同的种⼦值,进⽽产⽣不同的随机数序列。
再结合异或的⾃反性,写出如下代码:
#include<bits/stdc++.h>
using namespace std;
int a[45]={0x22, 0x0CA, 7, 0x19, 0x0F8, 0x0FB, 0x28, 0x9D, 0x1E, 0x80, 0x0AC, 0x0C9, 0x60, 0x46, 0x18, 0x21, 0x0DF, 0x95, 0x0D5, 0x70, 0x0C 5, 0x19, 0x0EA, 0x0B0, 0x9C, 0x83, 0x11, 0x4A, 0x93, 0x0C7, 0x91, 0x0F6, 0x14, 0x71, 0x2F, 0x22, 0x14, 0x0BF, 0x58, 0x76, 0};
int main()
{
srand(0x2021u);
for(int i=0;i<=39;i++)
{
cout<<(char)((unsigned __int8)rand()^a[i]);
}
return 0;
}
0xGame{d6ca93397ecb4d4e83792a7100737932}
5. Neverland
导致Neverland的原因有两点,第⼀是因为原程序中重复递归调⽤了之前调⽤过的函数,浪费了⼤量的时间,因此,我们可以采取”记忆化“的思路,将其结果保存下来,⽅便之后直接读取,⼆是因为idx⾥的数太⼤了,我们通过规律可知:在⼀定数量之后,idx中值的奇偶性直接影响结果,使其循环出现(其实是unsigned int反复溢出造成的现象)。
参考代码:
#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
unsigned int idx[45]={9, 0x0F, 0x0C, 3, 2, 0x10, 0x0B, 0x0E, 7, 0x0A, 0x2E, 0x2D, 0x2B, 0x2E, 0x2F, 0
x2D, 0x2F, 0x28, 0x31, 0x3A, 0x31, 0x33, 0 x33, 0x2B, 0x32, 0x37, 0x37, 0x38, 0x3C, 0x30, 0x0FFFFFFCE, 0xFFFFFF93, 0x0FFFFFFD8, 0x0FFFFFFF2, 0x0FFFFFFDF, 0x0FFFFFF70, 0x 0FFFFFF72, 0x0FFFFFFD0, 0x0FFFFFFA6, 0x0FFFFFF9A};
unsigned int enc[45]={0x0BFFCC, 0x0BFFFFF84, 0x3000043, 0x0DD, 0x59, 0x61, 0x0BFFF87, 0x30000035, 0x0BF99, 0x300032, 0x36, 0x0FFF FFFC9, 0x0FFFFFF98, 0x30, 0x0FFFFFF9F, 0x0FFFFFFCC, 0x0FFFFFFC8, 0x62, 0x0FFFFFF99, 0x30, 0x0FFFFFFC8, 0x0FFFFFF9A, 0x0FF FFFFC5, 0x0FFFFFF9E, 0x32, 0x0FFFFFFC4, 0x0FFFFFFC8, 0x60, 0x3D, 0x35, 0x3D, 0x0FFFFFFCB, 0x34, 0x3C, 0x0FFFFFF9F, 0x65, 0x65, 0x33, 0x66, 0x79};
unsigned int num[60];
int main()
{
char v0;
num[0]=7;num[1]=8;
for(int i=2;i<=60;i++)num[i]=3*num[i-1]+4*num[i-2]; //记忆化
for(int i = 0; i <= 39; ++i)
{
if(idx[i]>60){if(idx[i]%2)v0=4294967292; else v0=4;}
else v0=num[idx[i]]; //奇偶性
putchar((char)(v0 ^ LOBYTE(enc[i])));
}
return 0;
}
0xGame{1e625d4c04fe44f9b684d919708caa7b}
6. Roundabout
根据异或的⾃反性,写出如下代码:
#include<bits/stdc++.h>
using namespace std;
char b[20] = {0x74,'h','i','s','_','i','s','_','n','o','t','_','f','l','a','g'};
int v[45] = {0x44, 0x10, 0x2E, 0x12, 0x32, 0x0C, 8, 0x3D, 0x56, 0x0A, 0x10, 0x67,0, 0x41, 0, 1, 0x46, 0x5A, 0x44, 0x42, 0x6E, 0x0C, 0x44, 0x72, 0 x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F, 2, 1, 0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68, 0x5B, 0x12};
int main()
{
for(int i=0;i<42;i++)cout<<(char)(v[i] ^ b[i%16]);
return 0;
}
0xGame{b8ed8f-af22-11e7-bb4a-3cf862d1ee75}
7. Zero Three
使⽤python的Z3扩展库解⽅程,参考代码如下:
HINT: 程序计算flag会⽤到两部分计算:前⾯⼀部分会⽤到前半段flag,后⾯⼀部分计算会⽤到整段flag,如果你的z3约束求解迟迟未出结果,或许你可以尝试只约束后半部分计算,依然能得到正确的flag.
from z3 import *
x = Solver()
p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15 = Ints('p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15')
num0,num1,num2,num3,num4,num5,num6,num7 = Ints('num0 num1 num2 num3 num4 num5 num6 num7')
x.add(num0 == p0 + p1*256 + p2*256*256 + p3*256*256*256)
x.add(num1 == p4 + p5*256 + p6*256*256 + p7*256*256*256)
x.add(num2 == p8 + p9*256 + p10*256*256 + p11*256*256*256)
x.add(num3 == p12 + p13*256 + p14*256*256 + p15*256*256*256)
x.add(2 * p5 + 8225 - p0 - 9 * p3 - p4 - p9 + p10 - 6 * p11 - p13 - 3 * p14 - 5 * p15 == 5643)
x.add(3 * p14 + 8 * p10 - 3 * p2 - 6 * p0 + 8225 - p1 - 2 * p5 + 3 * p8 - 8 * p11 + 4 * p12 - 6 * p15 == 6620)
x.add((-5) * p12 - 7 * p6 - 3 * p1 + 8225 - 2 * p0 - p2 - 5 * p3 - 7 * p4 - 6 * p5 - 2 * p8 + 6 * p13 == 5538)
x.add(2 * p5 + 2 * p1 + 8225 - 2 * p0 - 2 * p3 + 3 * p4 - 2 * p8 - p10 - p12 - 2 * p14 - 2 * p15 == 7693)
x.add((-6) * p14 + 8225 - 2 * p1 - 2 * p2 - 9 * p3 + 2 * p4 - 5 * p7 + 2 * p8 - 9 * p9 - 4 * p10 - 6 * p15 == 4735)
x.add(9 * p14 - 7 * p10 + 8 * p9 + 5 * p0 + 8225 - p2 + p5 - 5 * p6 - 8 * p11 - p12 - 9 * p15 == 7060)
x.add(p13 - 5 * p7 - 3 * p2 - 3 * p0 + 8225 - 4 * p1 - 4 * p4 - p6 + 9 * p10 - 2 * p14 - 6 * p15 == 5864)
x.add((-9) * p14 - 3 * p10 + 9 * p1 - 6 * p0 + 8225 - 5 * p3 - 4 * p7 - 2 * p11 - 2 * p12 + p13 + 9 * p15 ==
7393)
x.add(6 * p9 - 5 * p8 - 3 * p6 + 9 * p2 + 8225 - p4 + 3 * p5 - 7 * p7 + 7 * p10 - 2 * p13 - p14 == 8442)
x.add(8 * p6 - 7 * p2 + 8225 - 8 * p1 - p3 + 6 * p4 - p7 + 5 * p8 - 4 * p10 - p14 + 7 * p15 == 8376)
x.add(-22827 * num4 + 21984 * num1 + -38534 * num5 - 32344 * num0 == -98460819657603)
x.add(-38215 * num2 + -37324 * num4 + -8436 * num5 + 15405 * num0 == -131665436206262)
x.add(10926 * num7 + -28942 * num1 + -34572 * num3 - 10538 * num5 == -121891239772992)
x.add(-30117 * num6 + -22990 * num2 + -20471 * num5 + 34494 * num7 == -57089882568260)
x.add(-33112 * num5 + -19335 * num4 + 34348 * num1 + 31445 * num2 == 56335531538050)
x.add(-13566 * num5 + 14758 * num0 + -19814 * num2 - 26447 * num4 == -81105980248303)
x.add(25898 * num5 + -15817 * num1 + 20463 * num7 - 33578 * num0 == -28860618440412)
x.add(-35429 * num7 + 36594 * num2 + -28801 * num6 - 14952 * num3 == -45384029412201)
x.check() #sat
del())
我将python中得到的num[]结果写⼊了当中,再写了个程序转化成flag(⾃⾏意会):
#include<bits/stdc++.h>
using namespace std;
int n,x,y,z;
int main()
{
freopen("","r",stdin);
while(scanf("%d",&n)!=EOF)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论