草庐IT

capture the ether靶场题解(Account)

luc1fer丶 2023-07-14 原文

题目预览

Fuzzy identity

分析

题目合约:

pragma solidity ^0.4.21;

interface IName {
    function name() external view returns (bytes32);
}

contract FuzzyIdentityChallenge {
    bool public isComplete;

    function authenticate() public {
        require(isSmarx(msg.sender));
        require(isBadCode(msg.sender));

        isComplete = true;
    }

    function isSmarx(address addr) internal view returns (bool) {
        return IName(addr).name() == bytes32("smarx");
    }

    function isBadCode(address _addr) internal pure returns (bool) {
        bytes20 addr = bytes20(_addr);
        bytes20 id = hex"000000000000000000000000000000000badc0de";
        bytes20 mask = hex"000000000000000000000000000000000fffffff";

        for (uint256 i = 0; i < 34; i++) {
            if (addr & mask == id) {
                return true;
            }
            mask <<= 4;
            id <<= 4;
        }

        return false;
    }
}

题目要求我们将isComplete变为true。
很明显必须调用authenticate函数,也就要饶过两个require。
第一个require要求我们满足IName函数,并且返回值为bytes32(“smarx”),很容易满足。
第二个require意思是,我们用来攻击的地址中必须存在"badc0de"这一串字符,也就很容易想到使用creat2来完成。

攻击

攻击合约:

pragma solidity ^0.4.21;
import "./FuzzyIdentity.sol";


contract attack{
    function name() external view returns (bytes32){
        return bytes32("smarx");
    }

    function att(address _Fuzzy) public {
        FuzzyIdentityChallenge(_Fuzzy).authenticate();
    }
}

部署合约:

contract deployer{
    bytes attackCode = hex"608060405234801561001057600080fd5b5061019a806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde0314610051578063db97040214610084575b600080fd5b34801561005d57600080fd5b506100666100c7565b60405180826000191660001916815260200191505060405180910390f35b34801561009057600080fd5b506100c5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506100ef565b005b60007f736d617278000000000000000000000000000000000000000000000000000000905090565b8073ffffffffffffffffffffffffffffffffffffffff1663380c7a676040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401600060405180830381600087803b15801561015357600080fd5b505af1158015610167573d6000803e3d6000fd5b50505050505600a165627a7a723058204273cdd8b92be0f5d505d2cc5fb213a3d50227101e51e54b95e9bd5592b6c6e80029";
    function deploy(bytes32 salt) public returns(address){
        bytes memory bytecode = attackCode;
        address addr;
        assembly {
            addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
        }
        return addr;
    }
    function getHash()public view returns(bytes32){
        return keccak256(attackCode);
    }
}

思路很简单,使用creat2,我们知道creat2可以根据用户输入salt的不同,部署可控地址的合约,我们只需要将攻击合约的字节码放入deploy函数,再根据脚本算出生成对应地址需要的salt。
脚本如下:

from web3 import Web3

s1 = '0xff7EF2e0048f5bAeDe046f6BF797943daF4ED8CB47'

s3 = '35206f900ec99a80b49aaffd98e9ad7e94f0de8df30a79b6797d52f7eaa76ea1'

i = 0
while(1):
    salt = hex(i)[2:].rjust(64, '0')
    s = s1+salt+s3
    hashed = Web3.sha3(hexstr=s)
    hashed_str = ''.join(['%02x' % b for b in hashed])
    if 'badc0de' in hashed_str[24:]:
        print(salt,hashed_str)
        break
    i += 1
    print(salt)


将部署合约的地址放入s1,攻击合约字节码哈希后放入s3,经过一段时间即可生成出salt,将salt放入deploy函数,即成功部署attack合约,调用攻击函数即可。

Public Key

分析

题目合约:

pragma solidity ^0.4.21;

contract PublicKeyChallenge {
    address owner = 0x92b28647ae1f3264661f72fb2eb9625a89d88a31;
    bool public isComplete;

    function authenticate(bytes publicKey) public {
        require(address(keccak256(publicKey)) == owner);

        isComplete = true;
    }
}

