• [N1CTF 2022] solve_pow,baby_N1ES


    周六作了两个N1CTF感觉很难就没做,有些东西只是不懂,不是很难。

    solve_pow

    这个题就是其一

    题目会给出一道2乘幂的题

    POW: 2^(2^168650911) mod 14410422756791856006977221261653848398173123908149127966358804284026606184669 = ?

    一开始想最后是取模,根据费小有a**(p-1)=1 (mod p),然后用公式求解

    1. powmod(2,pow(2,bit,p-1),p)
    2. #4661732238801194169405982400350387428895918512377690837157075128714991112731

    但是这个事有点麻烦,p不是素数,如果乘幂又太大了,后来看别人作的,用了bit_set这个函数,原来都没听说过,因为底是2,直接置bit位就行了

    所以正确的解法是

    1. powmod(2,bit_set(0,bit),p)
    2. #36808033546212382710607382805842490500296061506256519355047811358611503260

    不过只是当时卡在这了,不有另外一个方法,不用这个函数一样

    1. powmod(2,1<
    2. #36808033546212382710607382805842490500296061506256519355047811358611503260

     

    baby_N1ES

    这个题都没看到,其实这个题很简单,而且还有更简单的解法。

    原题

    1. from N1ES import N1ES
    2. import base64
    3. key = "wxy191iss00000000000cute"
    4. n1es = N1ES(key)
    5. flag = "N1CTF{*****************************************}"
    6. cipher = n1es.encrypt(flag)
    7. print base64.b64encode(cipher) # HRlgC2ReHW1/WRk2DikfNBo1dl1XZBJrRR9qECMNOjNHDktBJSxcI1hZIz07YjVx

    和一个N1ES.py的库

    1. # -*- coding: utf-8 -*-
    2. def round_add(a, b):
    3. f = lambda x, y: x + y - 2 * (x & y)
    4. res = ''
    5. for i in range(len(a)):
    6. res += chr(f(ord(a[i]), ord(b[i])))
    7. return res
    8. def permutate(table, block):
    9. return list(map(lambda x: block[x], table))
    10. def string_to_bits(data):
    11. data = [ord(c) for c in data]
    12. l = len(data) * 8
    13. result = [0] * l
    14. pos = 0
    15. for ch in data:
    16. for i in range(0, 8):
    17. result[(pos << 3) + i] = (ch >> i) & 1
    18. pos += 1
    19. return result
    20. s_box = [54, 132, 138, 83, 16, 73, 187, 84, 146, 30, 95, 21, 148, 63, 65, 189, 188, 151, 72, 161, 116, 63, 161, 91, 37,
    21. 24, 126, 107, 87, 30, 117, 185, 98, 90, 0, 42, 140, 70, 86, 0, 42, 150, 54, 22, 144, 153, 36, 90, 149, 54, 156,
    22. 8, 59, 40, 110, 56, 1, 84, 103, 22, 65, 17, 190, 41, 99, 151, 119, 124, 68, 17, 166, 125, 95, 65, 105, 133, 49,
    23. 19, 138, 29, 110, 7, 81, 134, 70, 87, 180, 78, 175, 108, 26, 121, 74, 29, 68, 162, 142, 177, 143, 86, 129, 101,
    24. 117, 41, 57, 34, 177, 103, 61, 135, 191, 74, 69, 147, 90, 49, 135, 124, 106, 19, 89, 38, 21, 41, 17, 155, 83,
    25. 38, 159, 179, 19, 157, 68, 105, 151, 166, 171, 122, 179, 114, 52, 183, 89, 107, 113, 65, 161, 141, 18, 121, 95,
    26. 4, 95, 101, 81, 156, 17, 190, 38, 84, 9, 171, 180, 59, 45, 15, 34, 89, 75, 164, 190, 140, 6, 41, 188, 77, 165,
    27. 105, 5, 107, 31, 183, 107, 141, 66, 63, 10, 9, 125, 50, 2, 153, 156, 162, 186, 76, 158, 153, 117, 9, 77, 156,
    28. 11, 145, 12, 169, 52, 57, 161, 7, 158, 110, 191, 43, 82, 186, 49, 102, 166, 31, 41, 5, 189, 27]
    29. def generate(o):
    30. k = permutate(s_box, o)
    31. b = []
    32. for i in range(0, len(k), 7):
    33. b.append(k[i:i + 7] + [1])
    34. c = []
    35. for i in range(32):
    36. pos = 0
    37. x = 0
    38. for j in b[i]:
    39. x += (j << pos)
    40. pos += 1
    41. c.append((0x10001 ** x) % (0x7f))
    42. return c
    43. class N1ES:
    44. def __init__(self, key):
    45. if (len(key) != 24 or isinstance(key, bytes) == False):
    46. raise Exception("key must be 24 bytes long")
    47. self.key = key
    48. self.gen_subkey()
    49. def gen_subkey(self):
    50. o = string_to_bits(self.key)
    51. k = []
    52. for i in range(8):
    53. o = generate(o)
    54. k.extend(o)
    55. o = string_to_bits([chr(c) for c in o[0:24]])
    56. self.Kn = []
    57. for i in range(32):
    58. self.Kn.append(map(chr, k[i * 8: i * 8 + 8]))
    59. return
    60. def encrypt(self, plaintext):
    61. if (len(plaintext) % 16 != 0 or isinstance(plaintext, bytes) == False):
    62. raise Exception("plaintext must be a multiple of 16 in length")
    63. res = ''
    64. for i in range(len(plaintext) / 16):
    65. block = plaintext[i * 16:(i + 1) * 16]
    66. L = block[:8]
    67. R = block[8:]
    68. for round_cnt in range(32):
    69. L, R = R, (round_add(L, self.Kn[round_cnt]))
    70. L, R = R, L
    71. res += L + R
    72. return res

    先读题,就是个分段加密,每次原来的左与Kn异或然后左右互换,作32轮。由于Kn是固定的,而且加密是异或,所以round_add并不需要处理,只要反过来作个decrypt就行了

    这有个小坑,python 2的程序需要改一下

    1. # -*- coding: utf-8 -*-
    2. def round_add(a, b): #xor
    3. f = lambda x, y: x + y - 2 * (x & y)
    4. res = b''
    5. for i in range(len(a)):
    6. #res += chr(f(ord(a[i]), ord(b[i])))
    7. res += bytes([f(a[i], b[i])])
    8. return res
    9. def permutate(table, block):
    10. return list(map(lambda x: block[x], table))
    11. def string_to_bits(data):
    12. #data = [ord(c) for c in data]
    13. data = [c for c in data]
    14. l = len(data) * 8
    15. result = [0] * l
    16. pos = 0
    17. for ch in data:
    18. for i in range(0, 8):
    19. result[(pos << 3) + i] = (ch >> i) & 1
    20. pos += 1
    21. return result
    22. s_box = [54, 132, 138, 83, 16, 73, 187, 84, 146, 30, 95, 21, 148, 63, 65, 189, 188, 151, 72, 161, 116, 63, 161, 91, 37,
    23. 24, 126, 107, 87, 30, 117, 185, 98, 90, 0, 42, 140, 70, 86, 0, 42, 150, 54, 22, 144, 153, 36, 90, 149, 54, 156,
    24. 8, 59, 40, 110, 56, 1, 84, 103, 22, 65, 17, 190, 41, 99, 151, 119, 124, 68, 17, 166, 125, 95, 65, 105, 133, 49,
    25. 19, 138, 29, 110, 7, 81, 134, 70, 87, 180, 78, 175, 108, 26, 121, 74, 29, 68, 162, 142, 177, 143, 86, 129, 101,
    26. 117, 41, 57, 34, 177, 103, 61, 135, 191, 74, 69, 147, 90, 49, 135, 124, 106, 19, 89, 38, 21, 41, 17, 155, 83,
    27. 38, 159, 179, 19, 157, 68, 105, 151, 166, 171, 122, 179, 114, 52, 183, 89, 107, 113, 65, 161, 141, 18, 121, 95,
    28. 4, 95, 101, 81, 156, 17, 190, 38, 84, 9, 171, 180, 59, 45, 15, 34, 89, 75, 164, 190, 140, 6, 41, 188, 77, 165,
    29. 105, 5, 107, 31, 183, 107, 141, 66, 63, 10, 9, 125, 50, 2, 153, 156, 162, 186, 76, 158, 153, 117, 9, 77, 156,
    30. 11, 145, 12, 169, 52, 57, 161, 7, 158, 110, 191, 43, 82, 186, 49, 102, 166, 31, 41, 5, 189, 27]
    31. def generate(o):
    32. k = permutate(s_box, o)
    33. b = []
    34. for i in range(0, len(k), 7):
    35. b.append(k[i:i + 7] + [1])
    36. c = []
    37. for i in range(32):
    38. pos = 0
    39. x = 0
    40. for j in b[i]:
    41. x += (j << pos)
    42. pos += 1
    43. c.append((0x10001 ** x) % (0x7f))
    44. return c
    45. class N1ES:
    46. def __init__(self, key):
    47. #if (len(key) != 24 or isinstance(key, bytes) == False):
    48. # raise Exception("key must be 24 bytes long")
    49. self.key = key
    50. self.gen_subkey()
    51. def gen_subkey(self):
    52. o = string_to_bits(self.key)
    53. k = []
    54. for i in range(8):
    55. o = generate(o)
    56. k.extend(o)
    57. #o = string_to_bits([chr(c) for c in o[0:24]])
    58. o = string_to_bits([c for c in o[0:24]])
    59. self.Kn = []
    60. for i in range(32):
    61. #self.Kn.append(map(chr, k[i * 8: i * 8 + 8]))
    62. self.Kn.append(k[i * 8: i * 8 + 8])
    63. return
    64. def encrypt(self, plaintext):
    65. #if (len(plaintext) % 16 != 0 or isinstance(plaintext, bytes) == False):
    66. # raise Exception("plaintext must be a multiple of 16 in length")
    67. res = b''
    68. for i in range(len(plaintext) // 16):
    69. block = plaintext[i * 16:(i + 1) * 16]
    70. L = block[:8]
    71. R = block[8:]
    72. for round_cnt in range(32):
    73. L, R = R, (round_add(L, self.Kn[round_cnt]))
    74. L, R = R, L
    75. res += L + R
    76. return res
    77. def decrypt(self, plaintext):
    78. #if (len(plaintext) % 16 != 0 or isinstance(plaintext, bytes) == False):
    79. # raise Exception("plaintext must be a multiple of 16 in length")
    80. res = b''
    81. for i in range(len(plaintext) // 16):
    82. block = plaintext[i * 16:(i + 1) * 16]
    83. L = block[:8]
    84. R = block[8:]
    85. for round_cnt in range(32):
    86. L, R = (round_add(R, self.Kn[round_cnt])), L
    87. L, R = R, L
    88. res += L + R
    89. return res

    然后直接解密

    1. from N1ES import N1ES
    2. import base64
    3. key = b"wxy191iss00000000000cute"
    4. n1es = N1ES(key)
    5. t = base64.b64decode('HRlgC2ReHW1/WRk2DikfNBo1dl1XZBJrRR9qECMNOjNHDktBJSxcI1hZIz07YjVx')
    6. print(n1es.decrypt(t))
    7. #b'N1CTF{F3istel_n3tw0rk_c4n_b3_ea5i1y_s0lv3d_/--/}'

    不过今天看了个WP,还有更简单的方法,这个东西是个循环,直接再加密,而且3次就循环,太容易了

    1. for i in range(3):
    2. t = n1es.encrypt(t)
    3. print(t)

    没作,也没保存确实可惜了,只是那个checkin没作出来。

  • 相关阅读:
    spring底层原理初探
    C/C++---------------LeetCode第1748.唯一元素的和
    Linux内核源码分析 (B.11) 从内核世界透视 mmap 内存映射的本质(原理篇)
    刷题记录(NC16708 过河卒,NC16619 传球游戏,NC16810 [NOIP1999]拦截导弹)
    计算机毕设 基于情感分析的网络舆情热点分析系统
    如何做好建设工程项目管理?
    mysql case when 不命中缓存
    Mapstruct @Mapper @Mapping 使用介绍以及总结
    【论文解读】Performance Comparison of H.264 and H.265 Encoders for 4K Video Sequences
    使用vite搭建vue3
  • 原文地址:https://blog.csdn.net/weixin_52640415/article/details/127777527