web680

进入页面显示post code to run!

传入code=phpinfo();

查看disable_functions

assert,system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstoped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,fopen,file_get_contents,fread,file,readfile,opendir,readdir,closedir,rewinddir

code=var_dump(scandir(“.”));查看当前目录下有什么东西.

发现有个secret_you_never_know

访问即可获得flag.

web681

用 dirsearch扫描,发现存在.svn,访问可以拿到www.zip获得源码。

index.php:

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
<?php
include "flag.php";

session_start();

if(isset($_SESSION['hat'])){
if($_SESSION['hat']=='green'){
output("<img src='images/green.jpg'>",8);
}else{
output("<img src='images/black.jpg'>",1);
echo $flag;
}

echo "<br><br><br><br><br><a href='logout.php'>I give up!</a>";
}else{
output("<img src='images/white.jpg'>",6);
echo "<br><br><br><br><br><a href='login.php'>I want to check the color of my hat!</a>";
}

function output($content,$count){
for($i=0;$i<$count;$i++){
echo $content;
}
}
?>

check.php:

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
<?php
error_reporting(0);
include "common.php";

session_start();

if (isset($_POST["name"])){
$name = str_replace("'", "", trim(waf($_POST["name"])));
if (strlen($name) > 11){
echo("<script>alert('name too long')</script>");
}else{
$sql = "select count(*) from ctfshow_users where username = '$name' or nickname = '$name'";
echo $sql;
$db = new db();
$result = $db->select_one_array($sql);
if ($result[0]){
$_SESSION['hat'] = 'black';
echo 'good job';
}else{
$_SESSION['hat'] = 'green';
}
header("Location: index.php");
}

}
?>

也就是让result[0]=true即可返回flag。

sql注入,使用||1#\即可绕过。

web682