合约要求我们输入的参数哈希后为owner的地址,简单来说就是要我们拿到这个地址的公钥。
这里涉及到以太坊上公私钥生成算法和椭圆曲线数字签名算法,这里不细讲,只需要知道,当知道消息hash,r,s,v也就是消息签名 的三部分,我们就可以得到对应的公钥。

我们去区块链浏览器上查询该地址曾经的交易记录,很轻松能够查到这笔由该地址发出的交易

根据web3.eth.getTransaction来获取到该交易的hash,r,s,v

利用这些已知数据通过脚本来获取到对应的公钥,脚本如下:

const EthereumTx = require('ethereumjs-tx');
const util = require('ethereumjs-util');

var rawTx = {
  nonce: '0x00',
  gasPrice: '0x3b9aca00',
  gasLimit: '0x15f90',
  to: '0x6B477781b0e68031109f21887e6B5afEAaEB002b',
  value: '0x00',
  data: '0x5468616e6b732c206d616e21',
  v: '0x29',
  r: '0xa5522718c0f95dde27f0827f55de836342ceda594d20458523dd71a539d52ad7',
  s: '0x5710e64311d481764b5ae8ca691b05d14054782c7d489f3511a7abf2f5078962'
};

var tx = new EthereumTx(rawTx);

pubkey=tx.getSenderPublicKey();
pubkeys=pubkey.toString('hex');
var address = util.sha3(pubkey).toString('hex').slice(24);

console.log(pubkeys);
console.log(address);

将对应的公钥放入authenticate调用即可。

攻击

运行脚本,算出公钥

公钥放入函数调用栏,调用即可完成

Account Takeover

分析

题目合约:

pragma solidity ^0.4.21;

contract AccountTakeoverChallenge {
    address owner = 0x6B477781b0e68031109f21887e6B5afEAaEB002b;
    bool public isComplete;

    function authenticate() public {
        require(msg.sender == owner);

        isComplete = true;
    }
}

与上题有些类似,只不过这个题需要我们拿到账户的私钥,并根据私钥使用该账户来调用这个函数。
同样能够在区块链浏览器上查到交易,且我们能够发现,本来r应该唯一的交易,确存在两笔交易拥有相同的r,我们可以根据这个计算出对应账户的私钥。

攻击

攻击脚本:


# -*-coding:utf-8-*-
from web3 import Web3, HTTPProvider
from pwn import log
infura_url = 'https://ropsten.infura.io/v3/[api_key]'
web3 = Web3(Web3.HTTPProvider(infura_url))

a= web3.eth.get_transaction("0x061bf0b4b5fdb64ac475795e9bc5a3978f985919ce6747ce2cfbbcaccaf51009")
log.info("r = {0}".format(a.r.hex()))
log.info("s = {0}".format(a.s.hex()))
log.info("v= {0}".format(a.v))

a= web3.eth.get_transaction("0xd79fc80e7b787802602f3317b7fe67765c14a7d40c3e0dcb266e63657f881396")
log.info("r = {0}".format(a.r.hex()))
log.info("s = {0}".format(a.s.hex()))
log.info("v= {0}".format(a.v))


r = 0x69a726edfb4b802cbf267d5fd1dabcea39d3d7b4bf62b9eeaeba387606167166
# txid:
0xd79fc80e7b787802602f3317b7fe67765c14a7d40c3e0dcb266e63657f881396
s2 = 0x7724cedeb923f374bef4e05c97426a918123cc4fec7b07903839f12517e1b3c8
z2 = 0x350f3ee8007d817fbd7349c477507f923c4682b3e69bd1df5fbb93b39beb1e04
# txid:
0x061bf0b4b5fdb64ac475795e9bc5a3978f985919ce6747ce2cfbbcaccaf51009
s1 = 0x2bbd9c2a6285c2b43e728b17bda36a81653dd5f4612a2e0aefdb48043c5108de
z1 = 0x4f6a8370a435a27724bbc163419042d71b6dcbeb61c060cc6816cda93f57860c
# prime order p
p = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
# based on Fermat's Little Theorem
# works only on prime n

