|
|
|
@ -14,50 +14,6 @@ For kill-able contracts, also check whether it is possible to direct the contrac |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _analyze_state(state): |
|
|
|
|
log.info("Suicide module: Analyzing suicide instruction") |
|
|
|
|
node = state.node |
|
|
|
|
instruction = state.get_current_instruction() |
|
|
|
|
to = state.mstate.stack[-1] |
|
|
|
|
|
|
|
|
|
log.debug("[SUICIDE] SUICIDE in function " + node.function_name) |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
try: |
|
|
|
|
transaction_sequence = solver.get_transaction_sequence( |
|
|
|
|
state, |
|
|
|
|
node.constraints + [to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF], |
|
|
|
|
) |
|
|
|
|
description = "Anyone can kill this contract and withdraw its balance to their own account." |
|
|
|
|
except UnsatError: |
|
|
|
|
transaction_sequence = solver.get_transaction_sequence( |
|
|
|
|
state, node.constraints |
|
|
|
|
) |
|
|
|
|
description = ( |
|
|
|
|
"The contract can be killed by anyone. Don't accidentally kill it." |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
debug = str(transaction_sequence) |
|
|
|
|
|
|
|
|
|
issue = Issue( |
|
|
|
|
contract=node.contract_name, |
|
|
|
|
function_name=node.function_name, |
|
|
|
|
address=instruction["address"], |
|
|
|
|
swc_id=UNPROTECTED_SELFDESTRUCT, |
|
|
|
|
bytecode=state.environment.code.bytecode, |
|
|
|
|
title="Unchecked SUICIDE", |
|
|
|
|
_type="Warning", |
|
|
|
|
description=description, |
|
|
|
|
debug=debug, |
|
|
|
|
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used), |
|
|
|
|
) |
|
|
|
|
return [issue] |
|
|
|
|
except UnsatError: |
|
|
|
|
log.info("[UNCHECKED_SUICIDE] no model found") |
|
|
|
|
|
|
|
|
|
return [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SuicideModule(DetectionModule): |
|
|
|
|
"""This module checks if the contact can be 'accidentally' killed by |
|
|
|
|
anyone.""" |
|
|
|
@ -70,6 +26,15 @@ class SuicideModule(DetectionModule): |
|
|
|
|
entrypoint="callback", |
|
|
|
|
pre_hooks=["SUICIDE"], |
|
|
|
|
) |
|
|
|
|
self._cache_address = {} |
|
|
|
|
|
|
|
|
|
def reset_module(self): |
|
|
|
|
""" |
|
|
|
|
Resets the module |
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
super().reset_module() |
|
|
|
|
self._cache_address = {} |
|
|
|
|
|
|
|
|
|
def execute(self, state: GlobalState): |
|
|
|
|
""" |
|
|
|
@ -77,8 +42,55 @@ class SuicideModule(DetectionModule): |
|
|
|
|
:param state: |
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
self._issues.extend(_analyze_state(state)) |
|
|
|
|
self._issues.extend(self._analyze_state(state)) |
|
|
|
|
return self.issues |
|
|
|
|
|
|
|
|
|
def _analyze_state(self, state): |
|
|
|
|
log.info("Suicide module: Analyzing suicide instruction") |
|
|
|
|
node = state.node |
|
|
|
|
instruction = state.get_current_instruction() |
|
|
|
|
if self._cache_address.get(instruction["address"], False): |
|
|
|
|
return [] |
|
|
|
|
to = state.mstate.stack[-1] |
|
|
|
|
|
|
|
|
|
log.debug("[SUICIDE] SUICIDE in function " + node.function_name) |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
try: |
|
|
|
|
transaction_sequence = solver.get_transaction_sequence( |
|
|
|
|
state, |
|
|
|
|
node.constraints |
|
|
|
|
+ [to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF], |
|
|
|
|
) |
|
|
|
|
description = "Anyone can kill this contract and withdraw its balance to their own account." |
|
|
|
|
except UnsatError: |
|
|
|
|
transaction_sequence = solver.get_transaction_sequence( |
|
|
|
|
state, node.constraints |
|
|
|
|
) |
|
|
|
|
description = ( |
|
|
|
|
"The contract can be killed by anyone. Don't accidentally kill it." |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
debug = str(transaction_sequence) |
|
|
|
|
|
|
|
|
|
self._cache_address[instruction["address"]] = True |
|
|
|
|
issue = Issue( |
|
|
|
|
contract=node.contract_name, |
|
|
|
|
function_name=node.function_name, |
|
|
|
|
address=instruction["address"], |
|
|
|
|
swc_id=UNPROTECTED_SELFDESTRUCT, |
|
|
|
|
bytecode=state.environment.code.bytecode, |
|
|
|
|
title="Unchecked SUICIDE", |
|
|
|
|
_type="Warning", |
|
|
|
|
description=description, |
|
|
|
|
debug=debug, |
|
|
|
|
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used), |
|
|
|
|
) |
|
|
|
|
return [issue] |
|
|
|
|
except UnsatError: |
|
|
|
|
log.info("[UNCHECKED_SUICIDE] no model found") |
|
|
|
|
|
|
|
|
|
return [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detector = SuicideModule() |
|
|
|
|