SN0INT(1) sn0int SN0INT(1) (NAME) sn0int - OSINT (RUNNING YOUR FIRST INVESTIGATION) . sn0int . sn0int : $ sn0int ___/ . ____ , __ .' /\ ` , __ _/_ ( |' `. | / | | |' `. | `--. | | |,' | | | | | \___.' / | /`---' / / | \__/ osint | recon | security irc.hackint.org:6697/#sn0int [+] Connecting to database [+] Downloading public suffix list [+] Downloading "GeoLite2-City.mmdb" [+] Downloading "GeoLite2-ASN.mmdb" [+] Loaded 0 modules [*] No modules found, run pkg quickstart to install default modules [sn0int][default] > pkg quickstart : [sn0int][default] > pkg quickstart [+] Installing kpcyrd/asn [+] Installing kpcyrd/ctlogs [+] Installing kpcyrd/dns-resolve [+] Installing kpcyrd/geoip [+] Installing kpcyrd/hackertarget-subdomains [+] Installing kpcyrd/otx-subdomains [+] Installing kpcyrd/passive-spider [+] Installing kpcyrd/pgp-keyserver [+] Installing kpcyrd/threatminer-ipaddr [+] Installing kpcyrd/threatminer-subdomains [+] Installing kpcyrd/url-scan [+] Installing kpcyrd/waybackurls [+] Loaded 12 modules [sn0int][default] > (workspace) : [sn0int][default] > workspace demo [+] Connecting to database [sn0int][demo] > (entity) (scope) : [sn0int][demo] > add domain Domain: example.com [sn0int][demo] > : (domain) (subdomain) . public suffix . .com (public suffix) example.com sn0int domain . www.example.com (subdomain) . example.com . example.com dns (dns zone) . select : [sn0int][demo] > select domains #1, "example.com" [sn0int][demo] > : [sn0int][demo] > select domains where id=1 #1, "example.com" [sn0int][demo] > [sn0int][demo] > select domains where value like %.com #1, "example.com" [sn0int][demo] > [sn0int][demo] > select domains where ( value like e% and value like %m ) or false #1, "example.com" [sn0int][demo] > : value . (Running a module) . : [sn0int][demo] > pkg list kpcyrd/asn (0.1.0) Run a asn lookup for an ip address kpcyrd/ctlogs (0.1.0) Query certificate transparency logs to discover subdomains kpcyrd/dns-resolve (0.1.0) Query subdomains to discovery ip addresses and verify the record is visible kpcyrd/geoip (0.1.0) Run a geoip lookup for an ip address kpcyrd/hackertarget-subdomains (0.1.0) Query hackertarget for subdomains of a domain kpcyrd/otx-subdomains (0.1.0) Query alienvault otx passive dns for subdomains of a domain kpcyrd/passive-spider (0.1.0) Scrape known http responses for urls kpcyrd/pgp-keyserver (0.1.0) Query pgp keyserver for email addresses kpcyrd/threatminer-ipaddr (0.1.0) Query ThreatMiner passive dns for subdomains of an ip address kpcyrd/threatminer-subdomains (0.1.0) Query ThreatMiner passive dns for subdomains of a domain kpcyrd/url-scan (0.1.0) Scan subdomains for websites kpcyrd/waybackurls (0.1.0) Discover subdomains from wayback machine [sn0int][demo] > (certificate transparency logs) : [sn0int][demo] > use ctlogs [sn0int][demo][kpcyrd/ctlogs] > run [*] "example.com" : Subdomain: "www.example.com" [*] "example.com" : Subdomain: "m.example.com" [*] "example.com" : Subdomain: "dev.example.com" [*] "example.com" : Subdomain: "products.example.com" [*] "example.com" : Subdomain: "support.example.com" [+] Finished kpcyrd/ctlogs [sn0int][demo][kpcyrd/ctlogs] > . . : run -j3 (concurrently) . . no-sql (schema) . . dns : [sn0int][demo][kpcyrd/ctlogs] > use dns-resolve [sn0int][demo][kpcyrd/dns-resolve] > run [*] "www.example.com" : Updating "www.example.com" (resolvable => true) [*] "www.example.com" : IpAddr: 93.184.216.34 [*] "www.example.com" : "www.example.com" -> 93.184.216.34 [*] "m.example.com" : Updating "m.example.com" (resolvable => false) [*] "dev.example.com" : Updating "dev.example.com" (resolvable => false) [*] "products.example.com" : Updating "products.example.com" (resolvable => false) [*] "support.example.com" : Updating "support.example.com" (resolvable => false) [+] Finished kpcyrd/dns-resolve [sn0int][demo][kpcyrd/dns-resolve] > : IP (scope) (resolvable) . (resolvable) : [sn0int][demo][kpcyrd/dns-resolve] > use url-scan [sn0int][demo][kpcyrd/url-scan] > target #1, "www.example.com" 93.184.216.34 #2, "m.example.com" #3, "dev.example.com" #4, "products.example.com" #5, "support.example.com" [sn0int][demo][kpcyrd/url-scan] > target where resolvable [+] 1 entities selected [sn0int][demo][kpcyrd/url-scan] > target #1, "www.example.com" 93.184.216.34 [sn0int][demo][kpcyrd/url-scan] > target . : [sn0int][demo][kpcyrd/url-scan] > run [*] "www.example.com" : Url: "http://www.example.com/" (200) [*] "www.example.com" : Url: "https://www.example.com/" (200) [+] Finished kpcyrd/url-scan [sn0int][demo][kpcyrd/url-scan] > 80 443 (probe) http . (urls) : [sn0int][demo][kpcyrd/url-scan] > select urls #1, "http://www.example.com/" (200) #2, "https://www.example.com/" (200) [sn0int][demo][kpcyrd/url-scan] > . delete . (flag) . noscope : [sn0int][demo] > use ctlogs [sn0int][demo][kpcyrd/ctlogs] > target #1, "example.com" [sn0int][demo][kpcyrd/ctlogs] > add domain Domain: google.com [sn0int][demo][kpcyrd/ctlogs] > target #1, "example.com" #2, "google.com" [sn0int][demo][kpcyrd/ctlogs] > noscope domains where value=google.com [+] Updated 1 rows [sn0int][demo][kpcyrd/ctlogs] > target #1, "example.com" [sn0int][demo][kpcyrd/ctlogs] > (unscoped) . scope : [sn0int][demo][kpcyrd/ctlogs] > target #1, "example.com" [sn0int][demo][kpcyrd/ctlogs] > scope domains where true [+] Updated 2 rows [sn0int][demo][kpcyrd/ctlogs] > target #1, "example.com" #2, "google.com" [sn0int][demo][kpcyrd/ctlogs] > : unscoped=1 . (CONFIGURATION) . . Linux/BSD ~/.config/sn0int.toml OSX ~/Library/Preferences/sn0int.toml Windows %APPDATA%/sn0int.toml [core] registry . https://sn0int.com . no-autoupdate sn0int . true . sn0int . . namespace sn0int : [namespaces] foo = "/opt/sn0int/foo" bar = "~/repos/a/b/c/sn0int-modules" foo bar . sn0int ~/.local/share/sn0int/modules .git . [network] : [network] proxy = "127.0.0.1:9050" tor ( socks5 ) . dns . (FUNCTION REFERENCE) asn_lookup ASN IP . asn as_org . . lookup = asn_lookup('1.1.1.1') if last_err() then return end base64_decode base64 (padding) . base64_decode("ww==") base64_encode base64 (padding) . base64_encode("\x00\xff") base64_custom_decode base64 (padding) . -- base64 base64_custom_decode('b2hhaQ==', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', '=') -- base64 no padding base64_custom_decode('b2hhaQ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', '') -- base64 url safe base64_custom_decode('b2hhaQ==', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', '=') base64 + . -- base64 base64_custom_encode('ohai', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', '=') -- base64 no padding base64_custom_encode('ohai', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', '') -- base64 url safe base64_custom_encode('ohai', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', '=') base32_custom_decode base32 + . -- rfc-4648 base32 base32_custom_decode('N5UGC2I=', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', '=') -- z-base-32 base32_custom_decode('p7wgn4e', 'ybndrfg8ejkmcpqxot1uwisza345h769', '') base32_custom_encode base32 + . -- rfc-4648 base32 x = base32_custom_encode('ohai', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', '=') -- z-base-32 x = base32_custom_encode('ohai', 'ybndrfg8ejkmcpqxot1uwisza345h769', '') clear_err . : last_err. if last_err() then -- ignore this error clear_err() end create_blob blob. blob . blob blob . blob . blob = create_blob("some bytes") debug(blob) datetime UTC. DATETIME . now = datetime() : sn0int time_unix . : . sn0int_time . . nil . db_add . domain_id = db_add('domain', { value='example.com', }) db_add_ttl . . ttl ttl . ttl . -- this link is valid for 2min domain_id = db_add_ttl('network-device', { network_id=1, device_id=13, }, 120) db_activity . : db_activity({ topic='harness/activity-ping:dummy', time=sn0int_time(), content={ a='b', foo={ bar=1337, }, msg='ohai', }, }) activity . db_select (scope) . nil . . db_select . domain_id = db_select('domain', 'example.com') if domain_id ~= nil then -- do something end db_update . . db_update . db_update('ipaddr', arg, { asn=lookup['asn'], as_org=lookup['as_org'], }) dns . dns dns NoError x['error'] nil . x['answers'] . . : record query_type A AAAA MX AXFR . nameserver . . tcp tcp true/false. timeout . records = dns('example.com', { record='A', }) if last_err() then return end if records['error'] ~= nil then return end records = records['answers'] : DNS last_err() . . : socks5 . error . error('ohai') geoip_lookup geoip ip . : o continent o continent_code o country o country_code o city o latitude o longitude . lookup = geoip_lookup('1.1.1.1') if last_err() then return end (Hex) . hex("\x6F\x68\x61\x69\x0A\x00") hmac_md5 hmac md5. . hmac_md5("secret", "my authenticated message") hmac_sha1 hmac sha1. . hmac_sha1("secret", "my authenticated message") hmac_sha2_256 hmac sha2_256. . hmac_sha2_256("secret", "my authenticated message") hmac_sha2_512 hmac sha2_512. . hmac_sha2_512("secret", "my authenticated message") hmac_sha3_256 hmac sha3_256. . hmac_sha3_256("secret", "my authenticated message") hmac_sha3_512 hmac sha3_512. . hmac_sha3_512("secret", "my authenticated message") html_select html css . text attrs . csrf = html_select(html, 'input[name="csrf"]') token = csrf["attrs"]["value"] html_select . html_select_list(html, 'input[name="csrf"]') http_mksession (session) . requests.Session python-requests . session = http_mksession() http_request http . . . method url . {} . : query query url . headers (headers) . basic_auth basic auth {"user, "password"}. user_agent user agent . json json . form form . follow_redirects (redirects) . 1 . 0 . body . into_blob true blob blob blob . proxy socks5 127.0.0.1:9050. . binary true http . . req = http_request(session, 'POST', 'https://httpbin.org/post', { json={ user=user, password=password, } }) resp = http_send(req) if last_err() then return end if resp['status'] ~= 200 then return 'http status error: ' .. resp['status'] end http_request . : status http headers text binary ( binary=true) blob into_blob blob . req = http_request(session, 'POST', 'https://httpbin.org/post', { json={ user=user, password=password, } }) resp = http_send(req) if last_err() then return end if resp['status'] ~= 200 then return 'http status error: ' .. resp['status'] end http_fetch http_send . : into_blob blob . -- short form data = http_fetch(req) if last_err() then return end -- long form resp = http_send(req) if last_err() then return end if resp['status'] ~= 200 then return 'http status error: ' .. resp['status'] end http_fetch_json http_fetch json . -- short form data = http_fetch_json(req) if last_err() then return end -- long form resp = http_send(req) if last_err() then return end if resp['status'] ~= 200 then return 'http status error: ' .. resp['status'] end data = json_decode(resp['text']) if last_err() then return end blob mime type . img = img_load(blob) if last_err() then return end debug(img) img_exif exif . exif = img_exif(blob) if last_err() then return end debug(exif) img_ahash Mean (aHash). hash = img_ahash(blob) if last_err() then return end debug(hash) img_dhash Gradient (dHash). hash = img_dhash(blob) if last_err() then return end debug(hash) img_phash DCT (pHash). hash = img_phash(blob) if last_err() then return end debug(hash) img_nudity . 0 2 . 1 . nudity = img_nudity(blob) if last_err() then return end debug(nudity) (info) . info('ohai') intval . x = strval('1234') json_decode lua json. json_decode("{\"data\":{\"password\":\"fizz\",\"user\":\"bar\"},\"list\":[1,3,3,7]}") json_decode_stream json_decode json . json_decode_stream("{\"data\":1}{\"data\":2}") json_encode . x = json_encode({ some=1, fancy={ data='structures', } }) print(x) key_trunc_pad (truncate/pad) . -- if longer than 32 bytes: truncate to 32 -- if shorter than 32 bytes: pad with \x00 local key = key_trunc_pad(password, 32, 0) keyring (namespace) . keyring . creds = keyring('aws') print(creds[1]['accesskey']) print(creds[1]['secretkey']) ( ) . nil . if last_err() then -- Something went wrong, abort return end md5 md5 . hex(md5("\x00\xff")) mqtt_connect mqtt . local sock = mqtt_connect('mqtts://mqtt.example.com', { username='foo', password='secret', }) if last_err() then return end mqtt_subscribe (topic) . QoS 0 . mqtt_subscribe(sock, '#', 0) if last_err() then return end mqtt_recv mqtt . publish . (read timeout) mqtt_connect nil . local pkt = mqtt_recv(sock) if last_err() then return end if pkt == nil then -- read timeout, consider sending a ping or disconnect if the previous ping failed elseif pkt['type'] == 'pong' then -- broker sent a pong elseif pkt['type'] == 'publish' then local payload = utf8_decode(pkt['body']) if last_err() then return end info(payload) end mqtt_ping pingreq pingresp . . mqtt_ping(sock) if last_err() then return end pgp_pubkey_armored unarmor. pgp_pubkey_armored uids sigs fingerprint pgp rfc 4880. . key = pgp_pubkey_armored([===[ -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2 mQENBFu6q90BCADgD7Q9aH5683yt7hzPktDkAUNAZJHwYhUNeyGK43frPyDRWQmq N+oXTfiYWLQN+d7KNBTnF9uwyBdaLM7SH44lLNYo8W09mVM2eK+wt19uf5HYNgAE 8la45QLo/ce9CQVe1a4oXNWq6l0FOY7M+wLe+G2wMwz8RXGgwd/qQp4/PB5YpUhx nAnzClxvwymrL6BQXsRcKSMSD5bIzIv95n105CvW5Hql7JR9zgOR+gHqVOH8HBUc ZxMumrTM6aKLgAhgM8Sn36gCFOfjlG1b1OFLZhUtgro/nnEOmAurRsCZy8M5h8QM FpZChIH8kgHs90F/CCvGjMq3qvWcH8ZsPUizABEBAAG0NUhhbnMgQWNrZXIgKGV4 YW1wbGUgY29tbWVudCkgPGhhbnMuYWNrZXJAZXhhbXBsZS5jb20+iQFOBBMBCAA4 FiEEyzeO1eEwbB03hcqBM00IodGdlj8FAlu6q90CGwMFCwkIBwIGFQgJCgsCBBYC AwECHgECF4AACgkQM00IodGdlj/AJQgAjmk+iP5b7Jt7+f+lU4Oprlf3f3DG/uh5 Ge6MjV7cvtxlhZJRD5hxGt9RwwnEp61TBSbrem288pM89ilQfTNe0wUr9OzwWzh/ 8Ngl5iWnD2ah3Mpi5R1V/YMNf2cnwVjqNvfkRHdNc43pZOkC2GoiTUn0QY0UBpOW ZMN3//ANi6ZtiK/L0IZQND/gKvOzu/4tfaJeBl26T3cVYj53p3G3jhlb92vVa8SR uL3S3bzd1h5snDgU1uXHmNHGbhkEc4KUneQ0V9/bdZrg6OzFAfM1ghgfoId+YpQH er9L26ISL3QF58wdEXfIdHYEmMlANjBMO2cUlQXgONuCgkMuY7GBmrkBDQRbuqvd AQgA41jqCumCxYV0NdSYNnTSSDRyd69dOUYCAPT80iZ739s7KKJS9X9KVfGmDjfi u2RcfR/KYj53HoyOm4Pm/+ONN8De4ktzXpIpJxGC+O8NBvd9vkboAS6qnCjK7KVE r91ymxxVKp2dzZvVfpIjWVZR5i2EAvS5vw8UK4gL8ALH+S9leJFZrQWcgyoJOJzH Rzr9pesX2HvdgcNG1O6QUArlsnsTnqpi/hu7tQa8tifBpWDeArOA23Y2DgeehdDF lSU/8KD4J+AkFrWWlcTaMsvSChXQkCHEMRIcSOfXtdpX5KJSE7UBQdD1opm+mR79 VeHnuJAAVZZtUZmJA7pjdKykYQARAQABiQE2BBgBCAAgFiEEyzeO1eEwbB03hcqB M00IodGdlj8FAlu6q90CGwwACgkQM00IodGdlj8bMAf+Lq3Qive4vcrCTT4IgvVj arOACdcbtt5RhVBTimT19rDWNH+m+PfPjo3FSlBj5cm70KAXUS2LBFFxhakTZ/Mq cQroWZpVbBxj4kipEVVJZFdUZQaDERJql0xYGOQrNMQ4JGqJ84BRrtOExjSqo41K hAhNe+bwPGH9/Igiixc4tH07xa7TOy4MyJv/6gpbHy/lW1hqpCAgM5fT/im5/6QF k0tED6vIuc54IWiOmwCnjZiQnJ8uCwEu+cuJ5Exwy9CNERLp5v0y4eG+0E+at9j/ macOg39qf09t53pTqe9dWv5NIi319TeBsKZ2lb0crrQjsbHqk0DAUwgQuoANqLku vA== =kRIv -----END PGP PUBLIC KEY BLOCK----- ]===]) if last_err() then return end print(key) print . print({ some=1, fancy={ data='structures', } }) : . . psl_domain_from_dns_name (public suffix list) . www.a.b.c.d.example.co.uk example.co.uk . domain = psl_domain_from_dns_name('www.a.b.c.d.example.co.uk') print(domain == 'example.co.uk') (ratelimit) y x . run thread . -- allow this to pass every 250ms ratelimit_throttle('foo', 1, 250) -- allow this to pass not more than 4 times per second ratelimit_throttle('foo', 4, 1000) . regex_find regex . regex nil (capture groups) . m = regex_find(".(.)", "abcdef") if m == nil then print('No captures') end print(m[1] == 'ab') print(m[2] == 'b') regex_find_all regex_find . m = regex_find_all(".(.)", "abcdef") print(m[1][1] == 'ab') print(m[1][2] == 'b') print(m[2][1] == 'cd') print(m[2][2] == 'd') print(m[3][1] == 'ef') print(m[3][2] == 'f') semver_match . sn0int_version . semver_match('=0.11.2', sn0int_version()) semver_match('>0.11.2', sn0int_version()) semver_match('<0.11.2', sn0int_version()) semver_match('~0.11.2', sn0int_version()) semver_match('^0.11.2', sn0int_version()) semver_match('0.11.2', sn0int_version()) -- synonym for ^0.11.2 semver_match('<=0.11.2', sn0int_version()) semver_match('>=0.11.2', sn0int_version()) semver_match('>=0.4.0, <=0.10.0', sn0int_version()) set_err (global error object). run . set_err rust . function foo() set_err("something failed") end foo() if last_err() then return end sha1 . hex(sha1("\x00\xff")) sha2_256 sha2_256 . hex(sha2_256("\x00\xff")) sha2_512 sha2_512 . hex(sha2_512("\x00\xff")) sha3_256 sha3_256 . hex(sha3_256("\x00\xff")) sha3_512 sha3_512 . hex(sha3_512("\x00\xff")) sleep . . sleep(1) sn0int_time UTC . DATETIME . now = sn0int_time() : sn0int time_unix . sn0int_time (unix timestamp) . time_unix strptime . time = sn0int_time_from(1567931337) sn0int_version sn0int . semver_match . info(sn0int_version()) sock_connect tcp . : tls tls true ( ). sni_value host sni . disable_tls_verify : tls. . sn0int (ciphers) . proxy socks5 127.0.0.1:9050. . connect_timeout tcp n . read_timeout n . . write_timeout n . sock = sock_connect("127.0.0.1", 1337, { tls=true, }) sock_upgrade_tls tcp tls . sock_connect tls true . sni sni . sock_connect tls=true . sock = sock_connect("127.0.0.1", 1337, {}) if last_err() then return end tls = sock_upgrade_tls(sock, { sni_value='example.com', }) if last_err() then return end info(tls) : read_timeout n . . write_timeout n . sock_options(sock, { read_timeout=3, }) sock_send . sock_send(sock, "hello world") sock_recv . x = sock_recv(sock) sock_sendline . (newline) . sock_sendline(sock, line) sock_recvline . . x = sock_recvline(sock) sock_recvall EOF. x = sock_recvall(sock) sock_recvline_contains needle . x = sock_recvline_contains(sock, needle) (regex) . x = sock_recvline_regex(sock, "^250 ") sock_recvn n . x = sock_recvn(sock, 4) sock_recvuntil needle needle. x = sock_recvuntil(sock, needle) sock_sendafter needle data . sock_sendafter(sock, needle, data) sock_newline \n. sock_newline(sock, "\r\n") sodium_secretbox_open . crypto_secretbox_xsalsa20poly1305 . key_trunc_pad . nonce . plain = sodium_secretbox_open(encrypted, key) if last_err() then return end txt = utf8_decode(plain) if last_err() then return end info(txt) status . status('ohai') stdin . . stdin_readline() : sn0int run --stdin . stdin_read_to_end stdin EOF utf-8 . stdin_read_to_end() : sn0int run --stdin . str_find . (literal) lua. nil . x = str_find('asdf', 'sd') print(x == 2) str_replace . (literal) lua. . x = str_replace('this is old', 'old', 'new') print(x == 'this is new') strftime (timestamp) time_unix strftime. t = strftime('%d/%m/%Y %H:%M', 1558584994) strptime (unix timestamp) strftime. t = strptime('%d/%m/%Y %H:%M', '23/05/2019 04:16') . x = strval(1234) time_unix 1 1970 0:00:00 UTC (UNIX timestamp) . strftime . now = time_unix() url_decode (query string) (map). url_unescape . v = url_decode('a=b&c=d') print(v['a'] == 'b') print(v['c'] == 'd') url_encode (map) (query string). url_escape . v = url_encode({ a='b', c='d', }) print(v == 'a=b&c=d') url_escape (url escaping) . v = url_escape('foo bar?') print(v == 'foo%20bar%3F') url_join . : x = url_join('https://example.com/x', '/foo') print(x == 'https://example.com/foo') x = url_join('https://example.com/x', 'https://github.com/') print(x == 'https://github.com/') url_parse url . : o scheme o host o port o path o query o fragment o params url = url_parse('https://example.com') print(url['scheme'] == 'https') print(url['host'] == 'example.com') print(url['path'] == '/') (URL escaping) . v = url_unescape('foo%20bar%3F') print(v == 'foo bar?') utf8_decode / . . x = utf8_decode({65, 65, 65, 65}) if last_err() then return end print(x == 'AAAA') warn . warn('ohai') warn_once . run . warn_once('ohai') warn_once('ohai') ws_connect websocket. ws://example.com/asdf wss:// . : headers (headers) . proxy socks5 127.0.0.1:9050. . connect_timeout tcp n . read_timeout n . . write_timeout n . sock = ws_connect("wss://example.com/asdf", {}) : read_timeout n . . write_timeout n . ws_options(sock, { read_timeout=3, }) ws_recv_text . . Ping . msg = ws_recv_text(sock) ws_recv_binary . . Ping . msg = ws_recv_binary(sock) ws_recv_json ws_send_text json_decode . msg = ws_recv_json(sock) ws_send_text websocket. ws_send_text(sock, "ohai!") ws_send_binary websocket. ws_send_binary(sock, "\x00\x01\x02") json websocket . ws_send_text(sock, { foo="ohai!", x={ y={1,3,3,7}, }, }) x509_parse_pem pem . . x = x509_parse_pem([[-----BEGIN CERTIFICATE----- MIID9DCCA3qgAwIBAgIQBWzetBRl/ycHFsBukRYuGTAKBggqhkjOPQQDAjBMMQsw CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSYwJAYDVQQDEx1EaWdp Q2VydCBFQ0MgU2VjdXJlIFNlcnZlciBDQTAeFw0xODAzMzAwMDAwMDBaFw0yMDAz MjUxMjAwMDBaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMN U2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEdMBsGA1UE AwwUKi5jbG91ZGZsYXJlLWRucy5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC AASyRQsxrFBjziHmfDQjGsXBU0WWl3oxh7vg6h2V9f8lBMp18PY/td9R6VvJPa20 AwVzIJI+dL6OSxviaIZEbmK7o4ICHDCCAhgwHwYDVR0jBBgwFoAUo53mH/naOU/A buiRy5Wl2jHiCp8wHQYDVR0OBBYEFN+XTeVDs7BBp0LykM+Jf64SV4ThMGMGA1Ud EQRcMFqCFCouY2xvdWRmbGFyZS1kbnMuY29thwQBAQEBhwQBAAABghJjbG91ZGZs YXJlLWRucy5jb22HECYGRwBHAAAAAAAAAAAAERGHECYGRwBHAAAAAAAAAAAAEAEw DgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBp BgNVHR8EYjBgMC6gLKAqhihodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1l Y2MtZzEuY3JsMC6gLKAqhihodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc3NjYS1l Y2MtZzEuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEW HGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMHsGCCsGAQUF BwEBBG8wbTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEUG CCsGAQUFBzAChjlodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRF Q0NTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADAKBggqhkjOPQQDAgNo ADBlAjEAjoyy2Ogh1i1/Kh9+psMc1OChlQIvQF6AkojZS8yliar6m8q5nqC3qe0h HR0fExwLAjAueWRnHX4QJ9loqMhsPk3NB0Cs0mStsNDNG6/DpCYw7XmjoG3y1LS7 ZkZZmqNn2Q8= -----END CERTIFICATE----- ]]) if last_err() then return end print(x) xml_decode lua xml . x = xml_decode('bar') if last_err() then return end body = x['children'][1] foo = body['children'][1] print(foo['attrs']['fizz']) print(foo['text']) xml_named . x = xml_decode('bar') if last_err() then return end body = x['children'][1] foo = xml_named(body, 'foo') if foo ~= nil then print(foo) end kpcyrd (COPYRIGHT) 2018-2020, kpcyrd July 17, 2025 SN0INT(1)