jule2022这个比赛到目前才30+人参赛,比赛时间有9天,正赛还没有结束,所以先不写。这是比赛前的热身部分。这部分不计分。
估计有些人是因为找不到入口链接,又是国外的比赛,不放脑瓜顶上确实不好找。
01
这个忘了叫啥名了,给了一篇全大写的文章,字母被替换了。字频好像不大准还不如眼准。比如单个字符也就是I,a,两个的in,on,of,an,还有最常见的the,手工换完得到一个转换表。
ABCDEFGHIJKLMNOPQRSTUVWXYZ
rfdscobqlgtmawkpxhenzuyvji
根据这个表把加密的flag转一下,再包上壳就OK了
nsii_nsii_nsii_rfn_krs_kvatkmgisd
well_well_well_how_the_turntables
02 I was tangled in.. in.. strings
这是个逆向题,内容比较简单,IDA打开找到密码,输入密码就给flag
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int i; // [esp+0h] [ebp-C4h]
size_t v5; // [esp+4h] [ebp-C0h]
int v6[9]; // [esp+8h] [ebp-BCh]
__int16 v7; // [esp+2Ch] [ebp-98h]
int v8[9]; // [esp+2Eh] [ebp-96h]
__int16 v9; // [esp+52h] [ebp-72h]
char s[100]; // [esp+54h] [ebp-70h] BYREF
unsigned int v11; // [esp+B8h] [ebp-Ch]
int *p_argc; // [esp+BCh] [ebp-8h]
p_argc = &argc;
v11 = __readgsdword(0x14u);
printf("=== Legionnaire OS v2.31 ===\n\nPASSWORD PROTECTED\nEnter password: ");
fgets(s, 100, stdin);
v5 = strlen(s);
if ( v5 && s[v5 - 1] == 10 )
s[v5 - 1] = 0;
puts("Checking password...");
sleep(2u);
if ( !strcmp(pass, s) )
{
v6[0] = -1217341131;
v6[1] = 395690639;
v6[2] = -1332891898;
v6[3] = -1612059337;
v6[4] = 1522026396;
v6[5] = -477460208;
v6[6] = 689504828;
v6[7] = 933803535;
v6[8] = 689362930;
v7 = 30952;
v8[0] = -868840074;
v8[1] = 603823550;
v8[2] = -989925278;
v8[3] = -125313979;
v8[4] = 802822374;
v8[5] = -739977628;
v8[6] = 1143496011;
v8[7] = 1390071888;
v8[8] = 443790017;
v9 = 1421;
for ( i = 0; i <= 0x25; ++i )
putchar((char)(*((_BYTE *)v6 + i) ^ *((_BYTE *)v8 + i)));
putchar(10);
}
else
{
puts("YOU ARE NOT WORTHY!!");
}
return 0;
}
当然也可以把这些变量转字符,注意小端。(显然不是专为本次比赛出的题,flag壳都不一样)
┌──(kali㉿kali)-[~/ctf/other]
└─$ ./legionnaire
=== Legionnaire OS v2.31 ===
PASSWORD PROTECTED
Enter password: AV3ryL0ngAndH4rdc0dedP4ssw0rd
Checking password...
CTF{1_h4d_str1ngz_but_n0w_1m_fre3ee3e}
03 ZopCrypti
这是个misc题,附件是个压缩包,打开是一个文件和一个带密码的压缩包,这个文件在压缩包里也有一个相同的。显然是zip的明文攻击,不过包是unix格式找的。在win上软件处理不了,但在linux 下用pkcrack也报错。
04 secret words
又回到逆向,是个异或题,密文和key都给出
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v3; // r12
size_t v4; // rax
int i; // [rsp+4h] [rbp-6Ch]
char s1[5]; // [rsp+Bh] [rbp-65h] BYREF
char v8[8]; // [rsp+10h] [rbp-60h] BYREF
__int64 v9; // [rsp+18h] [rbp-58h]
int v10; // [rsp+20h] [rbp-50h]
char s[40]; // [rsp+30h] [rbp-40h] BYREF
unsigned __int64 v12; // [rsp+58h] [rbp-18h]
v12 = __readfsqword(0x28u);
*(_QWORD *)v8 = 0x5F1D1D1F15285B3FLL;
v9 = 0x5A1F045C0D300E02LL;
v10 = 0x125A3E;
strcpy(s1, "lion");
printf("What is the secret word? ");
fgets(s, 32, stdin);
s[strlen(s) - 1] = 0;
if ( !strcmp(s1, s) )
{
puts("Correct!");
for ( i = 0; i < strlen(v8); ++i )
{
v3 = v8[i];
v4 = strlen(s1);
putchar(v3 ^ (unsigned __int8)s1[i % v4]);
}
putchar(10);
}
else
{
puts("Wrong!");
}
return 0;
}
确实是热身,
v8 = b'_\x1D\x1D\x1F\x15([?'[::-1]+b'Z\x1F\x04\\\r0\x0E\x02'[::-1]+b'\x12Z>'[::-1]
from pwn import xor
xor(b'lion', v8)
#b'S2G{str1ng_c0mp4R3}'
05 M4
这是个enigma加密,但是未知参数太多了,不知道怎么弄
from enigma.machine import EnigmaMachine
import string
import random
import datetime
import time
# Wrap the flag inside S2G{...}
flag = 'FAKEFLAG'
morse_code_dict = { 'A':'.-', 'B':'-...', 'C':'-.-.', 'D':'-..', 'E':'.', 'F':'..-.', 'G':'--.', 'H':'....', 'I':'..', 'J':'.---', 'K':'-.-', 'L':'.-..', 'M':'--', 'N':'-.', 'O':'---', 'P':'.--.', 'Q':'--.-', 'R':'.-.', 'S':'...', 'T':'-', 'U':'..-', 'V':'...-', 'W':'.--', 'X':'-..-', 'Y':'-.--', 'Z':'--..'}
with open('german.txt') as f:
wordlist = [w.strip() for w in f.read().split('\n')]
wordlist = [w.upper() for w in wordlist]
wordlist = [w.replace('Ö', 'OE') for w in wordlist]
wordlist = [w.replace('Ä', 'AE') for w in wordlist]
wordlist = [w.replace('Ü', 'UE') for w in wordlist]
wordlist = list(filter(lambda w: len(w) > 0 and all(c in string.ascii_uppercase for c in w), wordlist))
def generate_machine():
rotors = [random.choice(['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'Beta', 'Gamma']) for _ in range(3)]
reflector = random.choice(['B', 'C', 'B-Thin', 'C-Thin'])
ring_settings = ' '.join([random.choice(string.ascii_uppercase) for _ in range(3)])
plugboard_chars = list(string.ascii_uppercase)
random.shuffle(plugboard_chars)
plugboard_settings = ' '.join(''.join(plugboard_chars[j*10+i] for j in range(2)) for i in range(10))
machine = EnigmaMachine.from_key_sheet(
rotors=rotors,
reflector=reflector,
ring_settings=ring_settings,
plugboard_settings=plugboard_settings
)
return machine
def generate_daily_machine():
global daily_machine, daily_machine_display
daily_machine = generate_machine()
daily_machine_display = ''.join(random.choice(string.ascii_uppercase) for _ in range(3)) #3个 大写字母
def generate_message():
message = ''.join(random.choice(wordlist) for _ in range(random.randint(1, 50)))
message += flag
return message
def encrypt_message(machine, machine_display, message):
machine.set_display(machine_display)
enc = machine.process_text(message)
return ' '.join(map(lambda x: morse_code_dict[x], enc))
start_date = datetime.datetime(1942, 2, 2, 0, 0, 0)
end_date = datetime.datetime(1943, 3, 17, 0, 0, 0)
current_timestamp = time.mktime(start_date.timetuple()) + random.randint(1, 60 * 60 * 3)
end_timestamp = time.mktime(end_date.timetuple())
generate_daily_machine()
messages = []
while current_timestamp < end_timestamp:
message = encrypt_message(daily_machine, daily_machine_display, generate_message())
date = datetime.datetime.fromtimestamp(current_timestamp).strftime("%Y-%m-%d %H:%M:%S")
message = f'[{date}]: {message}'
messages.append(message)
last_timestamp = current_timestamp
current_timestamp += random.randint(1, 60 * 60 * 3)
if datetime.datetime.fromtimestamp(last_timestamp).date() != datetime.datetime.fromtimestamp(current_timestamp).date():
generate_daily_machine()
with open('intercepted.txt', 'w') as f:
f.write('\n'.join(messages))
同一数据加padding 加密N多次,但中间参数不停地取随机数。不知道怎么弄了。
06 Hidden
这个就没的说了,flag文件名是.flag.txt 这在unix下会隐身,但在windows下直接就显示了。
07 Password manager
这个给了一堆密文,但没给远端,光从几个密文上推似乎不大可能,如果有远端???
from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import pad, unpad
passwords_directory = './passwords/'
def encrypt(site, username, password):
plaintext = pad(f'{username}||{password}'.encode(), AES.block_size)
with open(f'{passwords_directory}{site}.enc', 'wb') as f:
ciphertext = cipher.encrypt(plaintext)
f.write(ciphertext)
def decrypt(site):
with open(f'{passwords_directory}{site}.enc', 'rb') as f:
ciphertext = f.read()
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
username, password = plaintext.decode().split('||')
return [username, password]
def print_commands():
print('Commands:')
print('\t1. Encrypt')
print('\t2. Decrypt')
print('\t0. Exit')
print('Welcome back, Frank!')
master_password = input('Enter your master password to continue: ')
cipher = AES.new(master_password.encode(), AES.MODE_ECB)
print_commands()
while (cmd := input('Enter command: ')) != '0':
if cmd == '1':
site = input('Site: ')
username = input('Username: ')
password = input('Password: ')
encrypt(site, username, password)
print('Successfully encrypted the username and password!')
elif cmd == '2':
site = input('Site: ')
username, password = decrypt(site)
print(f'Username: {username}')
print(f'Password: {password}')
else:
print('Invalid command.')
print()
print_commands()
08 RSA
一个p,q都给了的RSA
p = 0xa362776cb254f1d1acd87499eb4eeedbb9e46dcb4c534e82ac6b004c47a062593b408e15d258fae7dd529e80a5f1f50e1bcedd243f8e1f82feacdad83ee83149c7ca518e4f72f149c724175a8ab23aa2cf9b6a4fe5696150820d24d1ef6b817d5ede5889087a030359b5ffb1d0e6909fcfd387cc2bf2f1f43728cc63823b3959
q = 0x84269ba361b3446c90d6f0cf69bd106c2d9ca57e3bdfce2aa39d216eabccbcfe2a5cce0c21d420b15fa4775941dec1368c5495eba1673752dfa66a5fe5670022a05a2ea878a89844cee43ba555f892132d501aff10fae4ca9b4a1731259637c84b98571a8da5d634284f2d5e7c77753fa56cefab72cc8ed92b5f62873e04b605
N = 0x54576986aa71d8401f05e3d5c602068580d152be05841dc76f838e0a00e30914d17be60e16bfe416292316d4c0a4d4efe8523ab675b02fa050a3179ce69df420b0d895d862147eb9ebe643e404751962e62ae0a3a010f34f96f14910319378e615a966d6cd483308ed1e87c4cfd911a505675399a7d41b5aca17b2e3b9f7e64635dfcb4e969594bd0c8cdd3391464b0e030ee61852121593ef3d7b1f8c4971c39b0400370827ba343c0b1bf2cd1b79581ef8484eb5823409f09160179d3d5ea16c98a11e44c59b97b7efd9f5befbef7e62174dacbdb2ad99325df0ccaf59bb38f0e83b70ac3d29dbae9a111cf94ad0646907bac4586d3880f4696d47195164bd
e = 0x10001
c = 0x4660a7e3c58f7597807a454f20c633232ed3ccd263cb48a342fe42b559939565fdc2e6cf7ac240e6d553b5d17f9746902bbc9d33d73bb5a70c697dad138f61a7c6ca524408d05f646f01f782e5aca8f159234619855c65392bf7f050884f3862d7e9e02a78a5cdb7d3809201a75f8ce6b1025a3fdf84f0f918db723bdf24c1980a0bb3a0878596aaaea96fa6f31d2e7e09c6e8638d040ca2786e623a1be5afa8c19a072dae6b34015b86ec057c37c7c625bb2c90dda0fcc877952bace1cb8db0f8f2fc82cadb6115098be05250801b18aa31ce8fa8d12423f1b5674b28de38f2557388b5e0b9569dcef469c295666bbe121d70cf84146119610e316e0945f0f
#sage
phi = (p-1)*(q-1)
d = inverse_mod(e,phi)
m = pow(c,d,N)
bytes.fromhex(hex(m)[2:])
b'S2G{y0U_d3CrYpt3d_Th3_RSA_3NcRyp73d_S3cR3t_m3sS4G3!!!}'
09 Leak
给了一个SQLite3的数据库表文件,打开似乎不大容易还得安装软件,直接按文本打开搜S2G的base64找到
在文件中搜base64('S2G{') UzJH
UzJHe2Q0dDRiNHMzX2wzNGshfQ==
S2G{d4t4b4s3_l34k!}
反正是热身赛,都无所谓,作着玩玩。