Giter VIP home page Giter VIP logo

Comments (9)

newmsk avatar newmsk commented on August 18, 2024

Hello, I've found the point that cause the hang or deadlock, but it's a little diffcult for me to fix it.

  1. operate_on_backtrace, the function will check if the esp and ebp in stack range(fs:[8] - fs:[4] (win32)),if esp and ebp not in the range, it will never call the func and always return 0.
  2. At every hooked function start, there is an enter_hook function to determine enter the hook or not, and one reason not enter hook is that function called by hook. The call path is enter_hook -> __called_by_hook -> operate_on_backtrace(stack_pointer, frame_pointer, NULL, addr_in_our_dll_range), so if stack_pointer and frame_pointer not in range, callback function addr_in_our_dll_range will never be called and __called_by_hook always return 0, means the function is not called by hook.
  3. As mentioned above, the sample wrapped by a loader written in golang. Golang have a feature that it manages the stack by itself, so sometimes the stack_pointer and frame_pointer will not in the range. As a result, there will be a situation that a hooked function called by hook will still enter hook and do some log stuffs.
  4. In situation of the sample, it will hangs because criticalsection g_mutex and g_writing_log_buffer_mutex owned by different thread and wait for each other. Or g_mutex cs and g_heap's cs owned by different thead and wait for each other.
  5. I tried to delete the range check and another error occurred. In short, windows SEH also depends on stack, golang stack will also cause SEH not working as expected. The backtrace code
ULONG_PTR addr = *(ULONG_PTR *)(_ebp + sizeof(ULONG_PTR));
_ebp = *(ULONG_PTR *)_ebp;

error handler will nerver called if esp and ebp in golang stack. I seached in google and find golang exception handling on windows not compatible with SEH, it's implemented by VEH(golang/go@3750904). So is it a must to replace all the __try ... __except ... code by VEH for golang samples?
6. Finally, when i debug the deadlock, sometimes it will hangs after calling ZwSuspendThread(maybe golang gc called), so i have a assumption, if the suspended thread hold a cs(for example g_mutex), and the caller prepare to do log stuff in SuspendThread hook code requiring the g_mutex, so ZwSuspendThread never return and suspended thread never be resumed. Does this situation exists?

from capemon.

kevoreilly avatar kevoreilly commented on August 18, 2024

Hi newmsk, firstly thank you for investigating this issue. This is tricky stuff and I am swamped with 'sample crashes due to unknown hooking problem' type issue so it's great to actually see such a good start in getting to the root of the problem.

I will try and look into this soon and hopefully we can chip away on a fix.

from capemon.

kevoreilly avatar kevoreilly commented on August 18, 2024

Let me know if you would be willing to test an attempt at a fix I just tried?
capemon.zip

I have just added a check not to enter hook if no return address & 'parent' return address:

index 88711f2..2a69e04 100644
--- a/hooking.c
+++ b/hooking.c
@@ -323,6 +323,9 @@ int WINAPI enter_hook(hook_t *h, ULONG_PTR sp, ULONG_PTR ebp_or_rip)
                if (!hookinfo->main_caller_retaddr)
                        operate_on_backtrace(sp, ebp_or_rip, hookinfo, set_caller_info_fallback);

+               if (!hookinfo->main_caller_retaddr && !hookinfo->parent_caller_retaddr)
+                       return 0;
+
                api_dispatch(h, hookinfo);

                return 1;

It seems to show calls from the sample:

image

But then seems to go in an infinite loop suspending and resuming a thread... Still an improvement over hanging though?

from capemon.

newmsk avatar newmsk commented on August 18, 2024

I have tested the dll in my environment, it seems works as expected.The host item also comes out.
image
There is the full report and if you need any other log file, just let me know.
96aca8d49d297aeed2bc046e6cb68f6785a9160ac2fb9b63d908f0b392436207.zip

from capemon.

newmsk avatar newmsk commented on August 18, 2024

However, if i add extra options="unpacker=1", it will hang after set breakpoint at shellcode begin,maybe there is another point that will cause deadlock.If i find it, i will tell you as soon as possible.
image

