Misc

md7

const fs = require("fs");
const readline = require("readline");
const md5 = require("md5");

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});

function askQuestion(query) {
return new Promise(resolve => rl.question(query, resolve));
}

function normalize(numStr) {
if (!/^\d+$/.test(numStr)) {
return null;
}
return numStr.replace(/^0+/, "") || "0";
}

console.log("Welcome to our hashing factory ");
console.log("let's see how much trouble you can cause");

function generateHash(input) {
input = input
.split("")
.reverse()
.map(d => ((parseInt(d, 10) + 1) % 10).toString())
.join("");

const prime1 = 31;
const prime2 = 37;
let hash = 0;
let altHash = 0;

for (let i = 0; i < input.length; i++) {
hash = hash * prime1 + input.charCodeAt(i);
altHash = altHash * prime2 + input.charCodeAt(input.length - 1 - i);
}

const factor = Math.abs(hash - altHash) % 1000 + 1;
const normalized = +input;
const modulator = (hash % factor) + (altHash % factor);
const balancer = Math.floor(modulator / factor) * factor;
return normalized + balancer % 1;
}

(async () => {
try {
const used = new Set();

for (let i = 0; i < 100; i++) {
const input1 = await askQuestion(`(${i + 1}/100) Enter first number: `);
const input2 = await askQuestion(`(${i + 1}/100) Enter second number: `);

const numStr1 = normalize(input1.trim());
const numStr2 = normalize(input2.trim());

if (numStr1 === null || numStr2 === null) {
console.log("Only digits are allowed.");
process.exit(1);
}

if (numStr1 === numStr2) {
console.log("Nope");
process.exit(1);
}

if (used.has(numStr1) || used.has(numStr2)) {
console.log("😈");
process.exit(1);
}

used.add(numStr1);
used.add(numStr2);

const hash1 = generateHash(numStr1);
const hash2 = generateHash(numStr2);

if (md5(hash1.toString()) !== md5(hash2.toString())) {
console.log(`⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⠟⠷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣤⣤⣾⠿⢫⡤⠀⣄⢈⠛⠷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⡶⠛⠋⢡⣾⡿⣿⡴⠁⠀⠀⣿⣾⣿⡁⠈⠛⠶⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣦⣤⡀⠀⠀⠀⠀⢀⣤⡾⠟⠋⠐⠂⠸⠿⣿⣿⠿⠀⠩⠛⠀⠛⠻⣦⡅⠀⠀⠀⠀⠙⢧⡄⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠌⠙⠷⣦⣴⡾⠟⡡⠴⠂⠀⠀⠀⠀⠀⠀⠙⠦⠴⣤⣄⡀⠛⠶⣽⣮⡀⠀⠀⠀⠀⠀⠻⡄⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣧⣰⢠⢞⡛⠉⠙⠋⠁⠀⠀⠀⠀⠀⠀⣀⡀⢄⡂⢰⡘⢿⢻⣤⢃⠄⡉⢻⡗⠀⠀⠀⠀⠀⢿⡀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⡇⣸⡇⠀⠀⠀⠀⠀⠀⠀⢀⡀⢾⣋⡝⣬⣟⣴⣫⣟⢾⣶⣿⣾⣤⣭⣿⠀⠀⠀⠀⠀⠘⣷⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣧⣿⡇⠀⠀⠀⠀⠀⠀⢠⣼⠏⣾⣿⣽⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⡀⡀⣽⣇⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣼⡧⠀⠀⠈⢀⣱⣘⣿⣿⣋⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣹⣿⣿⣿⣿⣤⠃⡜⢻⣟⣿⡇⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣯⣽⡗⣌⣺⠡⣘⣾⣿⣿⣿⣯⣞⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣹⣿⣿⣿⢧⣙⣔⣻⣿⣿⣿⡀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢈⣿⣿⣿⡹⢛⠶⣾⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡧⢌⠹⢹⣾⣿⢿⡇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠿⣷⣌⢺⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠐⢪⡐⣣⣿⣿⣿⠇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⣿⡿⠀⠉⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⢉⣦⣍⣝⣿⣿⠏⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⣿⠁⢰⠀⠁⢘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⣩⠒⢢⢰⡘⣿⣿⡏⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣦⠟⠀⠀⠈⢩⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠱⠀⠈⠄⢂⣿⣿⣿⠁⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣿⡄⠀⠀⠀⠀⠀⠻⢿⣿⣿⣿⣿⡿⢟⣿⣿⣿⣿⢛⣿⣿⣿⡿⠉⠀⠀⠀⠀⢠⣸⣿⡏⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⡾⠟⠛⠛⠳⣶⣿⣟⢆⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⠱⣋⠔⡢⠑⣎⠣⣜⣶⠿⠃⠀⠀⠀⠀⠀⠠⠇⣿⠁⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣠⣤⠤⣤⣤⣼⠏⠀⠀⠀⠀⠀⠀⠙⠿⣿⣷⣄⠀⠀⠀⠀⠀⠈⠹⣿⡆⡑⠈⠄⠑⠨⢹⣥⣲⡶⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢀⣠⡴⢾⣿⡿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⣿⣿⠀⠀⠀⠀⠀⠀⠀⠈⢿⣾⣅⠀⢈⠡⢩⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀
⠀⠀⢀⣀⣴⣾⡟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣥⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⢣⠀⠀⠀⢀⠀⠀⠀⢢⣾⣿⣿⣶⡼⢣⣽⣿⣻⡿⠀⠀⠀⠀⠀⠀⠀⠀⠈⢷⣄⠀⠀⠀⠀⠀
⣤⡾⠋⠉⠀⠀⠹⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣷⢦⣄⣀⣠⣤⣴⣶⣿⣿⠟⠉⠀⠀⠀⠀⢳⡀⠀⢸⠟⢿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠳⣄⠀⠀⠀
⣿⠁⠀⠀⠀⠀⠈⠻⠦⠄⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣮⣭⣥⣶⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠈⢷⣦⡀⢛⡾⣿⣿⣿⣿⢿⣭⡖⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢳⣄⠀
⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣟⡛⡟⢿⢻⣟⣿⣿⠔⠂⠀⠀⠀⠀⠀⠀⠀⠀⠸⣷⣾⡐⣿⣿⣿⣼⡿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣆
⣟⠀⠀⠀⠀⣠⡄⠀⠀⠀⠀⢻⡄⠀⠀⠀⠀⠀⢸⡯⢜⠩⢖⡩⡟⠙⢿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⢿⣷⣿⣿⡿⠟⠟⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡍
⡇⠀⠀⠀⠀⣿⠇⠀⠀⠀⠀⢸⣇⠀⠀⠀⠀⠀⢸⣿⢎⡑⢮⣇⣇⠀⠀⢿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠩⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡜
⡇⠀⠀⠀⠀⢿⡇⠀⠀⠀⠀⢼⣯⠀⠀⠀⠀⠀⠘⣿⢦⣱⣾⣿⠋⠀⠀⠀⠹⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⡼
⡿⠀⣀⠀⠀⢺⣇⠀⠀⠀⠀⣸⣿⡀⠀⠀⠀⣀⣼⠟⠛⠉⠉⠀⠀⠀⠀⠀⢀⣼⣿⣶⡀⠀⠤⢀⡤⣤⣙⡴⣀⢤⣄⠲⠤⢄⡀⣀⡀⢀⣀⣀⡀⠄⡀⡀⢀⡀⢀⠀⡄⢤⡈⣵⡐
⣷⣀⠈⡄⢈⠽⣿⡀⠆⢀⡤⢸⣿⣷⣠⣠⣼⠟⠁⠀⢀⣤⡤⣤⣤⣤⢶⣩⣾⣿⣿⠼⣇⠀⡆⢦⡔⢦⢭⡹⣬⢏⠶⣭⣛⢮⡝⣧⣾⡱⢮⣱⣙⢦⡵⣩⡶⣜⣬⡳⣎⣧⣝⡶⣽
⠟⠷⠿⠛⠾⠿⡿⢷⣯⣬⣵⣷⣾⣿⣯⣿⣷⣠⣤⣼⣩⣴⣦⣭⣴⣽⣿⣿⣟⣩⢃⡾⢀⢣⠼⣦⢽⣚⡶⣽⣎⣿⣻⢶⣯⣟⣾⣳⢯⣟⣯⣷⣻⢮⣽⣷⣻⡽⣾⡽⣽⢾⡽⣞⣷`);
process.exit(1);
}

console.log("Correct!");
}

console.log("\ngg , get your flag\n");
const flag = fs.readFileSync("flag.txt", "utf8");
console.log(flag);

} finally {
rl.close();
}
})();

