Giter VIP home page Giter VIP logo

flare-wmi's People

Contributors

davidpany avatar williballenthin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flare-wmi's Issues

Index mapping entry count off by several hundred in some cases

In some mapping files I encountered, the mapping_entry_count is too high by several hundred entries, causing an EOF error when trying to parse it (https://github.com/fireeye/flare-wmi/blob/master/python-cim/cim/cim.py#L55).

This seems to only happens for the index mapping (hence the EOF). When "bruteforcing" (calculating backwards from the end of the file) the free_dword_count field, you can see that the actual amount of mapping entries should be way lower.

I haven't found any hint on how to calculate this offset, so I was hoping maybe you spotted something while researching the format that could explain this.

Unfortunately I'm unable to share said "corrupt" files. They still seem to work fine as far as Windows is concerned, though.

CIM key segment separator seems to be \ not /

Regarding: https://github.com/fireeye/flare-wmi/blob/master/python-cim/cim/cim.py#L300

python-cim uses the / as the CIM key segment separator but judging from the data it looks like the CIM key segment separator should be \ instead e.g.

\NS_E98854F51C0C7D3BA51357D7346C8D70\KI_69B44508F5182CE4342AEEFF63CE23FF\I_6860E034D074AB5C3CBA1074FBB6B982

In:

0x00000000  11 00 00 00 52 00 4f 00  4f 00 54 00 5c 00 73 00  ....R.O.O.T.\.s.
0x00000010  75 00 62 00 73 00 63 00  72 00 69 00 70 00 74 00  u.b.s.c.r.i.p.t.
0x00000020  69 00 6f 00 6e 00 23 00  00 00 5f 00 5f 00 45 00  i.o.n.#..._._.E.
0x00000030  76 00 65 00 6e 00 74 00  43 00 6f 00 6e 00 73 00  v.e.n.t.C.o.n.s.
0x00000040  75 00 6d 00 65 00 72 00  50 00 72 00 6f 00 76 00  u.m.e.r.P.r.o.v.
0x00000050  69 00 64 00 65 00 72 00  52 00 65 00 67 00 69 00  i.d.e.r.R.e.g.i.
0x00000060  73 00 74 00 72 00 61 00  74 00 69 00 6f 00 6e 00  s.t.r.a.t.i.o.n.
0x00000070  08 00 00 00 70 00 72 00  6f 00 76 00 69 00 64 00  ....p.r.o.v.i.d.
0x00000080  65 00 72 00 6b 00 00 00  5c 00 4e 00 53 00 5f 00  e.r.k...\.N.S._.
0x00000090  45 00 39 00 38 00 38 00  35 00 34 00 46 00 35 00  E.9.8.8.5.4.F.5.
0x000000a0  31 00 43 00 30 00 43 00  37 00 44 00 33 00 42 00  1.C.0.C.7.D.3.B.
0x000000b0  41 00 35 00 31 00 33 00  35 00 37 00 44 00 37 00  A.5.1.3.5.7.D.7.
0x000000c0  33 00 34 00 36 00 43 00  38 00 44 00 37 00 30 00  3.4.6.C.8.D.7.0.
0x000000d0  5c 00 4b 00 49 00 5f 00  36 00 39 00 42 00 34 00  \.K.I._.6.9.B.4.
0x000000e0  34 00 35 00 30 00 38 00  46 00 35 00 31 00 38 00  4.5.0.8.F.5.1.8.
0x000000f0  32 00 43 00 45 00 34 00  33 00 34 00 32 00 41 00  2.C.E.4.3.4.2.A.
0x00000100  45 00 45 00 46 00 46 00  36 00 33 00 43 00 45 00  E.E.F.F.6.3.C.E.
0x00000110  32 00 33 00 46 00 46 00  5c 00 49 00 5f 00 36 00  2.3.F.F.\.I._.6.
0x00000120  38 00 36 00 30 00 45 00  30 00 33 00 34 00 44 00  8.6.0.E.0.3.4.D.
0x00000130  30 00 37 00 34 00 41 00  42 00 35 00 43 00 33 00  0.7.4.A.B.5.C.3.
0x00000140  43 00 42 00 41 00 31 00  30 00 37 00 34 00 46 00  C.B.A.1.0.7.4.F.
0x00000150  42 00 42 00 36 00 42 00  39 00 38 00 32 00 00 00  B.B.6.B.9.8.2...
0x00000160  00 00 00 00 00 00                                 ......

Also notice the leading .

I would suggest python-cim sticking to representation that is closest to the format, unless not possible.

[Question] Support for other versions other than xp/win7 ?

So we were trying to parse a Win 2012 CIM db and consistently get a MissingIndexFileError when passing win7 as an argument with the 2012 db.
Just wanted to make sure that this is expected if we try to parse a CIM belonging to a different version.

Thanks!

MissingMappingFileError

via @BannersSecret in #2:

Thanks for coming back to me so quickly. When I run that, I get:

Traceback (most recent call last):
  File "samples/list.py", line 29, in <module>
    main(*sys.argv[1:])
  File "samples/list.py", line 22, in main
    tree = Tree(c)
  File "/usr/local/lib/python2.7/dist-packages/cim/objects.py", line 1577, in __init__
    self._object_resolver = ObjectResolver(cim, Index(cim.cim_type, cim.logical_index_store))
  File "/usr/local/lib/python2.7/dist-packages/funcy/objects.py", line 25, in __get__
    res = instance.__dict__[self.fget.__name__] = self.fget(instance)
  File "/usr/local/lib/python2.7/dist-packages/cim/cim.py", line 774, in logical_index_store
    return LogicalIndexStore(self, self._index_file_path, self.index_mapping)
  File "/usr/local/lib/python2.7/dist-packages/cim/cim.py", line 765, in index_mapping
    _, current_index_mapping = self.mappings
  File "/usr/local/lib/python2.7/dist-packages/funcy/objects.py", line 25, in __get__
    res = instance.__dict__[self.fget.__name__] = self.fget(instance)
  File "/usr/local/lib/python2.7/dist-packages/cim/cim.py", line 746, in mappings
    fp = self._current_mapping_file
  File "/usr/local/lib/python2.7/dist-packages/funcy/objects.py", line 25, in __get__
    res = instance.__dict__[self.fget.__name__] = self.fget(instance)
  File "/usr/local/lib/python2.7/dist-packages/cim/cim.py", line 739, in _current_mapping_file
    raise MissingMappingFileError()
cim.cim.MissingMappingFileError

The 'wbem' folder contains all the files extracted from that folder on the suspect machine. Have I done that right.....?

Thanks again for your help.

Compile Error - Win 8.1

Tried to build using VS2013 and VS2015 and received the error below.

"Error 1 error C1083: Cannot open include file: 'vld.h': No such file or directory [enter full path here]\wmiparser\includevld.h 5 1 WMIParser"

run time error on kali with python 3.5

Hi,
I have installed python-cim using the ubuntu script. I changed the version strings for python 3.4 onto 3.5. The installation was successful. When starting up I get the output below.

Any idea what needs to be changed?

Thx

DEBUG:cim.cim.CIM:_current_mapping_file: finding current mapping file
DEBUG:cim.cim.CIM:_current_mapping_file: MAPPING1.MAP: version: 0xaa88
DEBUG:cim.cim.CIM:_current_mapping_file: MAPPING2.MAP: version: 0xaa73
DEBUG:cim.cim.CIM:_current_mapping_file: MAPPING3.MAP: version: 0xaa79
DEBUG:cim.cim.CIM:_current_mapping_file: current mapping file: wbem/Repository/MAPPING1.MAP
QApplication: invalid style override passed, ignoring it.
DEBUG:PyQt5.uic.uiparser:UI version is 4.0
DEBUG:PyQt5.uic.uiparser:uiname is MainWindow
DEBUG:PyQt5.uic.uiparser:toplevel widget is QMainWindow
DEBUG:PyQt5.uic.properties:setting property geometry
DEBUG:PyQt5.uic.properties:setting property windowTitle
DEBUG:PyQt5.uic.uiparser:push QMainWindow MainWindow
DEBUG:PyQt5.uic.uiparser:push QWidget centralWidget
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QVBoxLayout verticalLayout_2
DEBUG:PyQt5.uic.properties:setting property currentIndex
DEBUG:PyQt5.uic.uiparser:push QTabWidget contentTabWidget
DEBUG:PyQt5.uic.uiparser:push QWidget browseTab
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QHBoxLayout horizontalLayout_3
DEBUG:PyQt5.uic.properties:setting property orientation
DEBUG:PyQt5.uic.uiparser:push QSplitter splitter
DEBUG:PyQt5.uic.properties:setting property minimumSize
DEBUG:PyQt5.uic.uiparser:push QTreeView browseTreeView
DEBUG:PyQt5.uic.uiparser:pop widget QTreeView browseTreeView
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QSplitter object at 0x7f2ef6da9168>
DEBUG:PyQt5.uic.properties:setting property minimumSize
DEBUG:PyQt5.uic.uiparser:push QWidget browseDetails
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QVBoxLayout verticalLayout_5
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QVBoxLayout browseDetailsLayout
DEBUG:PyQt5.uic.uiparser:pop layout QVBoxLayout browseDetailsLayout
DEBUG:PyQt5.uic.uiparser:pop layout QVBoxLayout verticalLayout_5
DEBUG:PyQt5.uic.uiparser:pop widget QWidget browseDetails
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QSplitter object at 0x7f2ef6da9168>
DEBUG:PyQt5.uic.uiparser:pop widget QSplitter splitter
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QWidget object at 0x7f2ef733cf78>
DEBUG:PyQt5.uic.uiparser:pop layout QHBoxLayout horizontalLayout_3
DEBUG:PyQt5.uic.uiparser:pop widget QWidget browseTab
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QTabWidget object at 0x7f2ef733cee8>
DEBUG:PyQt5.uic.uiparser:push QWidget queryTab
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QVBoxLayout verticalLayout_3
DEBUG:PyQt5.uic.properties:setting property frameShape
DEBUG:PyQt5.uic.properties:setting property frameShadow
DEBUG:PyQt5.uic.uiparser:push QFrame queryInputFrame
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QHBoxLayout horizontalLayout_2
DEBUG:PyQt5.uic.properties:setting property text
DEBUG:PyQt5.uic.uiparser:push QLabel label_2
DEBUG:PyQt5.uic.uiparser:pop widget QLabel label_2
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QFrame object at 0x7f2ef6da9c18>
DEBUG:PyQt5.uic.uiparser:push QLineEdit queryInputLineEdit
DEBUG:PyQt5.uic.uiparser:pop widget QLineEdit queryInputLineEdit
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QFrame object at 0x7f2ef6da9c18>
DEBUG:PyQt5.uic.properties:setting property text
DEBUG:PyQt5.uic.uiparser:push QPushButton queryInputActionButton
DEBUG:PyQt5.uic.uiparser:pop widget QPushButton queryInputActionButton
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QFrame object at 0x7f2ef6da9c18>
DEBUG:PyQt5.uic.uiparser:pop layout QHBoxLayout horizontalLayout_2
DEBUG:PyQt5.uic.uiparser:pop widget QFrame queryInputFrame
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QWidget object at 0x7f2ef6da9af8>
DEBUG:PyQt5.uic.properties:setting property sizePolicy
DEBUG:PyQt5.uic.properties:setting property frameShape
DEBUG:PyQt5.uic.properties:setting property frameShadow
DEBUG:PyQt5.uic.uiparser:push QFrame queryResultsFrame
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QVBoxLayout verticalLayout_4
DEBUG:PyQt5.uic.properties:setting property orientation
DEBUG:PyQt5.uic.uiparser:push QSplitter splitter_2
DEBUG:PyQt5.uic.properties:setting property editTriggers
DEBUG:PyQt5.uic.uiparser:push QListView queryResultsList
DEBUG:PyQt5.uic.uiparser:pop widget QListView queryResultsList
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QSplitter object at 0x7f2eec074048>
DEBUG:PyQt5.uic.properties:setting property sizePolicy
DEBUG:PyQt5.uic.properties:setting property minimumSize
DEBUG:PyQt5.uic.properties:setting property frameShape
DEBUG:PyQt5.uic.properties:setting property frameShadow
DEBUG:PyQt5.uic.uiparser:push QFrame queryResultsViewFrame
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QVBoxLayout verticalLayout_6
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QVBoxLayout queryResultsViewLayout
DEBUG:PyQt5.uic.uiparser:pop layout QVBoxLayout queryResultsViewLayout
DEBUG:PyQt5.uic.uiparser:pop layout QVBoxLayout verticalLayout_6
DEBUG:PyQt5.uic.uiparser:pop widget QFrame queryResultsViewFrame
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QSplitter object at 0x7f2eec074048>
DEBUG:PyQt5.uic.uiparser:pop widget QSplitter splitter_2
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QFrame object at 0x7f2ef6da9ee8>
DEBUG:PyQt5.uic.uiparser:pop layout QVBoxLayout verticalLayout_4
DEBUG:PyQt5.uic.uiparser:pop widget QFrame queryResultsFrame
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QWidget object at 0x7f2ef6da9af8>
DEBUG:PyQt5.uic.properties:setting property sizePolicy
DEBUG:PyQt5.uic.properties:setting property frameShape
DEBUG:PyQt5.uic.properties:setting property frameShadow
DEBUG:PyQt5.uic.uiparser:push QFrame frame_2
DEBUG:PyQt5.uic.properties:setting property pyuicMargins
DEBUG:PyQt5.uic.properties:setting property pyuicSpacing
DEBUG:PyQt5.uic.uiparser:push QHBoxLayout horizontalLayout
DEBUG:PyQt5.uic.properties:setting property text
DEBUG:PyQt5.uic.uiparser:push QPushButton queryResultsSaveButton
DEBUG:PyQt5.uic.uiparser:pop widget QPushButton queryResultsSaveButton
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QFrame object at 0x7f2eec074318>
DEBUG:PyQt5.uic.uiparser:pop layout QHBoxLayout horizontalLayout
DEBUG:PyQt5.uic.uiparser:pop widget QFrame frame_2
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QWidget object at 0x7f2ef6da9af8>
DEBUG:PyQt5.uic.uiparser:pop layout QVBoxLayout verticalLayout_3
DEBUG:PyQt5.uic.uiparser:pop widget QWidget queryTab
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QTabWidget object at 0x7f2ef733cee8>
DEBUG:PyQt5.uic.uiparser:pop widget QTabWidget contentTabWidget
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QWidget object at 0x7f2ef733cca8>
DEBUG:PyQt5.uic.uiparser:pop layout QVBoxLayout verticalLayout_2
DEBUG:PyQt5.uic.uiparser:pop widget QWidget centralWidget
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QMainWindow object at 0x7f2ef733cd38>
DEBUG:PyQt5.uic.properties:setting property geometry
DEBUG:PyQt5.uic.uiparser:push QMenuBar menuBar
DEBUG:PyQt5.uic.uiparser:pop widget QMenuBar menuBar
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QMainWindow object at 0x7f2ef733cd38>
DEBUG:PyQt5.uic.uiparser:push QToolBar mainToolBar
DEBUG:PyQt5.uic.uiparser:pop widget QToolBar mainToolBar
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QMainWindow object at 0x7f2ef733cd38>
DEBUG:PyQt5.uic.uiparser:push QStatusBar statusBar
DEBUG:PyQt5.uic.uiparser:pop widget QStatusBar statusBar
DEBUG:PyQt5.uic.uiparser:new topwidget <PyQt5.QtWidgets.QMainWindow object at 0x7f2ef733cd38>
DEBUG:PyQt5.uic.properties:setting property text
DEBUG:PyQt5.uic.uiparser:pop widget QMainWindow MainWindow
DEBUG:PyQt5.uic.uiparser:new topwidget None
Traceback (most recent call last):
  File "/home/kali/cim/flare-wmi/python-cim/samples/ui/tree.py", line 203, in rowCount
    return len(parentItem.children)
  File "/home/kali/cim/flare-wmi/python-cim/samples/ui/tree.py", line 99, in children
    self._children = [TreeNode(self, c) for c in self._data.children]
  File "/home/kali/cim/env/lib/python3.5/site-packages/funcy/objects.py", line 28, in __get__
    res = instance.__dict__[self.fget.__name__] = self.fget(instance)
  File "flare-wmi/python-cim/samples/ui.py", line 79, in children
    range(self._ctx.cim.data_mapping.map.header.physical_page_count)]
  File "/home/kali/cim/env/lib/python3.5/site-packages/vstruct/__init__.py", line 395, in __getattr__
    raise AttributeError()
