CTF-PWN: WEB_and_PWN [第一届“吾杯”网络安全技能大赛 Calculator] 赛后学习(不会)

附件

calculate.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <!-- 设置字符编码为 UTF-8,支持多语言字符集 -->
    <meta charset="UTF-8">
    
    <!-- 设置响应式视图,确保页面在不同设备上自适应显示 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <!-- 网页标题,显示在浏览器标签栏 -->
    <title>Calculation Result</title>
</head>
<body>
    <!-- 页面主标题 -->
    <h1>Calculation Result</h1>
    
    <!-- 显示计算结果的段落,默认显示 'Loading...' -->
    <p id="result">Loading...</p>
    
    <!-- 返回计算器页面的链接 -->
    <a href="/index.html">Back to Calculator</a>
</body>
</html>

index.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <!-- 设置字符编码为 UTF-8,支持多语言字符集 -->
    <meta charset="UTF-8">
    
    <!-- 设置响应式视图,确保页面在不同设备上自适应显示 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <!-- 网页标题,显示在浏览器标签栏 -->
    <title>Calculator</title>
</head>
<body>
    <!-- 页面主标题 -->
    <h1>Simple Calculator</h1>
    
    <!-- 表单用于计算操作,提交方式为 GET 请求 -->
    <form action="/calculate.html" method="get">
        
        <!-- 输入框:第一个数字,带有标签 -->
        <label for="a">Number 1:</label>
        <input type="number" id="a" name="a" required><br><br>
        
        <!-- 输入框:第二个数字,带有标签 -->
        <label for="b">Number 2:</label>
        <input type="number" id="b" name="b" required><br><br>
        
        <!-- 下拉框:选择运算符,支持加法、减法、乘法和除法 -->
        <label for="op">Operation:</label>
        <select id="op" name="op" required>
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select><br><br>
        
        <!-- 提交按钮,触发计算操作 -->
        <button type="submit">Calculate</button>
    </form>
</body>
</html>

保护

❯ checksec --file=./pwn
[*] '/home/a5rz/Desktop/pwn/file/pwn'
    Arch:       amd64-64-little
    RELRO:      Full RELRO
    Stack:      No canary found
    NX:         NX unknown - GNU_STACK missing
    PIE:        PIE enabled
    Stack:      Executable
    RWX:        Has RWX segments
    SHSTK:      Enabled
    IBT:        Enabled

sudo运行

❯ sudo ./pwn
Server started on port 80

此html向服务器发送了这样的东西

php 复制代码
D:/calculate.html?a=1&b=1&op=%2B

a是数字1,b是数字2,op是选择加减乘除

找到调用Page not found!的地方

c 复制代码
__int64 __fastcall sub_1843(unsigned int a1, const char *a2) {
    // 本地变量定义,用于存储各种数据
    size_t v3; // 用于存储缓冲区的长度
    size_t v4; // 用于存储 HTTP 响应的长度
    size_t v5; // 用于存储 HTTP 错误响应的长度
    size_t v6; // 用于存储页面未找到的响应长度
    char s[512]; // 用于存储处理过的查询字符串
    char buf[256]; // 用于存储 HTTP 响应内容
    char nptr[32]; // 用于存储第一个参数(a)
    char v10; // 用于存储操作符(+、-、*、/)
    char v11[47]; // 用于存储第二个参数(b)
    char v12; // 用于存储操作符
    __int64 v13; // 用于存储第一个数字(a)
    __int64 v14; // 用于存储第二个数字(b)
    char *v15; // 用于指向查询字符串中的位置
    __int64 v16; // 用于存储计算结果

    // 判断请求的 URL 是否是"GET /index.html"或"GET / ",如果是,则返回一个 HTML 文件
    if ( !strncmp(a2, "GET /index.html", 0xFuLL) || !strncmp(a2, "GET / ", 6uLL) ) {
        return sub_1532(a1, "index.html");
    }

    // 如果请求 URL 是"GET /calculate.html?",则进一步处理计算逻辑
    if ( !strncmp(a2, "GET /calculate.html?", 0x14uLL) ) {
        // 找到查询字符串("?" 后面的部分)
        v15 = strchr(a2, 63); // 63 是 "?" 的 ASCII 值
        if ( v15 ) {
            // 从查询字符串开始处提取数据
            snprintf(s, 0x200uLL, "%s", ++v15); // 复制查询字符串到 s
            sub_1744(s); // 可能是对字符串 s 进行某些处理(具体实现不明)

            // 清空缓存
            nptr[0] = 0;
            v11[0] = 0;
            v10 = 0;

            // 解析查询字符串中的参数
            if ( (unsigned int)__isoc99_sscanf(s, "a=%31[^&]&b=%31[^&]&op=%256s", nptr, v11, &v10) == 3 ) {
                // 将参数转换为整数
                v14 = atoll(nptr); // 将第一个参数(a)转换为长整型
                v13 = atoll(v11); // 将第二个参数(b)转换为长整型
                v12 = v10; // 将操作符保存到 v12

                v16 = 0LL; // 默认结果为 0

                // 根据操作符执行相应的计算
                if ( v10 == 43 ) { // 如果操作符是 "+",进行加法
                    v16 = v14 + v13;
                } else if ( v12 == 45 ) { // 如果操作符是 "-",进行减法
                    v16 = v14 - v13;
                } else if ( v12 == 42 ) { // 如果操作符是 "*",进行乘法
                    v16 = v13 * v14;
                } else if ( v12 == 47 && v13 ) { // 如果操作符是 "/" 且第二个数不为零,进行除法
                    v16 = v14 / v13;
                } else {
                    v16 = 0LL; // 如果操作符无效,结果为 0
                }

                // 生成成功响应,包含计算结果
                snprintf(buf, 0x100uLL, 
                         "HTTP/1.1 200 OK\r\n"
                         "Content-Type: text/html\r\n"
                         "\r\n"
                         "<!DOCTYPE html><html><head><title>Result</title></head><body><h1>Result: %lld</h1><a href=\"/index.html\">Back"
                         " to Calculator</a></body></html>", v16);

                // 获取响应内容的长度
                v3 = strlen(buf);
                // 发送响应
                send(a1, buf, v3, 0);
                return sub_1679(v16); // 可能是处理计算结果的函数(具体实现不明)
            } else {
                // 如果查询参数不正确,返回 400 错误响应
                snprintf(buf, 0x100uLL, "HTTP/1.1 400 Bad Request\r\n\r\nInvalid query!");
                v4 = strlen(buf);
                return send(a1, buf, v4, 0);
            }
        } else {
            // 如果没有查询字符串,返回 400 错误响应
            snprintf(buf, 0x100uLL, "HTTP/1.1 400 Bad Request\r\n\r\nMissing query!");
            v5 = strlen(buf);
            return send(a1, buf, v5, 0);
        }
    } else {
        // 如果请求的 URL 不匹配,返回 404 错误响应
        snprintf(buf, 0x100uLL, "HTTP/1.1 404 Not Found\r\n\r\nPage not found!");
        v6 = strlen(buf);
        return send(a1, buf, v6, 0);
    }
}