from capemon.

newmsk avatar newmsk commented on August 18, 2024

The check code you added will prevent all code executed on golang stack from entering hook.
It not only prevent capmon's own code from entering hook, but also other sample code.
In this situation, the RtlDispatchException hook code that responsible for handling capemon breakpoints will never been executed, so the sample will hang at EXCEPTION_SINGLE_STEP exception.
I force the enter_hook function return 1 when the hooked function name is the RtlDispatchException, it works well.But I don't know if this code will cause other problems.

from capemon.

kevoreilly avatar kevoreilly commented on August 18, 2024

Ah yes I didn't extend the previous checks for RtlDispatchException or NtContinue both of which are essential for the proper functioning of the debugger. It might be a good idea to force the hook in these cases...

... but it may also be worth trying to add the golang stack range to the operate_on_backtrace stack checks to properly handle called apis. I have no idea at the moment about how we might do that but I will look into it.

from capemon.

kevoreilly avatar kevoreilly commented on August 18, 2024

Would you mind giving this a go:
capemon.zip

'''
if ((hookinfo->disable_count < 1) && (h->allow_hook_recursion || (!__called_by_hook(sp, ebp_or_rip) /&& !is_ignored_thread(GetCurrentThreadId())/))) {

	hookinfo->last_hook = hookinfo->current_hook;
	hookinfo->current_hook = h;
	hookinfo->stack_pointer = sp;
	hookinfo->return_address = *(ULONG_PTR *)sp;
	hookinfo->frame_pointer = ebp_or_rip;

	/* set caller information */
	hookinfo->main_caller_retaddr = 0;
	hookinfo->parent_caller_retaddr = 0;

	operate_on_backtrace(sp, ebp_or_rip, hookinfo, set_caller_info);

	if (!hookinfo->main_caller_retaddr)
		operate_on_backtrace(sp, ebp_or_rip, hookinfo, set_caller_info_fallback);

	if (h->new_func == &New_RtlDispatchException || h->new_func == &New_NtContinue)
		return 1;

	if (!hookinfo->main_caller_retaddr && !hookinfo->parent_caller_retaddr)
		return 0;

	if (g_config.api_rate_cap && Old_GetSystemTimeAsFileTime) {
		if (h->hook_disabled)
			return 0;
		h->counter++;
		if (h->counter > HOOK_LIMIT) {
			DebugOutput("api-rate-cap: %s hook disabled due to count.\n", h->funcname);
			h->hook_disabled = 1;
			return 0;
		}
		Old_GetSystemTimeAsFileTime(&ft);
		if (ft.dwLowDateTime - h->hook_timer < HOOK_TIME_SAMPLE) {
			h->rate_counter++;
			if (h->rate_counter > HOOK_RATE_LIMIT/g_config.api_rate_cap) {
				DebugOutput("api-rate-cap: %s hook disabled due to rate.\n", h->funcname);
				h->rate_counter = 0;
				h->hook_disabled = 1;
				return 0;
			}
		}
		else {
			h->rate_counter = 0;
			h->hook_timer = ft.dwLowDateTime;
		}
	}

	api_dispatch(h, hookinfo);

	return 1;
}

'''

from capemon.

newmsk avatar newmsk commented on August 18, 2024

I've tried it, but it hanged even without option="unpacker=1".Here is the debug log

