Coder Social home page Coder Social logo

rdbo / libmem Goto Github PK

View Code? Open in Web Editor NEW
669.0 12.0 82.0 2.15 MB

Advanced Game Hacking Library for C/C++, Rust and Python (Windows/Linux/FreeBSD) (Process/Memory Hacking) (Hooking/Detouring) (Cross Platform) (x86/x64/ARM/ARM64) (DLL/SO Injection) (Internal/External) (Assembler/Disassembler)

License: GNU Affero General Public License v3.0

C 67.45% C++ 0.49% CMake 4.38% Python 8.05% Shell 2.62% Rust 16.39% Dockerfile 0.39% Makefile 0.05% Lua 0.17%
memory c code-injection syscall process c-plus-plus python function-call hook detour-hook

libmem's Introduction

libmem-logo

Advanced Game Hacking Library (C/C++/Rust/Python) (Windows/Linux/FreeBSD)

Made by rdbo

Discord Server

https://discord.com/invite/Qw8jsPD99X

License

This project is licensed under the GNU AGPLv3.0 (no later versions)

Read LICENSE for more information

NOTE: Submodules and external dependencies might have their own licenses! Check for other LICENSE files as well.

Features

  • Cross Platform (Windows/Linux/FreeBSD)
  • Cross Architecture (x86/x64/ARM/ARM64)

libmem can:

  • Find Processes
  • Find Modules
  • Find Symbols
  • Read/Write/Set Memory
  • Allocate/Protect Memory
  • Scan Memory by Pattern/Signature
  • Resolve pointer scans/pointer maps
  • Hook/Unhook Functions
  • Assemble/Dissassemble Code (JIT)
  • Do VMT Hooking/Unhooking
  • Load/Unload Modules
  • Get Page Information
  • Enumerate Process Threads

And much more!

Examples

For the API manual, access the documentation

For more examples, access the examples directory

C/C++

#include <libmem/libmem.h>

int main()
{
	lm_module_t mod;
	lm_address_t main_sym;

	LM_FindModule("mygamemodule.so", &mod);
	main_sym = LM_FindSymbolAddress(&mod, "main");
	printf("[*] Module Name: %s\n", mod.name);
	printf("[*] Module Path: %s\n", mod.path);
	printf("[*] Module Base: %p\n", mod.base);
	printf("[*] Module Size: %p\n", mod.size);
	printf("[*] Module End:  %p\n", mod.end);
	printf("[*] Main Addr:   %p\n"), main_sym);

	return 0;
}

Rust

use libmem::*;

fn some_function() {
    // ...
}

fn hk_some_function() {
    // ...
}

unsafe fn test() {
    // reading/writing memory
    let number : i32 = 0;
    let number_addr = &number as *const i32 as lm_address_t;
    let value : i32 = 1337;
    LM_WriteMemory(number_addr, &value).unwrap(); // write 1337 to number
    let read_number : i32 = LM_ReadMemory(number_addr).unwrap();
    println!("[*] Number Value: {}", read_number); // it will show 1337

    // hooking/detouring functions
    let func_addr = some_function as *const () as lm_address_t;
    let hk_addr = hk_some_function as *const () as lm_address_t;
    println!("[*] Hooking 'some_function'");
    println!("[*] Original Address: {:#x}", func_addr);

    let trampoline = LM_HookCode(func_addr, hk_addr).unwrap();
    println!("[*] Trampoline: {:#x?}", trampoline);

    some_function(); // this will call 'hk_some_function'

    // restore the original code from 'some_function'
    LM_UnhookCode(some_function_addr, trampoline).unwrap();

    println!("[*] Unhooked 'some_function'");
    some_function(); // call 'some_function' to see if it has been unhooked
}

fn main() {
    unsafe {
        test();
    }
}

Python

from libmem import *

# Assemble/Disassemble code
print("[*] Assembly")
inst = LM_Assemble("mov eax, ebx")
print(f"{code} : {inst.bytes}")

