Giter Site home page Giter Site logo

ethersplay's Introduction

ethersplay

Binary Ninja plugin which enables an EVM disassembler and related analysis tools.

Example

Installation

Ethersplay only supports Python >= 3.6.

Ensure that your Binary Ninja's Python library is set to Python 3.6+. You can change the ScriptingProvider in the Advanced Settings.

Plugin Manager Installation

If you install the plugin via the Binary Ninja Plugin Manager, dependency installation should be automatic.

Manual Installation

Install the dependencies:

$ pip install -r requirements.txt

Create a symbolic link to the Binary Ninja plugin folder. E.g., in macOS

cd ~/Library/Application\ Support/Binary\ Ninja/plugins
ln -s <your_download_location>/ethersplay/ethersplay .

Ubuntu:

cd ~/.binaryninja/plugins
ln -s <your_download_location>/ethersplay/ethersplay .

How to Use

Ethersplay takes as input the evm bytecode in raw binary format.

To have the bytecode of a solidity file, use solc:

  • solc --bin-runtime file.sol: to print the bytecode of the runtime part of the contract (for most of the cases).
  • solc --bin file.sol: to print the initialisation bytecode of the contract (constructor),

Example using test.sol with following contents:

contract Test {
    uint256 value;
    function Test() {
        value = 5;
    }
    function set_value(uint256 v) {
        value = v;
    }
    function() payable {}
}

Run solidity to compile: solc --bin-runtime test.sol

solc prints the bytecode to stdout in the format below:

======= test.sol:Test =======
Binary of the runtime part:
60606040523615603d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063b0f2b72a146041575b5b5b005b3415604b57600080fd5b605f60048080359060200190919050506061565b005b806000819055505b505600a165627a7a72305820c177a64bf54a26574918ddc2201f7ab2dd8619d6c3ee87ce9aaa1eb0e0b1d4650029

Copy the ascii hex string, and then create a new file in Binary Ninja. Right-click and select Paste From -> Raw Hex. The output should look identical to the earlier example image. Save this file as test.evm and close it. Alternatively, paste the ascii hex string into a new text file, and run the utils/convert_bytecode.py on that file.

test.evm can now be loaded into Binary Ninja.

Note: The file must end in .evm to be recognized as an EVM bytecode binary file.

Plugins

Render Flowgraphs

Generates a clean control flow graph of all functions.

Before:

before

After:

!after

Manticore coverage

Colors the basic blocks explored through Manticore (using the visited.txt or *.trace files).

ethersplay's People

Contributors

ansermino avatar computerality avatar dependabot[bot] avatar dguido avatar disconnect3d avatar ekilmer avatar itszn avatar joshwatson avatar montyly avatar offlinemark avatar psifertex avatar sneakerhax avatar t4sk avatar tcode2k16 avatar tlatkdgus1 avatar withzombies avatar woodruffw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ethersplay's Issues

Generate Flowgraphs

Use the new FlowGraph API in Binary Ninja to generate graphs for each function. We can use this to also generate graphs for internal functions.

runtime bytecode ignored

It is a common use case to analyze a file that contains contract init and runtime (rt) bytecode. If you give this to ethersplay, it only analyzes the init bytecode, which is not very useful. if it is possible, ethersplay should detect runtime bytecode and disassemble it also.

at the very least, ethersplay should allow the use to click "create function here" at the location of the rt bytecode. currently, this seems broken.

here is an example bytecode file with both init and rt code

x.bytecode.zip

How do I hide variable names?

On the screenshot there are no var names:

screen

but on my machine it looks like this:

screen shot 2018-05-18 at 03 15 07

How do I disable those {var_...} thingies?

Duplicated contract code when opened in ethersplay

when you open this file, it seems there is an extra copy of the dispatch stub and the fallback function appended to the end.

