0


2024年---第十五届蓝桥杯网络安全CTF赛道Writeup(Web、Misc、Crypto、Reverse)

第一题:爬虫协议

1.1 题目描述:

  1. 小兰同学在开发网站时了解到一个爬虫协议,该协议指网站可建立一个特别的txt文件来告诉搜索引擎哪些页面可以抓取,哪些不可以抓取,而搜索引擎则通过读取该txt文件来识别这个页面是否允许被抓取,爬虫协议并不是一个规范而只是约定俗成的,所以不能保证网站的隐私。

1.2 题目界面:

  1. 打开题目网址

1.3 解题步骤:

  1. 1):尝试访问robots.txt文件

  1. 2):尝试访问0f3f8d7ec56c0c50f9d73724902648a5

  1. 3):尝试访问0f3f8d7ec56c0c50f9d73724902648a5/da87bd9aca438bf00a80d12c8912f3a0

  1. 4):得到flag{42d5c8f1-259d-462c-a8bd-4bc1f50d354d}

第二题:流量分析

2.1 解题步骤:

  1. 1):用wireshark打开题目所给文件

  1. 2):导出对象

  1. 3):选择HTTP对象导出

  1. 4):用记事本打开flag%20%7cbase64%20-w%200%27);文件

  1. 5):base64解密文件内容ZmxhZ3s3ZDZmMTdhNC0yYjBhLTQ2N2QtOGE0Mi02Njc1MDM2OGMyNDl9Cg==得到flag{7d6f17a4-2b0a-467d-8a42-66750368c249}

第三题:AES加密

3.1 题目界面:

  1. ![](https://img-blog.csdnimg.cn/direct/c707a106f8ad404384155ce7535bfe44.png)

3.2 解题步骤:

  1. 1):分析得出:题目界面已经告诉我们采用的是AES加密,并且告诉我们keygamelab@gamelab@IVgamelab@gamelab@ModeCBC模式,输出为Hex十六进制4da72144967f1c25e6273950bf29342aae635e2396ae17c80b1bff68d90f16679bb45c15852e0ce88d4864d93e9e3be2
  2. 2):打开解密工具cc(CyberChef),输入keyIVMode以及密文,点击decode解密得到flag{6500e76e-15fb-42e8-8f29-a309ab73ba38}

第四题:RSA加密

4.1 题目文件为task.py,文件代码内容如下所示:

  1. from Crypto.Util.number import *
  2. from gmpy2 import *
  3. flag = b'xxx'
  4. m = bytes_to_long(flag)
  5. p = getPrime(512)
  6. q = next_prime(p)
  7. e = 65537
  8. n = p * q
  9. phi = (p - 1) * (q - 1)
  10. d = inverse(e, phi)
  11. d1 = d % q
  12. d2 = d % p
  13. c = pow(m, e, n)
  14. print(n)
  15. print(d1)
  16. print(d2)
  17. print(c)
  18. # 94581028682900113123648734937784634645486813867065294159875516514520556881461611966096883566806571691879115766917833117123695776131443081658364855087575006641022211136751071900710589699171982563753011439999297865781908255529833932820965169382130385236359802696280004495552191520878864368741633686036192501791
  19. # 4218387668018915625720266396593862419917073471510522718205354605765842130260156168132376152403329034145938741283222306099114824746204800218811277063324566
  20. # 9600627113582853774131075212313403348273644858279673841760714353580493485117716382652419880115319186763984899736188607228846934836782353387850747253170850
  21. # 36423517465893675519815622861961872192784685202298519340922692662559402449554596309518386263035128551037586034375613936036935256444185038640625700728791201299960866688949056632874866621825012134973285965672502404517179243752689740766636653543223559495428281042737266438408338914031484466542505299050233075829