print("[*] Disassembly:")
inst = LM_Disassemble(bytearray(b"\x55"))
print(f"{inst.bytes} : {inst.mnemonic} {inst.op_str}")

Unnoficial Bindings

These bindings are done by the community/third-parties and are not affiliated with the libmem project or its author.

Their code can have their own licenses as well, diverging from libmem's.

CMake Usage (without installing)

Add the following commands to your CMakeLists.txt.

They will fetch libmem-config.cmake from the root of this repository, which will download libmem binaries for your system and include libmem in your CMake project.

include(FetchContent)

# Download and set up libmem
FetchContent_Declare(libmem-config URL "https://raw.githubusercontent.com/rdbo/libmem/config-v1/libmem-config.cmake" DOWNLOAD_NO_EXTRACT TRUE)
FetchContent_MakeAvailable(libmem-config)
set(CMAKE_PREFIX_PATH "${libmem-config_SOURCE_DIR}" "${CMAKE_PREFIX_PATH}")
set(LIBMEM_DOWNLOAD_VERSION "4.4.0")

# Find libmem package
find_package(libmem CONFIG REQUIRED)

Use the following to link against libmem (NOTE: it might be necessary to link against other dependencies - go to the Dependencies section for more information):

# Link against libmem
target_link_libraries(<YOUR_TARGET_NAME> PRIVATE libmem::libmem)

Installing

Windows

Note: If you download a binary version of libmem in the GitHub releases, you only need to install the Windows SDK. Building is not necessary, just add libmem/include to your project's include directories and link it against the binary you downloaded.

  1. Install the Windows SDK: Windows 7 - Windows 10/11

  2. Install Python 3 (Check the option to add Python to PATH) (Use Python 3.8.9 for Windows 7)

  3. Install Visual Studio 2022 or newer (with C++ support and CMake) (older versions might work, but they were not tested). NOTE: You can install only the Visual Studio Build Tools if you don't want the whole IDE.

  4. Install Git Bash

  5. Run a Visual Studio Developer Command Prompt (or x64 Native Tools Command Prompt for VS 2022 for 64 bits) as Administrator

  6. Run the following command to append libmem's destination directory to your %PATH% user variable (WARNING - watch for your %PATH% size limit!):

     setx PATH "%PATH%;%ProgramFiles%\libmem\include;%ProgramFiles%\libmem\lib"
    
  7. Continue reading at Build and Install

Linux

Note: The following commands are for Debian/Ubuntu based distributions. Make sure to find the appropriate commands for your Linux distribution.

  1. Open a terminal

  2. Install GCC, G++, Git, CMake, Make, Python 3, and the Linux headers:

     sudo apt install gcc g++ git cmake make python3 linux-headers
    
  3. Continue reading at Build and Install

FreeBSD

  1. Add a mountpoint for the procfs filesystem in your /etc/fstab by appending the following line:

     proc		/proc		procfs	rw	0	0
    
  2. Manually mount the procfs. This will only be necessary if you don't reboot. If you reboot, it will be automatically mounted because of the line at /etc/fstab. Run the following command (as root):

     mount -t procfs proc /proc
    
  3. Install Git, CMake and Python3 (run as root) (clang, clang++ and make should already be installed):

     pkg install git cmake python3
    
  4. Continue reading at Build and Install

Build and Install

Note: Run the following commands on Git Bash (Windows) or a terminal (Linux/FreeBSD).

Clone the repository:

git clone --recursive --depth 1 https://github.com/rdbo/libmem

Generate the CMake cache:

mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release

Compile libmem:

Windows: nmake

Unix-like: make -j 4

Install libmem (run as root or as Administrator):

Windows: nmake install

Unix-like: make install

After installing, follow the the proper Usage section for your programming language

Usage (C/C++)

Add #include <libmem/libmem.h> (C/C++) or #include <libmem/libmem.hpp> (C++) to your source code. Link the generated libmem library against your binary (liblibmem.so for Unix-like or libmem.dll for Windows). For GCC-like compilers: add the flag -llibmem to your compiler and it should link it.