AttributeError
Abort

Improve CimType enum definitions based on MSDN documentation

Regarding: https://github.com/fireeye/flare-wmi/blob/master/python-cim/cim/objects.py#L81

FYI the values of the CimType enum are defined here:

The second link indicates that there potentially is a NONE or NULL type definitions as well (presumably 0 judging by other Microsoft type definitions e.g. OLE Property Types)

Unable to run ui.py - PyQt5.QtGui error

Hi,

I'm trying to get ui.py working (all the other tools are working perfectly), however I keep hitting on this error:

Traceback (most recent call last):
  File "ui.py", line 7, in <module>
    from PyQt5.QtGui import *
ImportError: No module named PyQt5.QtGui

Command used was: python ui.py win7 /path/to/wbem/repository

I've Googled this thing to death (tried mkvirtualenv solutions, manually installing Qt5, etc.) with no success.

I'm running Ubuntu 14.04 x64 in a VM, and have following the steps you've provided (used the automated script, as well as installing each dependency one at a time). Everything seems to be on.

Appreciate this isn't an issue with ui.py.

Thanks!

JSON output option

Additional functions that dump the definition, layout and instance in a JSON format.

Parser Issue.

So I'm getting some issues with the application when I try to run it. After installation and setup, I browse to the folder where "cim.py" is held. After putting in:

sudo python cim.py win7 /path/to/file 

I'm getting the error "ValueError: Attempted relative import in non-package"

So, I try python 3. Same command as above, except i use python3 instead. Then I get the error "ImportError: No module named 'funcy'". After reviewing the code of the parser, it looks like there is, in fact, a module named 'funcy'. Any thoughts as to how to get it working? Thanks!

Issues decoding unicode values in metadata

Not every field is decoding cleanly, horrible hack used to clean as built in python decoding kept dying:

python-cim/cim/objects.py

Line 514, replace function get_string in class DataRegion with:

    def get_string(self, ref):
        s = WMIString()
        s.vsParse(self.data, offset=int(ref))
        try:
            return str(s.s.decode("UTF-8"))
        except UnicodeEncodeError:
            if s.s.startswith("Microsoft") and s.s.endswith("Operating System"):
                return("Microsoft Windows Operating System")
            else:
                return("")

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.