def inverse_mod(a, n):
    return pow(a, n - 2, n)

k=(z1-z2)*inverse_mod(s1-s2,p)%p               #derivekfors1-s2
pk = (s1 * k - z1) * inverse_mod(r, p) % p     # derive private key 
pkNeg=(-s1*(-k%p)-z1)*inverse_mod(r,p)%p       #-k(modp)of s1 - s2 == -s1 + s2, check -s1
log.info('k           = {:x}'.format(k))
log.info('k negation  = {:x}'.format(-k % p))


if pk == pkNeg:  # should not be false
    log.success('private key = {:x}'.format(pk))


k=(z1-z2)*inverse_mod(s1+s2,p)%p #derivekfors1+s2
pk = (s1 * k - z1) * inverse_mod(r, p) % p # derive private key pkNeg=(-s1*(-k%p)-z1)*inverse_mod(r,p)%p #-k(modp)of s1 + s2 == -s1 - s2, double check -s1
log.info('k           = {:x}'.format(k))
log.info('k negation  = {:x}'.format(-k % p))

if pk == pkNeg:  # should not be false
    log.success('private key = {:x}'.format(pk))


from eth_account import Account
acct =Account.from_key("614f5e36cd55ddab0947d1723693fef5456e5bee24738ba90bd33c0c6e68e269")
log.info('account addr {:x}'.format(acct.address))

私钥计算出来后,导入账户,并使用该账户调用合约即可。