#include <libmem/libmem.h> /* C/C++ */
#include <libmem/libmem.hpp> /* Force C++ */

Usage (Rust)

Add the following line to your Cargo.toml under [dependencies]:

libmem = "4"

Import libmem in your Rust source code:

use libmem::*;

Usage (Python)

Make sure to have Python >= 3.6 active
Either install the libmem package from PyPi by running the following command:

pip install --upgrade libmem

Or build and install it yourself by running the following commands:

cd libmem-py
python configure.py
python setup.py install

Now to import libmem, just do the following in your Python code:

from libmem import *

Dependencies

All:

  • capstone (included in root project)
  • keystone (included in root project)
  • LIEF (included in root project)
  • libstdc++ (used in keystone, LIEF and LLVM)
  • libmath (used in keystone)

Windows:

  • Windows SDK (-luser32, -lpsapi, -lntdll)

Linux/Android:

  • libdl (-ldl)

BSD:

  • libdl (-ldl)
  • libkvm (-lkvm)
  • libprocstat (-lprocstat)
  • libelf (-lelf)

API Overview

LM_EnumProcesses
LM_GetProcess
LM_GetProcessEx
LM_FindProcess
LM_IsProcessAlive
LM_GetSystemBits

LM_EnumThreads
LM_EnumThreadsEx
LM_GetThread
LM_GetThreadEx
LM_GetThreadProcess

LM_EnumModules
LM_EnumModulesEx
LM_FindModule
LM_FindModuleEx
LM_LoadModule
LM_LoadModuleEx
LM_UnloadModule
LM_UnloadModuleEx

LM_EnumSymbols
LM_FindSymbolAddress
LM_DemangleSymbol
LM_FreeDemangleSymbol
LM_EnumSymbolsDemangled
LM_FindSymbolAddressDemangled

LM_EnumPages
LM_EnumPagesEx
LM_GetPage
LM_GetPageEx

LM_ReadMemory
LM_ReadMemoryEx
LM_WriteMemory
LM_WriteMemoryEx
LM_SetMemory
LM_SetMemoryEx
LM_ProtMemory
LM_ProtMemoryEx
LM_AllocMemory
LM_AllocMemoryEx
LM_FreeMemory
LM_FreeMemoryEx
LM_DeepPointer
LM_DeepPointerEx

LM_DataScan
LM_DataScanEx
LM_PatternScan
LM_PatternScanEx
LM_SigScan
LM_SigScanEx

LM_HookCode
LM_HookCodeEx
LM_UnhookCode
LM_UnhookCodeEx

LM_Assemble
LM_AssembleEx
LM_FreeCodeBuffer
LM_Disassemble
LM_DisassembleEx
LM_FreeInstructions
LM_CodeLength
LM_CodeLengthEx

LM_VmtNew
LM_VmtHook
LM_VmtUnhook
LM_VmtGetOriginal
LM_VmtReset
LM_VmtFree

Contributing

Read the file CONTRIBUTING.md in the root directory of this repository

Projects

Made with libmem:

libmem's People

Contributors

alextwothousand avatar clairecharles avatar darrenthebozz avatar hypnootika avatar illegal-instruction-co avatar leadrdrk avatar molotovcherry avatar nathan818fr avatar rdbo 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

libmem's Issues

Change Free/Destroy/Etc parameter to pointer

The "object" that will be freed/destroyed should be passed in as a pointer, and its value should become NULL.
For example, LM_UnhookCode does not take the trampoline as a pointer, but it should, because the trampoline will be freed.

libmem very slow on bsd

Working on it. It's taking a long time to read the /proc/<pid>/map file. I'll try different approaches.

Deprecate v3 API

There's no need to keep the old v3 API on the code, it just adds more mess and trouble to maintain.

TODO: fix libmem

libmem is a project I have work on and off for a very long time. It has had many different versions, one completely different than the other, because the more I got better at programming, the more ideas I had to make it better.
Unfortunately, libmem has become practically unmaintainable, mainly for the following reasons:

  • It is not modular: everything is on libmem.h and libmem.c, including the code for all different platforms and architectures, making it a mess with all the preprocessor directives.
  • It has too many features: libmem should have followed the KISS process (Keep It Simple Stupid), instead of adding too many features, such as multiple different hooking methods, debugger functions, overly-complicated code injection (such as the LM_FunctionCallEx).

