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 指向的函数结果
}

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

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

相关推荐
网络安全(华哥)10 小时前
网络安全概论
网络·安全·web安全
芯盾时代11 小时前
智能汽车的数字钥匙安全
物联网·安全·网络安全·汽车·信息与通信
安全方案13 小时前
2024信息安全网络安全等安全意识(附培训PPT下载)
网络·安全·web安全
浩浩测试一下14 小时前
Web渗透测试之XSS跨站脚本之JS输出 以及 什么是闭合标签 一篇文章给你说明白
前端·javascript·安全·web安全·网络安全·html·系统安全
黑客老陈14 小时前
BaseCTF scxml 详解
开发语言·网络·python·sql·安全·web安全
浩浩测试一下15 小时前
Web渗透测试之XSS跨站脚本 防御[WAF]绕过手法
前端·web安全·网络安全·系统安全·xss·安全架构
万亿少女的梦16816 小时前
基于php的web系统漏洞攻击靶场设计与实践
前端·安全·web安全·信息安全·毕业设计·php
DataDynamos数动实验室17 小时前
【计算机网络】IPSec的安全协议和封装模式
网络·计算机网络·网络安全
Aimin202219 小时前
网络安全---信息收集
网络安全
网络安全工程师老王19 小时前
HTML Application利用
网络安全·信息安全·渗透测试·html