4.2 解题步骤:

  1. 1):分析得出:我们得知道这个算法的原理,就是现在pq是两个素数Q,而且他俩在素数序列里面就是一前一后的关系。所以我们要把他俩的乘积开根号得到的结果一定是在pq之间的一个数字,(而且一定不是素数,因为pq就是紧邻的两个素数)。那我们找这个开方出来的数字的下一个素数,一定是q,因此我们再让n/q就可以得到两个素数。
  2. 2):解法一,得到flag{5f00e1b9-2933-42ad-b4e1-069f6aa98e9a}:
  1. import gmpy2
  2. import sympy
  3. # import Cryptodome.Util.number
  4. from Crypto.Util.number import *
  5. import binascii
  6. n=94581028682900113123648734937784634645486813867065294159875516514520556881461611966096883566806571691879115766917833117123695776131443081658364855087575006641022211136751071900710589699171982563753011439999297865781908255529833932820965169382130385236359802696280004495552191520878864368741633686036192501791
  7. x=gmpy2.iroot(n,2)[0]# 取第0个元素,也就是第一个元素
  8. p=sympy.nextprime(x)
  9. q=n//p
  10. e=65537
  11. d=gmpy2.invert(e,(p-1)*(q-1))
  12. print(p)
  13. print(q)
  14. print(d)
  15. c=36423517465893675519815622861961872192784685202298519340922692662559402449554596309518386263035128551037586034375613936036935256444185038640625700728791201299960866688949056632874866621825012134973285965672502404517179243752689740766636653543223559495428281042737266438408338914031484466542505299050233075829
  16. m=pow(c,d,n)
  17. print(m)
  18. print(long_to_bytes(m))

  1. 3):解法二,直接yafu分解n,得到p,q的值,然后计算得到flag

第五题:DWT盲水印

5.1 题目文件如下所示:

5.2 解题步骤:

  1. 1):破解orign压缩包:打开压缩包发现压缩包里面的serect.txt是密码字典,未加密,可以解压出来,然后用serect.txt字典破解压缩包orign.zip,得到a.png也就是原始图片。
  2. 2):打开lose.py分析发现为DWT盲水印代码:
  1. class WaterMarkDWT:
  2. def __init__(self, origin: str, watermark: str, key: int, weight: list):
  3. self.key = key
  4. self.img = cv2.imread(origin)
  5. self.mark = cv2.imread(watermark)
  6. self.coef = weight
  7. def arnold(self, img):
  8. r, c = img.shape
  9. p = np.zeros((r, c), np.uint8)
  10. a, b = 1, 1
  11. for k in range(self.key):
  12. for i in range(r):
  13. for j in range(c):
  14. x = (i + b * j) % r
  15. y = (a * i + (a * b + 1) * j) % c
  16. p[x, y] = img[i, j]
  17. return p
  18. def deArnold(self, img):
  19. r, c = img.shape
  20. p = np.zeros((r, c), np.uint8)
  21. a, b = 1, 1
  22. for k in range(self.key):
  23. for i in range(r):
  24. for j in range(c):
  25. x = ((a * b + 1) * i - b * j) % r
  26. y = (-a * i + j) % c
  27. p[x, y] = img[i, j]
  28. return p
  29. def get(self, size: tuple = (1200, 1200), flag: int = None):
  30. img = cv2.resize(self.img, size)
  31. img1 = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
  32. img2 = cv2.cvtColor(self.mark, cv2.COLOR_RGB2GRAY)
  33. c = pywt.wavedec2(img2, 'db2', level=3)
  34. [cl, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1)] = c
  35. d = pywt.wavedec2(img1, 'db2', level=3)
  36. [dl, (dH3, dV3, dD3), (dH2, dV2, dD2), (dH1, dV1, dD1)] = d
  37. a1, a2, a3, a4 = self.coef
  38. ca1 = (cl - dl) * a1
  39. ch1 = (cH3 - dH3) * a2
  40. cv1 = (cV3 - dV3) * a3
  41. cd1 = (cD3 - dD3) * a4
  42. waterImg = pywt.waverec2([ca1, (ch1, cv1, cd1)], 'db2')
  43. waterImg = np.array(waterImg, np.uint8)
  44. waterImg = self.deArnold(waterImg)
  45. kernel = np.ones((3, 3), np.uint8)
  46. if flag == 0:
  47. waterImg = cv2.erode(waterImg, kernel)
  48. elif flag == 1:
  49. waterImg = cv2.dilate(waterImg, kernel)
  50. cv2.imwrite('水印.png', waterImg)
  51. return waterImg
  52. if __name__ == '__main__':
  53. img = 'a.png'
  54. k = 20
  55. xs = [0.2, 0.2, 0.5, 0.4]
  56. W1 = WaterMarkDWT(img, waterImg, k, xs)
  1. 3):编写exp.py得到flag.png
  1. import cv2
  2. import pywt
  3. import numpy as np
  4. class WaterMarkDWT:
  5. def __init__(self, origin: str, watermark: str, key: int, weight: list):
  6. self.key = key
  7. self.img = cv2.imread(origin)
  8. self.mark = cv2.imread(watermark)
  9. self.coef = weight
  10. def arnold(self, img):
  11. r, c = img.shape
  12. p = np.zeros((r, c), np.uint8)
  13. a, b = 1, 1
  14. for k in range(self.key):
  15. for i in range(r):
  16. for j in range(c):
  17. x = (i + b * j) % r
  18. y = (a * i + (a * b + 1) * j) % c
  19. p[x, y] = img[i, j]
  20. return p
  21. def deArnold(self, img):
  22. r, c = img.shape
  23. p = np.zeros((r, c), np.uint8)
  24. a, b = 1, 1
  25. for k in range(self.key):
  26. for i in range(r):
  27. for j in range(c):
  28. x = ((a * b + 1) * i - b * j) % r
  29. y = (-a * i + j) % c
  30. p[x, y] = img[i, j]
  31. return p
  32. def get(self, size: tuple = (1200, 1200), flag: int = None):
  33. img = cv2.resize(self.img, size)
  34. img1 = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
  35. img2 = cv2.cvtColor(self.mark, cv2.COLOR_RGB2GRAY)
  36. c = pywt.wavedec2(img2, 'db2', level=3)
  37. [cl, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1)] = c
  38. d = pywt.wavedec2(img1, 'db2', level=3)
  39. [dl, (dH3, dV3, dD3), (dH2, dV2, dD2), (dH1, dV1, dD1)] = d
  40. a1, a2, a3, a4 = self.coef
  41. ca1 = (cl - dl) * a1
  42. ch1 = (cH3 - dH3) * a2
  43. cv1 = (cV3 - dV3) * a3
  44. cd1 = (cD3 - dD3) * a4
  45. waterImg = pywt.waverec2([ca1, (ch1, cv1, cd1)], 'db2')
  46. waterImg = np.array(waterImg, np.uint8)
  47. waterImg = self.deArnold(waterImg)
  48. kernel = np.ones((3, 3), np.uint8)
  49. if flag == 0:
  50. waterImg = cv2.erode(waterImg, kernel)
  51. elif flag == 1:
  52. waterImg = cv2.dilate(waterImg, kernel)
  53. cv2.imwrite('水印.png', waterImg)
  54. return waterImg
  55. if __name__ == '__main__':
  56. img = 'a.png'
  57. newImg='newImg.png'
  58. k = 20
  59. #xs = [0.2, 0.2, 0.5, 0.4]
  60. coef=[5,5,2,2.5]
  61. #waterImg='flag.png'
  62. W1 = WaterMarkDWT(img, newImg, k, coef)
  63. waterimg=W1.get()