generateHash()函数对输入的处理是反转,每位数字加一模十,然后拼接回去
return normalized + balancer % 1; balancer是整数,所以不用管它,这里就只剩normalized
const normalized = +input;这里是前导零的一个利用
比如(1,19)

1 -> '2' -> +'2' -> 2
19 -> '91' -> '02' -> +'02' > 2

这样它们的字符串md5就一样了,我们只要找到100组各不一样的数字即可

from pwn import *
from tqdm import trange

def transform(s: str) -> str:
s = s[::-1]
res = ""
for char in s:
digit = int(char)
new_digit = (digit + 1) % 10
res += str(new_digit)
return res

def reverse_transform(t: str) -> str:
res = ""
for char in t:
digit = int(char)
original_digit = (digit - 1 + 10) % 10
res += str(original_digit)
return res[::-1]

def generate_pairs():
pairs = []
used_numbers = set()
i = 1
while len(pairs) < 100:
s1 = str(i)
t1 = transform(s1)
t2 = "0" + t1
s2 = reverse_transform(t2)
if s1 != s2 and s1 not in used_numbers and s2 not in used_numbers:
if int(transform(s1)) == int(transform(s2)):
pairs.append((s1, s2))
used_numbers.add(s1)
used_numbers.add(s2)
i += 1
return pairs