查看hint里面未混淆的js代码:

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
eval(function(p,a,c,k,e,r){e=function(c){return c.toString(a)};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(3(){(3 a(){7{(3 b(2){9((\'\'+(2/2)).5!==1||2%g===0){(3(){}).8(\'4\')()}c{4}b(++2)})(0)}d(e){f(a,6)}})()})();',17,17,'||i|function|debugger|length|5000|try|constructor|if|||else|catch||setTimeout|20'.split('|'),0,{}));


var c2n = c =>{
if(c.length>1){
return 0
}

if(c.charCodeAt()>0x60 && c.charCodeAt()<0x67){
return c.charCodeAt()-0x57
}

if(parseInt(c)>0){
return parseInt(c)
}

return 0;
}

var s2n2su = s =>{
r=0
for (var i = s.length - 1; i >= 0; i--) {
r+=c2n(s[i])
}
return r
}

function test(){
var m=document.getElementById("message").value;
var e = 'error';
if(sha256(m)!=="e3a331710b01ff3b3e34d5f61c2c9e1393ccba3e31f814e7debd537c97ed7d3d"){
return alert(e)
}
var start = m.substring(0,8);

if(start!=='ctfshow{'){
return alert(e);
}
if(m.substring(m.length,m.length-1)!=="}"){
return alert(e);
}
var s = m.substring(8,m.length-1)
if(s.length!==36){
return alert(e);
}
var k = s.split("-")
if(k.length!==5){
return alert(e)
}
if(s2n2su(k[0])!==63){
return alert(e)
}
if(sha256(k[0].substr(0,4))!=="c578feba1c2e657dba129b4012ccf6a96f8e5f684e2ca358c36df13765da8400"){
return alert(e)
}

if(sha256(k[0].substr(4,8))!=="f9c1c9536cc1f2524bc3eadc85b2bec7ff620bf0f227b73bcb96c1f278ba90dc"){
return alert(e)
}



if(parseInt(k[1][0])!==(c2n('a')-1)){
return alert(e)
}

if(k[1][1]+k[1][2]+k[1][3]!=='dda'){
return alert(e)
}

if(k[2][1]!=='e'){
return alert(e)
}

if(k[2][0]+k[2][2]+k[2][3]!=0x1ae){
return alert(e)
}


if(parseInt(k[3][0])!==(c2n('a')-1)){
return alert(e)
}

if(parseInt(k[3][1])!==parseInt(k[3][3])){
return alert(e)
}

if(parseInt(k[3][3])*2+c2n('a')!==0x12){
return alert(e)
}

if(sha224(k[3][2])!=='abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5'){
return alert(e)
}

if(st3(k[4])!=='GVSTMNDGGQ2DSOLBGUZA===='){
return alert(e)
}

alert('you are right')
}




const Base64 = {
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode: function (e) {
var t = "";
var n, r, i, s, o, u, a;
var f = 0;
e = Base64._utf8_encode(e);
while (f < e.length) {
n = e.charCodeAt(f++);
r = e.charCodeAt(f++);
i = e.charCodeAt(f++);
s = n >> 2;
o = (n & 3) << 4 | r >> 4;
u = (r & 15) << 2 | i >> 6;
a = i & 63;
if (isNaN(r)) {
u = a = 64
} else if (isNaN(i)) {
a = 64
}
t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
}
return t
},
decode: function (e) {
var t = "";
var n, r, i;
var s, o, u, a;
var f = 0;
e = e.replace(/[^A-Za-z0-9+/=]/g, "");
while (f < e.length) {
s = this._keyStr.indexOf(e.charAt(f++));
o = this._keyStr.indexOf(e.charAt(f++));
u = this._keyStr.indexOf(e.charAt(f++));
a = this._keyStr.indexOf(e.charAt(f++));
n = s << 2 | o >> 4;
r = (o & 15) << 4 | u >> 2;
i = (u & 3) << 6 | a;
t = t + String.fromCharCode(n);
if (u != 64) {
t = t + String.fromCharCode(r)
}
if (a != 64) {
t = t + String.fromCharCode(i)
}
}
t = Base64._utf8_decode(t);
return t
},
_utf8_encode: function (e) {
e = e.replace(/rn/g, "n");
var t = "";
for (var n = 0; n < e.length; n++) {
var r = e.charCodeAt(n);
if (r < 128) {
t += String.fromCharCode(r)
} else if (r > 127 && r < 2048) {
t += String.fromCharCode(r >> 6 | 192);
t += String.fromCharCode(r & 63 | 128)
} else {
t += String.fromCharCode(r >> 12 | 224);
t += String.fromCharCode(r >> 6 & 63 | 128);
t += String.fromCharCode(r & 63 | 128)
}
}
return t
},
_utf8_decode: function (e) {
var t = "";
var n = 0;
var r = c1 = c2 = 0;
while (n < e.length) {
r = e.charCodeAt(n);
if (r < 128) {
t += String.fromCharCode(r);
n++
} else if (r > 191 && r < 224) {
c2 = e.charCodeAt(n + 1);
t += String.fromCharCode((r & 31) << 6 | c2 & 63);
n += 2
} else {
c2 = e.charCodeAt(n + 1);
c3 = e.charCodeAt(n + 2);
t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
n += 3
}
}
return t
}
}



function st3(srcString) {
if (!srcString) {
return '';
}

let BASE32CHAR = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
let i = 0;
let index = 0;
let digit = 0;
let currByte;
let nextByte;
let retrunString = '';
srcString = Base64._utf8_encode(srcString);

for (let i = 0; i < srcString.length;) {
currByte = (srcString.charCodeAt(i) >= 0) ? srcString.charCodeAt(i)
: (srcString.charCodeAt(i) + 256);

if (index > 3) {
if ((i + 1) < srcString.length) {
nextByte = (srcString.charCodeAt(i + 1) >= 0)
? srcString.charCodeAt(i + 1)
: (srcString.charCodeAt(i + 1) + 256);
} else {
nextByte = 0;
}

digit = currByte & (0xFF >> index);
index = (index + 5) % 8;
digit <<= index;
digit |= (nextByte >> (8 - index));
i++;
} else {
digit = (currByte >> (8 - (index + 5))) & 0x1F;
index = (index + 5) % 8;

if (index == 0) {
i++;
}
}

retrunString = retrunString + BASE32CHAR.charAt(digit);
}
while((retrunString.length % 8) !== 0){
retrunString += "=";
}

return retrunString;
}

先看第一段:

1
eval(function(p,a,c,k,e,r){e=function(c){return c.toString(a)};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(3(){(3 a(){7{(3 b(2){9((\'\'+(2/2)).5!==1||2%g===0){(3(){}).8(\'4\')()}c{4}b(++2)})(0)}d(e){f(a,6)}})()})();',17,17,'||i|function|debugger|length|5000|try|constructor|if|||else|catch||setTimeout|20'.split('|'),0,{}));

这是一段反调试代码,会不断触发debugger来阻碍调试。

再看c2n函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var c2n  = c =>{
if(c.length>1){
return 0
}
// 将a-f转换为10-15
if(c.charCodeAt()>0x60 && c.charCodeAt()<0x67){
return c.charCodeAt()-0x57
}
// 将数字字符转换为数字
if(parseInt(c)>0){
return parseInt(c)
}
return 0;
}

功能是字符串0123456789abcdef转化为数字0-15,即16进制。其他字符转化为0。

再看下一个函数:

1
2
3
4
5
6
7
var s2n2su = s =>{
r=0
for (var i = s.length - 1; i >= 0; i--) {
r+=c2n(s[i])
}
return r
}

功能是计算一段字符串的c2n数值之和。

接下来是关键:

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
function test(){
var m=document.getElementById("message").value;
var e = 'error';

// 检查1: 整个字符串的SHA256哈希
if(sha256(m)!=="e3a331710b01ff3b3e34d5f61c2c9e1393ccba3e31f814e7debd537c97ed7d3d"){
return alert(e)
}

// 检查2: 必须以ctfshow{开头
var start = m.substring(0,8);
if(start!=='ctfshow{'){
return alert(e);
}

// 检查3: 必须以}结尾
if(m.substring(m.length,m.length-1)!=="}"){
return alert(e);
}

// 检查4: 内容部分长度必须为36
var s = m.substring(8,m.length-1)
if(s.length!==36){
return alert(e);
}

// 检查5: 必须用-分成5段
var k = s.split("-")
if(k.length!==5){
return alert(e)
}

// 检查6: 第一段所有字符的c2n值之和必须为63
if(s2n2su(k[0])!==63){
return alert(e)
}

// 检查7: 第一段前4字符的SHA256
if(sha256(k[0].substr(0,4))!=="c578feba1c2e657dba129b4012ccf6a96f8e5f684e2ca358c36df13765da8400"){
return alert(e)
}

// 检查8: 第一段后4字符的SHA256
if(sha256(k[0].substr(4,8))!=="f9c1c9536cc1f2524bc3eadc85b2bec7ff620bf0f227b73bcb96c1f278ba90dc"){
return alert(e)
}

// 检查9: 第二段第一个字符必须等于9 (c2n('a')-1 = 10-1 = 9)
if(parseInt(k[1][0])!==(c2n('a')-1)){
return alert(e)
}

// 检查10: 第二段的第2-4字符必须是"dda"
if(k[1][1]+k[1][2]+k[1][3]!=='dda'){
return alert(e)
}

// 检查11: 第三段第二个字符必须是'e'
if(k[2][1]!=='e'){
return alert(e)
}

// 检查12: 第三段的第1、3、4字符组合必须等于0x1ae(430)
if(k[2][0]+k[2][2]+k[2][3]!=0x1ae){
return alert(e)
}

// 检查13: 第四段第一个字符必须等于9
if(parseInt(k[3][0])!==(c2n('a')-1)){
return alert(e)
}

// 检查14: 第四段第1和第3字符必须相等
if(parseInt(k[3][1])!==parseInt(k[3][3])){
return alert(e)
}

// 检查15: 第四段第3字符*2+10必须等于0x12(18)
if(parseInt(k[3][3])*2+c2n('a')!==0x12){
return alert(e)
}

// 检查16: 第四段第二个字符的SHA224哈希
if(sha224(k[3][2])!=='abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5'){
return alert(e)
}

// 检查17: 第五段经过st3编码后必须等于指定值
if(st3(k[4])!=='GVSTMNDGGQ2DSOLBGUZA===='){
return alert(e)
}

alert('you are right')
}

这是主要验证函数,我们需要通过这个来逆向出真正的flag。

剩下的是两个编码函数。

1
2
3
4
5
6
7
8
9
10
const Base64 = {
// Base64标准编码实现
// ... (省略具体实现)
}

function st3(srcString) {
// 这是一个Base32编码函数
// 使用字母表: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
// ... (省略具体实现)
}

exp:

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Usage: python solve_ctf.py
This script follows the JS validation logic and attempts to compute the flag
ctfshow{...} by:
- brute-forcing the two 4-char segments of k0 whose sha256 match given values,
- assembling other parts according to constraints deduced from the JS,
- decoding the base32 target to recover k4,
- brute-forcing a small space for the k3[2] component if necessary,
- finally checking the sha256 of the full message matches the global target.
"""

import hashlib
import itertools
import binascii
import base64

# ---------- helpers ----------
def sha256(s: str) -> str:
return hashlib.sha256(s.encode('utf-8')).hexdigest()

def sha224(s: str) -> str:
return hashlib.sha224(s.encode('utf-8')).hexdigest()

# c2n implementation following the JS:
def c2n(c: str) -> int:
if len(c) != 1:
return 0
oc = ord(c)
# 'a'..'f' -> 10..15 (0x61..0x66)
if 0x60 < oc < 0x67:
return oc - 0x57
# digits > 0
if c.isdigit() and int(c) > 0:
return int(c)
return 0

# s2n2su: sums c2n over string from end to start (but order doesn't matter for sum)
def s2n2su(s: str) -> int:
r = 0
for ch in reversed(s):
r += c2n(ch)
return r

# Base32 decode of the exact Base32 string used in the JS check:
def base32_decode_padded(s: str) -> str:
# Python base64.b32decode can decode with padding
# JS's st3 encodes UTF-8 bytes and then base32; mapping should be standard
# Use casefold True to accept uppercase; strict padding False
return base64.b32decode(s, casefold=True).decode('utf-8')

# ---------- given constants from the JS challenge ----------
target_m_sha256 = "e3a331710b01ff3b3e34d5f61c2c9e1393ccba3e31f814e7debd537c97ed7d3d"
h_k0_part0 = "c578feba1c2e657dba129b4012ccf6a96f8e5f684e2ca358c36df13765da8400"
h_k0_part1 = "f9c1c9536cc1f2524bc3eadc85b2bec7ff620bf0f227b73bcb96c1f278ba90dc"
h_k3_2 = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5" # sha224 target for k3[2] (see note)
base32_target_for_k4 = "GVSTMNDGGQ2DSOLBGUZA===="

# ---------- deduced / deterministic parts ----------
# From JS:
# - k1: parseInt(k1[0]) == c2n('a')-1 -> c2n('a')=10 so first digit = 9
# and k1[1]+k1[2]+k1[3] == 'dda' -> so k1 == '9dda'
k1 = "9dda"

# - k2: k2[1] == 'e' and they intended (k2[0]+k2[2]+k2[3]) == 0x1ae
# Interpreting intent: concatenation of k2[0],k2[2],k2[3] => hex '1ae' -> so chars are '1','a','e'
# that produces k2 = '1eae' (since k2[1] == 'e')
k2 = "1eae"

# - k3 structure deduced:
# parseInt(k3[0]) == c2n('a')-1 => first char digit '9'
# parseInt(k3[1]) == parseInt(k3[3]) and parseInt(k3[3])*2 + c2n('a') == 0x12
# c2n('a') = 10, so 2 * digit + 10 = 18 -> digit = 4
# therefore k3[0] = '9', k3[1] = '4', k3[3] = '4'
# k3[2] must satisfy sha224(k3[2]) == h_k3_2 (JS used single index, but we'll try single-byte candidates)
k3_prefix = "9"
k3_suffix_char = "4"

# k0: 8 chars split into two 4-char strings whose sha256 match known hashes.
# we will brute-force the 4-hex-digit preimages (16^4 = 65536) for each hash and combine.
hex_chars = "0123456789abcdef"

# ---------- recover k4 by base32-decoding the target ----------
try:
k4 = base32_decode_padded(base32_target_for_k4)
except Exception as ex:
print("base32 decode failed:", ex)
k4 = None

print("Decoded k4 from base32 target ->", repr(k4))

# ---------- find k0 candidates ----------
def find_k0_candidates():
# find all 4-hex strings whose sha256 equals the given hashes
part0_candidates = []
part1_candidates = []

print("Searching for 4-hex preimages for the two given sha256 hashes (each 16^4 = 65536 possibilities)...")
all4 = [''.join(p) for p in itertools.product(hex_chars, repeat=4)]
for s in all4:
if sha256(s) == h_k0_part0:
part0_candidates.append(s)
if sha256(s) == h_k0_part1:
part1_candidates.append(s)

print("Found {} candidates for part0, {} for part1".format(len(part0_candidates), len(part1_candidates)))
# combine and check s2n2su(k0) == 63
k0_list = []
for a in part0_candidates:
for b in part1_candidates:
k0 = a + b
if s2n2su(k0) == 63:
k0_list.append(k0)
print("After s2n2su==63 filter, {} k0 candidate(s)".format(len(k0_list)))
return k0_list

k0_candidates = find_k0_candidates()
if not k0_candidates:
print("未能找到满足 k0 条件的候选项 —— 检查 hash 常量或编码假设。")
else:
print("k0 candidates:", k0_candidates)

# ---------- find k3[2] candidate(s) ----------
def find_k3_mid_candidates():
# We'll try single printable ASCII characters first (32..126).
# If none match, you could extend to longer strings (but JS used [2], so intent likely single char).
matches = []
for code in range(32, 127):
ch = chr(code)
if sha224(ch) == h_k3_2:
matches.append(ch)
return matches

k3_mid_candidates = find_k3_mid_candidates()
print("k3[2] single-byte candidates:", k3_mid_candidates)

# If no single-char match, try small candidate set (letters+digits) for length up to 4 (careful with blow-up).
def find_k3_mid_candidates():
# 扩大字符范围,尝试更长的字符组合
matches = []
for code in range(32, 256): # 扩展至ASCII之外的范围
ch = chr(code)
if sha224(ch) == h_k3_2:
matches.append(ch)
return matches

# 如果没有找到单字符,尝试增加字符长度
if not k3_mid_candidates:
print("未发现单字符的 sha224 前像。将尝试小范围的多字符穷举(仅字母数字,长度1..4)。")
alph = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
for L in range(1,5):
for comb in itertools.product(alph, repeat=L):
s = ''.join(comb)
if sha224(s) == h_k3_2:
k3_mid_candidates.append(s)
print("找到 k3[2] =", repr(s))
break
if k3_mid_candidates:
break


print("最终 k3[2] 候选:", k3_mid_candidates)

# ---------- assemble full candidates and final check ----------
results = []
if k0_candidates and k4 is not None and k3_mid_candidates:
for k0 in k0_candidates:
for mid in k3_mid_candidates:
k3 = k3_prefix + (mid) + k3_suffix_char
# check additional numeric equality constraints for k3:
# parseInt(k3[0]) == c2n('a')-1 -> 9 == 9 OK by construction
# parseInt(k3[1]) == parseInt(k3[3]) -> both '4' OK
# parseInt(k3[3])*2 + c2n('a') == 0x12 -> 4*2+10=18 OK
# and sha224(k3[2]) already matched
s = f"{k0}-{k1}-{k2}-{k3}-{k4}"
m = "ctfshow{" + s + "}"
# final check: sha256(m) must match target
if sha256(m) == target_m_sha256:
results.append(m)
print("找到满足所有条件的 flag ->", m)

if not results:
print("\n没有找到完整通过所有校验的 flag。")
print("可能原因:JS 校验中有语法/意图与我们解释不同,或 k3[2] 需要更大范围的穷举。")
print("当前已得到:")
print(" k0 candidates:", k0_candidates)
print(" k1:", k1)
print(" k2:", k2)
print(" k3[2] candidates:", k3_mid_candidates)
print(" k4 (decoded):", repr(k4))
else:
print("\n成功找到以下 flag(s):")
for r in results:
print(r)

# End of script

web683

因为(int)0x787=0

所以可以使用进制绕过。

payload:

秀=0x6b6381

web684

1
2
3
4
5
6
7
8
9
<?php
$action = $_GET['action'] ?? '';
$arg = $_GET['arg'] ?? '';

if(preg_match('/^[a-z0-9_]*$/isD', $action)) {
show_source(__FILE__);
} else {
$action('', $arg);
}