第六题:Reverse逆向RC4

6.1 题目文件rc4.exe如下所示:

6.2 解题步骤:

  1. 1):die检测无壳,32位程序。

  1. 2):用IDA32打开,发现keygamelab@,提取数组v5进行RC4解密得到flag

第七题:ECDSA椭圆曲线数字签名算法

7.1 题目代码如下所示:

  1. import ecdsa
  2. import random
  3. def ecdsa_test(dA,k):
  4. sk = ecdsa.SigningKey.from_secret_exponent(
  5. secexp=dA,
  6. curve=ecdsa.SECP256k1
  7. )
  8. sig1 = sk.sign(data=b'Hi.', k=k).hex()
  9. sig2 = sk.sign(data=b'hello.', k=k).hex()
  10. r1 = int(sig1[:64], 16)
  11. s1 = int(sig1[64:], 16)
  12. s2 = int(sig2[64:], 16)
  13. return r1,s1,s2
  14. if __name__ == '__main__':
  15. n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
  16. a = random.randint(0,n)
  17. flag = 'flag{' + str(a) + "}"
  18. b = random.randint(0,n)
  19. print(ecdsa_test(a,b))
  20. # (4690192503304946823926998585663150874421527890534303129755098666293734606680, 111157363347893999914897601390136910031659525525419989250638426589503279490788, 74486305819584508240056247318325239805160339288252987178597122489325719901254)

7.2 代码分析:

  1. 椭圆曲线数字签名算法,它利用椭圆曲线密码学(ECC)对数字签名算法(DSA)进行模拟,其安全性基于椭圆曲线离散对数问题。但是当某些数值相同时会出现一些安全问题。
  2. 分析代码可以看出,存在随机数重复使用。具体来说,这段代码中签名的过程中使用了相同的随机数 k 来对不同的消息进行签名。这种情况下,可以通过分析两个相同 k 值对应的消息签名来恢复私钥 dA
  3. ECDSA 中,每次签名过程中都会使用一个随机数 k,以确保生成唯一的签名。然而,如果相同的随机数 k 被重复使用来对不同的消息进行签名,攻击者就有可能通过数学分析和推导计算出私钥 dA