So how to fix it?
My plan is to do the following:

  • Modulate libmem: I could do that by separating the OS-specific and Arch-specific code, and rely on better written third-party libraries, such as the addition of the capstone and keystone libraries instead of writing my own assembler/disassembler. I'm not sure yet how am I going to modulate it in practice because everything is so entangled together, but I'm sure there is a way.
  • Remove overkill features: offer only one hooking method per architecture, no debugging functions as they're not the main focus of libmem, etc.
  • Follow a Unix-like directory structure for the project: instead of putting everything under the libmem folder, there should be a include and source folders (like in capstone and keystone, similar to the Unix /usr directory), since the library should be compiled first and then included into your project, and not compiled along with your project.
  • Make it 'installable': At least on Unix-like systems, there should be a way to install the libmem shared library into /usr/local/lib to make it easier for linking the library.
  • Add better documentation: there used to be a documentation, but since the project started changing very often, I deleted the old one. After all of other points are fixed, there should be a very detailed documentation about all libmem APIs to make developer's lives easier.

These are only the stuff I could remember right now, and I hope I can close this issue in the future.
If you want to contribute, make a pull request.
There's a lot of work ahead of libmem.

Subroutine hooking

How do you go about doing subroutine hooks, like how zeex/subhook does it?

I almost figured out how all of libmem's API works, which is awesome ๐Ÿ˜

I wish to document it sometime in the future, to better hope those who may need it. libmem is definitely a fantastic replacement to doing this stuff other ways.

libmem examples/shared library won't build in bsd

The build scripts are made for bash and it might not be installed or it might not be at /bin. Run the following commands as root:
pkg install bash
ln -s /usr/local/bin/bash /bin/bash
The build scripts should work fine now.

Are gateway's on the mem::in::detour_trampoline functional?

I have a project where this library was needed for taskmanager(thank you!) and while working on it, I found something rather strange with mem::in::detour_trampoline (or I am using it incorrectly) as the trampoline executes but the returning gateway fails to return.
this is how the detour was created:
o_function= (function_t) mem::in::detour_trampoline(IsServer, (void *)IsServerHook, mem::in::detour_size(MEM_ASM_x86_JMP64), MEM_ASM_x86_JMP64);
and here is the respective hook:

typedef bool(* function_t)(void *ret);
bool __fastcall IsServerHook(void *ret)
{
    GlobalSettings = ret;
    std::cout << "exe" << std::endl;
    return o_function(ret);
}

it prints out the exe string and then upon return, process crashes.
before jumping(executes):
image

returning back(crashes on 'ret' instruction):
image

*nix: don't read the whole files at once

It would be more optimized to read a section of the /proc/<pid>/maps file at a time and parse it; if the results were found, free the buffer and return; else, just read once again. This might be applicable to other files, such as /proc/<pid>/status, but since they're not so big, it might not be necessary for performance increase. Instead, it might be a good idea to read until the end of life and pass the read line to a function.

Minimize includes in libmem.h

Since the library is being modulated, there's no need to include every single required header on libmem.h and import all of that stuff into the other programmer's source code; instead, move them to headers or source files in src/.

Does this work with arm ?

Hi,

I would like to use mem.read for reading android memory simple functions like
so it will be basically
long addressreturn=Read(address);
string stringreturn=ReadString(address,ize,bytesToRead);

#if defined (arm)
//arm read syscall for process_vm_writev 377
int syscallWrite = 377;
//arm read syscall for process_vm_readv 376
int syscallRead = 376;

Problem with me is i get read data error because entity might be removed and i try to read it it cause the memory stack crouption. and i get detected.

if you build that class for me i can pay you
i know its quick work for you but it will support your time.
please do let me know my discord is Hammad2224#9851