有关capture the ether靶场题解(Account)的更多相关文章

  1. ruby-on-rails - Twilio 的未定义方法 `account' - 2

    我正在使用twilio并得到:错误undefinedmethod`account'forTwilio。client=Twilio::REST::Client.new('twilio_sid','twilio_token')#CreateandsendanSMSmessageclient.account.sms.messages.create(from:"+12345678901",to:user.contact,body:"Thanksforsigningup.Toverifyyouraccount,pleasereplyHELLOtothismessage.")

  2. ruby-on-rails - "554 Please activate your Mailgun account. Check your inbox or log in to your control panel to resend the activation email."错误 Ruby on Rails - 2

    我正在使用RubyonRails构建网络应用程序。我正在使用Mailgun作为这个应用程序的邮件程序。当我使用Facebook注册时它工作正常但是当我尝试使用电子邮件和密码注册时,我不断收到此错误“554请激活您的Mailgun帐户。检查您的收件箱或登录到您的控制面板以重新发送激活电子邮件。“我已经在mailgun仪表板中将eamil授权给授权收件人。这是我的代码:Registrations_controller.rbclassRegistrationsControllerconfig/environments/development.rbRails.application.confi

  3. 【算法题解】20. 两数之和 - 2

    这是一道简单题题目来自:https://leetcode.cn/problems/two-sum/题目给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。提示:22nums.length104−109−109nums[i]109−109−109target109只会存在一个有效答案进阶:你可以想出一个时间复杂度小于O(n2)O(n^2)O(n2)的算法吗?示例1:输入:nums=[2,7,11,15],targe

  4. ruby-on-rails - rails : Your user account isn't allowed to install to the system RubyGems - 2

    我正在运行命令bundleinstall在项目文件夹中。在某些项目文件夹中,它会产生错误,而在其他项目文件夹中,它不会产生错误。错误是:Youruseraccountisn'tallowedtoinstalltothesystemRubyGems我知道这可以通过遵循推荐的建议来解决:bundleinstall--pathvendor/bundle我的问题是为什么行为不一致? 最佳答案 在我的例子中,我按照错误消息的建议解决了问题:Youruseraccountisn'tallowedtoinstalltothesystemRubyG

  5. javascript - 调试 AllAuth : social account not logging user in despite connecting successfully - 2

    单击登录表单中的facebook登录按钮会正确显示fb登录弹出窗口,但在输入凭据后弹出窗口关闭并且没有任何反应。在不重新加载页面的情况下再次单击按钮确认fb帐户已连接,因为浏览器控制台打印:FB.login()calledwhenuserisalreadyconnected.然而,用户数据库中没有新条目出现,用户没有被重定向,也没有登录。所以问题似乎出在AllAuth处理事情的方式上。但是在后端的任何地方都没有出现任何调试信息,这使得这有点难以弄清楚。这是allauth设置:LOGIN_REDIRECT_URL='/'LOGOUT_REDIRECT_URL='/'DEFAULT_FRO

  6. javascript - 来自 Braintree 沙箱错误 : PAYPAL_SANDBOX_ACCOUNT_NOT_LINKED 的 PayPal 集成 - 2

    当我尝试从Braintree测试我的PayPal集成时,我遇到了这个错误。这是我的客户端代码(实际上是从官网复制过来的,稍作修改):braintree.client.create({authorization:ClientToken},function(err,clientInstance){if(err){console.error(err);return;}//CreateaPayPalCheckoutcomponent.braintree.paypalCheckout.create({client:clientInstance},function(paypalCheckoutEr

  7. 蓝桥杯第十四届省赛完整题解 C/C++ B组 - 2

    没有测评,不知道对不对,仅仅过样例而已试题A:日期统计本题总分:5分【问题描述】小蓝现在有一个长度为100的数组,数组中的每个元素的值都在0到9的范围之内。数组中的元素从左至右如下所示:5686916124919823647759503875815861830379270588570991944686338516346707827689565614010094809128502533现在他想要从这个数组中寻找一些满足以下条件的子序列:   1.子序列的长度为8;   2.这个子序列可以按照下标顺序组成一个yyyymmdd格式的日期,并且要求这个日期是2023年中的某一天的日期,例如202309

  8. 2023第十四届蓝桥杯C/C++B组省赛题解 - 2

    2023蓝桥C/C++B组省赛文章目录2023蓝桥C/C++B组省赛试题A:日期统计题目描述枚举参考代码试题B:01串的熵题目描述枚举|模拟参考代码试题C:冶炼金属题意描述取交集参考代码试题D:飞机降落题意描述DFS+剪枝,懒得写试题E:接龙数列题意描述DP参考代码试题F:岛屿个数题意描述dfs|连通块参考代码试题G:子串简写题意描述前缀和参考代码试题H:整数删除题意描述双向链表|最小堆参考代码试题I:景区导游题意描述带权LCA参考代码试题J:砍树题意描述树上差分参考代码试题A:日期统计题目描述【问题描述】小蓝现在有一个长度为100的数组,数组中的每个元素的值都在0到9的范围之内。数组中的元素

  9. LeetCode——链表简单题题解 - 2

    83.删除排序链表中的重复元素题目描述给定一个已排序的链表的头head,删除所有重复的元素,使每个元素只出现一次。返回已排序的链表。输入:head=[1,1,2]输出:[1,2]解题思路:用一个指向节点类型的指针保存头结点,用另一个指向节点类型的指针对该链表进行遍历,由于是有序的,当出现不同的值就说明不会再出现跟前面的值相同的节点了,最后循环结束的条件是遍历到最后一个节点的时候,也就是该节点的next指向空的时候,停止循环,返回该保存的头结点,另外,如果传过来的头结点是空,则直接返回空。参考代码:/***Definitionforsingly-linkedlist.*structListNod

  10. CTF综合靶场渗透系列-Billu_b0x - 2

    Billu_b0x文章目录Billu_b0x前言目标运行环境信息收集漏洞挖掘测试首页SQL注入利用文件包含漏洞获取php源码、passwd文件通过得到的mysql密码登录phpmyadmin继续暴破phpmy目录,文件包含phpmyadmin配置文件获取shell登录index首页,并获得cmdshell和反弹shell找一个可写权限目录,写入菜刀马提升权限查看内核、系统版本,寻找提权exp编译、提权后记前言最近新找到的一个靶场,跟vulnhub靶场渗透思路差不多,不过没有设计到内网的渗透,只是单方面的进行渗透提权,获取对方的主机权限,对于打CTF的小伙伴们还是很有帮助的。但我感觉这次的难度好

随机推荐