加上calculate.html

patch反调试!(这东西卡了我好久,没注意他,我一直以为调试不上是gdb的问题)

发现一个非常奇怪的函数

c 复制代码
__int64 __fastcall sub_1679(__int64 a1)
{
    // 定义一个指向无参函数返回__int64类型的指针 v2
    __int64 (*v2)(void); // [rsp+28h] [rbp-8h]

    // 调用 mmap 函数映射一个 8 字节的内存区域
    // mmap(0LL, 8uLL, 7, 34, -1, 0LL) 中的参数:
    // 0LL        - 映射地址从操作系统自动选择
    // 8uLL       - 映射的大小为 8 字节
    // 7          - 映射保护标志 (PROT_READ | PROT_WRITE)
    // 34         - 映射映射类型(MAP_ANONYMOUS | MAP_PRIVATE)
    // -1         - 不关联任何文件(-1 表示匿名映射)
    // 0LL        - 映射偏移量为 0
    v2 = (__int64 (*)(void))mmap(0LL, 8uLL, 7, 34, -1, 0LL);

    // 检查 mmap 是否成功,如果返回值为 -1,表示映射失败
    if (v2 == (__int64 (*)(void))-1LL)
    {
        perror("mmap failed"); // 输出错误信息
        exit(1); // 退出程序,返回错误代码 1
    }

    // 将传入的参数 a1 存储在映射区域的起始位置
    *(_QWORD *)v2 = a1;

    // 调用映射区域开始处的函数并返回其结果
    // v2 是一个指向函数的指针,因此 v2() 表示调用此函数并返回其返回值
    return v2(); // 调用并返回函数指针 v2 指向的函数结果
}

再加上栈可执行,估计出题人是想让我们利用这里,这个函数能执行任意指针

跟上一道题一样不给基地址?这题到底怎么做的爆破吗?

相关推荐
MC何失眠1 小时前
vulnhub靶场【哈利波特】三部曲之Fawkes
网络·python·学习·网络安全
B站计算机毕业设计超人5 小时前
计算机毕业设计Python异常流量检测 流量分类 流量分析 网络流量分析与可视化系统 网络安全 信息安全 机器学习 深度学习
大数据·人工智能·python·深度学习·web安全·机器学习·课程设计
练小杰5 小时前
谈论 PHP与XSS
开发语言·经验分享·笔记·网络安全·php·xss
xing.yu.CTF8 小时前
攻防世界-fileclude-文件包含
网络·安全·web安全·文件包含漏洞·基础漏洞
岛屿旅人9 小时前
警惕开源信息成为泄密源头
网络·安全·网络安全
网络安全技术分享9 小时前
新手参加2025年CTF大赛——Web题目的基本解题流程
前端·学习·安全·web安全·php·ddos
群联云防护小杜10 小时前
阿里云流量异常:是黑客攻击吗?如何识别和应对
网络·网络协议·安全·web安全·阿里云·云计算·ddos
尘佑不尘10 小时前
shell编程7,bash解释器的 for循环+while循环
linux·开发语言·笔记·后端·web安全·bash·shell编程