Thanks
Regards,
Hammad

Pattern Scan Problems (External)

Problem 1: Slow scan if the scanned memory length is too big
Problem 2: Returns the wrong value on Windows when scanning big chunks of memory
Thanks to @karliky for pointing the issues

mem_string_replace not working

I just noticed there's a problem in mem_string_replace and I'm working on it. Just opening this issue to let you know.

Add Rust Language support

I have learned Rust a while ago, and I want to (at some point) port libmem to Rust. I can't promise anything though, since I've never ported any C APIs to Rust and since I have to solve all of the other issues first.

Store process bits on lm_process_t struct

There's no need to keep calling LM_GetProcessBitsEx all the time you want to do a bits-dependent operation. It should be stored when the process handle is opened with LM_OpenProcessEx.

Freeing invalid pointer

Somewhere in the code, an invalid address is being free'd. I'm still looking for this problem and it might take some time to even identify where is this occurring

Tests should test everything

The tests cover a lot of libmem's surface area, but they still don't test everything, like LM_HookCodeEx. That should change.

Simplify Detour API

Instead of having LM_MakeTrampoline, LM_DestroyTrampoline, etc, what could be done is have a single LM_Detour function that has a parameter which would be the pointer to a trampoline. If that pointer is not null, generate the trampoline. If it is null, don't do anything.
Prototype:

LM_API lm_size_t
LM_Detour(lm_address_t src, lm_address_t dst, lm_address_t *ptrampoline);

LM_API lm_bool_t
LM_RestoreDetour(lm_address_t ptrampoline, lm_size_t size);

Remove internal.h

The file internal.h was useful when there were helpers; now they're gone so the file seems useless. I will keep it until I manage to solve most of the other issues just to make sure I really won't use it. If I can manage to solve the other issues and the file remains useless, it will be deleted.

process_vm_readv & process_vm_writev for android