2021-09-13 10:33:04,246 [root] INFO: Date set to: 20211020T08:51:41, timeout set to: 60
2021-10-20 08:51:41,078 [root] DEBUG: Starting analyzer from: C:\\tmpbwehxj7k
2021-10-20 08:51:41,078 [root] DEBUG: Storing results at: C:\\ofHrTIjGdO
2021-10-20 08:51:41,078 [root] DEBUG: Pipe server name: \\\\.\\PIPE\\EnQPJiTUQ
2021-10-20 08:51:41,078 [root] DEBUG: Python path: C:\\Users\\win7x64\\AppData\\Local\\Programs\\Python\\Python38-32
2021-10-20 08:51:41,078 [root] INFO: Analysis package \"exe\" has been specified.
2021-10-20 08:51:41,078 [root] DEBUG: Importing analysis package \"exe\"...
2021-10-20 08:51:41,281 [root] DEBUG: Initializing analysis package \"exe\"...
2021-10-20 08:51:41,281 [root] INFO: Analyzer: Package modules.packages.exe does not specify a DLL option
2021-10-20 08:51:41,281 [root] INFO: Analyzer: Package modules.packages.exe does not specify a DLL_64 option
2021-10-20 08:51:41,281 [root] INFO: Analyzer: Package modules.packages.exe does not specify a loader option
2021-10-20 08:51:41,281 [root] INFO: Analyzer: Package modules.packages.exe does not specify a loader_64 option
2021-10-20 08:51:41,296 [root] DEBUG: Importing auxiliary module \"modules.auxiliary.browser\"...
2021-10-20 08:51:41,312 [root] DEBUG: Importing auxiliary module \"modules.auxiliary.curtain\"...
2021-10-20 08:51:41,328 [root] DEBUG: Importing auxiliary module \"modules.auxiliary.digisig\"...
2021-10-20 08:51:41,328 [root] DEBUG: Importing auxiliary module \"modules.auxiliary.disguise\"...
2021-10-20 08:51:41,343 [root] DEBUG: Importing auxiliary module \"modules.auxiliary.screenshots\"...
2021-10-20 08:51:41,343 [modules.auxiliary.screenshots] DEBUG: Importing 'time'
2021-10-20 08:51:41,343 [modules.auxiliary.screenshots] DEBUG: Importing 'StringIO'
2021-10-20 08:51:41,343 [modules.auxiliary.screenshots] DEBUG: Importing 'Thread'
2021-10-20 08:51:41,343 [modules.auxiliary.screenshots] DEBUG: Importing 'Auxiliary'
2021-10-20 08:51:41,343 [modules.auxiliary.screenshots] DEBUG: Importing 'NetlogFile'
2021-10-20 08:51:41,343 [modules.auxiliary.screenshots] DEBUG: Importing 'Screenshot'
2021-10-20 08:51:41,359 [lib.api.screenshot] DEBUG: Importing 'math'
2021-10-20 08:51:41,359 [lib.api.screenshot] DEBUG: Importing 'PIL.ImageChops'
2021-10-20 08:51:41,390 [lib.api.screenshot] DEBUG: Importing 'PIL.ImageGrab'
2021-10-20 08:51:41,390 [lib.api.screenshot] DEBUG: Importing 'PIL.ImageDraw'
2021-10-20 08:51:41,390 [modules.auxiliary.screenshots] DEBUG: Imports OK
2021-10-20 08:51:41,390 [root] DEBUG: Importing auxiliary module \"modules.auxiliary.tlsdump\"...
2021-10-20 08:51:41,406 [root] DEBUG: Importing auxiliary module \"modules.auxiliary.usage\"...
2021-10-20 08:51:41,406 [root] DEBUG: Initializing auxiliary module \"Browser\"...
2021-10-20 08:51:41,406 [root] DEBUG: Started auxiliary module Browser
2021-10-20 08:51:41,406 [root] DEBUG: Initializing auxiliary module \"Curtain\"...
2021-10-20 08:51:41,406 [root] DEBUG: Started auxiliary module Curtain
2021-10-20 08:51:41,406 [root] DEBUG: Initializing auxiliary module \"DigiSig\"...
2021-10-20 08:51:41,406 [modules.auxiliary.digisig] DEBUG: Checking for a digital signature.
2021-10-20 08:51:41,609 [modules.auxiliary.digisig] DEBUG: File is not signed.
2021-10-20 08:51:41,609 [modules.auxiliary.digisig] INFO: Uploading signature results to aux/DigiSig.json
2021-10-20 08:51:41,828 [root] DEBUG: Started auxiliary module DigiSig
2021-10-20 08:51:41,828 [root] DEBUG: Initializing auxiliary module \"Disguise\"...
2021-10-20 08:51:41,828 [modules.auxiliary.disguise] INFO: Disguising GUID to 35e0f26b-2f4c-4704-9453-9d1adf77db9b
2021-10-20 08:51:41,828 [root] DEBUG: Started auxiliary module Disguise
2021-10-20 08:51:41,828 [root] DEBUG: Initializing auxiliary module \"Screenshots\"...
2021-10-20 08:51:41,828 [root] DEBUG: Started auxiliary module Screenshots
2021-10-20 08:51:41,828 [root] DEBUG: Initializing auxiliary module \"TLSDumpMasterSecrets\"...
2021-10-20 08:51:41,828 [modules.auxiliary.tlsdump] INFO: lsass.exe found, pid 476
2021-10-20 08:51:41,828 [lib.api.process] INFO: Monitor config for process 476: C:\\tmpbwehxj7k\\dll\\476.ini
2021-10-20 08:51:41,843 [lib.api.process] INFO: Option 'tlsdump' with value '1' sent to monitor
2021-10-20 08:51:41,843 [lib.api.process] INFO: 64-bit DLL to inject is C:\\tmpbwehxj7k\\dll\\MQnqpgg.dll, loader C:\\tmpbwehxj7k\\bin\\rFPfrNHK.exe
2021-10-20 08:51:41,875 [root] DEBUG: Loader: Injecting process 476 with C:\\tmpbwehxj7k\\dll\\MQnqpgg.dll.
2021-10-20 08:51:41,890 [root] DEBUG: Python path set to 'C:\\Users\\win7x64\\AppData\\Local\\Programs\\Python\\Python38-32'.
2021-10-20 08:51:41,890 [root] DEBUG: TLS secret dump mode enabled.
2021-10-20 08:51:41,890 [root] INFO: Disabling sleep skipping.
2021-10-20 08:51:41,890 [root] DEBUG: Monitor initialised: 64-bit capemon loaded in process 476 at 0x000007FEF3640000, thread 1644, image base 0x00000000FFE90000, stack from 0x00000000013D4000-0x00000000013E0000
2021-10-20 08:51:41,890 [root] DEBUG: Commandline: C:\\Windows\\sysnative\\lsass.exe
2021-10-20 08:51:41,906 [root] INFO: Loaded monitor into process with pid 476
2021-10-20 08:51:41,906 [root] DEBUG: InjectDllViaThread: Successfully injected Dll into process via RtlCreateUserThread.
2021-10-20 08:51:41,906 [root] DEBUG: Successfully injected DLL C:\\tmpbwehxj7k\\dll\\MQnqpgg.dll.
2021-10-20 08:51:41,906 [lib.api.process] INFO: Injected into suspended 64-bit process with pid 476
2021-10-20 08:51:41,906 [root] DEBUG: Started auxiliary module TLSDumpMasterSecrets
2021-10-20 08:51:41,906 [root] DEBUG: Initializing auxiliary module \"Usage\"...
2021-10-20 08:51:41,906 [root] DEBUG: Started auxiliary module Usage
2021-10-20 08:51:49,546 [root] INFO: Restarting WMI Service
2021-10-20 08:51:51,640 [lib.api.process] INFO: Successfully executed process from path \"C:\\Users\\win7x64\\AppData\\Local\\Temp\\96aca8d49d297aeed2bc046e6cb68f6785a9160ac2fb9b63d908f0b392436207.exe\" with arguments \"\" with pid 2216
2021-10-20 08:51:51,640 [lib.api.process] INFO: Monitor config for process 2216: C:\\tmpbwehxj7k\\dll\\2216.ini
2021-10-20 08:51:51,640 [lib.api.process] INFO: 32-bit DLL to inject is C:\\tmpbwehxj7k\\dll\\uVnabOj.dll, loader C:\\tmpbwehxj7k\\bin\
qnBGKN.exe
2021-10-20 08:51:51,750 [root] DEBUG: Loader: Injecting process 2216 (thread 2964) with C:\\tmpbwehxj7k\\dll\\uVnabOj.dll.
2021-10-20 08:51:51,750 [root] DEBUG: InjectDllViaIAT: Successfully patched IAT.
2021-10-20 08:51:51,750 [root] DEBUG: Successfully injected DLL C:\\tmpbwehxj7k\\dll\\uVnabOj.dll.
2021-10-20 08:51:51,750 [lib.api.process] INFO: Injected into suspended 32-bit process with pid 2216
2021-10-20 08:51:53,750 [lib.api.process] INFO: Successfully resumed process with pid 2216
2021-10-20 08:51:53,968 [root] DEBUG: Python path set to 'C:\\Users\\win7x64\\AppData\\Local\\Programs\\Python\\Python38-32'.
2021-10-20 08:51:53,968 [root] DEBUG: Dropped file limit defaulting to 100.
2021-10-20 08:51:53,968 [root] INFO: LogServerThread run before handle_logs 0x0
2021-10-20 08:51:53,968 [root] DEBUG: RestoreHeaders: Restored original import table.
2021-10-20 08:51:53,968 [root] DEBUG: Monitor initialised: 32-bit capemon loaded in process 2216 at 0x70770000, thread 2964, image base 0x400000, stack from 0x186000-0x190000
2021-10-20 08:51:53,984 [root] DEBUG: Commandline: \"C:\\Users\\win7x64\\AppData\\Local\\Temp\\96aca8d49d297aeed2bc046e6cb68f6785a9160ac2fb9b63d908f0b392436207.exe\"
2021-10-20 08:51:53,984 [root] DEBUG: Initialising Yara...
2021-10-20 08:51:53,984 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\BuerLoader.yar
2021-10-20 08:51:54,000 [root] INFO: Disabling sleep skipping.
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\DridexLoader.yar
2021-10-20 08:51:54,000 [root] INFO: Disabling sleep skipping.
2021-10-20 08:51:54,000 [root] INFO: Disabling sleep skipping.
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\Formbook.yar
2021-10-20 08:51:54,000 [root] INFO: Disabling sleep skipping.
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\Guloader.yar
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\IcedID.yar
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\Pafish.yar
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\SingleStepAntiHook.yar
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\UrsnifV3.yar
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\VBCrypter.yar
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rule file C:\\tmpbwehxj7k\\data\\yara\\Zloader.yar
2021-10-20 08:51:54,000 [root] DEBUG: YaraInit: Compiled rules saved to file C:\\tmpbwehxj7k\\data\\yara\\capemon.yac
2021-10-20 08:51:54,000 [root] INFO: Loaded monitor into process with pid 2216
2021-10-20 08:51:54,000 [root] DEBUG: caller_dispatch: Adding region at 0x00400000 to caller regions list (ntdll::LdrLoadDll returns to 0x00459905).
2021-10-20 08:51:54,015 [root] DEBUG: YaraScan: Scanning 0x00400000, size 0x221bc2
2021-10-20 08:51:54,015 [root] DEBUG: caller_dispatch: Dump of calling region at 0x00400000 skipped (ntdll::LdrLoadDll returns to 0x00459905 mapped as \\Device\\HarddiskVolume2\\Users\\win7x64\\AppData\\Local\\Temp\\96aca8d49d297aeed2bc046e6cb68f6785a9160ac2fb9b63d908f0b392436207.exe).
2021-10-20 08:51:54,031 [root] DEBUG: DLL loaded at 0x73560000: C:\\Windows\\system32\\winmm (0x32000 bytes).
2021-10-20 08:51:54,031 [root] DEBUG: DLL loaded at 0x71E40000: C:\\Windows\\system32\\powrprof (0x25000 bytes).
2021-10-20 08:51:54,031 [root] DEBUG: DLL loaded at 0x75C20000: C:\\Windows\\syswow64\\SETUPAPI (0x19d000 bytes).
2021-10-20 08:51:54,031 [root] DEBUG: DLL loaded at 0x768F0000: C:\\Windows\\syswow64\\CFGMGR32 (0x27000 bytes).
2021-10-20 08:51:54,031 [root] DEBUG: DLL loaded at 0x76C20000: C:\\Windows\\syswow64\\OLEAUT32 (0x8f000 bytes).
2021-10-20 08:51:54,031 [root] DEBUG: DLL loaded at 0x74E30000: C:\\Windows\\syswow64\\DEVOBJ (0x12000 bytes).
2021-10-20 08:51:54,031 [root] DEBUG: MapSectionViewHandler: Added section view with handle 0x140 and local view 0x73230000 to global list.
2021-10-20 08:51:54,047 [root] DEBUG: MapSectionViewHandler: Updated local view to 0x006A0000 for section view with handle 0x140.
2021-10-20 08:51:54,048 [root] DEBUG: MapSectionViewHandler: Updated local view to 0x74D40000 for section view with handle 0x140.
2021-10-20 08:51:54,050 [root] DEBUG: MapSectionViewHandler: Updated local view to 0x006A0000 for section view with handle 0x140.
2021-10-20 08:51:54,053 [root] DEBUG: MapSectionViewHandler: Updated local view to 0x74D40000 for section view with handle 0x140.
2021-10-20 08:51:54,055 [root] DEBUG: MapSectionViewHandler: Updated local view to 0x006A0000 for section view with handle 0x140.
2021-10-20 08:51:54,057 [root] DEBUG: MapSectionViewHandler: Updated local view to 0x73550000 for section view with handle 0x140.
2021-10-20 08:51:54,059 [root] DEBUG: MapSectionViewHandler: Updated local view to 0x006A0000 for section view with handle 0x140.
2021-10-20 08:51:54,059 [root] DEBUG: VirtualProtectEx: Rescinding caller region at 0x00400000 due to protection change.
2021-10-20 08:51:54,059 [root] DEBUG: caller_dispatch: Adding region at 0x00400000 to caller regions list (kernel32::VirtualProtectEx returns to 0x00459905).
2021-10-20 08:51:54,059 [root] DEBUG: YaraScan: Scanning 0x00400000, size 0x221bc2
2021-10-20 08:51:54,075 [root] DEBUG: caller_dispatch: Dump of calling region at 0x00400000 skipped (kernel32::VirtualProtectEx returns to 0x00459905 mapped as \\Device\\HarddiskVolume2\\Users\\win7x64\\AppData\\Local\\Temp\\96aca8d49d297aeed2bc046e6cb68f6785a9160ac2fb9b63d908f0b392436207.exe).
2021-10-20 08:52:53,823 [root] INFO: Analysis timeout hit, terminating analysis.
2021-10-20 08:52:53,826 [lib.api.process] INFO: Terminate event set for process 476
2021-10-20 08:52:53,828 [root] DEBUG: Terminate Event: Skipping dump of process 476
2021-10-20 08:52:53,830 [lib.api.process] INFO: Termination confirmed for process 476
2021-10-20 08:52:53,833 [root] INFO: Terminate event set for process 476.
2021-10-20 08:52:53,833 [root] DEBUG: Terminate Event: CAPE shutdown complete for process 476
2021-10-20 08:52:53,835 [lib.api.process] INFO: Terminate event set for process 2216
2021-10-20 08:52:58,841 [lib.api.process] INFO: Termination confirmed for process 2216
2021-10-20 08:52:58,856 [root] INFO: Terminate event set for process 2216.
2021-10-20 08:52:58,859 [root] INFO: Created shutdown mutex.
2021-10-20 08:52:59,861 [root] INFO: Shutting down package.
2021-10-20 08:52:59,864 [root] INFO: Stopping auxiliary modules.
2021-10-20 08:52:59,868 [root] INFO: Finishing auxiliary modules.
2021-10-20 08:52:59,871 [root] INFO: Shutting down pipe server and dumping dropped files.
2021-10-20 08:52:59,875 [root] WARNING: Folder at path \"C:\\ofHrTIjGdO\\debugger\" does not exist, skip.
2021-10-20 08:52:59,877 [root] WARNING: Folder at path \"C:\\ofHrTIjGdO\\tlsdump\" does not exist, skip.
2021-10-20 08:52:59,882 [root] INFO: Analysis completed.

from capemon.

Related Issues (20)

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.