[I] mark forge ~/c/e/s/tmp ❯ xxd fallback-empty-func.evm
00000000: 4556 4d60 8060 4052 6004 3610 603f 5760  EVM`.`@R`.6.`?W`
00000010: 0035 7c01 0000 0000 0000 0000 0000 0000  .5|.............
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 9004 63ff ffff ff16 8063 0c55 699c 1460  ..c......c.Ui..`
00000040: 4d57 5b34 8015 604a 5760 0080 fd5b 5000  MW[4..`JW`...[P.
00000050: 5b34 8015 6058 5760 0080 fd5b 5060 5f60  [4..`XW`...[P`_`
00000060: 6156 5b00 5b56 00a1 6562 7a7a 7230 5820  aV[.[V..ebzzr0X
00000070: 210d ee2f 7e07 8f5b e8b2 aaf3 a368 8021  !../~..[.....h.!
00000080: 4511 6015 dd72 47bd 89a0 ee26 f6d8 33ef  E.`..rG....&..3.
00000090: 0029 0a                                  .).

fallback-empty-func.evm.zip

image

Indefinite Loop Analysis

With a number of contracts, I've encountered cases where Ethersplay gets stuck attempting to explore loops. In such cases, it may fail to explore the rest of the contract and BN will perpetually spit out an 'analysis' status message.

Sample contract: poc.zip

To repro, simply open poc.bytecode with BinaryNinja + Ethersplay.

The analysis for the provided PoC gets stuck within dispatch. Granted, the dispatch for this contract is a bit of a monstrosity.

I can grab a few more contracts demonstrating similar behavior if needed.

Move utils into the actual plugin directory

printSourceCode.py makes the assumption that the user has symlinked ethersplay in the Binary Ninja plugin directory, then does the following:

path_to_line_number = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                   os.sep.join(["..", "utils"]))
sys.path.append(path_to_line_number)

from solidityLineNumber import SolidityLineNumber

Symlinking correctly on Windows is not completely intuitive, so this is likely not done on that platform, which then breaks this plugin. All files needed for plugin functionality should be moved into the directory that is placed in the plugins directory so that it will always work as expected.

Numerous tracebacks on Master

Today I pulled master, and selected a contract at random from recent transactions on etherescan.io: https://etherscan.io/address/0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208

As ethersplay begins exploring the contract, it spews hundreds of tracebacks:

Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 314, in 'calling callback function'
  File "C:\tools\disassemblers\BinaryNinja\plugins\..\python\binaryninja\architecture.py", line 521, in _get_instruction_text
    info = self.get_instruction_text(buf.raw, addr)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\evm.py", line 290, in get_instruction_text
    instruction = EVMAsm.disassemble_one(data, addr)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\evmasm.py", line 561, in disassemble_one
    opcode = ord(next(bytecode))
StopIteration
Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 314, in 'calling callback function'
  File "C:\tools\disassemblers\BinaryNinja\plugins\..\python\binaryninja\architecture.py", line 552, in _free_instruction_text
    raise ValueError("freeing token list that wasn't allocated")
ValueError: freeing token list that wasn't allocated
Traceback (most recent call last):
  File "C:\tools\disassemblers\BinaryNinja\plugins\..\python\binaryninja\binaryview.py", line 234, in _function_updated
    self.notify.function_updated(self.view, function.Function(self.view, core.BNNewFunctionReference(func)))
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\analysis.py", line 234, in function_updated
    function_dynamic_jump_start(view, func)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 821, in function_dynamic_jump_start
    sv.explore()
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 805, in explore
    elems = [filter_vals(x.get_vals()) for x in elems]
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 798, in filter_vals
    if None in vals:
TypeError: argument of type 'NoneType' is not iterable

This was the first contract I pulled :-x

POC: 0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208.zip

Jumpdests in immediates should be treated as invalid

EVM does not allow jumping to jumpdests that happen to be in immediate values (ie pushed values).

For example something like this contract.

pragma solidity ^0.4.0;
contract Jump {
    function test() public {
        assembly {
            let b := add(0x5b604160425500,1)
            jump(0x5a)
        }
    }
}

When calling test(), EVM will always throw when it tries to execute the jump. However ethersplay shows it falling though to the embedded code:

Geth makes a bitmap of all valid jumpdests to determine if any jumpdests are in immediate values.

Code in this form probably won't be generated naturally, but it could be used for obfuscation. By jumping into a function hash in the dispatch (like my recent challenge did), I was able to confuse ethersplay into producing a loop and being unable to identify the dispatched functions:

(I use a function aekS() which hashes to 0x5b61291c, jumpdest; push2 XX)

Multiple swarm hashes can result in endless loop

Currently there is a possible infinite loop when multiple swarm hashes are in the bytecode. I think the Problem is in evm.py#L373

Currently the line is:

offset = data[offset+1:].find(b'\xa1ebzzr0')

However, here find will return the offset in the string slice and not in the original data, so it is possible for the next offset to be smaller than the previous offset.

Replacing that line with

offset = data.find(b'\xa1ebzzr0', offset + 1)

seems to fix the problem.

add to the plugin manager?

If ya'll are interested, it wouldn't take much to add ethersplay to the plugin manager which would be nice for discoverability. In short, update the plugin.json, and create the appropriately versioned release.

(You might find https://github.com/vector35/release_helper helpful, as incrementing the version number in the plugin and creating the tag/release can be mildly tedious otherwise).

Other than that, just let me know when the changes are done and I'll add it to the plugin manager. We'll automatically keep it updated to track the releases, no future notification necessary.

Cannot load test.evm

I tried to load test.evm from examples and I get this error

Disallowing the creation of segment @ 0x97 with dataOffset @ 0x97 and length 0x97 which is larger than the parent's length
Added EVM entry point at 0x0
Traceback (most recent call last):
  File "/home/t4sk/bkp/dev/binaryninja/plugins/../python/binaryninja/binaryview.py", line 2023, in _init
    return self.init()
  File "/home/t4sk/.binaryninja/plugins/ethersplay/evm.py", line 443, in init
    scope=SettingsScope.SettingsContextScope
  File "/usr/lib64/python3.7/enum.py", line 349, in __getattr__
    raise AttributeError(name) from None
AttributeError: SettingsContextScope
BinaryView of type 'EVM' failed to initialize!

Has anyone else encountered this issue?

Manticore coverage fails

I tried to use ethersplay with manticore and I could not make it work.

  • I downloaded the latest version of Binary Ninja, Ethersplay and manticore.
  • I used the example contract you have in the Readme (Test.sol),
  • I compiled the contract, got the runtime-bin, saved it as test.evm (adding 0x as prefix)
  • I open the file in Binary Ninja, the correct graph is displayed, everyone is happy.
  • I run manticore Test.sol and a new directory is created. Looks fine.
  • I right click->EVM Manticore Highlight, and I open the visited.txt file as stated in the Readme.
  • Nothing happens, an error is shown in the log:
Traceback (most recent call last):
  File "/home/test/binary/binaryninja/plugins/../python/binaryninja/plugin.py", line 88, in _default_action
    action(view_obj)
  File "/home/test/.binaryninja/plugins/ethersplay/coverage.py", line 37, in function_coverage_start
    colorer.color(visited)
  File "/home/test/.binaryninja/plugins/ethersplay/coverage.py", line 20, in color
    self.color_at(int(addr, 16))
  File "/home/test/.binaryninja/plugins/ethersplay/coverage.py", line 29, in color_at
    func.set_instr_highlight(addr, blue)
AttributeError: 'Function' object has no attribute 'set_instr_highlight'

Investigate re-enabling LLIL

A lot of instructions were already implemented but all disabled before release last year.

Current blockers:

  • LLIL doesn't really support multiple address spaces (need at least 3: code, memory, and storage. can fake caller/blockchain data)
  • GAS needs accurate gas modeling, or we could just return a constant
  • Missing some instructions, need to make a list

Ethersplay does not restore analysis / CFG / exploration from saved BNDB

After correctly loading and analyzing an evm bytecode file with BinaryNinja + Ethersplay, the plugin doesn't save its exploration results/analysis to the BNDB when saved to disk. This makes it difficult to persist reversing notes or research for larger contracts spanning multiple sessions.

To repro, simply open any valid bytecode file with BinaryNinja + Ethersplay, let the analysis complete, and save the resulting BNDB to disk. When reopening the saved BNDB from disk, you will find that no exploration data, function definitions (etc...) have been saved to disk.

Python plugin 'ethersplay' could not be loaded

System: Windows 10
I try to install ethersplay in Plugin Manager and manual way, but neither works. The error information as follow:

Traceback (most recent call last):
  File "D:\BinaryNinja\BinaryNinja\plugins\python\ethersplay\__init__.py", line 4, in <module>
    from .evm import EVM, EVMView
  File "D:\BinaryNinja\BinaryNinja\plugins\python\ethersplay\evm.py", line 9, in <module>
    from interval3 import Interval, IntervalSet
ModuleNotFoundError: No module named 'interval3'
Python plugin 'ethersplay' could not be loaded
Unable to find plugin crytic_ethersplay

And the interval3 has been installed.

C:\Users\xx>pip install interval3
Requirement already satisfied: interval3 in d:\anaconda\lib\site-packages (2.0.0)

Python version is 3.8.3.

C:\Users\xx>python --version
Python 3.8.3

I am a novice, please advise. Thanks a lot.

Support hex encoded for usability

Basically every evm bytecode producing tool gives the output as ascii encoded hex. The loader should detect if all of the bytes are within hex-ascii range and then .decode('hex') it for the user.

TypeError: argument of type 'NoneType' is not iterable

From etherscan:

https://etherscan.io/address/0xe2c122847767effbb3f306724cded7e93a9dd9b9
https://etherscan.io/address/0x3ab4a46beae2a0b025eeed54db05819814ff287a

EVM/Ethersplay form: pocs.zip

Both these contracts will yield the following callstacks:

Traceback (most recent call last):
  File "C:\tools\disassemblers\BinaryNinja\plugins\..\python\binaryninja\binaryview.py", line 234, in _function_updated
    self.notify.function_updated(self.view, function.Function(self.view, core.BNNewFunctionReference(func)))
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\analysis.py", line 234, in function_updated
    function_dynamic_jump_start(view, func)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 821, in function_dynamic_jump_start
    sv.explore()
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 805, in explore
    elems = [filter_vals(x.get_vals()) for x in elems]
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 798, in filter_vals
    if None in vals:
TypeError: argument of type 'NoneType' is not iterable

IndexError @ last_jump = stack[-1]

I've experienced this crash in a handful of contracts. As a result, Ethersplay fails to explore the remainder of the contract, leaving much of it undefined.

Sample contract: poc.zip

To repro, simply open poc.bytecode with BinaryNinja + Ethersplay.

Traceback (most recent call last):
  File "C:\tools\disassemblers\BinaryNinja\plugins\lib\threading.py", line 810, in __bootstrap_inner
    self.run()
  File "C:\tools\disassemblers\BinaryNinja\plugins\..\python\binaryninja\plugin.py", line 420, in run
    self.task.run()
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\evm.py", line 390, in run
    run_initial_analysis(self.bv)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\evm.py", line 414, in run_initial_analysis
    function_dynamic_jump_start(view, f)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 285, in function_dynamic_jump_start
    sv.explore(func.basic_blocks[0])
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 272, in explore
    self._transfer_func(bb, [], [])
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 230, in _transfer_func
    self._transfer_func(son, bb_saw, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 223, in _transfer_func
    (stack, last_jump) = self._update_stack(bb, stack)
  File "C:\Users\user\AppData\Roaming\Binary Ninja\plugins\ethersplay\stack_value_analysis.py", line 202, in _update_stack
    last_jump = stack[-1]
IndexError: list index out of range

Function names are not recovered from bytecode for solidity 0.5.4

As in issue title I could not recover the function names of smart contracts written in Solidity 0.5.4
First I tried with my own complex smart contracts, but in all cases only one 'function' - 0x40 was recognised even if smart contract had multiple functions.

I went for a simpler contract

contract SimpleStore {
  function set(uint _value) public {
    value = _value;
  }

  function get() public view returns (uint) {
    return value;
  }
  uint value;
}

Bytecode:

608060405234801561001057600080fd5b5060da8061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610604f576000357c01000000000000000000000000000000000000000000000000000000009004806360fe47b11460545780636d4ce63c14607f575b600080fd5b607d60048036036020811015606857600080fd5b8101908080359060200190929190505050609b565b005b608560a5565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea165627a7a72305820f8a3447634c2d8fdcd7d04231ce39c3b2399b50b0f60889ca4c53d57fb0cf2b40029

And the result was the same - functions set and get were not recognised.

Screenshot 2019-03-15 at 14 58 44
Screenshot 2019-03-15 at 14 58 36

I'm operating on OSX version of binary ninja.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.