process_vm_readv & process_vm_writev methods not found in android

Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
Android NDK:
[armeabi-v7a] Compile thumb  : mem <= libmem.c
jni/libmem.c:3020:24: warning: implicit declaration of function 'process_vm_readv' is invalid in C99 [-Wimplicit-function-declaration]
                rdsize = (lm_size_t) process_vm_readv(proc.pid, &iodst, 1,
                                     ^
jni/libmem.c:3086:23: warning: implicit declaration of function 'process_vm_writev' is invalid in C99 [-Wimplicit-function-declaration]
                wrsize = (lm_size_t)process_vm_writev(proc.pid, &iosrc, 1,
                                    ^
2 warnings generated.
[armeabi-v7a] SharedLibrary  : libmem.so
ld: error: undefined symbol: process_vm_writev
>>> referenced by libmem.c:3086 (jni\libmem.c:3086)
>>>               ./obj/local/armeabi-v7a/objs/mem/libmem.o:(LM_WriteMemoryEx)

ld: error: undefined symbol: process_vm_readv
>>> referenced by libmem.c:3020 (jni\libmem.c:3020)
>>>               ./obj/local/armeabi-v7a/objs/mem/libmem.o:(LM_ReadMemoryEx)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [C:/Users/Unknow/AppData/Local/Android/Sdk/ndk/23.0.7123448/build//../build/core/build-binary.mk:718: obj/local/armeabi-v7a/libmem.so] Error 1```

Code injection problem on Linux

I found out that external functions related to code injection on Linux might cause the target program to crash.
The functions doing code injection are:

mem_ex_protect
mem_ex_allocate
mem_ex_deallocate
mem_ex_load_library

Full code review

After most of the current issues (mainly #26) have been solved, there should be a full code review to find flaws in the code before proceeding.

Assemble/Disassemble multiple instructions

The LM_Assemble and LM_Disassemble functions can only do operations with one instruction at a time right now, but the Capstone and Keystone libraries offer support for doing things with multiple instructions.
The idea is to find a way of adding an API that can take/write multiple instructions, but avoiding memory allocations and memory leaks somehow. If avoiding those things isn't possible, then the developer will be responsible for freeing the memory later.

Reduce/Fix Warnings

It gets a bit hard to find useful information from the compiler when it's generating hundreds of lines of warnings. They have to either be fixed or disabled.

[TUT] What should it looks like of mem::in::detour_trampoline in current version?

Hi, by referencing your AssaultCube-Multihack of this line:

Data::oSwapBuffers = (SwapBuffers_t)mem::in::detour_trampoline(Data::pSwapBuffers, (mem::voidptr_t)Hooks::SwapBuffers, Data::szSwapBuffers, mem::MEM_DT_M1);

see here

What should it looks like in current version of libmem?

This is the code what I've made:

lm_module_t opengl32;
namespace gl
{
  void* SwapBuffers;
}
using SwapBuffers_t = BOOL(__stdcall*)(_In_ HDC hDC);
namespace hook
{
  namespace gl
  {
    SwapBuffers_t SwapBuffers;
  }
}

// idk why crashed...
void Init(HMODULE hModule)
{
  LM_GetModule(LM_MOD_BY_STR, (void*)LM_STR("OPENGL32.dll"), &opengl32);

  gl::SwapBuffers = LM_GetSymbol(opengl32, (lm_cstring_t)"wglSwapBuffers");
  hook::gl::SwapBuffers=(SwapBuffers_t)LM_MakeTrampoline(gl::SwapBuffers, 5);
  LM_DetourCode(gl::SwapBuffers, &hook::gl::SwapBuffers, LM_DETOUR_JMP32);
}

Does mem_ex_get_module work?

So, I'm working on adding Node.js bindings to this library to use it with JavaScript. ๐Ÿš€

While working on this I found something weird, looks like mem_ex_get_module doesn't work:

    PID:                8020
    Process Name:       explorer.exe
    Process ID:         8020
    Module Name:
    Module Path:
    Module Base:        0000000000000000
    Module Size:        0000000000000000
    Module End:         0000000000000000

The first 3 lines are from mem_ex_get_pid and mem_ex_get_process and they do work fine ๐Ÿ‘ . Then comes process_mod_ex and they look empty or filled with 0000000000000000. The process name I'm using it's explorer.exe

Here is the source code, which I copied from https://github.com/rdbo/libmem/blob/master/example/example.cpp:

	mem_pid_t pid_ex = mem_ex_get_pid(mem_string_new(PROCESS_NAME));
	tprint("PID:                %i", pid_ex);

	//-- Get Process Information
	mem_process_t process_ex = mem_ex_get_process(pid_ex);
	tprint("Process Name:       %s", mem_string_c_str(&process_ex.name));
	tprint("Process ID:         %i", process_ex.pid);

	//-- Get Process Module
	mem_module_t process_mod_ex = mem_ex_get_module(process_ex, mem_string_new(PROCESS_NAME));
	tprint("Module Name:        %s", mem_string_c_str(&process_mod_ex.name));
	tprint("Module Path:        %s", mem_string_c_str(&process_mod_ex.path));
	tprint("Module Base:        %p", process_mod_ex.base);
	tprint("Module Size:        %p", (mem_voidptr_t)process_mod_ex.size);
	tprint("Module End:         %p", process_mod_ex.end);

Am I doing something wrong? ๐Ÿง‘โ€๐Ÿ’ป

Here is the whole source code just in case it helps:
bindings.txt

Use LIEF library to parse ELF and PE symbols

LIEF is a C++ library that can parse multiple types of binaries and among other features, dump their debug symbols.
As mentioned in the issue #26, libmem has to become more modular. Maintaining all of these features by myself is not a good idea, especially since there are libraries out there that will do a better job.
I have been trying to use LIEF on libmem, but because it is a C++ library, I've had a few problems integrating it. Nonetheless, I still think it's important to use it.

Give proper names to APIs, types, etc

Some things in libmem are not properly named. For example, LM_GetProcessIdEx. It should be something like LM_FindProcessId, since it has no guarantee that it will be got or not - on the other side LM_GetProcessId is always going to succeed by returning the current process ID.

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.