GDOUCTF 2023 由于当时比赛那天参加学校活动比较忙错过了比赛,那就看看题吧。
Absolute_Baby_Encrytpion 题目给了一段密文和js代码:
1 +}!q")hiim)#}-nvm)i-$#mvn#0mnbm)im#n+}!qnm8)i-$#mvnoc#0nz<$9inm!>-n1:1-nm8)i-$~c58n!}qhij#0[noic##m8nc8n?!8c}w!n]>&
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 let messagetoEncrypt = prompt ("Enter a string: " ).toLowerCase ();let charArray = messagetoEncrypt.split ("" );let encryptedString = "" ;let hasInvalidCharacter = false ;for (let i = 0 ; i < charArray.length ; i++) { switch (charArray[i]) { case 'a' : encryptedString = encryptedString.concat ('!' ) break ; case 'b' : encryptedString = encryptedString.concat ('1' ) break ; case 'c' : encryptedString = encryptedString.concat (')' ) break ; case 'd' : encryptedString = encryptedString.concat ('v' ) break ; case 'e' : encryptedString = encryptedString.concat ('m' ) break ; case 'f' : encryptedString = encryptedString.concat ('+' ) break ; case 'g' : encryptedString = encryptedString.concat ('q' ) break ; case 'h' : encryptedString = encryptedString.concat ('0' ) break ; case 'i' : encryptedString = encryptedString.concat ('c' ) break ; case 'j' : encryptedString = encryptedString.concat (']' ) break ; case 'k' : encryptedString = encryptedString.concat ('(' ) break ; case 'l' : encryptedString = encryptedString.concat ('}' ) break ; case 'm' : encryptedString = encryptedString.concat ('[' ) break ; case 'n' : encryptedString = encryptedString.concat ('8' ) break ; case 'o' : encryptedString = encryptedString.concat ('5' ) break ; case 'p' : encryptedString = encryptedString.concat ('$' ) break ; case 'q' : encryptedString = encryptedString.concat ('*' ) break ; case 'r' : encryptedString = encryptedString.concat ('i' ) break ; case 's' : encryptedString = encryptedString.concat ('>' ) break ; case 't' : encryptedString = encryptedString.concat ('#' ) break ; case 'u' : encryptedString = encryptedString.concat ('<' ) break ; case 'v' : encryptedString = encryptedString.concat ('?' ) break ; case 'w' : encryptedString = encryptedString.concat ('o' ) break ; case 'x' : encryptedString = encryptedString.concat ('^' ) break ; case 'y' : encryptedString = encryptedString.concat ('-' ) break ; case 'z' : encryptedString = encryptedString.concat ('_' ) break ; case '0' : encryptedString = encryptedString.concat ('h' ) break ; case '1' : encryptedString = encryptedString.concat ('w' ) break ; case '2' : encryptedString = encryptedString.concat ('e' ) break ; case '3' : encryptedString = encryptedString.concat ('9' ) break ; case '4' : encryptedString = encryptedString.concat ('g' ) break ; case '5' : encryptedString = encryptedString.concat ('z' ) break ; case '6' : encryptedString = encryptedString.concat ('d' ) break ; case '7' : encryptedString = encryptedString.concat ('~' ) break ; case '8' : encryptedString = encryptedString.concat ('=' ) break ; case '9' : encryptedString = encryptedString.concat ('x' ) break ; case '!' : encryptedString = encryptedString.concat ('j' ) break ; case '@' : encryptedString = encryptedString.concat (':' ) break ; case '#' : encryptedString = encryptedString.concat ('4' ) break ; case '$' : encryptedString = encryptedString.concat ('b' ) break ; case '%' : encryptedString = encryptedString.concat ('`' ) break ; case '^' : encryptedString = encryptedString.concat ('l' ) break ; case '&' : encryptedString = encryptedString.concat ('3' ) break ; case '*' : encryptedString = encryptedString.concat ('t' ) break ; case '(' : encryptedString = encryptedString.concat ('6' ) break ; case ')' : encryptedString = encryptedString.concat ('s' ) break ; case '_' : encryptedString = encryptedString.concat ('n' ) break ; case '+' : encryptedString = encryptedString.concat (';' ) break ; case '-' : encryptedString = encryptedString.concat ('\'' ) break ; case '=' : encryptedString = encryptedString.concat ('r' ) break ; case '`' : encryptedString = encryptedString.concat ('k' ) break ; case '~' : encryptedString = encryptedString.concat ('p' ) break ; case '{' : encryptedString = encryptedString.concat ('\"' ) break ; case '}' : encryptedString = encryptedString.concat ('&' ) break ; case '[' : encryptedString = encryptedString.concat ('/' ) break ; case ']' : encryptedString = encryptedString.concat ('\\' ) break ; case '|' : encryptedString = encryptedString.concat ('2' ) break ; case ':' : encryptedString = encryptedString.concat ('.' ) break ; case ';' : encryptedString = encryptedString.concat ('%' ) break ; case '\"' : encryptedString = encryptedString.concat ('|' ) break ; case '\'' : encryptedString = encryptedString.concat (',' ) break ; case '<' : encryptedString = encryptedString.concat ('@' ) break ; case '>' : encryptedString = encryptedString.concat ('{' ) break ; case ',' : encryptedString = encryptedString.concat ('u' ) break ; case '.' : encryptedString = encryptedString.concat ('7' ) break ; case '?' : encryptedString = encryptedString.concat ('y' ) break ; case '/' : encryptedString = encryptedString.concat ('a' ) break ; default : hasInvalidCharacter = true ; } } if (hasInvalidCharacter) { encryptedString = "Invalid String!" ; } else { console .log (`Your encoded string is ${encryptedString} ` ); }
简单的单表代换,写个python脚本就能得到flag:
1 2 3 4 str ='+}!q")hiim)#}-nvm)i-$#mvn#0mnbm)im#n+}!qnm8)i-$#mvnoc#0nz<$9inm!>-n1:1-nm8)i-$~c58n!}qhij#0[noic##m8nc8n?!8c}w!n]>&' book1='abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+=`~{}[]|:;\<>,.?/' book2='!1)vm+q0c](}[85$*i>#<?o^-_hwe9gzd~=xj:4b`13t6sn;rkp"&/\2.%|,@{u7ya' print ('' .join(book1[book2.index(i)]for i in str ))
Magic of Encoding 题目给了一大堆base64编码,先用cyberchef解码一下试试:
1 2 3 4 5 6 7 8 flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{not_the_correct_flag_lol} flag{not_the_correct_flag_lol} flag{not_the_correct_flag_lol} flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canflag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}flag{Xd_fake_flag_xD}find_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canflag{not_the_correct_flag_lol} flag{not_the_correct_flag_lol} flag{not_the_correct_flag_lol} flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}flag{not_the_correct_flag_lol}find_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}find_me_if_you_canPK.........T.V.........¥¹.}µ.}¥.}å½Õ}..¹.±..ía.}....}.±..}á.õ.±..ía.}....}.±..}á.õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±ô).±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±ô).±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±ô).±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ.. .....
可以看到一大群flag,后面还跟着生成了非常多的乱码,而且一眼望过去几乎全是重复句段,只是有的是假flag有的是乱码,在确定了并没有藏flag在这里面之后,我发现了:
1 find_me_if_you_canfind_me_if_you_canflag{Xd_fake_flag_xD}find_me_if_you_canPK.........T.V.........¥¹.}µ.}¥.}å½Õ}..¹.±..ía.}....}.±..}á.õ.±..ía.}....}.±..}á.õ.±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±ô).±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..}±½±ô).±..í¹½Ñ}Ñ¡.}.½ÉÉ..Ñ}.±..
在第一块这里正常句段转到乱码的地方出现了一个PK,这就代表可能藏了压缩包(这不是misc题吗……),通过比较乱码字段和假flag段的base64源码发现其实是一样的,所以题目中所有解码出的文本几乎都为假flag段。我猜测这里这些乱码的出现是因为PK压缩包base64加密的问题导致原来的假flag码加密错位导致出现了乱码,不过它们的base64码是一样的,可以用假flag直接去掉这些码,保留pk压缩包:
1 2 3 4 5 6 7 8 9 10 from base64 import *with open ('Magic_Of_Encoding.txt' ) as f: f=f.read() list = ["flag{Xd_fake_flag_xD}" ,"find_me_if_you_can" ,"flag{not_the_correct_flag_lol}" ,"\nflag{not_the_correct_flag_lol}\nflag{not_the_correct_flag_lol}\n" ] base64_flag_list = [b64encode(i.encode()).decode() for i in list ] for i in base64_flag_list: f = f.replace(i,"" ) with open ('2.txt' ,'wb' ) as t: t.write(b64decode(f))
将得到的二进制文本写入压缩包,解压得到flag。
Math Problem 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import secretfrom Crypto.Util.number import *p, q = getPrime(512 ), getPrime(512 ) e, n = 0x10001 , p * q c = pow (bytes_to_long(secret.flag), e, n) a, b = getPrime(512 ), getPrime(512 ) E = EllipticCurve(GF(p), [a, b]) G = E.lift_x(ZZ(getPrime(64 ))) print (f"{a = } \n{b = } \ny = {G.xy()[1 ]} " )''' e = 65537 n = 79239019133008902130006198964639844798771408211660544649405418249108104979283858140199725213927656792578582828912684320882248828512464244641351915288069266378046829511827542801945752252863425605946379775869602719406340271702260307900825314967696531175183205977973427572862807386846990514994510850414958255877 c = 45457869965165575324534408050513326739799864850578881475341543330291990558135968254698676312246850389922318827771380881195754151389802803398367341521544667542828862543407738361578535730524976113729406101764290984943061582342991118766322793847422471903811686775249409300301726906738475446634950949059180072008 a = 9303981927028382051386918702900550228062240363697933771286553052631411452412621158116514735706670764224584958899184294505751247393129887316131576567242619 b = 9007779281398842447745292673398186664639261529076471011805234554666556577498532370235883716552696783469143334088312327338274844469338982242193952226631913 y = 970090448249525757357772770885678889252473675418473052487452323704761315577270362842929142427322075233537587085124672615901229826477368779145818623466854 '''
G = E.lift_x(ZZ(getPrime(64)))
这段代码是为椭圆曲线创建一个点。具体来说,它接受一个x坐标作为输入,返回一个对应的点。这个点的纵坐标y是根据椭圆曲线上的方程计算得出的。
一道数学题,用了ECC算法。
题目把a和b都给了,已知方程参数和生成点y,x位数比较小,尝试使用coppersmith求x:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from Crypto.Util.number import *import gmpy2e = 65537 n = 79239019133008902130006198964639844798771408211660544649405418249108104979283858140199725213927656792578582828912684320882248828512464244641351915288069266378046829511827542801945752252863425605946379775869602719406340271702260307900825314967696531175183205977973427572862807386846990514994510850414958255877 c = 45457869965165575324534408050513326739799864850578881475341543330291990558135968254698676312246850389922318827771380881195754151389802803398367341521544667542828862543407738361578535730524976113729406101764290984943061582342991118766322793847422471903811686775249409300301726906738475446634950949059180072008 a = 9303981927028382051386918702900550228062240363697933771286553052631411452412621158116514735706670764224584958899184294505751247393129887316131576567242619 b = 9007779281398842447745292673398186664639261529076471011805234554666556577498532370235883716552696783469143334088312327338274844469338982242193952226631913 y = 970090448249525757357772770885678889252473675418473052487452323704761315577270362842929142427322075233537587085124672615901229826477368779145818623466854 p.<x>=PolynomialRing(Zmod(n)) f=x^3 +a*x+b-y^2 f=f.monic() x0=f.small_roots(X=2 ^64 ,beta=0.4 ,epsilon=0.01 )[0 ]
这里再详细的回顾一下f.small_roots()
这个函数,这行代码的含义是在多项式f中找到一个小于$2^{64}$的根。参数beta
表示多项式模的次数系数上限,epsilon
表示找到可接受的根的概率,这两个参数都控制了算法的时间复杂度和准确率 。由于多项式模问题是一个NP难问题,因此在实际运行中,可能需要多次运行算法才能找到一个合适的解。
NP难问题指的是一类NP问题,这些问题非常困难,目前没有已知的多项式算法能够在多项式时间内解决它们。因此不能保证在多项式时间内求解这些问题,但是可以在多项式时间内验证一个给定的解是否正确。——取自ChatGPT
这里如果不加epsilon参数会求不出来,测试设为0.01能求出小值根。
得到根之后代入回原方程组得到f值,由于是在模n多项式环下为0,f值小于n,和n有公共因子p,得到因式分解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from Crypto.Util.number import *import gmpy2e = 65537 n = 79239019133008902130006198964639844798771408211660544649405418249108104979283858140199725213927656792578582828912684320882248828512464244641351915288069266378046829511827542801945752252863425605946379775869602719406340271702260307900825314967696531175183205977973427572862807386846990514994510850414958255877 c = 45457869965165575324534408050513326739799864850578881475341543330291990558135968254698676312246850389922318827771380881195754151389802803398367341521544667542828862543407738361578535730524976113729406101764290984943061582342991118766322793847422471903811686775249409300301726906738475446634950949059180072008 x = 9757458594430450711 f = x**3 +a*x+b-y**2 p = gmpy2.gcd(f, n) q = n//p phi = (p-1 )*(q-1 ) d = gmpy2.invert(e, phi) m = pow (c, d, n) print (long_to_bytes(m))
babylua 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 local flag = '' local md5 = require ("md5" )math .randomseed (os .time ())local function randomStr (len) local rankStr = "" local randNum = 0 for i = 1 , len do randNum = math .random (1 , 2 ) if randNum == 1 then rankStr = rankStr .. string .char (math .random (65 , 90 )) elseif randNum == 2 then rankStr = rankStr .. string .char (math .random (97 , 122 )) end end return rankStr end local seed = randomStr(4 )local key = md5.sumhexa(md5.sumhexa(seed))print (key:sub (1 ,10 ))secret = {} for i = 1 , #flag do secret[i] = string .byte (flag:sub (i,i)) + string .byte (key:sub (i,i)) end for i, v in ipairs (secret) do io .write (v, ' ' ) end print ()
题目给了一种我没见过的语言,简单认识一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 local flag = '' local md5 = require ("md5" )math .randomseed (os .time ())local function randomStr (len) local result = "" local randNum = 0 for i = 1 , len do randNum = math .random (1 , 2 ) if randNum == 1 then result = result .. string .char (math .random (65 , 90 )) elseif randNum == 2 then result = result .. string .char (math .random (97 , 122 )) end end return result end local seed = randomStr(4 )local key = md5.sumhexa(md5.sumhexa(seed))print (key:sub (1 ,10 ))local secret = {}for i = 1 , #flag do secret[i] = string .byte (flag:sub (i,i)) + string .byte (key:sub (i,i)) end for i, v in ipairs (secret) do io .write (v, ' ' ) end print ()
题目给了两次md5加密后的前10位,四位的seed可以尝试爆破,用itertools库生成所有随机组合的大写小写字母:
1 2 3 4 5 6 7 8 9 10 11 12 import stringimport itertoolsfrom hashlib import md5chars = string.ascii_lowercase+string.ascii_uppercase cs = itertools.product(chars, repeat=4 ) for c in cs: s='' .join(c) h = md5((md5(s.encode()).hexdigest()).encode()).hexdigest() if h[:10 ]=='b5e62abe84' : print (s,h) break
爆破出之后直接按照他给的算法逆回去就得到flag了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import stringimport itertoolsfrom hashlib import md5chars = string.ascii_lowercase+string.ascii_uppercase cs = itertools.product(chars, repeat=4 ) for c in cs: s='' .join(c) h = md5((md5(s.encode()).hexdigest()).encode()).hexdigest() if h[:10 ]=='b5e62abe84' : print (s,h) break a = [200 , 161 , 198 , 157 , 173 , 169 , 199 , 150 , 105 , 163 , 193 , 175 , 173 , 194 , 135 , 131 , 135 , 225 ] for i in range (len (a)): num,b=a[i],ord (h[i]) print (chr (num-b),end='' )
WEEK 1 [EIS 2019]rsa1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from flag import FLAGfrom Crypto.Util.number import *import gmpy2import randomwhile True : p = int (gmpy2.next_prime(random.randint(10 **399 , 10 **400 -1 ))) q = int (str (p)[200 :]+str (p)[:200 ]) if gmpy2.is_prime(q): break m = bytes_to_long(FLAG) n = p*q e = 65537 c = pow (m,e,n) with open ("enc" ,"wb" ) as f: f.write(str (c)) f.write("\n" ) f.write(str (n)) ''' c=16396023285324039009558195962852040868243807971027796599580351414803675753933120024077886501736987010658812435904022750269541456641256887079780585729054681025921699044139927086676479128232499416835051090240458236280851063589059069181638802191717911599940897797235038838827322737207584188123709413077535201099325099110746196702421778588988049442604655243604852727791349351291721230577933794627015369213339150586418524473465234375420448340981330049205933291705601563283196409846408465061438001010141891397738066420524119638524908958331406698679544896351376594583883601612086738834989175070317781690217164773657939589691476539613343289431727103692899002758373929815089904574190511978680084831183328681104467553713888762965976896013404518316128288520016934828176674482545660323358594211794461624622116836 n=21173064304574950843737446409192091844410858354407853391518219828585809575546480463980354529412530785625473800210661276075473243912578032636845746866907991400822100939309254988798139819074875464612813385347487571449985243023886473371811269444618192595245380064162413031254981146354667983890607067651694310528489568882179752700069248266341927980053359911075295668342299406306747805925686573419756406095039162847475158920069325898899318222396609393685237607183668014820188522330005608037386873926432131081161531088656666402464062741934007562757339219055643198715643442608910351994872740343566582808831066736088527333762011263273533065540484105964087424030617602336598479611569611018708530024591023015267812545697478378348866840434551477126856261767535209092047810194387033643274333303926423370062572301 '''
看完代码可以发现,p为一个400位随机数,q是p的前200位和后200位互换位置得到的数,和之前做的有道hamburgerRSA比较像,已知:
把pq都分成两个部分a和b,每个都是200位,那么ab乘积也就是个400位的数。
现在,n的前200位是ab的前200位(先不考虑中间区段的进位),末200位为ab后200位(这个不会被进位卡混淆),可以得到ab的乘积,得到乘积之后,减回去稍微计算一下就能得到$a^2+b^2$:
我们先走到这里检查一下:
1 2 3 4 5 6 c=16396023285324039009558195962852040868243807971027796599580351414803675753933120024077886501736987010658812435904022750269541456641256887079780585729054681025921699044139927086676479128232499416835051090240458236280851063589059069181638802191717911599940897797235038838827322737207584188123709413077535201099325099110746196702421778588988049442604655243604852727791349351291721230577933794627015369213339150586418524473465234375420448340981330049205933291705601563283196409846408465061438001010141891397738066420524119638524908958331406698679544896351376594583883601612086738834989175070317781690217164773657939589691476539613343289431727103692899002758373929815089904574190511978680084831183328681104467553713888762965976896013404518316128288520016934828176674482545660323358594211794461624622116836 n=21173064304574950843737446409192091844410858354407853391518219828585809575546480463980354529412530785625473800210661276075473243912578032636845746866907991400822100939309254988798139819074875464612813385347487571449985243023886473371811269444618192595245380064162413031254981146354667983890607067651694310528489568882179752700069248266341927980053359911075295668342299406306747805925686573419756406095039162847475158920069325898899318222396609393685237607183668014820188522330005608037386873926432131081161531088656666402464062741934007562757339219055643198715643442608910351994872740343566582808831066736088527333762011263273533065540484105964087424030617602336598479611569611018708530024591023015267812545697478378348866840434551477126856261767535209092047810194387033643274333303926423370062572301 e = 65537 N=str (n) ab=int (N[:200 ]+N[600 :]) a2b2=(n-ab*pow (10 ,400 )-ab)//pow (10 ,200 )
输出发现$a^2+b^2$是负数,这肯定是不对的,问题出在哪里呢,可以看看之前的公式:
我们还有中间四百位没有考虑,$a^2+b^2$的位数是未知的。类比一下,对于一个两位数,$a^2+b^2$最小就是$10^2+10^2=200$,三位;最大有$99^2+99^2=19602$,五位。相应的,$a^2+b^2$的位数应该在399,400,401三个值上,如果出现401位,首位只能为1。
所以出现负数的结果,一定是$a^2+b^2$位数为401导致ab数值错误,稍微修改一下:
1 2 3 4 5 6 c=16396023285324039009558195962852040868243807971027796599580351414803675753933120024077886501736987010658812435904022750269541456641256887079780585729054681025921699044139927086676479128232499416835051090240458236280851063589059069181638802191717911599940897797235038838827322737207584188123709413077535201099325099110746196702421778588988049442604655243604852727791349351291721230577933794627015369213339150586418524473465234375420448340981330049205933291705601563283196409846408465061438001010141891397738066420524119638524908958331406698679544896351376594583883601612086738834989175070317781690217164773657939589691476539613343289431727103692899002758373929815089904574190511978680084831183328681104467553713888762965976896013404518316128288520016934828176674482545660323358594211794461624622116836 n=21173064304574950843737446409192091844410858354407853391518219828585809575546480463980354529412530785625473800210661276075473243912578032636845746866907991400822100939309254988798139819074875464612813385347487571449985243023886473371811269444618192595245380064162413031254981146354667983890607067651694310528489568882179752700069248266341927980053359911075295668342299406306747805925686573419756406095039162847475158920069325898899318222396609393685237607183668014820188522330005608037386873926432131081161531088656666402464062741934007562757339219055643198715643442608910351994872740343566582808831066736088527333762011263273533065540484105964087424030617602336598479611569611018708530024591023015267812545697478378348866840434551477126856261767535209092047810194387033643274333303926423370062572301 e = 65537 N=str (n) ab=int (str (int (N[:200 ])-1 )+N[600 :]) a2b2=(n-ab*pow (10 ,400 )-ab)//pow (10 ,200 )
现在就对了,已经知道了$ab,a^2+b^2$,用一些中学数学知识就能得到$a+b,a-b$,进而得到$a,b$,最终得到$p,q$,得解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from Crypto.Util.number import *import gmpy2c=16396023285324039009558195962852040868243807971027796599580351414803675753933120024077886501736987010658812435904022750269541456641256887079780585729054681025921699044139927086676479128232499416835051090240458236280851063589059069181638802191717911599940897797235038838827322737207584188123709413077535201099325099110746196702421778588988049442604655243604852727791349351291721230577933794627015369213339150586418524473465234375420448340981330049205933291705601563283196409846408465061438001010141891397738066420524119638524908958331406698679544896351376594583883601612086738834989175070317781690217164773657939589691476539613343289431727103692899002758373929815089904574190511978680084831183328681104467553713888762965976896013404518316128288520016934828176674482545660323358594211794461624622116836 n=21173064304574950843737446409192091844410858354407853391518219828585809575546480463980354529412530785625473800210661276075473243912578032636845746866907991400822100939309254988798139819074875464612813385347487571449985243023886473371811269444618192595245380064162413031254981146354667983890607067651694310528489568882179752700069248266341927980053359911075295668342299406306747805925686573419756406095039162847475158920069325898899318222396609393685237607183668014820188522330005608037386873926432131081161531088656666402464062741934007562757339219055643198715643442608910351994872740343566582808831066736088527333762011263273533065540484105964087424030617602336598479611569611018708530024591023015267812545697478378348866840434551477126856261767535209092047810194387033643274333303926423370062572301 e = 65537 N=str (n) ab=int (str (int (N[:200 ])-1 )+N[600 :]) a2b2=(n-ab*pow (10 ,400 )-ab)//pow (10 ,200 ) ajiab=gmpy2.iroot(a2b2+2 *ab,2 )[0 ] ajianb=gmpy2.iroot(a2b2-2 *ab,2 )[0 ] a=(ajiab+ajianb)//2 b=(ajiab-ajianb)//2 p=pow (10 ,200 )*a+b q=pow (10 ,200 )*b+a phi=(p-1 )*(q-1 ) d=gmpy2.invert(e,phi) m=pow (c,d,n) print (long_to_bytes(m))