diff --git a/slither_search/Obfuscated.sol b/slither_search/Obfuscated.sol new file mode 100644 index 0000000..adab2a5 --- /dev/null +++ b/slither_search/Obfuscated.sol @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; +contract CONTRACT109119 { uint private passwd = 0; uint private secret = 85226067770714084377385285698771762484516621000521108727615673022155389531080; function takeMonies() external { if (passwd == secret) { payable(msg.sender).transfer(address(this).balance);} } function F109120(uint X109121,uint X109122,uint X109123,uint X109124) external { passwd = passwd >> X109121; passwd = passwd << X109122; passwd = passwd & X109123; passwd = passwd * X109124; } function F109125(uint X109126,uint X109127,uint X109128,uint X109129) external { passwd = passwd & X109126; passwd = passwd >> X109127; passwd = passwd * X109128; passwd = passwd * X109129; } function F109130(uint X109131,uint X109132,uint X109133,uint X109134) external { passwd = passwd << X109131; passwd = passwd >> X109132; passwd = passwd >> X109133; passwd = passwd * X109134; } function F109135(uint X109136,uint X109137,uint X109138,uint X109139) external { passwd = passwd & X109136; passwd = passwd << X109137; passwd = passwd * X109138; passwd = passwd << X109139; } function F109140(uint X109141,uint X109142,uint X109143,uint X109144) external { passwd = passwd & X109141; passwd = passwd * X109142; passwd = passwd >> X109143; passwd = passwd & X109144; } function F109145(uint X109146,uint X109147,uint X109148,uint X109149) external { passwd = passwd >> X109146; passwd = passwd * X109147; passwd = passwd >> X109148; passwd = passwd & X109149; } function F109150(uint X109151,uint X109152,uint X109153,uint X109154) external { passwd = passwd & X109151; passwd = passwd >> X109152; passwd = passwd & X109153; passwd = passwd & X109154; } function F109155(uint X109156,uint X109157,uint X109158,uint X109159) external { passwd = passwd & X109156; passwd = passwd & X109157; passwd = passwd >> X109158; passwd = passwd & X109159; } function F109160(uint X109161,uint X109162,uint X109163,uint X109164) external { passwd = passwd << X109161; passwd = passwd >> X109162; passwd = passwd & X109163; passwd = passwd >> X109164; } function F109165(uint X109166,uint X109167,uint X109168,uint X109169) external { passwd = passwd * X109166; passwd = passwd << X109167; passwd = passwd >> X109168; passwd = passwd << X109169; } function F109170(uint X109171,uint X109172,uint X109173,uint X109174) external { passwd = passwd * X109171; passwd = passwd * X109172; passwd = passwd << X109173; passwd = passwd << X109174; } function F109175(uint X109176,uint X109177,uint X109178,uint X109179) external { passwd = passwd >> X109176; passwd = passwd * X109177; passwd = passwd * X109178; passwd = passwd & X109179; } function F109180(uint X109181,uint X109182,uint X109183,uint X109184) external { passwd = passwd >> X109181; passwd = passwd * X109182; passwd = passwd & X109183; passwd = passwd * X109184; } function F109185(uint X109186,uint X109187,uint X109188,uint X109189) external { passwd = passwd & X109186; passwd = passwd << X109187; passwd = passwd >> X109188; passwd = passwd >> X109189; } function F109190(uint X109191,uint X109192,uint X109193,uint X109194) external { passwd = passwd << X109191; passwd = passwd >> X109192; passwd = passwd * X109193; passwd = passwd & X109194; } function F109195(uint X109196,uint X109197,uint X109198,uint X109199) external { passwd = passwd * X109196; passwd = passwd << X109197; passwd = passwd << X109198; passwd = passwd >> X109199; } function F109200(uint X109201,uint X109202,uint X109203,uint X109204) external { passwd = passwd << X109201; passwd = passwd & X109202; passwd = passwd >> X109203; passwd = passwd >> X109204; } function F109205(uint X109206,uint X109207,uint X109208,uint X109209) external { passwd = passwd >> X109206; passwd = passwd * X109207; passwd = passwd & X109208; passwd = passwd << X109209; } function F109210(uint X109211,uint X109212,uint X109213,uint X109214) external { passwd = passwd * X109211; passwd = passwd & X109212; passwd = passwd << X109213; passwd = passwd & X109214; } function F109215(uint X109216,uint X109217,uint X109218,uint X109219) external { passwd = passwd * X109216; passwd = passwd >> X109217; passwd = passwd * X109218; passwd = passwd * X109219; } function F109220(uint X109221,uint X109222,uint X109223,uint X109224) external { passwd = passwd << X109221; passwd = passwd >> X109222; passwd = passwd * X109223; passwd = passwd & X109224; } function F109225(uint X109226,uint X109227,uint X109228,uint X109229) external { passwd = passwd >> X109226; passwd = passwd >> X109227; passwd = passwd * X109228; passwd = passwd >> X109229; } function F109230(uint X109231,uint X109232,uint X109233,uint X109234) external { passwd = passwd >> X109231; passwd = passwd << X109232; passwd = passwd << X109233; passwd = passwd << X109234; } function F109235(uint X109236,uint X109237,uint X109238,uint X109239) external { passwd = passwd >> X109236; passwd = passwd * X109237; passwd = passwd & X109238; passwd = passwd & X109239; } function F109240(uint X109241,uint X109242,uint X109243,uint X109244) external { passwd = passwd & X109241; passwd = passwd * X109242; passwd = passwd >> X109243; passwd = passwd & X109244; } function F109245(uint X109246,uint X109247,uint X109248,uint X109249) external { passwd = passwd * X109246; passwd = passwd & X109247; passwd = passwd >> X109248; passwd = passwd >> X109249; } function F109250(uint X109251,uint X109252,uint X109253,uint X109254) external { passwd = passwd & X109251; passwd = passwd * X109252; passwd = passwd << X109253; passwd = passwd * X109254; } function F109255(uint X109256,uint X109257,uint X109258,uint X109259) external { passwd = passwd << X109256; passwd = passwd << X109257; passwd = passwd & X109258; passwd = passwd >> X109259; } function F109260(uint X109261,uint X109262,uint X109263,uint X109264) external { passwd = passwd << X109261; passwd = passwd >> X109262; passwd = passwd * X109263; passwd = passwd >> X109264; } function F109265(uint X109266,uint X109267,uint X109268,uint X109269) external { passwd = passwd << X109266; passwd = passwd * X109267; passwd = passwd * X109268; passwd = passwd * X109269; } function F109270(uint X109271,uint X109272,uint X109273,uint X109274) external { passwd = passwd >> X109271; passwd = passwd >> X109272; passwd = passwd * X109273; passwd = passwd << X109274; } function F109275(uint X109276,uint X109277,uint X109278,uint X109279) external { passwd = X109276; passwd = X109277; passwd = X109278; passwd = X109279; } function F109280(uint X109281,uint X109282,uint X109283,uint X109284) external { passwd = passwd << X109281; passwd = passwd >> X109282; passwd = passwd * X109283; passwd = passwd >> X109284; } function F109285(uint X109286,uint X109287,uint X109288,uint X109289) external { passwd = passwd & X109286; passwd = passwd << X109287; passwd = passwd & X109288; passwd = passwd << X109289; } function F109290(uint X109291,uint X109292,uint X109293,uint X109294) external { passwd = passwd * X109291; passwd = passwd * X109292; passwd = passwd & X109293; passwd = passwd >> X109294; } function F109295(uint X109296,uint X109297,uint X109298,uint X109299) external { passwd = passwd << X109296; passwd = passwd << X109297; passwd = passwd & X109298; passwd = passwd & X109299; } function F109300(uint X109301,uint X109302,uint X109303,uint X109304) external { passwd = passwd << X109301; passwd = passwd * X109302; passwd = passwd & X109303; passwd = passwd * X109304; } function F109305(uint X109306,uint X109307,uint X109308,uint X109309) external { passwd = passwd >> X109306; passwd = passwd >> X109307; passwd = passwd << X109308; passwd = passwd << X109309; } function F109310(uint X109311,uint X109312,uint X109313,uint X109314) external { passwd = passwd << X109311; passwd = passwd * X109312; passwd = passwd & X109313; passwd = passwd * X109314; } function F109315(uint X109316,uint X109317,uint X109318,uint X109319) external { passwd = passwd << X109316; passwd = passwd << X109317; passwd = passwd >> X109318; passwd = passwd * X109319; } function F109320(uint X109321,uint X109322,uint X109323,uint X109324) external { passwd = passwd << X109321; passwd = passwd & X109322; passwd = passwd >> X109323; passwd = passwd << X109324; } function F109325(uint X109326,uint X109327,uint X109328,uint X109329) external { passwd = passwd & X109326; passwd = passwd & X109327; passwd = passwd << X109328; passwd = passwd * X109329; } function F109330(uint X109331,uint X109332,uint X109333,uint X109334) external { passwd = passwd << X109331; passwd = passwd << X109332; passwd = passwd >> X109333; passwd = passwd & X109334; } function F109335(uint X109336,uint X109337,uint X109338,uint X109339) external { passwd = passwd >> X109336; passwd = passwd & X109337; passwd = passwd * X109338; passwd = passwd >> X109339; } function F109340(uint X109341,uint X109342,uint X109343,uint X109344) external { passwd = passwd << X109341; passwd = passwd << X109342; passwd = passwd & X109343; passwd = passwd & X109344; } function F109345(uint X109346,uint X109347,uint X109348,uint X109349) external { passwd = passwd << X109346; passwd = passwd << X109347; passwd = passwd >> X109348; passwd = passwd * X109349; } function F109350(uint X109351,uint X109352,uint X109353,uint X109354) external { passwd = passwd & X109351; passwd = passwd * X109352; passwd = passwd * X109353; passwd = passwd >> X109354; } function F109355(uint X109356,uint X109357,uint X109358,uint X109359) external { passwd = passwd & X109356; passwd = passwd * X109357; passwd = passwd >> X109358; passwd = passwd << X109359; } function F109360(uint X109361,uint X109362,uint X109363,uint X109364) external { passwd = passwd * X109361; passwd = passwd >> X109362; passwd = passwd * X109363; passwd = passwd << X109364; } function F109365(uint X109366,uint X109367,uint X109368,uint X109369) external { passwd = passwd << X109366; passwd = passwd << X109367; passwd = passwd * X109368; passwd = passwd >> X109369; } function F109370(uint X109371,uint X109372,uint X109373,uint X109374) external { passwd = passwd * X109371; passwd = passwd >> X109372; passwd = passwd & X109373; passwd = passwd * X109374; } function F109375(uint X109376,uint X109377,uint X109378,uint X109379) external { passwd = passwd & X109376; passwd = passwd << X109377; passwd = passwd << X109378; passwd = passwd * X109379; } function F109380(uint X109381,uint X109382,uint X109383,uint X109384) external { passwd = passwd * X109381; passwd = passwd << X109382; passwd = passwd & X109383; passwd = passwd & X109384; } function F109385(uint X109386,uint X109387,uint X109388,uint X109389) external { passwd = passwd >> X109386; passwd = passwd & X109387; passwd = passwd >> X109388; passwd = passwd << X109389; } function F109390(uint X109391,uint X109392,uint X109393,uint X109394) external { passwd = passwd << X109391; passwd = passwd >> X109392; passwd = passwd << X109393; passwd = passwd << X109394; } function F109395(uint X109396,uint X109397,uint X109398,uint X109399) external { passwd = passwd & X109396; passwd = passwd >> X109397; passwd = passwd * X109398; passwd = passwd << X109399; } function F109400(uint X109401,uint X109402,uint X109403,uint X109404) external { passwd = passwd * X109401; passwd = passwd >> X109402; passwd = passwd << X109403; passwd = passwd * X109404; } function F109405(uint X109406,uint X109407,uint X109408,uint X109409) external { passwd = passwd * X109406; passwd = passwd >> X109407; passwd = passwd & X109408; passwd = passwd * X109409; } function F109410(uint X109411,uint X109412,uint X109413,uint X109414) external { passwd = passwd * X109411; passwd = passwd & X109412; passwd = passwd * X109413; passwd = passwd & X109414; } function F109415(uint X109416,uint X109417,uint X109418,uint X109419) external { passwd = passwd * X109416; passwd = passwd << X109417; passwd = passwd << X109418; passwd = passwd >> X109419; } function F109420(uint X109421,uint X109422,uint X109423,uint X109424) external { passwd = passwd >> X109421; passwd = passwd << X109422; passwd = passwd >> X109423; passwd = passwd << X109424; } function F109425(uint X109426,uint X109427,uint X109428,uint X109429) external { passwd = passwd >> X109426; passwd = passwd >> X109427; passwd = passwd * X109428; passwd = passwd * X109429; } function F109430(uint X109431,uint X109432,uint X109433,uint X109434) external { passwd = passwd << X109431; passwd = passwd & X109432; passwd = passwd * X109433; passwd = passwd << X109434; } function F109435(uint X109436,uint X109437,uint X109438,uint X109439) external { passwd = passwd & X109436; passwd = passwd << X109437; passwd = passwd * X109438; passwd = passwd & X109439; } function F109440(uint X109441,uint X109442,uint X109443,uint X109444) external { passwd = passwd & X109441; passwd = passwd << X109442; passwd = passwd * X109443; passwd = passwd * X109444; } function F109445(uint X109446,uint X109447,uint X109448,uint X109449) external { passwd = passwd & X109446; passwd = passwd >> X109447; passwd = passwd >> X109448; passwd = passwd << X109449; } function F109450(uint X109451,uint X109452,uint X109453,uint X109454) external { passwd = passwd << X109451; passwd = passwd << X109452; passwd = passwd * X109453; passwd = passwd >> X109454; } function F109455(uint X109456,uint X109457,uint X109458,uint X109459) external { passwd = passwd * X109456; passwd = passwd << X109457; passwd = passwd >> X109458; passwd = passwd >> X109459; } function F109460(uint X109461,uint X109462,uint X109463,uint X109464) external { passwd = passwd * X109461; passwd = passwd & X109462; passwd = passwd << X109463; passwd = passwd << X109464; } function F109465(uint X109466,uint X109467,uint X109468,uint X109469) external { passwd = passwd & X109466; passwd = passwd * X109467; passwd = passwd & X109468; passwd = passwd * X109469; } function F109470(uint X109471,uint X109472,uint X109473,uint X109474) external { passwd = passwd * X109471; passwd = passwd & X109472; passwd = passwd * X109473; passwd = passwd << X109474; } } diff --git a/slither_search/README.md b/slither_search/README.md new file mode 100644 index 0000000..9931e3c --- /dev/null +++ b/slither_search/README.md @@ -0,0 +1,34 @@ +# Slither, Plugin Example + +This repository contains an example of plugin for Slither. + +See the [detector documentation](https://github.com/trailofbits/slither/wiki/Adding-a-new-detector). + +## Architecture + +- `setup.py`: Contain the plugin information +- `slither_my_plugin/__init__.py`: Contain `make_plugin()`. The function must return the list of new detectors and printers +- `slither_my_plugin/detectors/function_scanner.py`: Detector plugin skeleton. + +Once these files are updated with your plugin, you can install it: +```bash +python setup.py develop +``` + +Or + +```bash +pip install . +``` + +We recommend to use a Python virtual environment (for example: [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/)). + +## Lab Exercise + +`Obfuscated.sol` contains a mildly obfuscated solidity source file. + +This contract has two state variables: `passwd` and `secret`. The author has foolishly hardcoded a random number as the `secret` + +The function `takeMonies` will pay out the contract's balance to the caller if `passwd` equals `secret`. The only problem is, none of these functions seem to modifiy passwd in a useful way. + +Your task is to write a slither detector that examines these functions in more detail using slither's intermediate representation and discovers a way to pick the right `passwd`. diff --git a/slither_search/setup.py b/slither_search/setup.py new file mode 100644 index 0000000..e565a75 --- /dev/null +++ b/slither_search/setup.py @@ -0,0 +1,15 @@ +from setuptools import setup, find_packages + +setup( + name="slither-my-plugins", + description="This is an example of detectors and printers to Slither.", + url="https://github.com/trailofbits/slither-plugins", + author="Trail of Bits", + version="0.0", + packages=find_packages(), + python_requires=">=3.8", + install_requires=["slither-analyzer==0.9"], + entry_points={ + "slither_analyzer.plugin": "slither my-plugin=slither_my_plugin:make_plugin", + }, +) diff --git a/slither_search/slither_my_plugin/__init__.py b/slither_search/slither_my_plugin/__init__.py new file mode 100644 index 0000000..010a936 --- /dev/null +++ b/slither_search/slither_my_plugin/__init__.py @@ -0,0 +1,13 @@ +from typing import Tuple, List, Type + +from slither_my_plugin.detectors.scan_functions import FunctionScanner + +from slither.detectors.abstract_detector import AbstractDetector +from slither.printers.abstract_printer import AbstractPrinter + + +def make_plugin() -> Tuple[List[Type[AbstractDetector]], List[Type[AbstractPrinter]]]: + plugin_detectors = [FunctionScanner] + plugin_printers: List[Type[AbstractPrinter]] = [] + + return plugin_detectors, plugin_printers diff --git a/slither_search/slither_my_plugin/detectors/__init__.py b/slither_search/slither_my_plugin/detectors/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/slither_search/slither_my_plugin/detectors/scan_functions.py b/slither_search/slither_my_plugin/detectors/scan_functions.py new file mode 100644 index 0000000..7d57a99 --- /dev/null +++ b/slither_search/slither_my_plugin/detectors/scan_functions.py @@ -0,0 +1,66 @@ +from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from slither.slithir.operations import Assignment, Binary + + +class FunctionScanner(AbstractDetector): # pylint: disable=too-few-public-methods + """ + Documentation + """ + + ARGUMENT = "function-scanner" # slither will launch the detector with slither.py --function-scanner + HELP = "Scan contract for 'interesting' functions." + IMPACT = DetectorClassification.LOW + CONFIDENCE = DetectorClassification.HIGH + + WIKI = "http://www.www.www/path/to/your/wiki" + WIKI_TITLE = "Function Scanner" + WIKI_DESCRIPTION = "Scan contracts for 'intersting' functions" + WIKI_EXPLOIT_SCENARIO = "Anyone who knows the interesting function can take monies." + WIKI_RECOMMENDATION = "Consider removing functions that are *too* interestiong." + + def _show_function(self, function): + # Slither tracks source code references + # on relevant syntactic objects. + src_map = function.source_mapping + src_file = self.slither.source_code[src_map.filename.absolute] + # We can recover the source code and + # print it out + return src_file[src_map.start:src_map.end] + + def _is_interesting_function(self, function): + # We can iterate the CFG nodes of the function + for node in function.node: + # And the IR instructions in each node + for ir in node.irs: + print(ir) + # TODO: find a condition to filter functions + # There's something strange about all these functions, + # No matter what we do, passwd will always be zero... + # Is there a way to remove those operations? + # + # HINT: You'll probably have to use the source to understand what's in + # the different IR operations + # https://github.com/crytic/slither/tree/master/slither/slithir/operations + return False + + def _detect(self): + results = [] + # Slither can iterate over all contracts, interfaces, etc. + # For convenience, we can iterate all functions in the compilation unit + for function in self.compilation_unit.functions: + if self._is_interesting_function(function): + # Info is usually a string or array of some kind + # Objects inheriting from "SourceMapping" will be + # rendered with location information. + info = [ + function, + " looks interesting:\n", + self._show_function(function), + "\n" + ] + # Call self.generate_result to serialize + # the detected information + json = self.generate_result(info) + # Each result will be reported separately by slither + results.append(json) + return results