TSALVIA技術メモ

CTFのWriteupや気になったツールについて書いていきます。また、このサイトはGoogle Analyticsを利用しています。

S.H.E.L.L CTF 2021 Writeup

S.H.E.L.L CTF 2021 について

S.H.E.L.L CTF 2021 が開催されました。
2021年6月5日午後15時30分 ~ 2021年6月7日午後15時30分(48時間)

ctftime.org

今回も2人で参加しました。結果は 22/533位、3551点でした。
実際に2人で解いた問題の Writeup を紹介します。

f:id:tsalvia:20210609004003p:plain

S.H.E.L.L CTF 2021 Writeup(16問)

Web Security

anonym

Anonymous are back and they really hate robots.
http://3.142.122.1:8887

http://3.142.122.1:8887/robots.txt

User-agent: *
Disallow: /yfhdgvs.txt

http://3.142.122.1:8887/yfhdgvs.txt にアクセスするとフラグが表示された。

SHELL{n0_ro80t5_4llow3d_50886509749a98ef14ec2bc45c57958e}

Under Development

http://3.142.122.1:8885/

http://3.142.122.1:8885/ にアクセスすると、以下のように表示される

This web app is still under development.

curl から確認すると、Cookie が送られてきているのが分かる。

$ curl http://3.142.122.1:8885/ -v
*   Trying 3.142.122.1:8885...
* TCP_NODELAY set
* Connected to 3.142.122.1 (3.142.122.1) port 8885 (#0)
> GET / HTTP/1.1
> Host: 3.142.122.1:8885
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Set-Cookie: privilege=dXNlcg%3D%3D; Path=/
< Accept-Ranges: bytes
< Cache-Control: public, max-age=0
< Last-Modified: Sun, 30 May 2021 06:01:58 GMT
< ETag: W/"15b-179bbdd5ff0"
< Content-Type: text/html; charset=UTF-8
< Content-Length: 347
< Date: Sun, 06 Jun 2021 08:29:44 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web App Home Page</title>
</head>
<body>
    <div> This web app is still under development. </div>
    <!--TODO: Develop auth, buy some cookies from the supermarket-->
</body>
* Connection #0 to host 3.142.122.1 left intact

dXNlcg%3D%3D を URLデコード、Base64デコードすると user になる。
adminBase64エンコード、URLエンコードすると YWRtaW4%3D になる。

privilege=YWRtaW4%3DCookie 設定してアクセスすると、フラグが表示される。

f:id:tsalvia:20210608234255p:plain

SHELL{0NLY_0R30_8e1a91a632ecaf2dd6026c943eb3ed1e}

Fun with Tokens

I have got secret information that this webapp is vulnerable. Did i fail in verifying passwords ?
http://3.142.122.1:9334/

f:id:tsalvia:20210608235155p:plain

マウスの中ボタンで、Admins にアクセスすると、ユーザ一覧がダウンロードされる。

0xd4127c3c
din_djarin11

Login にアクセスするとログインページが表示される。

f:id:tsalvia:20210608235242p:plain

Admins( http://3.142.122.1:9334/adminNames )に curl でアクセスすると、getFile にリダイレクトされているのが分かる。

$ curl http://3.142.122.1:9334/adminNames
Found. Redirecting to /getFile?file=admins

file パラメータを指定することで任意のファイルをダウンロードすることができる(ただし7文字制限がある)。

$ curl http://3.142.122.1:9334/getFile?file=1234567
No such file or directory: /app/public/1234567
$ curl http://3.142.122.1:9334/getFile?file=12345678
File name too big!

../.env を指定すると、secret=G00D_s0ld13rs_k33p_s3cret5 を取得することができる。

$ curl http://3.142.122.1:9334/getFile?file=../.env
secret=G00D_s0ld13rs_k33p_s3cret5

次に login ページについて調べてみると、POST でアクセスしたときに、token ヘッダがセットされていることが判明した。

token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImhhcXJzdmFycSIsInBhc3N3b3JkIjoiaGFxcnN2YXJxIiwiYWRtaW4iOiJzbnlmciIsImlhdCI6MTYyMjk3MDM4MX0.WXHAuQBY8bErkjr4QWwNu8raiIL7rjwJV9vUxCGOIKA
$ curl http://3.142.122.1:9334/login -X POST -v
*   Trying 3.142.122.1:9334...
* TCP_NODELAY set
* Connected to 3.142.122.1 (3.142.122.1) port 9334 (#0)
> POST /login HTTP/1.1
> Host: 3.142.122.1:9334
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImhhcXJzdmFycSIsInBhc3N3b3JkIjoiaGFxcnN2YXJxIiwiYWRtaW4iOiJzbnlmciIsImlhdCI6MTYyMjk3MDM4MX0.WXHAuQBY8bErkjr4QWwNu8raiIL7rjwJV9vUxCGOIKA
< Accept-Ranges: bytes
< Cache-Control: public, max-age=0
< Last-Modified: Wed, 12 May 2021 11:19:24 GMT
< ETag: W/"2f7-179604d8660"
< Content-Type: text/html; charset=UTF-8
< Content-Length: 759
< Date: Sun, 06 Jun 2021 09:06:21 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
<!DOCTYPE html>
<html>
<head>
<title>Token Fun</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" shrink-to-fit="no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript" src="/static/scripts/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="/static/scripts/plugin-active.js"></script>
</head>
<body>
  <h2>Have Fun With Tokens</h2>
  <header>
  <nav id="sidebar-wrapper">
    <ul class="sidebar-nav">
      <li class="sidebar-nav-item">
        <a class="smooth-scroll" href="/adminNames">Admins</a>
      </li>
      <li class="sidebar-nav-item">
        <a class="smooth-scroll" href="/login">Login</a>
      </li>
    </ul>
  </nav>
</header>
</body>
* Connection #0 to host 3.142.122.1 left intact

Base64デコードすると、JWT のトークンであることが分かった。

{"alg":"HS256","typ":"JWT"}{"username":"haqrsvarq","password":"haqrsvarq","admin":"snyfr","iat":1622970381}

../.env から secret の値が判明しているので、jwt.io で任意の値に書き換えることができる。

jwt.io で以下のパラメータのトークンを生成する。

username: ROT13(din_djarin11)
password: ROT13(ir0nm4n)
admin: ROT13(true)

f:id:tsalvia:20210608235511p:plain

Authorization ヘッダに以下を設定して、http://3.142.122.1:9334/admin にアクセスする

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InF2YV9xd25ldmExMSIsInBhc3N3b3JkIjoidmUwYXo0YSIsImFkbWluIjoiZ2VociIsImlhdCI6MTYyMjk3MDM4MX0.6FdyWpGljviqcRVktVLr7gG2CxbiVTHkhFV-OQ0NrY8

f:id:tsalvia:20210608235631p:plain

アクセスすると以下のように返ってくる。

Hey din_djarin11! Here's your flag: FURYY{G0x3af_q0_z4gg3e_4r91ns4506s384q460s0s0p6r9r5sr4n}

FURYY{G0x3af_q0_z4gg3e_4r91ns4506s384q460s0s0p6r9r5sr4n} を ROT13 するとフラグになった。

SHELL{T0k3ns_d0_m4tt3r_4e91af4506f384d460f0f0c6e9e5fe4a}

Forensics

Grass is green

左上の方に書いてあった。左ローテート 3回 が一番見やすい。

f:id:tsalvia:20210609002036p:plain

SHELL{LonELY_Im_MR.lONely_YOU_are_MY_loVE}

Cryptography

encoder

can you decrypt this text : "ZOLSS{W1G_D3HY_4_T45R}"

NOTE: do not shift the numbers and the special charecters( '{' , '}' , '_' ).

CyberChef の ROT13 でずらすだけ(Amount を19にしたらフラグになった)

ZOLSS{W1G_D3HY_4_T45R}
↓
SHELL{P1Z_W3AR_4_M45K}

SHELL{P1Z_W3AR_4_M45K}

EASY-RSA

n = 1763350599372172240188600248087473321738860115540927328389207609428163138985769311
e = 65537
c = 33475248111421194902497742876885935310304862428980875522333303840565113662943528

factordb で n の素因数分解ができた

from Crypto.Util.number import long_to_bytes
from gmpy2 import invert as inverse

def main():
    n = 1763350599372172240188600248087473321738860115540927328389207609428163138985769311
    e = 65537
    c = 33475248111421194902497742876885935310304862428980875522333303840565113662943528

    p = 31415926535897932384626433832795028841
    q = 56129192858827520816193436882886842322337671

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

    m = pow(c, d, n)
    flag = long_to_bytes(m).decode()
    print(flag)

if __name__ == '__main__':
    main()
$ python3 solve.py 
shell{switchin_to_asymmetric}

shell{switchin_to_asymmetric}

Algoric-Shift

ciphered text : HESL{LRAT5PN51010T_CNPH1R}3

Try decrypting:

012345678 を暗号化したところ、120453786 になった。

暗号化されたフラグも同じようにずらすと、答えになった。

enc_flag = 'HESL{LRAT5PN51010T_CNPH1R}3'
flag = ['A'] * len(enc_flag)
for i, ch in enumerate(enc_flag):
    if i % 3 == 0:
        flag[i + 1] = ch
    elif i % 3 == 1:
        flag[i + 1] = ch
    elif i % 3 == 2:
        flag[i - 2] = ch

print(''.join(flag))
$ python3 solve.py 
SHELL{TRAN5P051T10N_C1PH3R}

SHELL{TRAN5P051T10N_C1PH3R}

haxxor

Encrypted string : 0x2-0x19-0x14-0x1d-0x1d-0x2a-0x9-0x61-0x3-0x62-0x15-0xe-0x60-0x5-0xe-0x19-0x4-0x19-0x2c
key

CyberChef で 16進数をバイナリに変えて、XOR Brute Force したら解けた。

SHELL{0R3D_1T_HUH}

BruteforceRSA

Flag Format : shellctf{}

EASY-RSA とほぼ同じ
factordb で n を素因数分解することができた

from Crypto.Util.number import long_to_bytes
from gmpy2 import invert as inverse

def main():
    n = 105340920728399121621249827556031721254229602066119262228636988097856120194803
    e = 65537
    c = 36189757403806675821644824080265645760864433613971142663156046962681317223254

    p = 320163545884759912335372936276795190799
    q = 329022220307104142121947724162904472797

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

    m = pow(c, d, n)
    flag = long_to_bytes(m).decode()
    print(flag)

if __name__ == '__main__':
    main()
$ python3 solve.py 
shellctf{k3y_s1ze_m@tter$}

shellctf{k3y_s1ze_m@tter$}

arc-cipher

cipher_text : a7 f9 de 54 29 92 7f 61 9a 7a 5f f3 f4 1a 88 a1 8f ca 97 47

ソースコードを眺めたところ、処理の流れが RC4 のように見える。
key = "MANGEKYOU" と書かれているので、 CyberChefRC4 で復号したところフラグになった。

SHELL{S4SKU3_UCH1H4}

PowerRSA

Something's not quite secure.
nc 34.92.214.217 8887
Flag format : shell{}

netcat で接続すると、以下のように出力される。

$ nc 34.92.214.217 8887
Public Key =
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnFjkilLnvEYoBkGhiN+f
OalnbBDUSJHQGJz1U11rklrc9AMfFW5fgXcTfboKeUlCdW4gA25uFEHxumwsTkQ2
UT6P07Iw0gdkxesf/fIHitVq8wPIJQMXzdB1EhZSFLt6oX9eu1LniUdMF9sJNSzJ
luzjiQDoXgAE2OD2YAjMMP7hrXBtvqi5VTPDb8ueBPUwGH8sZ8WBeGXhqHSp59XK
WXM3ODltQYaQnNlgxYnKugxTW8jQphABkTksil68sZ1i3SJn76fT2sGxrPvfW+I6
NWs3F+DOkGWD41yd3BUW6ze/7KeeQJJzVI/hsNt/7DMKW0mVdPMIYm/LqNh3tRjl
81WrnhLSBy+8GP8UWdVAiuqLTvPUTrdIqH22jgjJ7CVp2KcvCTkFPfhzdYC5keiH
z53sbP4fKBvvP5ZHNtwp2gGBdA1og1wCp/gzgJsBUtuMZ5ELI3zk+2ugC2j0yqSY
6EVEouNkUJ1Zjlh8+bYAN7gguDxs70Hq1e9pXKsJUcjCMyEfUTQpfJWPtxr1dOLV
+cHVOowvECA5VD1bOB2ZcK2/FbvLsqVyULSx5CUNFzhbPFomPRngYur39HAC+OEq
CND/BzJozGxcxMdh5L5MW/c0xeC8hR9+3GSNc8hf6+eS0LW5CufPBExN6i9GE9Nn
DoHbPc4/xfw5raCR1ybfMaUCAwEAAQ==
-----END PUBLIC KEY-----
Encrypted Flag = 0x9abaf94cbc5f07e0b13c1b9ec5f94a87762f370d8d89384333ed791f21f1568f9b018894350cb435cd76c1744b24ec1b6d009e5e0164c0d3826b41178f458329bb92e4fb789a14438ad649db7b25e3a64d4130f4cf9729673096ecf869da15da89956a245105c677060f5b6e973739318b51d3a62d812384f3d1fa32dbf70a6725d11b1f16fadc8d6d20e793ee55bccae492f4d6212937238780e4b2bd059794ff967cb3acef0b89d7a34a4897a622e9eeccd9de3f30a39b74debcea3a89aaa770e90f17f143bb55d2952d9ca0c90f9cda0d5243e4dfef38bd8fdd64a6a2442b5862b84cad8a69feec12e3266079d4b6b2e8350eacacf59c3bf448cb5eb0efbccfbf4064ada1742e4a17b5ee87fa7dac8d4bbd34b4f0bf82b2bbd84cf88e5f89df453cea1ac97de245cd3c25d59f10192fc6ae44c3654581efd5b98151929efb38f99c51dd7b024afd41eead27e1235010b923d1879b013b2e5242aae392a5edb9d5d3e381d7466db6bf4011c2dd569a871391c1fbed9591428750339ec9bdccd45da2f631dc00961d3702a9999e64a417b0ddca7316318bcf681837838b1716bbbfbcb5d2b71a3b17a014391124536e9c9cbfafff1e9dfe5393d89fb96a678876935a26c3b13697f963ac12aa4ffe3f42c8cb597980b6c9099c8f6ebe8a48b74e08d082b7042dcca822dec429b2536ff91c2391ef0d791e4e29559321a65005

pycryptodome で公開鍵から n と e を抽出する

from Crypto.PublicKey import RSA

Public_Key = '''-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnFjkilLnvEYoBkGhiN+f
OalnbBDUSJHQGJz1U11rklrc9AMfFW5fgXcTfboKeUlCdW4gA25uFEHxumwsTkQ2
UT6P07Iw0gdkxesf/fIHitVq8wPIJQMXzdB1EhZSFLt6oX9eu1LniUdMF9sJNSzJ
luzjiQDoXgAE2OD2YAjMMP7hrXBtvqi5VTPDb8ueBPUwGH8sZ8WBeGXhqHSp59XK
WXM3ODltQYaQnNlgxYnKugxTW8jQphABkTksil68sZ1i3SJn76fT2sGxrPvfW+I6
NWs3F+DOkGWD41yd3BUW6ze/7KeeQJJzVI/hsNt/7DMKW0mVdPMIYm/LqNh3tRjl
81WrnhLSBy+8GP8UWdVAiuqLTvPUTrdIqH22jgjJ7CVp2KcvCTkFPfhzdYC5keiH
z53sbP4fKBvvP5ZHNtwp2gGBdA1og1wCp/gzgJsBUtuMZ5ELI3zk+2ugC2j0yqSY
6EVEouNkUJ1Zjlh8+bYAN7gguDxs70Hq1e9pXKsJUcjCMyEfUTQpfJWPtxr1dOLV
+cHVOowvECA5VD1bOB2ZcK2/FbvLsqVyULSx5CUNFzhbPFomPRngYur39HAC+OEq
CND/BzJozGxcxMdh5L5MW/c0xeC8hR9+3GSNc8hf6+eS0LW5CufPBExN6i9GE9Nn
DoHbPc4/xfw5raCR1ybfMaUCAwEAAQ==
-----END PUBLIC KEY-----
'''

pubkey = RSA.importKey(Public_Key)
n = pubkey.n
e = pubkey.e
print('n =', n)
print('e =', e)
$ python3 parse_pubkey.py 
n = 637841078992790835162545469329286530272453544342014802413597802255455496383858337924100110894825758687742970070140170785519206224630196349340549159337859732155342647130667548491652536947418385282076081984301752395655278215274259123898531671510789372362087349190364138996395578694586775529335851081731263453238371544442231281408093208699332288138176380310125175184687443029417533001256037026948427362538182059007191165567038326351969506872408506354661232212244475008472119449944792126849713522156550842675061105463960659819569962889921953362608357370828586021370417408323866857981604016606499919020183769327897556407373881595472745700109475532395362055670005654465211949314614879870197726608273956267681241743966137146509495969974344430418089421168025779353639144082792724012236160587200227207172077968516293910782112806207821695565415445532782299158854563664952628404958937676655675829009891291081576726313965161971921934750422762092011795688420749476439187024347242499451319625109180867193919793070069304519572570570958349852522819925068591846496549213271394277576064058826488463389848830708699321727950412058117677125314200037419029032333822195659635417762704928585120467356964106252076606924158430797000011931920242350443712164261
e = 65537

primefac で素因数分解することができた

$ python3 -m primefac 637841078992790835162545469329286530272453544342014802413597802255455496383858337924100110894825758687742970070140170785519206224630196349340549159337859732155342647130667548491652536947418385282076081984301752395655278215274259123898531671510789372362087349190364138996395578694586775529335851081731263453238371544442231281408093208699332288138176380310125175184687443029417533001256037026948427362538182059007191165567038326351969506872408506354661232212244475008472119449944792126849713522156550842675061105463960659819569962889921953362608357370828586021370417408323866857981604016606499919020183769327897556407373881595472745700109475532395362055670005654465211949314614879870197726608273956267681241743966137146509495969974344430418089421168025779353639144082792724012236160587200227207172077968516293910782112806207821695565415445532782299158854563664952628404958937676655675829009891291081576726313965161971921934750422762092011795688420749476439187024347242499451319625109180867193919793070069304519572570570958349852522819925068591846496549213271394277576064058826488463389848830708699321727950412058117677125314200037419029032333822195659635417762704928585120467356964106252076606924158430797000011931920242350443712164261 | tr " " "\n"
637841078992790835162545469329286530272453544342014802413597802255455496383858337924100110894825758687742970070140170785519206224630196349340549159337859732155342647130667548491652536947418385282076081984301752395655278215274259123898531671510789372362087349190364138996395578694586775529335851081731263453238371544442231281408093208699332288138176380310125175184687443029417533001256037026948427362538182059007191165567038326351969506872408506354661232212244475008472119449944792126849713522156550842675061105463960659819569962889921953362608357370828586021370417408323866857981604016606499919020183769327897556407373881595472745700109475532395362055670005654465211949314614879870197726608273956267681241743966137146509495969974344430418089421168025779353639144082792724012236160587200227207172077968516293910782112806207821695565415445532782299158854563664952628404958937676655675829009891291081576726313965161971921934750422762092011795688420749476439187024347242499451319625109180867193919793070069304519572570570958349852522819925068591846496549213271394277576064058826488463389848830708699321727950412058117677125314200037419029032333822195659635417762704928585120467356964106252076606924158430797000011931920242350443712164261:
25255515813239507763038062828274158627213964434029360904034727073162480467501868620594875271406697596582062082030719426102268108365309215478740590990739956475214624378921033040164759679974055502626733711927304275524439772587558381820090424873221156649284685808198239733036647123384574595128095097153189572862865480492169399362806888349281817251809351266887599224507263437892651698930452700855288299116088269580309088746754202183303286426347035665905704798986062966226378809924474951727247346766929468429520066529091912983937452710041692649223542369490578218174897197410658728019724342448189448085925342097828513356033
25255515813239507763038062828274158627213964434029360904034727073162480467501868620594875271406697596582062082030719426102268108365309215478740590990739956475214624378921033040164759679974055502626733711927304275524439772587558381820090424873221156649284685808198239733036647123384574595128095097153189572862865480492169399362806888349281817251809351266887599224507263437892651698930452700855288299116088269580309088746754202183303286426347035665905704798986062966226378809924474951727247346766929468429520066529091912983937452710041692649223542369490578218174897197410658728019724342448189448085925342097828513354917

p、q が判明したので、後は復号する。 復号後なぜか\x00 が1文字毎に挿入されていたので、replace で除去した

from Crypto.Util.number import long_to_bytes
from gmpy2 import invert as inverse

c = 0x9abaf94cbc5f07e0b13c1b9ec5f94a87762f370d8d89384333ed791f21f1568f9b018894350cb435cd76c1744b24ec1b6d009e5e0164c0d3826b41178f458329bb92e4fb789a14438ad649db7b25e3a64d4130f4cf9729673096ecf869da15da89956a245105c677060f5b6e973739318b51d3a62d812384f3d1fa32dbf70a6725d11b1f16fadc8d6d20e793ee55bccae492f4d6212937238780e4b2bd059794ff967cb3acef0b89d7a34a4897a622e9eeccd9de3f30a39b74debcea3a89aaa770e90f17f143bb55d2952d9ca0c90f9cda0d5243e4dfef38bd8fdd64a6a2442b5862b84cad8a69feec12e3266079d4b6b2e8350eacacf59c3bf448cb5eb0efbccfbf4064ada1742e4a17b5ee87fa7dac8d4bbd34b4f0bf82b2bbd84cf88e5f89df453cea1ac97de245cd3c25d59f10192fc6ae44c3654581efd5b98151929efb38f99c51dd7b024afd41eead27e1235010b923d1879b013b2e5242aae392a5edb9d5d3e381d7466db6bf4011c2dd569a871391c1fbed9591428750339ec9bdccd45da2f631dc00961d3702a9999e64a417b0ddca7316318bcf681837838b1716bbbfbcb5d2b71a3b17a014391124536e9c9cbfafff1e9dfe5393d89fb96a678876935a26c3b13697f963ac12aa4ffe3f42c8cb597980b6c9099c8f6ebe8a48b74e08d082b7042dcca822dec429b2536ff91c2391ef0d791e4e29559321a65005
n = 637841078992790835162545469329286530272453544342014802413597802255455496383858337924100110894825758687742970070140170785519206224630196349340549159337859732155342647130667548491652536947418385282076081984301752395655278215274259123898531671510789372362087349190364138996395578694586775529335851081731263453238371544442231281408093208699332288138176380310125175184687443029417533001256037026948427362538182059007191165567038326351969506872408506354661232212244475008472119449944792126849713522156550842675061105463960659819569962889921953362608357370828586021370417408323866857981604016606499919020183769327897556407373881595472745700109475532395362055670005654465211949314614879870197726608273956267681241743966137146509495969974344430418089421168025779353639144082792724012236160587200227207172077968516293910782112806207821695565415445532782299158854563664952628404958937676655675829009891291081576726313965161971921934750422762092011795688420749476439187024347242499451319625109180867193919793070069304519572570570958349852522819925068591846496549213271394277576064058826488463389848830708699321727950412058117677125314200037419029032333822195659635417762704928585120467356964106252076606924158430797000011931920242350443712164261
e = 65537
p = 25255515813239507763038062828274158627213964434029360904034727073162480467501868620594875271406697596582062082030719426102268108365309215478740590990739956475214624378921033040164759679974055502626733711927304275524439772587558381820090424873221156649284685808198239733036647123384574595128095097153189572862865480492169399362806888349281817251809351266887599224507263437892651698930452700855288299116088269580309088746754202183303286426347035665905704798986062966226378809924474951727247346766929468429520066529091912983937452710041692649223542369490578218174897197410658728019724342448189448085925342097828513356033
q = 25255515813239507763038062828274158627213964434029360904034727073162480467501868620594875271406697596582062082030719426102268108365309215478740590990739956475214624378921033040164759679974055502626733711927304275524439772587558381820090424873221156649284685808198239733036647123384574595128095097153189572862865480492169399362806888349281817251809351266887599224507263437892651698930452700855288299116088269580309088746754202183303286426347035665905704798986062966226378809924474951727247346766929468429520066529091912983937452710041692649223542369490578218174897197410658728019724342448189448085925342097828513354917

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

m = pow(c, d, n)
flag = long_to_bytes(m)
print(flag)

flag = long_to_bytes(m).replace(b'\x00', b'')
print(flag)
$ python3 solve.py 
b'\xff\xfes\x00h\x00e\x00l\x00l\x00{\x00e\x00n\x00t\x00r\x000\x00p\x00y\x00_\x001\x00s\x00_\x00t\x00h\x003\x00_\x00k\x003\x00y\x00_\x00L\x009\x00m\x00l\x00I\x00s\x00T\x00t\x00B\x005\x005\x007\x00I\x00/\x00N\x00h\x004\x00g\x00q\x00L\x008\x007\x00M\x00x\x00c\x00u\x00g\x00L\x00I\x00f\x00Z\x00I\x00}\x00'
b'\xff\xfeshell{entr0py_1s_th3_k3y_L9mlIsTtB557I/Nh4gqL87MxcugLIfZI}'

shell{entr0py_1s_th3_k3y_L9mlIsTtB557I/Nh4gqL87MxcugLIfZI}

Puny Factors

They are puny but in prime shape. nc 34.92.214.217 8889 Flag format : shellctf{}

netcat で接続すると、以下のように表示される。

$ nc 34.92.214.217 8889
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxaU4leBa2MT6B0WADbE8
jFqN2IEM/p+qxj8EuGhWWRpAG1W8XVyDPts3HqEeklMC1zKUHfZkVvfEMBMYx6D2
H0w4rP4tHVvplx8sszmbjGJK1OQ6Cgym0OgJhp2C7yVQuZ7QpeZvfaZcaV1sLsbR
JGIHy9qZsljSdQG/71bFcbdgS9/Y60ij/I5OcQYe1pcbKEt+3Jyc9wgkykSlABeG
X3B/RP66Qg7XsbsEVs8OoeC5UOAcCxdw5YzchnBs9hWXlx8hpQAaPHwM3j8hgGqn
6JFFm+5rHT3xVYyifrqm0kaVVm4L60TmFmRHwsTPakfpLHOQM8ASuYQBitaISpU+
4mmC2rGBiWeqMxsq3asaSjJ32JlzA3GITivDXdcNbjrqX1ZsFlyuF1idLfC8UXbb
JgERaBXLcrnl1dMy2Bl5hrlC58gkparR2c+NpSo8T7FtobmkAokYkhRZQY596ROw
KPVG+JCN0hL2ZvQN2iJpDBJB6ImjzY5wPMwyGoVz3bvSMcgNKi0/Qdqljpv6qA+V
vq+15+W0/cxqjh+QjkMn3BgRIkDK7ygKqZ0SPyhRf5OU13HzQIM7K3WiJ4++djlV
WG35V49Z0s5VSX9XXdPKycHtskbF+9EiWVz2ybEOlLQIlFwNpncTXIwURx7oZmZK
ka8CKEn8bx09w2Po46ZBr60CAwEAAQ==
-----END PUBLIC KEY-----
c =  438395558321802376695013003313784436235704703002392605244852764168767184506614623093268402587251449238807252770826638966441343734361031775909064902412369157476271347375869878748776974708581636868685316149901187009984658083187562067610964204199634367595947219927439997992175667473381871870314474809031366658566941872295143159754037171679918076468984827127418354017260513729376018940367629412638465884738457960959569335194549372776259319313648101467969801808044124374298254699141434049425641809087635488037466829669425408634461670500011704846620869207074536532440624220697740433653152604313703845558191829595799233518882273713255972365513474592829792818745305748195183129328284527354571526078862436962266887466691930471409479661998628116563398920377814760591929579435495855596276638076921011788488053093957853190979923665081548247298037427484357045652524762103011499409034776197814122579488081835320260111429856439309600201073151342710498710025976763226000164357553790388296731324122983981774873301563515923930248888243927772720898745512877359932579119401609119237628164232730827022375275310136688704632300367157756436280865250792675945890203659137435951276788489488197627512087945495989829784649107367854328056974493200378381420588495

secret.py を見ると、同じ素数が使いまわされていることが分かる。

from Crypto.Util.number import getPrime,inverse,long_to_bytes,bytes_to_long
from Crypto.PublicKey import RSA
flag = "shellctf{something_here}"

n = getPrime(4096)
e = 65537
phi = (n-1)*(n-1)
d = inverse(e,phi)

encrypted_flag = pow(bytes_to_long(flag.encode()),e,n)

decrypted_flag = long_to_bytes(pow(encrypted_flag,d,n)).decode()

assert decrypted_flag == flag 
print(RSA.construct((n,e)).publickey().exportKey().decode())
print("c = ",encrypted_flag)

素数が使いまわされているので、後はRSAの復号をすればいい

from Crypto.PublicKey import RSA
from Crypto.Util.number import long_to_bytes
from gmpy2 import invert as inverse

Public_Key = '''-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxaU4leBa2MT6B0WADbE8
jFqN2IEM/p+qxj8EuGhWWRpAG1W8XVyDPts3HqEeklMC1zKUHfZkVvfEMBMYx6D2
H0w4rP4tHVvplx8sszmbjGJK1OQ6Cgym0OgJhp2C7yVQuZ7QpeZvfaZcaV1sLsbR
JGIHy9qZsljSdQG/71bFcbdgS9/Y60ij/I5OcQYe1pcbKEt+3Jyc9wgkykSlABeG
X3B/RP66Qg7XsbsEVs8OoeC5UOAcCxdw5YzchnBs9hWXlx8hpQAaPHwM3j8hgGqn
6JFFm+5rHT3xVYyifrqm0kaVVm4L60TmFmRHwsTPakfpLHOQM8ASuYQBitaISpU+
4mmC2rGBiWeqMxsq3asaSjJ32JlzA3GITivDXdcNbjrqX1ZsFlyuF1idLfC8UXbb
JgERaBXLcrnl1dMy2Bl5hrlC58gkparR2c+NpSo8T7FtobmkAokYkhRZQY596ROw
KPVG+JCN0hL2ZvQN2iJpDBJB6ImjzY5wPMwyGoVz3bvSMcgNKi0/Qdqljpv6qA+V
vq+15+W0/cxqjh+QjkMn3BgRIkDK7ygKqZ0SPyhRf5OU13HzQIM7K3WiJ4++djlV
WG35V49Z0s5VSX9XXdPKycHtskbF+9EiWVz2ybEOlLQIlFwNpncTXIwURx7oZmZK
ka8CKEn8bx09w2Po46ZBr60CAwEAAQ==
-----END PUBLIC KEY-----
'''

c =  438395558321802376695013003313784436235704703002392605244852764168767184506614623093268402587251449238807252770826638966441343734361031775909064902412369157476271347375869878748776974708581636868685316149901187009984658083187562067610964204199634367595947219927439997992175667473381871870314474809031366658566941872295143159754037171679918076468984827127418354017260513729376018940367629412638465884738457960959569335194549372776259319313648101467969801808044124374298254699141434049425641809087635488037466829669425408634461670500011704846620869207074536532440624220697740433653152604313703845558191829595799233518882273713255972365513474592829792818745305748195183129328284527354571526078862436962266887466691930471409479661998628116563398920377814760591929579435495855596276638076921011788488053093957853190979923665081548247298037427484357045652524762103011499409034776197814122579488081835320260111429856439309600201073151342710498710025976763226000164357553790388296731324122983981774873301563515923930248888243927772720898745512877359932579119401609119237628164232730827022375275310136688704632300367157756436280865250792675945890203659137435951276788489488197627512087945495989829784649107367854328056974493200378381420588495

pubkey = RSA.importKey(Public_Key)
n = pubkey.n
e = pubkey.e
print('n =', n)
print('e =', e)

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

m = pow(c, d, n)
flag = long_to_bytes(m)
print(flag)
$ python3 solve.py 
n = 806322861959466701153514038406844914182747166526080174736377745980674716555725490766681626566043260120682420824868316073396193362024390882335257412908771260474999293600579643566945319121804919248085997351874345676354857857473972441213476065150452838875886310619849512131643027898342627365324026643353428537966743511944890323985000437263222895323134128886261937664266641786948992154750838925176256901473951899992747314057821755750767765921813337477401428299930796289513819123483301575486653685410079033342921477046607347574015919073398381186977747632247430259320202090705384479548812641905890180605594681315462030742848212919660851496105019984550250720921757164494470361359677529849562445217451452922533777111776869196499200919028160236378681085893920603211789942740561879638297743748843688531008344335704670403176671115854092649447384217365867958751615695214609518308424284147963214012037545924281629303027548754921764283248415629573081634574841296056069843776605858111240669604239915340117392644408645985430125771656667240533495686447938802050067631495819226425234737491534813467389171120350672423761879255192205553213889378836118407685268753162887278988365476406089806561499511763794595103444629455631049585792307726958751832453037
e = 65537
b'shellctf{pr1m3s_ar3_sup3r_int3re$tinG}'

shellctf{pr1m3s_ar3_sup3r_int3re$tinG}

Reverse Engineering

check_flag

Was cleaning the junk out of my PC, when I found this really old executable. Help me look for the flag.

strings するだけ

$ strings checkflag.exe | grep SHELL
SHELL{bas1c_r3v}

SHELL{bas1c_r3v}

assembly

fun1(0x74,0x6f) + fun1(0x62,0x69) = ?
Note : submit flag in hexadecimal format and wrap it in SHELL{ & }.

以下のように書かれたファイルが与えられている。

fun1:
    <+0>: push   ebp
    <+1>:    mov    ebp,esp
    <+3>:    sub    esp,0x10
    <+6>:    mov    eax,DWORD PTR [ebp+0xc]
    <+9>:    mov    DWORD PTR [ebp-0x4],eax
    <+12>:   mov    eax,DWORD PTR [ebp+0x8]
    <+15>:   mov    DWORD PTR [ebp-0x8],eax
    <+18>:   jmp    <fun1+28>
    <+20>:   add    DWORD PTR [ebp-0x4],0x7
    <+24>:   add    DWORD PTR [ebp-0x8],0x70
    <+28>:   cmp    DWORD PTR [ebp-0x8],0x227
    <+35>:   jle    <fun1+20>
    <+37>:   mov    eax,DWORD PTR [ebp-0x4]
    <+40>:   leave  
    <+41>:   ret  

上記のファイルを再現して、実行するとフラグになる。

#include <stdio.h>

int fun1(int n1, int n2) {
    int eax, ebp_4, ebp_8;

    eax = n2;
    ebp_4 = eax;
    eax = n1;
    ebp_8 = eax;

fun1_20:
    ebp_4 += 0x7;
    ebp_8 += 0x70;

fun1_28:
    if (ebp_8 <= 0x227) {
        goto fun1_20;
    }
    eax = ebp_4;
    return eax;
}

int main(void) {
    printf("SHELL{0x%x}\n", fun1(0x74,0x6f) + fun1(0x62,0x69));
    return 0;
}
$ gcc solve.c
$ ./a.out
SHELL{0x117}

SHELL{0x117}

keygen

Can you get the flag from the given file.

以下のファイルが与えられている。

def checkends(password):
    end_status = 0
    if password[:6] == "SHELL{":
        end_status = 1
    if password[28] == "}":
        end_status = 1
    return end_status
def checkmiddle1(password):
    middle1_status = 0
    if password[27] == "1"  and password[17] == "4" and password[8] == "n" and password[23] == "y" and password[10] == "0":
        middle1_status = 1
    if password[11] == "n" and password[12] == "z" and password[13] == "a" and password[21] == "g" and password[15] == "u":
        middle1_status = 1
    if password[16] == "r"and password[7] == "3" :
        middle1_status = 1
    return middle1_status
def checkmiddle2(password):
    middle2_status = 0
    if password[18] == "_" and password[25] == "5" and password[20] == "4" and password[14] == "k" and password[22] == "3" and password[9] == "b"  and password[24] ==  "0":
        middle2_status = 1
    if  password[19] == "k" and password[26] == "h" and password[6] == "s" :
        middle2_status = 1
    return middle2_status
# driver code

a = input("enter your flag:")
if checkends(a) == 1 and checkmiddle1(a) == 1 and checkmiddle2(a) == 1:
    print("congrats thats the flag.")
else:
    print("Wrong flag.")

check関連の関数内にある配列を並べるとフラグになる。

password = [''] * 100
for i, c in enumerate("SHELL{"):
    password[i] = c
password[28] = "}"
password[27] = "1"
password[17] = "4" 
password[8] = "n" 
password[23] = "y" 
password[10] = "0"
password[11] = "n" 
password[12] = "z" 
password[13] = "a" 
password[21] = "g" 
password[15] = "u"
password[16] = "r"
password[7] = "3"
password[18] = "_" 
password[25] = "5" 
password[20] = "4" 
password[14] = "k" 
password[22] = "3" 
password[9] = "b"  
password[24] =  "0"
password[19] = "k" 
password[26] = "h" 
password[6] = "s"

print(''.join(password))
$ python3 solve.py
SHELL{s3nb0nzakur4_k4g3y05h1}

SHELL{s3nb0nzakur4_k4g3y05h1}

sakuna

Somebody told me this executable has priceless info hidden.

とりあえず、strings を実行してみると、以下のようになった。grep 結果を見ると、フラグが分割されているように見える。

$ strings sukuna.exe  | grep SHELL -C 5
D$ H
AUATUWVSH
T$ D
[^_]A\A]
fffff.
SHELL{
5hR1n3}
M3L0v4l3H
CongratsH
 your flH
ag is coH

Ghidra で文字列の参照箇所を確認すると、strcat で文字列を連結していた。

f:id:tsalvia:20210609003446p:plain

正しい順番で、文字列連結するとフラグになった。

SHELL{M3L0v4l3nT_5hR1n3}