当前位置:   article > 正文

NSSCTF-[NSSRound#X Basic]ez_z3 && [MoeCTF 2022]Art &&[HDCTF2023]basketball

NSSCTF-[NSSRound#X Basic]ez_z3 && [MoeCTF 2022]Art &&[HDCTF2023]basketball

目录

NSSCTF-[NSSRound#X Basic]ez_z3

 [MoeCTF 2022]Art

[HDCTF2023]basketball


NSSCTF-[NSSRound#X Basic]ez_z3

题目下载:下载

查壳:

发现有upx壳,但是使用upx -d命令不能脱壳,载入十六进制编辑器查看
把XYU改为UPX,就可以成功使用upx -d脱壳了。

载入IDA(部分使用了自定义命名)

 倒着往前看,输出“you get the flag”就要dword_1400254C4==1,而dword_1400254C4由sub_1400110E6()函数赋值而来,所以跟进sub_1400110E6()函数:

 要想返回1,则这个等式成立,即这两个数组相同。

返回到主函数,看其他的函数

看一下sub_1400112F8()函数:

这就是一个简单的异或。

看sub_14001103C()函数:是很多等式,可以用z3求出a1[0]-a1[19]。

看一下sub_140014CC0()函数:这是一个指数折半快速幂求法,可以参考:快速幂算法 超详细教程_qascetic的博客-CSDN博客
我在这里在简单阐述一下上面的这个快速幂流程,具体地大家可以参考上面的链接。a1是底数,a2是指数,首先判断指数是奇数还是偶数。

如果是偶数即if条件不成立,那么就a1*a1底数变为平方,a2>>2相当于除以2,指数折半,这样一直执行下去,直到a2为1,是奇数,这样就执行if的子句1把结果赋值给v3返回。

如果是奇数,就先分离出一个,然后在采用快速幂法,最后通过v3返回。

好了关键的函数都分析完了,整体思路就是:

1.先用z3约束器求出a1数组的值,也即异或操作里的a1数组
2.通过异或操作,a1已知,求出dword_140025520[]数组
3.dword_140025520[]已知,通过快速幂爆破出str

所以代码如下

  1. from z3 import *
  2. #z3约束器
  3. a1=[0]*20
  4. for i in range(20):
  5. a1[i]=Int('a1['+str(i)+']')
  6. s = Solver()
  7. s.add((20 * a1[19] * 19 * a1[18]
  8. + 14 * a1[13]
  9. + 13 * a1[12]
  10. + 11 * a1[10] * 10 * a1[9]
  11. + 30 * a1[5]
  12. + 5 * a1[4]
  13. + a1[0]
  14. + 2 * a1[1]
  15. - 3 * a1[2]
  16. - 4 * a1[3]
  17. - 7 * a1[6]
  18. + 8 * a1[7]
  19. - 9 * a1[8]
  20. - 12 * a1[11]
  21. - 16 * a1[15] * 15 * a1[14]
  22. - 17 * a1[16]
  23. - 18 * a1[17]) == 2582239)
  24. s.add((20 * a1[19] * 19 * a1[18]
  25. + 14 * a1[13]
  26. + 13 * a1[12]
  27. + 11 * a1[10] * 10 * a1[9]
  28. + 30 * a1[5]
  29. - 7 * a1[6]
  30. + 8 * a1[7]
  31. - 9 * a1[8]
  32. + 5 * a1[4]
  33. + 3 * a1[2]
  34. + 2 * a1[1] * a1[0]
  35. - 4 * a1[3]
  36. - 12 * a1[11]
  37. - 16 * a1[15] * 15 * a1[14]
  38. - (18 * a1[17]
  39. + 17 * a1[16])) == 2602741)
  40. s.add((19 * a1[18]
  41. + 18 * a1[17]
  42. + 14 * a1[13] * 13 * a1[12]
  43. + 12 * a1[11] * 11 * a1[10]
  44. + 9 * a1[8]
  45. + 7 * a1[6] * 30 * a1[5]
  46. + a1[0]
  47. - 2 * a1[1]
  48. - 4 * a1[3] * 3 * a1[2]
  49. - 5 * a1[4]
  50. + 8 * a1[7]
  51. - 10 * a1[9]
  52. - 15 * a1[14]
  53. - 17 * a1[16] * 16 * a1[15]
  54. - 20 * a1[19]) == 2668123)
  55. s.add((20 * a1[19] * 19 * a1[18]
  56. + 14 * a1[13]
  57. + (13 * a1[12] + 11 * a1[10] - 12 * a1[11]) * 10 * a1[9]
  58. + 30 * a1[5]
  59. + 5 * a1[4]
  60. + a1[0]
  61. + 2 * a1[1]
  62. - 3 * a1[2]
  63. - 4 * a1[3]
  64. - 7 * a1[6]
  65. + 8 * a1[7]
  66. - 9 * a1[8]
  67. - 16 * a1[15] * 15 * a1[14]
  68. - 17 * a1[16]
  69. - 18 * a1[17]) == 2520193)
  70. s.add((18 * a1[17]
  71. + 17 * a1[16]
  72. + 15 * a1[14]
  73. + 13 * a1[12] * 12 * a1[11]
  74. + 10 * a1[9]
  75. + 9 * a1[8] * 8 * a1[7]
  76. + 3 * a1[2] * 2 * a1[1] * a1[0]
  77. - 4 * a1[3]
  78. - 5 * a1[4]
  79. - 30 * a1[5]
  80. - 7 * a1[6]
  81. - 11 * a1[10]
  82. - 14 * a1[13]
  83. - 16 * a1[15]
  84. - 19 * a1[18]
  85. - 20 * a1[19]) == 8904587)
  86. s.add((18 * a1[17]
  87. + 7 * a1[6] * 30 * a1[5] * 5 * a1[4]
  88. + 4 * a1[3]
  89. + 8 * a1[7]
  90. + a1[0]
  91. - 2 * a1[1]
  92. - 3 * a1[2]
  93. - 9 * a1[8]
  94. - 11 * a1[10] * 10 * a1[9]
  95. - 16 * a1[15] * (13 * a1[12] + 12 * a1[11] - 14 * a1[13] - 15 * a1[14])
  96. - 17 * a1[16]
  97. - 19 * a1[18]
  98. - 20 * a1[19]) == 1227620874)
  99. s.add((20 * a1[19] * 19 * a1[18]
  100. + 17 * a1[16]
  101. + 14 * a1[13]
  102. + 13 * a1[12]
  103. + 12 * a1[11] * 11 * a1[10] * 10 * a1[9]
  104. + 7 * a1[6] * 30 * a1[5]
  105. + 5 * a1[4]
  106. + 3 * a1[2]
  107. + a1[0]
  108. + 2 * a1[1]
  109. + 4 * a1[3]
  110. + 8 * a1[7]
  111. - 9 * a1[8]
  112. - 16 * a1[15] * 15 * a1[14]
  113. - 18 * a1[17]) == 1836606059)
  114. s.add((20 * a1[19] * 19 * a1[18]
  115. + 16 * a1[15] * 15 * a1[14]
  116. + 14 * a1[13]
  117. + 13 * a1[12]
  118. + 12 * a1[11]
  119. + 7 * a1[6] * 30 * a1[5]
  120. + 5 * a1[4]
  121. + 2 * a1[1] * a1[0]
  122. - 3 * a1[2]
  123. + 4 * a1[3]
  124. + 8 * a1[7]
  125. - 9 * a1[8]
  126. - 10 * a1[9]
  127. - 11 * a1[10]
  128. - 17 * a1[16]
  129. - 18 * a1[17]) == 8720560)
  130. s.add((20 * a1[19] * 19 * a1[18]
  131. + 14 * a1[13]
  132. + 13 * a1[12]
  133. + 11 * a1[10] * (10 * a1[9] + 30 * a1[5] + 5 * a1[4] + 4 * a1[3] - 7 * a1[6] + 8 * a1[7] - 9 * a1[8])
  134. + a1[0]
  135. + 2 * a1[1]
  136. - 3 * a1[2]
  137. - 12 * a1[11]
  138. - (16 * a1[15] - 17 * a1[16] - 18 * a1[17]) * 15 * a1[14]) == 11387045)
  139. s.add((20 * a1[19] * 19 * a1[18]
  140. + 16 * a1[15] * 15 * a1[14]
  141. + 14 * a1[13]
  142. + 11 * a1[10] * 10 * a1[9]
  143. + 9 * a1[8]
  144. + 3 * a1[2]
  145. + a1[0]
  146. - 2 * a1[1]
  147. + 4 * a1[3]
  148. - 5 * a1[4]
  149. - 30 * a1[5]
  150. - 7 * a1[6]
  151. + 8 * a1[7]
  152. - 12 * a1[11]
  153. - 13 * a1[12]
  154. - 17 * a1[16]
  155. - 18 * a1[17]) == 7660269)
  156. s.add((20 * a1[19] * 19 * a1[18]
  157. + 14 * a1[13]
  158. + 13 * a1[12]
  159. + 11 * a1[10] * 10 * a1[9]
  160. - 12 * a1[11]
  161. + a1[0]
  162. + 2 * a1[1]
  163. - (4 * a1[3] * 3 * a1[2]
  164. - 5 * a1[4]
  165. - 30 * a1[5])
  166. - 7 * a1[6]
  167. + 8 * a1[7]
  168. - 9 * a1[8]
  169. - 16 * a1[15] * 15 * a1[14]
  170. - 17 * a1[16]
  171. - 18 * a1[17]) == 2461883)
  172. s.add((14 * a1[13]
  173. + 11 * a1[10] * 10 * a1[9]
  174. + 9 * a1[8] * 8 * a1[7]
  175. + 7 * a1[6]
  176. + 2 * a1[1] * a1[0]
  177. - 4 * a1[3] * 3 * a1[2]
  178. - 5 * a1[4]
  179. - 30 * a1[5]
  180. - 12 * a1[11]
  181. - 13 * a1[12]
  182. - 15 * a1[14]
  183. - 17 * a1[16] * 16 * a1[15]
  184. - 18 * a1[17]
  185. - 19 * a1[18]
  186. - 20 * a1[19]) == -966296)
  187. s.add((14 * a1[13]
  188. + 13 * a1[12]
  189. + (11 * a1[10] * 10 * a1[9] + 30 * a1[5] + 5 * a1[4] + 3 * a1[2] + 4 * a1[3] - 7 * a1[6] + 8 * a1[7] - 9 * a1[8])
  190. * 2
  191. * a1[1]
  192. + a1[0]
  193. - 12 * a1[11]
  194. - 15 * a1[14]
  195. - 16 * a1[15]
  196. - 17 * a1[16]
  197. - 18 * a1[17]
  198. - 20 * a1[19] * 19 * a1[18]) == 254500223)
  199. s.add((16 * a1[15] * 15 * a1[14]
  200. + 14 * a1[13]
  201. + 11 * a1[10] * 10 * a1[9]
  202. + 7 * a1[6] * 30 * a1[5]
  203. + a1[0]
  204. - 2 * a1[1]
  205. - 3 * a1[2]
  206. - 5 * a1[4] * 4 * a1[3]
  207. + 8 * a1[7]
  208. - 9 * a1[8]
  209. - 12 * a1[11]
  210. - 13 * a1[12]
  211. - 17 * a1[16]
  212. - 18 * a1[17]
  213. - 19 * a1[18]
  214. - 20 * a1[19]) == 6022286)
  215. s.add((18 * a1[17]
  216. + 16 * a1[15]
  217. - 17 * a1[16]
  218. + 14 * a1[13]
  219. + 12 * a1[11]
  220. + 11 * a1[10] * 10 * a1[9]
  221. + 30 * a1[5]
  222. + 5 * a1[4]
  223. + 4 * a1[3] * 3 * a1[2]
  224. + 2 * a1[1] * a1[0]
  225. - 9 * a1[8] * 8 * a1[7] * 7 * a1[6]
  226. - 13 * a1[12]
  227. - 15 * a1[14]
  228. - 19 * a1[18]
  229. - 20 * a1[19]) == -636956022)
  230. s.add((20 * a1[19] * 19 * a1[18]
  231. + 13 * a1[12]
  232. + 12 * a1[11]
  233. + 11 * a1[10] * 10 * a1[9]
  234. + 7 * a1[6]
  235. + 30 * a1[5]
  236. + 5 * a1[4]
  237. + 3 * a1[2] * 2 * a1[1] * a1[0]
  238. - 4 * a1[3]
  239. - 9 * a1[8] * 8 * a1[7]
  240. - 14 * a1[13]
  241. - 15 * a1[14]
  242. - 16 * a1[15]
  243. - 17 * a1[16]
  244. - 18 * a1[17]) == 10631829)
  245. s.add((20 * a1[19] * 19 * a1[18]
  246. + 16 * a1[15]
  247. - 17 * a1[16]
  248. - 18 * a1[17]
  249. + 15 * a1[14] * 14 * a1[13]
  250. + 13 * a1[12]
  251. + 11 * a1[10] * 10 * a1[9]
  252. - 12 * a1[11]
  253. + 7 * a1[6]
  254. + (4 * a1[3] - 5 * a1[4] - 30 * a1[5]) * 3 * a1[2]
  255. + a1[0]
  256. + 2 * a1[1]
  257. + 8 * a1[7]
  258. - 9 * a1[8]) == 6191333)
  259. s.add((14 * a1[13]
  260. + 10 * a1[9] * 9 * a1[8] * 8 * a1[7]
  261. + 5 * a1[4]
  262. + 4 * a1[3] * 3 * a1[2]
  263. + 2 * a1[1] * a1[0]
  264. - 7 * a1[6] * 30 * a1[5]
  265. - 11 * a1[10]
  266. - 13 * a1[12] * 12 * a1[11]
  267. - 16 * a1[15] * 15 * a1[14]
  268. - 18 * a1[17] * 17 * a1[16]
  269. - 20 * a1[19] * 19 * a1[18]) == 890415359)
  270. s.add((20 * a1[19]
  271. + 19 * a1[18]
  272. + 18 * a1[17]
  273. + 16 * a1[15]
  274. - 17 * a1[16]
  275. + 12 * a1[11]
  276. + 11 * a1[10]
  277. + 10 * a1[9]
  278. + 9 * a1[8]
  279. + 30 * a1[5]
  280. + a1[0]
  281. + 4 * a1[3] * 3 * a1[2] * 2 * a1[1]
  282. - 5 * a1[4]
  283. - 7 * a1[6]
  284. + 8 * a1[7]
  285. - 13 * a1[12]
  286. - 14 * a1[13]
  287. - 15 * a1[14]) == 23493664)
  288. s.add((20 * a1[19] * 19 * a1[18]
  289. + 13 * a1[12]
  290. + 12 * a1[11]
  291. + 10 * a1[9]
  292. + 3 * a1[2] * 2 * a1[1]
  293. + a1[0]
  294. - 4 * a1[3]
  295. - 5 * a1[4]
  296. + 8 * a1[7] * 7 * a1[6] * 30 * a1[5]
  297. - 9 * a1[8]
  298. - 11 * a1[10]
  299. - 14 * a1[13]
  300. - 16 * a1[15] * 15 * a1[14]
  301. - 17 * a1[16]
  302. - 18 * a1[17]) == 1967260144)
  303. for i in range(20):
  304. s.add(a1[i]<=0xFF) #每个字符是char类型
  305. s.add(a1[i]>=0)
  306. if s.check() == sat:
  307. print(s.model())
  308. #求dword_140025520[]
  309. a1=[104,97,104,97,104,97,116,104,105,115,105,115,102,97,99,107,102,108,97,103][::-1]
  310. d4D0=[4615, 19616, 20257, 57, 107811, 570, 2342, 19623, 25952,54, 108955, 19624, 113632, 14085, 2342, 30675, 39576,
  311. 25979, 24, 2833]
  312. #倒序
  313. d520=[]
  314. for i in range(len(a1)):
  315. b=a1[i]^d4D0[i]
  316. d520.append(b)
  317. print(d520)
  318. #求str,即flag
  319. flag=''
  320. a3= [7, 7, 7, 9, 5, 6, 7, 7, 7, 9, 7, 7, 5, 7, 7, 7, 5, 7, 9, 7]
  321. for i in range(20): #j是要求的
  322. for k in range(32,128):
  323. v3=1
  324. k1=k
  325. a2=a3[i]
  326. while(a2):
  327. if (a2 & 1):
  328. v3=v3*k1
  329. k1=k1*k1%1000
  330. a2=a2>>2
  331. if v3==d520[i]:
  332. flag+=chr(k)
  333. break
  334. print(flag)

 [MoeCTF 2022]Art

题目下载:下载

首先看一看题目标签和描述,可以获得一些小提示

可以知道考点是upx和dfs。

脱壳:直接upx -d 文件名就可以脱壳,载入IDA

 从上面提示可以知道这个方程有多个解,所以需要爆破来解,其中只有一个加密算法且存在多解的情况,所以采用dfs爆搜,代码如下:

  1. check = [0x2, 0x18, 0xf, 0xf8, 0x19, 0x4, 0x27, 0xd8, 0xeb, 0x0, 0x35, 0x48, 0x4d, 0x2a, 0x45, 0x6b, 0x59, 0x2e, 0x43, 0x1, 0x18, 0x5c, 0x9, 0x9, 0x9, 0x9, 0xb5, 0x7d]
  2. tmp = [0]*28
  3. tmp[len(check)-1]=check[-1]
  4. #(check[-1])
  5. def DFS(deep):
  6. if deep == 0:
  7. print(bytes(tmp))
  8. else:
  9. for i in range(0xff):
  10. if (i ^ 0x19) ^ (i % 0x11 + tmp[deep]) == check[deep - 1]:
  11. #print(i)
  12. tmp[deep - 1] = i
  13. DFS(deep - 1)
  14. DFS(len(check)-1)

[HDCTF2023]basketball

题目下载:下载

载入IDA,先看第一部分

 首先获得两个key,然后进行输入,输入到s数组。进入f()函数,

进行异或操作,里面有一个text_66函数,跟进:

容易知道text_66是辗转相除,这里的关键是求这两个key,采用爆破枚举方式,代码如下:
 

  1. str=[85, 105, 104, 120, 33, 104, 114, 33, 96, 33, 105, 98, 101, 117, 33, 124, 105, 106, 117, 33, 72, 33, 105, 100, 109, 113, 43, 120, 110, 116, 33, 104, 114, 43, 115, 100, 108, 104, 111, 101, 33, 120, 110, 116, 33, 117, 110, 33, 98, 73, 100, 98, 106, 33, 117, 105, 100, 33, 96, 115, 115, 96, 120, 33, 96, 111, 101, 33, 117, 105, 115, 100, 100, 33, 111, 116, 102, 99, 100, 115, 114, 33, 98, 96, 111, 33, 119, 98, 100, 118, 33, 96, 114, 33, 96, 33, 102, 115, 110, 116, 113]
  2. def f(k1_0,k2_0):
  3. for i in range(len(str)):
  4. k1_0 = (str[i] + k1_0) % 300
  5. k2_0 = (str[i] + k2_0) % 300
  6. str[i] ^= text_66(k1_0, k2_0)
  7. def text_66(a,b):
  8. aa=a
  9. ba=b
  10. if a<b:
  11. aa,ba=ba,aa
  12. if ba:
  13. result = text_66(ba, aa % ba)
  14. else:
  15. result = aa
  16. return result
  17. for x in range(100):
  18. for y in range(100):
  19. str=[85, 105, 104, 120, 33, 104, 114, 33, 96, 33, 105, 98, 101, 117, 33, 124, 105, 106, 117, 33, 72, 33, 105, 100, 109, 113, 43, 120, 110, 116, 33, 104, 114, 43, 115, 100, 108, 104, 111, 101, 33, 120, 110, 116, 33, 117, 110, 33, 98, 73, 100, 98, 106, 33, 117, 105, 100, 33, 96, 115, 115, 96, 120, 33, 96, 111, 101, 33, 117, 105, 115, 100, 100, 33, 111, 116, 102, 99, 100, 115, 114, 33, 98, 96, 111, 33, 119, 98, 100, 118, 33, 96, 114, 33, 96, 33, 102, 115, 110, 116, 113]
  20. f(x,y)
  21. flag=1
  22. for i in str:
  23. if i>=127 or i<32:
  24. flag=0
  25. break
  26. if flag==1:
  27. print(bytes(str))

 观察结果:I help you is remind you to check the array and three numbers can view as a group可以知道提示三个数可以看成一组,就可以想到RGB(之前没见过,所以我不能反应过来这个是RGB)

在根据给的hint:
可以写有关RGB的代码(这里学习一下)

  1. from PIL import Image
  2. with open('array.txt绝对地址', 'r') as f:
  3. data = f.readlines() # txt中所有字符串读入data
  4. for line in data:
  5. list = line.split(' ') # 将单个数据分隔开存好
  6. f.close()
  7. x = 637 # x坐标 通过对txt里的行数进行整数分解 宽度
  8. y = 561 # y坐标 x * y = 行数 高度
  9. im = Image.new("RGB", (x, y)) # 创建图片
  10. index = 0
  11. for j in range(0, y): # 通过每个rgb点生成图片
  12. for i in range(0, x):
  13. im.putpixel((i, j), (int(list[index]), int(list[index + 1]), int(list[index + 2]))) # 将rgb转化为像素
  14. index += 3
  15. im.show()

 运行后发现图片

再根据提示

 message是英文形式,根据我想打篮球得到:I want to play basketball,又因为要凑够28个,所以是I want to play basketballI w

在看main第二部分代码:

 刚才得到的便是str数组,num数组又已知,可以异或得到flag

  1. flag=[1, 100, 52, 53, 40, 15, 4, 69, 46, 109, 47, 40, 55, 55, 92, 94, 62, 70, 23, 72, 8, 82, 29, 65, 16, 117, 117, 10]
  2. xor_key='I want to play basketballI w'
  3. for i in range(len(flag)):
  4. flag[i]^=ord(xor_key[i])
  5. print(bytes(flag))
  6. #HDCTF{$1AM_DVN|<_5|-|0|-|<U}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/501700
推荐阅读
  

闽ICP备14008679号