ralphje / imagemounter Goto Github PK
View Code? Open in Web Editor NEWCommand line utility and Python package to ease the (un)mounting of forensic disk images
License: MIT License
Command line utility and Python package to ease the (un)mounting of forensic disk images
License: MIT License
Just wanted to note that when installing dependencies for additional capabilities, I had issues with a few (all the mount.xxx) commands.
MISSING mount.xfs
MISSING mount.jffs2
MISSING mount.squashfs
I installed the requested xfsprogs, mtd-tools, and squashfs-tools, but they still report as missing. Things like mksquashfs work fine. Tried on Ubuntu 20.04.3 and Kali. I haven't actually tried to use imount on those file systems, but just wonder if there is an issue with the --check
.
I see that this repository hasn't had many updates in the past couple years. it is still maintained? I help maintain a fork of this over at https://github.com/mitre/imagemounter (which itself is a bit behind the master branch here) and am wondering how long it would take to get updates pulled into this upstream repository and eventually onto PyPI as well.
Alternately, I am contemplating publishing our fork (after it is cleaned up a bit) to PyPI as well as something like imagemounter2
but don't want to jump right into that if it makes sense to collaborate more in tandem with you. Thanks!
I'm trying to determine if there's a good way to use imagemounter as a non-root user. I think it might be possible by adding a mountpoint in /etc/fstab
that allows non-root users to mount to it, and then allow passing the path to that mountpoint through the ImageParser
constructor, through to the Disk
constructor and mount
method. Something similar might be necessary to mount all the Volumes on a Disk.
Does this seem reasonable? I'm happy to implement it, but wanted to make sure it was in line with the direction of the project and I wasn't missing some more obvious way to do it.
Somehow, either the squashfs test is broken, or the support for it is entirely broken. The test is now temporarily disabled.
Apple File System (APFS) is the new file system used by Apple as a replacement for HFS+. The sgan81/apfs-fuse driver on GitHub looks like the best attempt at an open source solution to be able to mount this proprietary file system. Do you know of any other APFS drivers that might be better, or easier to integrate with imagemounter? Would it be worth going down the path to add beta support using this driver?
...and not for hardware raid controllers
When unmounting mounted .qcow2- or .vdi-images, the /dev/nbd# device fails to disconnect.
This is caused by the ismount check in _util.clean_unmount:
elif not os.path.ismount(mountpoint):
Because the /dev/nbd# device does not actually show up in the mounts lists, the check returns True and the check_call is never reached, so the /dev/nbd# device stays (erroneously) intact.
An option might be to change the above line to:
elif not os.path.ismount(mountpoint) and cmd[0] != 'qemu-nbd':
We have get_raw_path, but it is quite opaque what it is doing and now we have moved a lot of methods to filesystems.py, it is also incorrect.
We can then also drop _paths and just implement bindmounts.
We don't add the offset of partition tables to their nested volumes (this happens in the base of BSD, where a MBR will contain a BSD volume system).
However, more by luck than by accident, this seems to work fine in this case: the BSD disklabel actually lists all volume offsets from the start of the disk, so we're fine not adding self.offset
there.
However, I'm not sure this is the case for all nested volume systems. This requires some research.
Currently, imagemounter won't mount split images where the segments are denoted by 4 character extensions (eg: image.0001). I think this is a quick and simple change 2 line change to _utils.py, but may be missing something.
Hello, I have a strange and unexpected error after upgrading my Ubuntu virtual machine to the latest version, 16.04. I'm not sure what could be the problem. I'll install an older version of Ubuntu to overcome the problem in the short term, but I thought I should report the error here.
Commands saved in a bash script that worked previously now give this error:
[-] invalid literal for int() with base 10: '-------'
Here is the full output using -vvvv
:
Hello! I am trying to use imagemounter on the EnCase images provided for NIST's "Hacking Case" scenario. I have been unable to mount the files so far. What is the best way to help debug this?
Here is the output I get, using -v
:
Hello, I have tried mounting a large volume, and imagemounter dies when it runs out of memory. The volume is split into about 120 files, each 2 GB. On a virtual machine with 4 GB RAM, I can only get through about one-fourth of these files before running out of RAM, at which poiht imount
exits.
Here you can see as memory utilization ticks up with each file:
Here is a screenshot from when it dies:
Interestingly, I noticed that RAM was not freed up after imount
terminated. It turns out there were a lot of ewfmount
processes still lingering even after imount
had exited. I killall
ed them and got the RAM back.
Also, none of this is using swap. I added another big swap partition as an attempted workaround, but it didn't get used at all.
I don't know enough about the internals here to suggest a solution, but I'm happy to help troubleshoot.
I am running v3.0.0a2 (from Git).
Here is the output from imount``check
:
anseljh@anseljh-VirtualBox:~$ imount --check
The following commands are used by imagemounter internally. Without most commands, imagemounter works perfectly fine, but may lack some detection or mounting capabilities.
-- Mounting base disk images (at least one required, first three recommended) --
INSTALLED xmount
INSTALLED ewfmount
INSTALLED affuse
MISSING vmware-mount needed for VMWare disks
INSTALLED mountavfs
-- Detecting volumes and volume types (at least one required) --
INSTALLED mmls
MISSING pytsk3 install using pip
INSTALLED parted
-- Detecting volume types (all recommended, first two highly recommended) --
INSTALLED fsstat
INSTALLED file
INSTALLED blkid
MISSING python-magic install using pip
INSTALLED disktype
-- Mounting volumes (install when needed) --
MISSING mount.xfs needed for XFS volumes, part of the xfsprogs package
INSTALLED mount.ntfs
INSTALLED lvm
INSTALLED vmfs-fuse
MISSING mount.jffs2 needed for JFFS2 volumes, part of the mtd-tools package
MISSING mount.squashfs needed for SquashFS volumes, part of the squashfs-tools package
INSTALLED mdadm
INSTALLED cryptsetup
MISSING bdemount needed for Bitlocker Drive Encryption volumes, part of the libbde-utils package
MISSING vshadowmount needed for NTFS volume shadow copies, part of the libvshadow-utils package
I had dtried using sudo and root , it dosen't work at all.
Readonly mount is fine.
I had install xmount.
Running ImageMounter.py -s -e and it seems to run through the procedure fine.
Terminal tells me EWF1 mounted fine to my mount point
I can see the EWF1 file in the ewf_2018_xx_xx_xx-xx_xx directory has been created.
#EWF1 file tells us its a DOS/MBR boot sector and NFTS
I can see that my mount directory is active (green) but no image data whatsover within. (ls -a)
I can also umount the same mount directory without error, so something is in there, just can't see it. I have tried mounting to several different mount points in different locations. Get same issue.
Using the ever so slightly longer method of Mounting the same E01 file using ewfmount works fine and I can see image data in destination mount directory.
I would really like this to work though as it's cool.
Thanks.
Pete
(massive UK Newbie - sorry)
When size is somehow None, it is still added as --sizelimit in loopback device creation.
Should also investigate how it would become None.
I get an error when LVM is inside an encrypted LUKS partition. It tries to determine the decrypted LUKS file system type instead of the logical volume. This is on version 3.1.0.
# imount -vvvv --fstypes 6=luks /media/veracrypt1/forensics/test.E01
[ snip ]
[+] Found allocated : block offset: 3123200, length: 973649935
Initializing volume 6:-
[+] Mounting volume 6:-
$ fsstat /tmp/image_mounter_uek4ki6g/ewf1 -o 3123200
$ losetup -f
< /dev/loop0
$ losetup -r -o 1599078400 --sizelimit 498508766720 /dev/loop0 /tmp/image_mounter_uek4ki6g/ewf1
$ cryptsetup isLuks /dev/loop0
[-] No key material provided for 6:-
$ cryptsetup -r luksOpen /dev/loop0 image_mounter_luks_39596
Enter passphrase for /tmp/image_mounter_uek4ki6g/ewf1:
$ cryptsetup status image_mounter_luks_39596
< /dev/mapper/image_mounter_luks_39596 is active.
< type: LUKS2
< cipher: aes-xts-plain64
< keysize: 512 bits
< key location: keyring
< device: /dev/loop0
< loop: /tmp/image_mounter_uek4ki6g/ewf1
< sector size: 512
< offset: 32768 sectors
< size: 973617167 sectors
< mode: readonly
Initializing volume 6.0:LUKS Volume
[+] Mounting volume 6.0:LUKS Volume
Trying to determine fs type from 'LUKS Volume'
Trying to determine fs type from 'None'
$ blkid -p -O 0 /dev/mapper/image_mounter_luks_39596
< /dev/mapper/image_mounter_luks_39596: UUID="6RvJ8A-AgY9-Lk0d-G7gc-05tR-lKaG-tGVW7z" VERSION="LVM2 001" TYPE="LVM2_member" USAGE="raid"
Trying to determine fs type from 'LVM2_member'
[+] Detected lvm2_member as lvm
$ fsstat /dev/mapper/image_mounter_luks_39596 -o 0
$ losetup -f
< /dev/loop2
$ losetup -r -o 0 --sizelimit None /dev/loop2 /dev/mapper/image_mounter_luks_39596
losetup: failed to parse size: 'None': Invalid argument
[-] Loopback device could not be mounted.
Traceback (most recent call last):
File "/usr/local/lib/python3.9/dist-packages/imagemounter/volume.py", line 530, in _find_loopback
_util.check_call_(cmd, stdout=subprocess.PIPE)
File "/usr/local/lib/python3.9/dist-packages/imagemounter/_util.py", line 116, in check_call_
return subprocess.check_call(cmd, *args, **kwargs)
File "/usr/lib/python3.9/subprocess.py", line 373, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['losetup', '-r', '-o', '0', '--sizelimit', 'None', '/dev/loop2', '/dev/mapper/image_mounter_luks_39596']' returned non-zero exit status 1.
[-] Execution failed due to <class 'imagemounter.exceptions.NoLoopbackAvailableError'>
Traceback (most recent call last):
File "/usr/local/lib/python3.9/dist-packages/imagemounter/volume.py", line 530, in _find_loopback
_util.check_call_(cmd, stdout=subprocess.PIPE)
File "/usr/local/lib/python3.9/dist-packages/imagemounter/_util.py", line 116, in check_call_
return subprocess.check_call(cmd, *args, **kwargs)
File "/usr/lib/python3.9/subprocess.py", line 373, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['losetup', '-r', '-o', '0', '--sizelimit', 'None', '/dev/loop2', '/dev/mapper/image_mounter_luks_39596']' returned non-zero exit status 1.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/dist-packages/imagemounter/volume.py", line 750, in mount
self._open_lvm()
File "/usr/local/lib/python3.9/dist-packages/imagemounter/volume.py", line 976, in _open_lvm
self._find_loopback()
File "/usr/local/lib/python3.9/dist-packages/imagemounter/volume.py", line 533, in _find_loopback
raise NoLoopbackAvailableError()
imagemounter.exceptions.NoLoopbackAvailableError
[-] Exception while mounting 6.0:LUKS Volume
I'd like to be able to check imagemounter's dependencies and display the results differently than the current default of just printing them.
Would you be open to a PR that separates the logic of detect missing dependencies from presenting them as output?
https://github.com/ralphje/imagemounter/blob/master/imagemounter/cli/__init__.py#L6-L72
I have an E01 file that mounts just fine with imount
on Ubuntu 14.04, but not on 16.04. I have included the full output below. So far I have tracked it down to the version of the file
command installed which gives different output for this same file.
# Ubuntu 14.04
$ file --version
file-5.14
$ file my-ewf1-inside-the-E01
my-ewf1-inside-the-E01: x86 boot sector
# Ubuntu 16.04
$ file --version
file-5.25
$ file my-ewf1-inside-the-E01
my-ewf1-inside-the-E01: DOS/MBR boot sector, <blah blah blah - see full output below>
Because of this discrepancy, the fstype
here (https://github.com/ralphje/imagemounter/blob/v3.0.0/imagemounter/volume.py#L642) is returned as ntfs
on 14.04, but volumesystem
on 16.04.
If I add a continue
here: https://github.com/ralphje/imagemounter/blob/v3.0.0/imagemounter/volume.py#L586, it works for this one file, but I'm sure that looks like the wrong approach long term since I don't know the actual ramifications of that decision to other image/volume/disk/whatever types.
Sorry I don't have a pull request - I don't know how to solve it!
vagrant@vagrant:~$ sudo imount -vvvv win7-32-c-drive.E01
imagemounter version 3.0.0
[+] Mounting image win7-32-c-drive.E01 using auto...
$ ewfmount -X allow_other win7-32-c-drive.E01 /tmp/image_mounter_y2LwKj
Raw path to disk is /tmp/image_mounter_y2LwKj/ewf1
$ disktype /tmp/image_mounter_y2LwKj/ewf1
<
< --- /tmp/image_mounter_y2LwKj/ewf1
< Regular file, size 24.75 GiB (26578255872 bytes)
< NTFS file system
< Volume size 24.75 GiB (26578255360 bytes, 51910655 sectors)
<
[+] Mounted raw image [1/1]
[+] Mounting volumes in win7-32-c-drive.E01
$ mmls /tmp/image_mounter_y2LwKj/ewf1
< Cannot determine partition type
[-] Failed executing mmls command
Traceback (most recent call last):
File "/home/vagrant/imagemounter/imagemounter/volume_system.py", line 269, in _detect_mmls_volumes
output = _util.check_output_(cmd, stderr=subprocess.STDOUT)
File "/home/vagrant/imagemounter/imagemounter/_util.py", line 121, in check_output_
result = subprocess.check_output(cmd, *args, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 574, in check_output
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command '[u'mmls', u'/tmp/image_mounter_y2LwKj/ewf1']' returned non-zero exit status 1
[+] Detecting as single volume instead
$ file -sL /tmp/image_mounter_y2LwKj/ewf1
< /tmp/image_mounter_y2LwKj/ewf1: DOS/MBR boot sector, code offset 0x52+2, OEM-ID "NTFS ", sectors/cluster 8, Media descriptor 0xf8,
sectors/track 63, heads 255, hidden sectors 2048, dos < 4.0 BootSector (0x80), FAT (1Y bit by descriptor); NTFS, sectors/track 63, sectors 51910655,
$MFT start cluster 786432, $MFTMirror start cluster 2, bytes/RecordSegment 2^(-1*246), clusters/index block 1, serial number 02eac03a3ac036525;
contains Microsoft Windows XP/VISTA bootloader BOOTMGR
Initializing volume 0:DOS/MBR boot sector
[+] Mounting volume 0:DOS/MBR boot sector
Trying to determine fs type from 'DOS/MBR boot sector'
[+] Detected dos/mbr boot sector as volumesystem
$ fsstat /tmp/image_mounter_y2LwKj/ewf1 -o 0
$ mmls /tmp/image_mounter_y2LwKj/ewf1
< Cannot determine partition type
[-] Failed executing mmls command
Traceback (most recent call last):
File "/home/vagrant/imagemounter/imagemounter/volume_system.py", line 269, in _detect_mmls_volumes
output = _util.check_output_(cmd, stderr=subprocess.STDOUT)
File "/home/vagrant/imagemounter/imagemounter/_util.py", line 121, in check_output_
result = subprocess.check_output(cmd, *args, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 574, in check_output
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command '[u'mmls', u'/tmp/image_mounter_y2LwKj/ewf1']' returned non-zero exit status 1
[-] Execution failed due to <class 'imagemounter.exceptions.SubsystemError'> Command '[u'mmls', u'/tmp/image_mounter_y2LwKj/ewf1']' returned non-zero exit status 1
Traceback (most recent call last):
File "/home/vagrant/imagemounter/imagemounter/volume_system.py", line 269, in _detect_mmls_volumes
output = _util.check_output_(cmd, stderr=subprocess.STDOUT)
File "/home/vagrant/imagemounter/imagemounter/_util.py", line 121, in check_output_
result = subprocess.check_output(cmd, *args, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 574, in check_output
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command '[u'mmls', u'/tmp/image_mounter_y2LwKj/ewf1']' returned non-zero exit status 1
[-] Execution failed due to <class 'imagemounter.exceptions.SubsystemError'> Command '[u'mmls', u'/tmp/image_mounter_y2LwKj/ewf1']' returned non-zero exit status 1
Traceback (most recent call last):
File "/home/vagrant/imagemounter/imagemounter/volume.py", line 714, in mount
for _ in self.volumes.detect_volumes():
File "/home/vagrant/imagemounter/imagemounter/volume_system.py", line 124, in detect_volumes
for v in self._detect_mmls_volumes(vstype):
File "/home/vagrant/imagemounter/imagemounter/volume_system.py", line 287, in _detect_mmls_volumes
raise SubsystemError(e)
SubsystemError: Command '[u'mmls', u'/tmp/image_mounter_y2LwKj/ewf1']' returned non-zero exit status 1
[-] Exception while mounting 24.75 GiB 0:NTFS [Windows XP]
>>> Press [enter] to continue...
[+] Parsed all volumes!
[+] Analysis complete, unmounting...
$ fusermount -u /tmp/image_mounter_y2LwKj
[+] All cleaned up
(Just the relevant bits)
$ file -sL /tmp/image_mounter_TG_2Ki/ewf1
< /tmp/image_mounter_TG_2Ki/ewf1: x86 boot sector
Initializing volume 0:x86 boot sector
[+] Mounting volume 0:x86 boot sector
Trying to determine fs type from 'x86 boot sector'
Trying to determine fs type from 'None'
$ blkid -p -O 0 /tmp/image_mounter_TG_2Ki/ewf1
< /tmp/image_mounter_TG_2Ki/ewf1: UUID="2EAC03A3AC036525" TYPE="ntfs" USAGE="filesystem"
Trying to determine fs type from 'ntfs'
[+] Detected ntfs as ntfs
$ fsstat /tmp/image_mounter_TG_2Ki/ewf1 -o 0
$ mount /tmp/image_mounter_TG_2Ki/ewf1 /tmp/im_0_rs27ob_ -t ntfs -o show_sys_files,noexec,force,loop,offset=0,ro
[+] Mounted volume 24.75 GiB 0:NTFS [Windows XP] on /tmp/im_0_rs27ob_.
>>> Press [enter] to unmount the volume, or ^C to keep mounted...
I am unable to mount any volumes using the most recent commit to master. I included the output showing that the volume could not be mounted. I am getting this error on several images.
# imount -vvv WinXP.E01
imagemounter version 3.1.0
[+] Mounting image WinXP.E01 using auto...
$ ewfmount -X allow_other WinXP.E01 /tmp/image_mounter_whfx6imf
Raw path to disk is /tmp/image_mounter_whfx6imf/ewf1
$ disktype /tmp/image_mounter_whfx6imf/ewf1
[+] Mounted raw image [1/1]
[+] Mounting volumes in WinXP.E01
$ mmls /tmp/image_mounter_whfx6imf/ewf1
[+] Found meta volume: block offset: 0000000000, length: 0000000001
Initializing volume 0:Primary Table (#0)
[-] Skipped 512 B 0:Primary Table (#0) meta volume
[+] Found unallocated space: block offset: 0000000000, length: 0000000063
Initializing volume 1:Unallocated
[-] Skipped 31.5 KiB 1:Unallocated unalloc volume
[+] Found allocated NTFS / exFAT (0x07): block offset: 0000000063, length: 0003140865
Initializing volume 2:NTFS / exFAT (0x07)
[+] Mounting volume 2:NTFS / exFAT (0x07)
Trying to determine fs type from fsdescription 'NTFS / exFAT (0x07)'
Current certainty levels: Counter({<class 'imagemounter.filesystems.NtfsFileSystem'>: 40, <class 'imagemounter.filesystems.ExfatFileSystem'>: 30, <class 'imagemounter.filesystems.FatFileSystem'>: -50})
Highest certainty item is lower than 50, continuing...
Trying to determine fs type from guid 'None'
$ blkid -p -O 32256 /tmp/image_mounter_whfx6imf/ewf1
Trying to determine fs type from blikid 'ntfs'
Current certainty levels: Counter({<class 'imagemounter.filesystems.NtfsFileSystem'>: 140, <class 'imagemounter.filesystems.ExfatFileSystem'>: 30, <class 'imagemounter.filesystems.FatFileSystem'>: -50})
$ fsstat /tmp/image_mounter_whfx6imf/ewf1 -o 63 -f ntfs
$ mount /tmp/image_mounter_whfx6imf/ewf1 /tmp/im_2_k5hh6gc0_ -o show_sys_files,noexec,force,streams_interface=windows,loop,offset=32256,sizelimit=1608122880,ro -t ntfs
[-] Could not mount volume 1.5 GiB 2:NTFS [Windows XP]
[+] Found unallocated space: block offset: 0003140928, length: 0000004800
Initializing volume 3:Unallocated
[-] Skipped 2.34 MiB 3:Unallocated unalloc volume
[+] Parsed all volumes!
[+] Analysis complete, unmounting...
[+] Unmounting volume 2:NTFS / exFAT (0x07)
$ umount /tmp/im_2_k5hh6gc0_
$ fusermount -u /tmp/image_mounter_whfx6imf
[+] All cleaned up
I tried the same command, but using everything except for the most recent commit (everything up to and including Rename fstype to filesystem). That seems to work so I'd like to get a better idea of the intended changes in the most recent commit to master and what it would take to fix the new volume errors.
# imount -vvv WinXP.E01
imagemounter version 3.1.0
[+] Mounting image WinXP.E01 using auto...
$ ewfmount -X allow_other WinXP.E01 /tmp/image_mounter_tf9ud80k
Raw path to disk is /tmp/image_mounter_tf9ud80k/ewf1
$ disktype /tmp/image_mounter_tf9ud80k/ewf1
[+] Mounted raw image [1/1]
[+] Mounting volumes in WinXP.E01
$ mmls /tmp/image_mounter_tf9ud80k/ewf1
[+] Found meta volume: block offset: 0000000000, length: 0000000001
Initializing volume 0:Primary Table (#0)
[-] Skipped 512 B 0:Primary Table (#0) meta volume
[+] Found unallocated space: block offset: 0000000000, length: 0000000063
Initializing volume 1:Unallocated
[-] Skipped 31.5 KiB 1:Unallocated unalloc volume
[+] Found allocated NTFS / exFAT (0x07): block offset: 0000000063, length: 0003140865
Initializing volume 2:NTFS / exFAT (0x07)
[+] Mounting volume 2:NTFS / exFAT (0x07)
Trying to determine fs type from fsdescription 'NTFS / exFAT (0x07)'
Current certainty levels: Counter({<class 'imagemounter.filesystems.NtfsFileSystem'>: 40, <class 'imagemounter.filesystems.ExfatFileSystem'>: 30, <class 'imagemounter.filesystems.FatFileSystem'>: -50})
Highest certainty item is lower than 50, continuing...
Trying to determine fs type from guid 'None'
$ blkid -p -O 32256 /tmp/image_mounter_tf9ud80k/ewf1
Trying to determine fs type from blikid 'ntfs'
Current certainty levels: Counter({<class 'imagemounter.filesystems.NtfsFileSystem'>: 140, <class 'imagemounter.filesystems.ExfatFileSystem'>: 30, <class 'imagemounter.filesystems.FatFileSystem'>: -50})
$ fsstat /tmp/image_mounter_tf9ud80k/ewf1 -o 63 -f ntfs
$ mount /tmp/image_mounter_tf9ud80k/ewf1 /tmp/im_2_1j_bjy6c_ -o show_sys_files,noexec,force,streams_interface=windows,loop,offset=32256,sizelimit=1608122880,ro -t ntfs
[+] Mounted volume 1.5 GiB 2:NTFS [Windows XP] on /tmp/im_2_1j_bjy6c_.
>>> Press [enter] to unmount the volume, or ^C to keep mounted...
[+] Unmounting volume 2:NTFS / exFAT (0x07)
$ umount /tmp/im_2_1j_bjy6c_
[+] Found unallocated space: block offset: 0003140928, length: 0000004800
Initializing volume 3:Unallocated
[-] Skipped 2.34 MiB 3:Unallocated unalloc volume
[+] Parsed all volumes!
[+] Analysis complete, unmounting...
$ fusermount -u /tmp/image_mounter_tf9ud80k
[+] All cleaned up
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.