• [2022安恒夏令营] 5个小题


    这个比赛的人比较少,中间又有强网杯,作了5个小题

    目录

    crypto

    misc 2

    misc 3

    re1

    re2


    crypto

    题目

    1. from secret import flag
    2. from Crypto.Util.number import *
    3. seed = bytes_to_long(flag)
    4. bits = seed.bit_length()
    5. while True:
    6. p = getPrime(bits + 1)
    7. if p > seed:
    8. break
    9. print(p)
    10. a = getRandomRange(1, p)
    11. b = getRandomRange(1, p)
    12. for _ in range(3):
    13. seed = (a * seed + b) % p
    14. print(seed)
    15. # 31893593182018727625473530765941216190921866039118147474754069955393226712079257707838327486268599271803
    16. # 25820280412859586557218124484272275594433027771091486422152141535682739897353623931875432576083022273940
    17. # 24295465524789348024814588142969609603624462580932512051939198335014954252359986260009296537423802567677
    18. # 14963686422550871447791815183480974143372785034397446416396172429864269108509521776424254168481536292904

    flag是第一个seed,然后每次用seed = (a*seed +b)%p得到下一个,可以用手工得到两个方程

    1. s3-s2 = a(s2-s1) mod p #求a
    2. s3 = a*s2 + b mod p #求b

     得到a,b以后就能直接得到flag

    1. p = 31893593182018727625473530765941216190921866039118147474754069955393226712079257707838327486268599271803
    2. s1= 25820280412859586557218124484272275594433027771091486422152141535682739897353623931875432576083022273940
    3. s2= 24295465524789348024814588142969609603624462580932512051939198335014954252359986260009296537423802567677
    4. s3= 14963686422550871447791815183480974143372785034397446416396172429864269108509521776424254168481536292904
    5. from gmpy2 import *
    6. # s3-s2 = a(s2-s1) mod p
    7. t = invert(s2-s1, p)
    8. a = (t*(s3-s2))%p
    9. a = 25714049524051800625758372225598770398614533519595256157902456884372427008002817231382013589153912429484
    10. # s3 = a*s2 + b mod p
    11. b = (s3 - a*s2 )%p
    12. b = 10170297191068284996927402215696494489341479919496467043387273609973505047115652911086290426648313876559
    13. #s1 = a*s0 + b mod p
    14. a1 = invert(a,p)
    15. s0 = ((s1 - b)*a1 )%p
    16. s0 = 14337636555117933152506165016723944787939761429733562849369091223517166614830298165864272285381681301117
    17. bytes.fromhex(hex(s0)[2:])
    18. #flag{e4syRsa1snotdifficult5996642D0A7415EF}
    19. #e4syRsa1snotdifficult5996642D0A7415EF

    misc 2

    题目程序

    1. # from flag import FLAG
    2. import random
    3. from PIL import Image
    4. from hashlib import md5
    5. from Crypto.Util.number import long_to_bytes as n2b
    6. FLAG = b'A'*28
    7. random.seed(793211)
    8. def pbl(bits):
    9. num = random.getrandbits(bits)
    10. bins = []
    11. while num:
    12. bins.append(num & 1)
    13. num >>= 1
    14. while len(bins) != bits:
    15. bins.append(0)
    16. return bins
    17. assert len(FLAG) == 28
    18. cat = Image.open('1.png')
    19. cat1 = Image.new('L', cat.size)
    20. cat2 = Image.new('L', cat.size)
    21. cat3 = Image.new('L', cat.size)
    22. x, y = cat.size
    23. bits = x * y
    24. r1, r2 = pbl(bits), pbl(bits)
    25. r3 = FLAG + n2b(random.getrandbits((bits - len(FLAG)) * 8))
    26. r3 = list(r3)
    27. random.shuffle(r3)
    28. for i in range(x):
    29. for j in range(y):
    30. pix = cat.getpixel((i, j))
    31. cat1.putpixel((i, j), pix[0] ^ r1[i * y + j])
    32. cat2.putpixel((i, j), pix[1] ^ r2[i * y + j])
    33. cat3.putpixel((i, j), pix[2] ^ r3[i * y + j])
    34. img = Image.new('RGB', cat.size)
    35. for p1, p3 in zip(cat1.getdata(), cat3.getdata()):
    36. print(p1, p3)
    37. break
    38. #img.putdata([(p1, 0, p3) for p1, p3 in zip(cat1.getdata(), cat3.getdata())])
    39. #img.save('xx.png')

    附件给了两个图片,然后给定加密程序,可以看到 第2个图的B通道是第1个图片B通过与flag异或的结果,异或序列是一个随机数序列,seed已经给出,通过seed可以得到这个序列。

    1. import random
    2. from PIL import Image
    3. from hashlib import md5
    4. from Crypto.Util.number import long_to_bytes as n2b
    5. def pbl(bits):
    6. num = random.getrandbits(bits)
    7. bins = []
    8. while num:
    9. bins.append(num & 1)
    10. num >>= 1
    11. while len(bins) != bits:
    12. bins.append(0)
    13. return bins
    14. cat = Image.open('1.png')
    15. xx = Image.open('xx.png')
    16. x, y = cat.size
    17. bits = x * y
    18. r3 = [0]*bits
    19. for i in range(x):
    20. for j in range(y):
    21. pix = cat.getpixel((i, j))
    22. pxx = xx.getpixel((i, j))
    23. r3[i * y + j] = pix[2]^pxx[2]
    24. #print(r3)
    25. r_ord = [i for i in range(bits)]
    26. random.seed(793211)
    27. r1, r2 = pbl(bits), pbl(bits)
    28. random.getrandbits((bits - 28) * 8)
    29. random.shuffle(r_ord)
    30. #print(r_ord)
    31. flag = [0]*28
    32. for i in range(bits):
    33. if r_ord[i]<28:
    34. flag[r_ord[i]] = r3[i]
    35. print(bytes(flag))
    36. #flag{lovely_cat_with_random}

    misc 3

    这个给了一个pyc的文件,无法反编译,先用dis打印出来可视字节码再手工翻译

    1. import marshal
    2. import dis
    3. import numpy as np
    4. def a1():
    5. code = open('whatisthis.cpython-38.pyc', 'rb').read()[16:]
    6. code = marshal.loads(code)
    7. dis.dis(code)

    输出

    1. 2 0 LOAD_CONST 0 (0)
    2. 2 LOAD_CONST 1 (None)
    3. 4 IMPORT_NAME 0 (marshal)
    4. 6 STORE_NAME 0 (marshal)
    5. 8 LOAD_CONST 0 (0)
    6. 10 LOAD_CONST 1 (None)
    7. 12 IMPORT_NAME 1 (numpy)
    8. 14 STORE_NAME 2 (np)
    9. 16 LOAD_CONST 2 (235)
    10. 18 LOAD_CONST 3 (26)
    11. 20 LOAD_CONST 4 (15)
    12. 22 LOAD_CONST 5 (8)
    13. ...同上都是数据,此处略掉十万行...
    14. 259458 LOAD_CONST 19 (18)
    15. 259460 LOAD_CONST 123 (7)
    16. 259462 EXTENDED_ARG 1
    17. 259464 EXTENDED_ARG 506
    18. 259466 BUILD_LIST 129723
    19. 259468 STORE_NAME 3 (LKmDJNIyYcklUJMlklygvZUBQUjRuhRGVrWiKDrdMsRjAshBxlXysnzMLXrrIHpovIRyoQWZQjvPbolMpJBkxXFMJtrfuQmXoNUXPfHZwdAYdYwDkuGOtJZLcYUnzCnm)
    20. 4 259470 LOAD_CONST 133 ("Don't try to reverse this python script. You will be disappointed about it ")
    21. 259472 STORE_NAME 4 (SrvcwKKBZzolvVvpsMTzdEwhhsZYRBHaCjDkbjjaeTtrvMAYGjFHGGJofdCqlwsVlHZardbOZULepuWWTLSbZwjixarkVXPHOeMpPdArcybkUWoaMvoZrxGVzKPsUUAn)
    22. 5 259474 LOAD_CONST 134 ('475')
    23. 259476 STORE_NAME 5 (EPwKMzdvDfYeFVrZDDSRPDqULNPDfaOYUKVpGuxabUwVBfovYMvOjkRbvwTxzTpgUXJOKvlUFGGJbfEEvIlyQBdsCEoTcmMWEqLKTrMwWLdjVsYnfNJsXtRKefaSastz)
    24. 6 259478 LOAD_NAME 2 (np)
    25. 259480 LOAD_ATTR 6 (random)
    26. 259482 LOAD_METHOD 7 (seed)
    27. 259484 LOAD_NAME 2 (np)
    28. 259486 LOAD_METHOD 8 (sum)
    29. 259488 LOAD_CONST 135 (object at 0x0000022FAE5EA6B0, file "/root/share/vm_share/³ö̢/notDefined/new/NotDefined_obfu.py", line 5>)
    30. 259490 LOAD_CONST 136 ('')
    31. 259492 MAKE_FUNCTION 0
    32. 259494 LOAD_NAME 5 (EPwKMzdvDfYeFVrZDDSRPDqULNPDfaOYUKVpGuxabUwVBfovYMvOjkRbvwTxzTpgUXJOKvlUFGGJbfEEvIlyQBdsCEoTcmMWEqLKTrMwWLdjVsYnfNJsXtRKefaSastz)
    33. 259496 GET_ITER
    34. 259498 CALL_FUNCTION 1
    35. 259500 CALL_METHOD 1
    36. 259502 CALL_METHOD 1
    37. 259504 POP_TOP
    38. 7 259506 LOAD_NAME 9 (range)
    39. 259508 LOAD_NAME 10 (len)
    40. 259510 LOAD_NAME 3 (LKmDJNIyYcklUJMlklygvZUBQUjRuhRGVrWiKDrdMsRjAshBxlXysnzMLXrrIHpovIRyoQWZQjvPbolMpJBkxXFMJtrfuQmXoNUXPfHZwdAYdYwDkuGOtJZLcYUnzCnm)
    41. 259512 CALL_FUNCTION 1
    42. 259514 CALL_FUNCTION 1
    43. 259516 GET_ITER
    44. 259518 FOR_ITER 32 (to 259584)
    45. 259520 STORE_NAME 11 (EFAAANzoMBMeiWmpiPLHzCedWRoczlJwzpxHuBDPSWIlfFxpOqFiIZmWbvpOgrVNCsngbdYnwnxskvnFKLFfwMYNRmzfDisiWwXruLUffUyerjtrsmPoNzMUMpAatNWH)
    46. 8 259522 LOAD_NAME 3 (LKmDJNIyYcklUJMlklygvZUBQUjRuhRGVrWiKDrdMsRjAshBxlXysnzMLXrrIHpovIRyoQWZQjvPbolMpJBkxXFMJtrfuQmXoNUXPfHZwdAYdYwDkuGOtJZLcYUnzCnm)
    47. 259524 LOAD_NAME 11 (EFAAANzoMBMeiWmpiPLHzCedWRoczlJwzpxHuBDPSWIlfFxpOqFiIZmWbvpOgrVNCsngbdYnwnxskvnFKLFfwMYNRmzfDisiWwXruLUffUyerjtrsmPoNzMUMpAatNWH)
    48. 259526 DUP_TOP_TWO
    49. 259528 BINARY_SUBSCR
    50. 259530 LOAD_NAME 2 (np)
    51. 259532 LOAD_ATTR 6 (random)
    52. 259534 LOAD_METHOD 12 (randint)
    53. 259536 LOAD_CONST 137 (27)
    54. 259538 CALL_METHOD 1
    55. 259540 INPLACE_XOR
    56. 259542 ROT_THREE
    57. 259544 STORE_SUBSCR
    58. 259546 EXTENDED_ARG 3
    59. 259548 EXTENDED_ARG 1013
    60. 259550 JUMP_ABSOLUTE 259518 (to 519036)
    61. 259552 LOAD_NAME 13 (exec)
    62. 259554 LOAD_NAME 0 (marshal)
    63. 259556 LOAD_METHOD 14 (loads)
    64. 259558 LOAD_NAME 15 (bytearray)
    65. 259560 LOAD_NAME 3 (LKmDJNIyYcklUJMlklygvZUBQUjRuhRGVrWiKDrdMsRjAshBxlXysnzMLXrrIHpovIRyoQWZQjvPbolMpJBkxXFMJtrfuQmXoNUXPfHZwdAYdYwDkuGOtJZLcYUnzCnm)
    66. 259562 CALL_FUNCTION 1
    67. 259564 CALL_METHOD 1
    68. 259566 CALL_FUNCTION 1
    69. 259568 POP_TOP
    70. 259570 LOAD_CONST 1 (None)
    71. 259572 RETURN_VALUE
    72. Disassembly of object at 0x0000022FAE5EA6B0, file "/root/share/vm_share/³ö̢/notDefined/new/NotDefined_obfu.py", line 5>:
    73. 5 0 BUILD_LIST 0
    74. 2 LOAD_FAST 0 (.0)
    75. 4 FOR_ITER 12 (to 30)
    76. 6 STORE_FAST 1 (EFAAANzoMBMeiWmpiPLHzCedWRoczlJwzpxHuBDPSWIlfFxpOqFiIZmWbvpOgrVNCsngbdYnwnxskvnFKLFfwMYNRmzfDisiWwXruLUffUyerjtrsmPoNzMUMpAatNWH)
    77. >> 8 LOAD_GLOBAL 0 (ord)
    78. 10 LOAD_FAST 1 (EFAAANzoMBMeiWmpiPLHzCedWRoczlJwzpxHuBDPSWIlfFxpOqFiIZmWbvpOgrVNCsngbdYnwnxskvnFKLFfwMYNRmzfDisiWwXruLUffUyerjtrsmPoNzMUMpAatNWH)
    79. 12 CALL_FUNCTION 1
    80. 14 LIST_APPEND 2
    81. 16 JUMP_ABSOLUTE 4 (to 8)
    82. 18 RETURN_VALUE

    手工翻译结果

    1. import marshal
    2. import numpy as np
    3. LKmD = [...]
    4. Srvc = "Don't try to reverse this python script. You will be disappointed about it "
    5. EPwK = '475'
    6. np.random.seed(np.sum([ord(i) for i in EPwK]))
    7. for EFAA in range(len(LKmD)):
    8. LKmD[EFAA] ^= np.random.randint(27)
    9. exec(marshal.loads(bytearray(LKmD)))

     大意是前边那个数组与已知seed的随机序列异或得到一个串再执行,写函数处理一下,再用dis输出

    1. def a2():
    2. fp = open('aaa.txt')
    3. [fp.readline() for i in range(8)]
    4. v = [int(fp.readline().split('(')[1].split(')')[0]) for i in range(129723)]
    5. EPwK = '475'
    6. np.random.seed(np.sum([ord(i) for i in EPwK]))
    7. for i in range(len(v)):
    8. v[i] ^= np.random.randint(27)
    9. code = marshal.loads(bytes(v))
    10. dis.dis(code)

     后边的结果就更简单了,就是直接给一个字符串的原码,然后执行,翻译后

    1. import marshal
    2. sv1 = [...略掉十成个数字...]
    3. def sv2(key):
    4. sv3 = list(range(256))
    5. sv4 = 0
    6. for sv5 in range(256):
    7. sv4 = (sv4 + sv3[sv5] + ord(key[sv5 % len(key)])) % 256
    8. sv3[sv5], sv3[sv4] = sv3[sv4], sv3[sv5]
    9. return sv3
    10. def sv6(p):
    11. sv7 = sv2('h0lyduck')
    12. sv8 = []
    13. sv5 = sv4 = 0
    14. for sv9 in p:
    15. sv5 = (sv5 + 1) % 256
    16. sv4 = (sv4 + sv7[sv5]) % 256
    17. sv7[sv5], sv7[sv4] = sv7[sv4], sv7[sv5]
    18. sva = (sv7[sv5] + sv7[sv4]) % 256
    19. svb = sv7[sva]
    20. sv8.append(sv9 ^ svb)
    21. return sv8
    22. #exec(marshal.loads(bytearray(sv6(sv1))))
    23. import dis
    24. code = marshal.loads(bytearray(sv6(sv1)))
    25. dis.dis(code)

    第3得到都是直接的串,同样方法处理

    1. import marshal
    2. import struct
    3. from typing import List
    4. sv1 = [...略掉数据...]
    5. class sv2:
    6. def __init__(self, val: int):
    7. assert isinstance(val, int)
    8. self.val = val
    9. def __add__(self, other):
    10. return sv2((self.val + other.val) & 0xffffffff)
    11. def __xor__(self, other):
    12. return sv2(self.val ^ other.val)
    13. def __lshift__(self, nbit: int):
    14. sv3 = (self.val << nbit % 32) & 0xffffffff
    15. sv4 = (self.val & 0xffffffff) >> (32 - (nbit % 32))
    16. return sv2(sv3 | sv4)
    17. def __repr__(self):
    18. return hex(self.val)
    19. def __int__(self):
    20. return int(self.val)
    21. def sv5(sv6: sv2, b: sv2, sv7: sv2, d: sv2):
    22. sv6 += b
    23. d ^= sv6
    24. d <<= 16
    25. sv7 += d
    26. b ^= sv7
    27. b <<= 12
    28. sv6 += b
    29. d ^= sv6
    30. d <<= 8
    31. sv7 += d
    32. b ^= sv7
    33. b <<= 7
    34. return sv6, b, sv7, d
    35. def sv8(sv9: List[sv2], idx1, idx2, idx3, idx4):
    36. sv9[idx1], sv9[idx2], sv9[idx3], sv9[idx4] = \
    37. sv5(sv9[idx1], sv9[idx2], sv9[idx3], sv9[idx4])
    38. def sva(sv9: List[sv2]):
    39. sv8(sv9, 0, 4, 8, 12)
    40. sv8(sv9, 1, 5, 9, 13)
    41. sv8(sv9, 2, 6, 10, 14)
    42. sv8(sv9, 3, 7, 11, 15)
    43. sv8(sv9, 0, 5, 10, 15)
    44. sv8(sv9, 1, 6, 11, 12)
    45. sv8(sv9, 2, 7, 8, 13)
    46. sv8(sv9, 3, 4, 9, 14)
    47. return sv9
    48. def svb(sv9: List[sv2]) -> List[bytes]:
    49. return b''.join([struct.pack(', int(svc)) for svc in sv9])
    50. def svd(sve: bytes, svf: int, svg: bytes) -> bytes:
    51. svh = [sv2(svj) for svj in struct.unpack(', b'expand 32-byte k')]
    52. sve = [sv2(svj) for svj in struct.unpack(', sve)]
    53. svf = [sv2(svf)]
    54. svg = [sv2(svj) for svj in struct.unpack(', svg)]
    55. sv9 = svh + sve + svf + svg
    56. svk = sv9[:]
    57. for svm in range(10):
    58. sv9 = sva(sv9)
    59. sv9 = [svc + svn for svc, svn in zip(sv9, svk)]
    60. return svb(sv9)
    61. def svp(svj: bytes, y: bytes):
    62. return bytes(sv6 ^ b for sv6, b in zip(svj, y))
    63. def svq(sve: bytes, svf: int, svg: bytes, plaintext: bytes):
    64. sv7 = bytearray(0)
    65. for svr in range(len(plaintext) // 64):
    66. svs = svd(sve, svf + svr, svg)
    67. svt = plaintext[svr * 64:(svr + 1) * 64]
    68. sv7 += svp(svt, svs)
    69. if len(plaintext) % 64 != 0:
    70. svr = len(plaintext) // 64
    71. svs = svd(sve, svf + svr, svg)
    72. svt = plaintext[svr * 64:]
    73. sv7 += svp(svt, svs)
    74. return sv7
    75. sve = bytes.fromhex(
    76. '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f')
    77. svf = 0x00000001
    78. svg = bytes.fromhex('000000000000004a00000000')
    79. sv6 = svq(sve, svf, svg, bytearray(sv1))
    80. code = marshal.loads(sv6)
    81. import dis
    82. dis.dis(code)

    最后一次得到的文件,可以看到flag

    1. 3 0 LOAD_CONST 0 (0)
    2. 2 LOAD_CONST 1 (None)
    3. 4 IMPORT_NAME 0 (builtins)
    4. 6 STORE_NAME 0 (builtins)
    5. 5 8 LOAD_CONST 2 ('flag{Wow_Y0o0U_@re_MaSt3r_0F_Not_d3f1neD}')
    6. 10 STORE_NAME 1 (flag)
    7. 19 12 LOAD_CONST 3 (object enc at 0x000002567BCAD370, file "", line 5>)
    8. 14 LOAD_CONST 4 ('enc')
    9. 16 MAKE_FUNCTION 0
    10. 18 STORE_NAME 2 (enc)

    re1

    main里边直接调用加密程序,然后与密文核对

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. __int64 v3; // rcx
    4. __int64 v4; // rdx
    5. __int128 v6[2]; // [rsp+20h] [rbp-38h] BYREF
    6. char v7; // [rsp+40h] [rbp-18h]
    7. memset(v6, 0, sizeof(v6));
    8. v7 = 0;
    9. sub_140001020("I prefer TeaProPlus! can you give me this?\n");
    10. sub_140001020("TeaProPlus code:");
    11. sub_140001080("%32s", (const char *)v6);
    12. sub_1400010E0(v3, (unsigned int *)v6);
    13. v4 = 0i64;
    14. while ( *((_BYTE *)v6 + v4) == byte_1400032F0[v4] )
    15. {
    16. if ( (unsigned __int64)++v4 >= 0x20 )
    17. {
    18. sub_140001020("Oh yeah! Good code! flag{(your input)}\n");
    19. return 0;
    20. }
    21. }
    22. puts("oh NO!I want to drink TeaProPlus");
    23. return -1;
    24. }

     加密程序是一个变种的tea

    1. __int64 __fastcall sub_1400010E0(__int64 a1, unsigned int *a2)
    2. {
    3. unsigned int v7; // r9d
    4. unsigned int key; // edi
    5. unsigned int v1; // ebp
    6. unsigned int v0; // esi
    7. unsigned int v2; // r14d
    8. unsigned int v3; // r15d
    9. unsigned int v4; // r12d
    10. unsigned int v5; // r13d
    11. _DWORD *key2; // r11
    12. _DWORD *v11; // r10
    13. __int64 v12; // rbx
    14. _DWORD *v13; // r9
    15. __int64 result; // rax
    16. bool v15; // zf
    17. unsigned int v6; // [rsp+40h] [rbp+8h]
    18. int round; // [rsp+48h] [rbp+10h]
    19. unsigned int v18; // [rsp+50h] [rbp+18h]
    20. v7 = a2[7];
    21. key = 0;
    22. v1 = a2[1];
    23. v0 = *a2;
    24. v2 = a2[2];
    25. v3 = a2[3];
    26. v4 = a2[4];
    27. v5 = a2[5];
    28. v6 = a2[6];
    29. v18 = v7;
    30. round = 12;
    31. do
    32. {
    33. key -= 0x61C88647;
    34. key2 = &key3[(key >> 2) & 3];
    35. v0 += ((key ^ v1) + (*key2 ^ v7)) ^ (((16 * v7) ^ (v1 >> 3)) + ((v7 >> 5) ^ (4 * v1)));
    36. *a2 = v0;
    37. v11 = &key3[(key >> 2) & 3 ^ 1i64];
    38. v1 += ((*v11 ^ v0) + (key ^ v2)) ^ (((16 * v0) ^ (v2 >> 3)) + ((v0 >> 5) ^ (4 * v2)));
    39. a2[1] = v1;
    40. v12 = (key >> 2) & 3 ^ 3i64;
    41. v13 = &key3[(key >> 2) & 3 ^ 2i64];
    42. v2 += ((key ^ v3) + (*v13 ^ v1)) ^ (((16 * v1) ^ (v3 >> 3)) + ((v1 >> 5) ^ (4 * v3)));
    43. a2[2] = v2;
    44. v3 += ((key ^ v4) + (key3[v12] ^ v2)) ^ (((16 * v2) ^ (v4 >> 3)) + ((v2 >> 5) ^ (4 * v4)));
    45. a2[3] = v3;
    46. v4 += ((key ^ v5) + (*key2 ^ v3)) ^ (((16 * v3) ^ (v5 >> 3)) + ((v3 >> 5) ^ (4 * v5)));
    47. a2[4] = v4;
    48. v5 += ((*v11 ^ v4) + (key ^ v6)) ^ (((16 * v4) ^ (v6 >> 3)) + ((v4 >> 5) ^ (4 * v6)));
    49. a2[5] = v5;
    50. LODWORD(key2) = (((key ^ v18) + (*v13 ^ v5)) ^ (((16 * v5) ^ (v18 >> 3)) + ((v5 >> 5) ^ (4 * v18)))) + v6;
    51. a2[6] = (unsigned int)key2;
    52. v6 = (unsigned int)key2;
    53. result = key ^ v0;
    54. v18 += (result + (key3[v12] ^ (unsigned int)key2)) ^ (((16 * (_DWORD)key2) ^ (v0 >> 3))
    55. + (((unsigned int)key2 >> 5) ^ (4 * v0)));
    56. v15 = round-- == 1;
    57. v7 = v18;
    58. a2[7] = v18;
    59. }
    60. while ( !v15 );
    61. return result;
    62. }

    解密程序

    1. from pwn import u32,p32
    2. s = bytes.fromhex('473BBD10F9E05561C5EBF76A5F43238D0516091AEF403DD4676AB1B4A978356B')
    3. c = [0]*8
    4. for i in range(8):
    5. c[i] = u32(s[i*4: i*4+4])
    6. key = [0]*13
    7. k = 0
    8. for i in range(13):
    9. k = (k - 0x61C88647)%0x100000000
    10. key[i] = k
    11. key3 = [0x1234, 0x2345, 0x4567, 0x6789]
    12. for i in range(11, -1, -1):
    13. for j in range(7, -1, -1):
    14. p_next = (j+1)%8
    15. p_pre = (j-1)%8
    16. t = j%4
    17. c[j] = ( c[j] -
    18. ( ((key[i]^c[p_next]) + (key3[((key[i]>>2)&3) ^ t]^c[p_pre]) )
    19. ^ (((c[p_pre]<<4)^(c[p_next]>>3)) + ((c[p_pre]>>5)^(c[p_next]<<2)) ) )
    20. ) %0x100000000
    21. print(hex(key[i]))
    22. flag = b''
    23. for i in range(8):
    24. flag += p32(c[i])
    25. print(flag)
    26. #7f943921724d63dc0ac9c6febf99fa88

     

    re2

    main里边啥都没有,发现有反调,调用了TlsCallback_0

    1. void __stdcall TlsCallback_0(int a1, DWORD flOldProtect, int a3)
    2. {
    3. int i; // eax
    4. if ( flOldProtect == 1 )
    5. {
    6. VirtualProtect(StartAddress, 0x320u, 0x40u, &flOldProtect);
    7. for ( i = 0; i < 0x320; ++i )
    8. *((_BYTE *)StartAddress + i) ^= i;
    9. CreateThread(0, 0, StartAddress, 0, 0, 0);
    10. }
    11. }

    函数对程序块异或解密后起线程执行,先用程序给程序patch

    1. a1 = open('re2.exe', 'rb').read()
    2. a1 = list(a1)
    3. for i in range(800):
    4. a1[0x440 + i ] ^= i&0xff
    5. open('re_patch.exe', 'wb').write(bytes(a1))

    然后用ida打开patch后的程序可以看到加密代码

    1. DWORD __stdcall StartAddress(LPVOID lpThreadParameter)
    2. {
    3. int k; // ebx
    4. int v4[65534]; // [esp+Ch] [ebp-50530h]
    5. char v5[66816]; // [esp+40004h] [ebp-10538h] BYREF
    6. int v6[6]; // [esp+50504h] [ebp-38h]
    7. char *v7; // [esp+5051Ch] [ebp-20h]
    8. int v8; // [esp+50520h] [ebp-1Ch]
    9. int v9; // [esp+50524h] [ebp-18h]
    10. int v10; // [esp+50528h] [ebp-14h]
    11. int v11; // [esp+5052Ch] [ebp-10h]
    12. int i; // [esp+50530h] [ebp-Ch]
    13. int v13; // [esp+50534h] [ebp-8h]
    14. int j; // [esp+50538h] [ebp-4h]
    15. while ( !dword_41B2E4 )
    16. Sleep(0x3E8u);
    17. for ( i = 0; i < 112; ++i )
    18. byte_41B30A += *((_BYTE *)&loc_401450 + i);
    19. for ( i = 0; byte_41B2EC[i]; ++i )
    20. byte_41B2EC[i] ^= byte_41B30A;
    21. v6[0] = 81;
    22. v6[1] = 102;
    23. v6[2] = 114;
    24. v6[3] = 111;
    25. v6[4] = 115;
    26. v6[5] = 116;
    27. for ( j = 0; j < 256; ++j )
    28. *(_DWORD *)&v5[4 * j + 0x10100] = j;
    29. for ( j = 0; j < 256; ++j )
    30. v5[j + 0x10000] = v6[j % 6]; // key
    31. v13 = 0;
    32. for ( j = 0; j < 256; ++j )
    33. {
    34. v13 = (v5[j + 0x10000] + *(_DWORD *)&v5[4 * j + 65792] + v13) % 256;
    35. v10 = *(_DWORD *)&v5[4 * j + 65792];
    36. *(_DWORD *)&v5[4 * j + 65792] = *(_DWORD *)&v5[4 * v13 + 65792];
    37. *(_DWORD *)&v5[4 * v13 + 65792] = v10;
    38. }
    39. v11 = dword_41B2E8;
    40. v9 = 0;
    41. v13 = 0;
    42. j = 0;
    43. while ( v11-- )
    44. {
    45. j = (j + 1) % 256;
    46. v13 = (*(_DWORD *)&v5[4 * j + 65792] + v13) % 256;
    47. v10 = *(_DWORD *)&v5[4 * j + 65792];
    48. *(_DWORD *)&v5[4 * j + 65792] = *(_DWORD *)&v5[4 * v13 + 65792];
    49. *(_DWORD *)&v5[4 * v13 + 65792] = v10;
    50. v8 = (*(_DWORD *)&v5[4 * v13 + 65792] + *(_DWORD *)&v5[4 * j + 65792]) % 256;
    51. v4[v9++] = *(_DWORD *)&v5[4 * v8 + 65792];
    52. }
    53. for ( j = 0; j < dword_41B2E8; ++j )
    54. v5[j] = LOBYTE(v4[j]) ^ byte_41B2EC[j];
    55. v7 = v5;
    56. for ( k = 0; k < dword_41B2E8; ++k )
    57. {
    58. if ( v7[k] != *(_BYTE *)(k + 0x401307) )
    59. {
    60. puts(0x401345);
    61. _loaddll(0);
    62. break;
    63. }
    64. }
    65. puts((int)"right\n");
    66. j___fgetchar();
    67. return 0;
    68. }

    感觉好像叫RC4还是啥来着,先生成加密流,再与明文异或。反正对应写程序就行了

    1. a1 = open('re_patch.exe', 'rb').read()[0x707: 0x707+ 0x100]
    2. v6 = b'Qfrost'
    3. v51 = [i for i in range(256)]
    4. key = [v6[j%6] for j in range(256)]
    5. v13 = 0
    6. for j in range(256):
    7. v13 = (key[j] + v51[j] + v13) % 256
    8. v51[j], v51[v13] = v51[v13], v51[j]
    9. flen = 50
    10. v13 = 0
    11. v4 = [0]*flen
    12. j = 0
    13. for i in range(flen):
    14. j = (j+1)%256
    15. v13 = (v51[j] + v13)%256
    16. v51[j], v51[v13] = v51[v13], v51[j]
    17. v8 = (v51[j] + v51[v13])%256
    18. v4[i] = v51[v8]^a1[i]
    19. for i in range(256):
    20. tmp = bytes([i^v for v in v4])
    21. #if b'flag{' in tmp:
    22. print(tmp)
    23. #QDbg-Is_an_1ntereSting-Game!

  • 相关阅读:
    Linux:从入门到放弃
    JS中常用的Date内置对象&处理Date内置对象的一些方法
    数据库——创建和管理表
    第七章:单链表与双链表(数组模拟)
    ofxTimeMeasurements——OpenFrameworks插件,可以轻松测量C++代码任何部分的执行时间
    客厅、厨房、卫生间瓷砖怎么挑选,看完不再烦恼!福州中宅装饰,福州装修
    JS数组和字符串的原生方法
    支持向量机(SVM)算法基本原理&skearn实现
    什么是M365 Manager Plus?
    迅为龙芯开发板Linux工具之make工具和Makefile文件
  • 原文地址:https://blog.csdn.net/weixin_52640415/article/details/126119424