solution_pairs = generate_pairs()
conn = remote('numbers.p2.securinets.tn', 7011)
for i in trange(100):
num1, num2 = solution_pairs[i]
conn.sendlineafter(b"Enter first number: ", num1.encode())
conn.sendlineafter(b"Enter second number: ", num2.encode())
conn.recvline()
print(conn.recvall().decode().strip())
# Securinets{floats_in_js_xddddd}

Easy Jail

import random
import string

seed = random.randint(0, 2**20)
shift_rng = random.Random(seed)

class ProtectedFlag:
def __init__(self, value):
self._value = value

def __str__(self):
return "variable protected, sryy"

def __repr__(self):
return "variable protected, sryy"

def __getitem__(self, index):
try:
return self._value[index]
except Exception:
return "variable protected, sryy"

# Example flag
flag = ProtectedFlag("flag{dummy_flag}")

def shift_mapping(mapping):
# well guess how it was done >_<

def make_initial_mapping():
letters = list(string.ascii_lowercase)
shuffled = letters[:]
random.shuffle(shuffled)
return dict(zip(letters, shuffled))

def main():
valid_chars = set(string.ascii_lowercase + "[]()~><*+")
mapping = make_initial_mapping()
print("Welcome to the shifting jail! Enter text using only a-z, []()~><*+")

try:
while True:
user_in = input("> ").strip()
if len(user_in) > 150:
raise ValueError(f"Input exceeds 150 characters")

if not all(c in valid_chars for c in user_in):
print("Invalid input. Only [a-z] and []()~><*+ are allowed.")
continue

encoded = "".join(mapping[c] if c in mapping else c for c in user_in)

mapping = shift_mapping(mapping)
try:
result = eval(encoded, {"__builtins__": None}, {"flag": flag})
print(result)
except Exception:
print(encoded)

except KeyboardInterrupt:
print("\nGoodbye!")

if __name__ == "__main__":
main()