7.3 exp代码:

  1. import sympy
  2. from hashlib import sha1
  3. from Cryptodome.Util.number import long_to_bytes , bytes_to_long
  4. def calculate_private_key(r1, s1, s2, h1, h2, n):
  5. # 计算k值
  6. k = ((h1 - h2) * sympy.mod_inverse(s1 - s2, n)) % n
  7. # 计算私钥dA
  8. dA = (sympy.mod_inverse(r1, n) * (k * s1 - h1)) % n
  9. return dA
  10. if __name__ == "__main__":
  11. # 定义椭圆曲线的参数
  12. n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
  13. # 签名中的r1, s1, s2值
  14. r1 = 4690192503304946823926998585663150874421527890534303129755098666293734606680
  15. s1 = 111157363347893999914897601390136910031659525525419989250638426589503279490788
  16. s2 = 74486305819584508240056247318325239805160339288252987178597122489325719901254
  17. h1 = bytes_to_long(sha1(b'Hi.').digest())
  18. h2 = bytes_to_long(sha1(b'hello.').digest())
  19. private_key = calculate_private_key(r1, s1, s2, h1, h2, n)
  20. print(f'flag{{{private_key}}}')

获得flag{40355055231406097504270940121798355439363616832290875140843417522164091270174}

第八题:Reverse逆向xxtea

8.1 题目描述如下:

  1. Flag被使用了算法分成若干个小块,每个块使用相同的加密解密方法,但这个算法是对称加密,请分析密文并还原。

8.2 题目文件happytime

8.3 解题步骤

  1. 1):die检测无壳,64位程序。

  1. 2):拖进IDA分析。

printf输出提示信息Let’s have a drink,pay your answer(flag):,read在键盘读取flag输入,重要的关键函数是cry加密函数,接受v5和输入的flag,这里的11应该是flag被分割成了11组,最后一个循环比较加密后的flag和V6,刚好和上面v6数组对应:

3):根据cry函数的特征,可以判定这是XXTEA加密无疑,找到其中的DELTA,密文(main函数中的v6),和key(前面main函数的V5),即可编写脚本解密(输出的时候注意大小端序):

  1. #include <stdbool.h>
  2. #include <stdio.h>
  3. #define MX (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(p & 3) ^ e] ^ z))
  4. bool btea(unsigned int *v, int n, unsigned int *k)
  5. {
  6. unsigned int z = v[n - 1], y = v[0], sum = 0, e, DELTA = 0x61C88647;
  7. unsigned int p, q;
  8. if (n > 1)
  9. { /* enCoding Part */
  10. q = 415 / n + 114;
  11. while (q-- > 0)
  12. {
  13. sum += DELTA;
  14. e = (sum >> 2) & 3;
  15. for (p = 0; p < (n - 1); p++)
  16. {
  17. y = v[p + 1];
  18. z = v[p] += MX;
  19. }
  20. y = v[0];
  21. z = v[n - 1] += MX;
  22. }
  23. return 0;
  24. }
  25. else if (n < -1)
  26. { /* Decoding Part */
  27. n = -n;
  28. q = 415 / n + 114;
  29. sum = -q * DELTA;
  30. while (sum != 0)
  31. {
  32. e = (sum >> 2) & 3;
  33. for (p = n - 1; p > 0; p--)
  34. {
  35. z = v[p - 1];
  36. y = v[p] -= MX;
  37. }
  38. z = v[n - 1];
  39. y = v[0] -= MX;
  40. sum += DELTA;
  41. }
  42. return 0;
  43. }
  44. return 1;
  45. }
  46. int main()
  47. {
  48. unsigned int v[11] = {0x480AC20C, 0xCE9037F2, 0x8C212018, 0xE92A18D, 0xA4035274, 0x2473AAB1, 0xA9EFDB58, 0xA52CC5C8, 0xE432CB51, 0xD04E9223, 0x6FD07093}, key[4] = {0x79696755, 0x67346F6C, 0x69231231, 0x5F674231};
  49. int n = 11; // n为要加密的数据个数
  50. btea(v, -n, key); // 取正为加密,取负为解密
  51. char *p = (char *)v;
  52. for (int i = 0; i < 44; i++)
  53. {
  54. printf("%c", *p);
  55. p++;
  56. }
  57. return 0;
  58. }
  59. //flag{efccf8f0-0c97-12ec-82e0-0c9d9242e335}

恭喜CTF培训班的王思雨同学获得2024年蓝桥杯省赛一等奖,国赛三等奖的成绩。


本文转载自: https://blog.csdn.net/ctfayang/article/details/138605431
版权归原作者 ctfayang 所有, 如有侵权,请联系我们删除。

“2024年---第十五届蓝桥杯网络安全CTF赛道Writeup(Web、Misc、Crypto、Reverse)”的评论:

还没有评论