限制我们的输入为a-z []()~><*+",下划线、点都无法使用,但是它明确告诉了我们可以通过下标读取flag

源码对小写字母做了映射,同时还有一个黑盒函数shift_mapping,每输入一次都会被映射
先找找字母表有没有映射规律

yvgkwuqnfiodhltjapcbmezsrx
zwhlxvrogjpeimukbqdcnfatsy
yvgkwuqnfiodhltjapcbmezsrx
zwhlxvrogjpeimukbqdcnfatsy
aximywsphkqfjnvlcredogbutz
byjnzxtqilrgkowmdsfephcvua
aximywsphkqfjnvlcredogbutz
byjnzxtqilrgkowmdsfephcvua
czkoayurjmshlpxnetgfqidwvb
byjnzxtqilrgkowmdsfephcvua
aximywsphkqfjnvlcredogbutz
byjnzxtqilrgkowmdsfephcvua
aximywsphkqfjnvlcredogbutz
zwhlxvrogjpeimukbqdcnfatsy
aximywsphkqfjnvlcredogbutz
byjnzxtqilrgkowmdsfephcvua
czkoayurjmshlpxnetgfqidwvb
dalpbzvskntimqyofuhgrjexwc
ebmqcawtloujnrzpgvihskfyxd
fcnrdbxumpvkosaqhwjitlgzye
gdosecyvnqwlptbrixkjumhazf
heptfdzworxmqucsjylkvnibag
gdosecyvnqwlptbrixkjumhazf
fcnrdbxumpvkosaqhwjitlgzye
gdosecyvnqwlptbrixkjumhazf
heptfdzworxmqucsjylkvnibag

发现每次都是上一次+1/-1的偏移,那这样就好办了,会有26个可能的字母表,'flag'会被映射成26种可能

同时在Python中,可以利用空元组构造数字,这里等号用不了,但可以取反,通过~(()>()),可以构造出-1
通过加号连接可以构造出任意负数,再乘-1可以构造任意正数

因为这里有150的长度限制,所以需要正向遍历+反向遍历,然后手动剃掉中间重复的字符即可

from pwn import *
import string

def caesar_shift_string(text, shift):
shifted_text = ""
for char in text:
shifted_ord = (ord(char) - ord('a') + shift) % 26 + ord('a')
shifted_text += chr(shifted_ord)
return shifted_text


def generate_all_shifts(base_alphabet):
all_shifted_alphabets = []
for i in range(26):
shifted_version = caesar_shift_string(base_alphabet, i)
all_shifted_alphabets.append(shifted_version)
return all_shifted_alphabets

conn = remote("misc-b6c94dd8.p1.securinets.tn", 7000)
conn.sendlineafter(b"> ", f"{string.ascii_lowercase}".encode())
conn.recvline()
table = conn.recvline().strip().decode()
tables = generate_all_shifts(table)

for table in tables:
t = dict(zip(table, string.ascii_lowercase))
map = ["".join(t[i] for i in 'flag')]

def get_flag1():
flag = ''
for i in range(10, 30):
index = "[~(()>())*(~(()>())" + "+~(()>())" * i + ")]"
count = 1
while count:
for m in map:
if len(m) + len(index) > 150:
return flag
conn.sendline(f"{m}{index}".encode())
conn.recvline()
res = conn.recvline().strip().decode()
if len(res) == 1:
flag += res
count = 0

def get_flag2():
flag = ''
for i in range(30):
index = "[~(()>())" + "+~(()>())" * i + "]"
count = 1
while count:
for m in map:
if len(m) + len(index) > 150:
return flag
conn.sendline(f"{m}{index}".encode())
conn.recvline()
res = conn.recvline().strip().decode()
if len(res) == 1:
flag += res
count = 0

flag1 = get_flag1()
flag2 = get_flag2()[::-1]
print('Securinets{' + flag1 + flag2)
# Securinets{H0p3p3_Y0u_L0ST_1t!}
# Securinets{H0p3_Y0u_L0ST_1t!}