Basic Python IRC Op/Flood Bot (Manual)

opbot.py

#!/usr/bin/python
import os
import re
import socket
import sys
import time
def outp(s, l):
	print(">%s<" % (l))
	s.send("%s\r\n" % (l))
def main():
	print("Usage: prog [server] [nick] [pass] [chans]")
	sockdata = ""
	sockline = []
	linenumb = 0
	sockobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	sockobjc.connect((sys.argv[1], 6667))
	outp(sockobjc, "NICK %s" % (sys.argv[2]))
	outp(sockobjc, "USER pyop * * :pyop")
	while (1):
		sockdata += sockobjc.recv(1024)
		templist = sockdata.split("\n")
		templeng = len(templist)
		if (templeng > 1):
			for x in range(0, templeng - 1):
				sockline.append(templist[x].strip())
			sockdata = templist[templeng - 1]
		while (len(sockline) > 0):
			print("["+sockline[0]+"]")
			testline = sockline[0].lower()
			if (testline[:6] == "ping :"):
				outp(sockobjc, "PONG :%s" % (sockline[0][6:]))
			if (linenumb == 8):
				for channame in sys.argv[4:]:
					outp(sockobjc, "JOIN #%s" % (channame))
				linenumb += 1
			regxobjc = re.match("^:(.+)!(.+)@(.+)[ ]+privmsg[ ]+([^#]+)[ ]+:[ ]*%s[ ]+(.+)$" % (sys.argv[3]), sockline[0], re.I)
			if (regxobjc):
				outp(sockobjc, str(regxobjc.group(5)))
			sockline.pop(0)
			if (linenumb < 8):
				linenumb = min(linenumb + 1, 8)
if (__name__ == "__main__"):
	main()

floobot.py

#!/usr/bin/python
import os
import re
import socket
import sys
import time
def outp(s, l):
	print(">%s<" % (l))
	s.send("%s\r\n" % (l))
def pban(n, u, h, b):
	d = {"bh":".", "b4":".", "b6":":", "un":""}
	t = "un"; l = [h]
	if (re.match("^[0-9A-Za-z.-]+$", h, re.I)):
		t = "bh"; l = h.split(d["bh"])
	ipvf = h.split(d["b4"])
	if (len(ipvf) == 4):
		flag = 1
		try:
			for i in ipvf:
				j = int(i)
				if ((j < 0x00) or (0xff < j)):
					flag = 0
		except:
			flag = 0
		if (flag == 1):
			t = "b4"; l = ipvf
	ipvs = h.split(d["b6"])
	if ((2 < len(ipvs)) and (len(ipvs) < 9)):
		flag = 1
		for i in ipvs:
			if (not re.match("^[0-9a-f]{0,4}$", i, re.I)):
				flag = 0
		if (flag == 1):
			t = "b6"; l = ipvs
	try:
		mask = b[t].split("@")
		if (mask[0] == "l"):
			x = 0; m = (len(l) - 1); a = 1; c = -1
		if (mask[0] == "r"):
			x = (len(l) - 1); m = 0; a = -1; c = 1
		i = int(mask[1]); k = 0; j = abs(i)
		if (not mask[2]):
			mask[2] = None
		while (x != m):
			if (i > 0):
				l[x] = mask[2]
				i -= 1
			if (i < 0):
				if ((a == 1) and (k < (m + 1 - j))):
					l[k] = mask[2]
				if ((a != 1) and (k > (j - 1))):
					l[k] = mask[2]
				k += 1
			x += a
		while (None in l):
			l.remove(None)
		if (mask[0] == "l"):
			return ("%s@%s%s" % (b["mk"] % {"n":n, "u":u}, mask[3], d[t].join(l)))
		if (mask[0] == "r"):
			return ("%s@%s%s" % (b["mk"] % {"n":n, "u":u}, d[t].join(l), mask[3]))
	except:
		pass
	return ("%s@%s" % (b["mk"] % {"n":n, "u":u}, d[t].join(l)))
def main():
	print("Usage: prog [server] [nick] [pass] [chans]")
	sockdata = ""
	sockline = []
	linenumb = 0
	# note: the number order relates to: amount, time
	floorate = {"ki":[10, 30], "bk":[2, 90], "un":[9999, 3600]}
	# note: the ban mask should include: direction@depth@replacement@postfix
	banmasks = {"mk":"*!*", "bh":"l@-6@@*", "b4":"r@0@*@", "b6":"r@0@*@", "un":""}
	flootime = {}
	floocmds = {"ki":["KICK %(chan)s %(nick)s :kick-flood-trigger"], "bk":["MODE %(chan)s +b %(mask)s", "KICK %(chan)s %(nick)s :ban-flood-trigger"], "un":["MODE %(chan)s -b %(mask)s"]}
	sockobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	sockobjc.connect((sys.argv[1], 6667))
	outp(sockobjc, "NICK %s" % (sys.argv[2]))
	outp(sockobjc, "USER pyop * * :pyop")
	while (1):
		sockdata += sockobjc.recv(1024)
		templist = sockdata.split("\n")
		templeng = len(templist)
		if (templeng > 1):
			for x in range(0, templeng - 1):
				sockline.append(templist[x].strip())
			sockdata = templist[templeng - 1]
		prestime = int(time.time())
		while (len(sockline) > 0):
			print("["+sockline[0]+"]")
			testline = sockline[0].lower()
			if (testline[:6] == "ping :"):
				outp(sockobjc, "PONG :%s" % (sockline[0][6:]))
			if (linenumb == 8):
				for channame in sys.argv[4:]:
					outp(sockobjc, "JOIN #%s" % (channame))
				linenumb += 1
			regxobjc = re.match("^:(.+)!(.+)@(.+)[ ]+privmsg[ ]+([^#]+)[ ]+:[ ]*%s[ ]+(.+)$" % (sys.argv[3]), sockline[0], re.I)
			if (regxobjc):
				comdlist = str(regxobjc.group(5)).split(" ")
				comdleng = len(comdlist)
				comdflag = 0
				if (comdleng > 2):
					for flootype in floorate.keys():
						if (comdlist[0] == flootype):
							try:
								floorate[flootype] = [int(comdlist[1]), int(comdlist[2])]
								outp(sockobjc, "PRIVMSG %s :SET: %s" % (str(regxobjc.group(1)), comdlist))
							except:
								pass
							comdflag = 1
				if (comdleng > 1):
					for masktype in banmasks.keys():
						if (comdlist[0] == masktype):
							try:
								banmasks[masktype] = comdlist[1]
								outp(sockobjc, "PRIVMSG %s :SET: %s" % (str(regxobjc.group(1)), comdlist))
							except:
								pass
							comdflag = 1
				if (comdflag == 0):
					outp(sockobjc, str(regxobjc.group(5)))
			regxobjc = re.match("^:(.+)!(.+)@(.+)[ ]+privmsg[ ]+(#.+)[ ]+.*$", sockline[0], re.I)
			if (regxobjc):
				nickname = str(regxobjc.group(1))
				username = str(regxobjc.group(2))
				hostname = str(regxobjc.group(3))
				channame = str(regxobjc.group(4))
				bmaskstr = pban(nickname, username, hostname, banmasks)
				objckeyn = ("%s %s" % (channame, bmaskstr))
				if (not objckeyn in flootime.keys()):
					flootime[objckeyn] = {"ki":[0, -1], "bk":[0, -1], "un":[0, -1], "list":{}, "last":prestime}
				if (not nickname in flootime[objckeyn]["list"]):
					flootime[objckeyn]["list"][nickname] = {"nick":nickname, "user":username, "host":hostname, "chan":channame, "mask":bmaskstr}
				l = ["ki", "bk", "un"]; m = len(l)
				for x in range(0, m):
					t = l[x]
					# note: if the time from the last one of these has passed then clear the counters
					if (flootime[objckeyn][t][1] > 0):
						if ((prestime - flootime[objckeyn][t][1]) >= floorate[t][1]):
							flootime[objckeyn][t][0] = 0
							flootime[objckeyn][t][1] = -1
							if ((x + 1) < m):
								flootime[objckeyn][l[x+1]][0] = 0
								flootime[objckeyn][l[x+1]][1] = -1
					# note: increase the first counter to begin our monitoring
					if (x == 0):
						flootime[objckeyn][t][0] += 1
						if (flootime[objckeyn][t][1] < 0):
							flootime[objckeyn][t][1] = prestime
					# note: if the rate is exceeded then perform some action and notify the next counter
					if (flootime[objckeyn][t][0] >= floorate[t][0]):
						flootime[objckeyn][t][0] = 0
						flootime[objckeyn][t][1] = -1
						if ((x + 1) < m):
							u = l[x+1]
							flootime[objckeyn][u][0] += 1
							if (flootime[objckeyn][u][1] < 0):
								flootime[objckeyn][u][1] = prestime
							if (flootime[objckeyn][u][0] >= floorate[u][0]):
								t = u
						if (t == l[x]):
							for k in flootime[objckeyn]["list"].keys():
								for floocomd in floocmds[t]:
									outp(sockobjc, floocomd % flootime[objckeyn]["list"][k])
				flootime[objckeyn]["last"] = prestime
			sockline.pop(0)
			if (linenumb < 8):
				linenumb = min(linenumb + 1, 8)
		# note: undo a given action after a certain amount of time
		for k in flootime.keys():
			if ((prestime - flootime[k]["last"]) >= floorate["un"][1]):
				if (flootime[k]["un"][1] > 0):
					for l in flootime[k]["list"].keys():
						for floocomd in floocmds["un"]:
							outp(sockobjc, floocomd % flootime[k]["list"][l])
				del flootime[k]
if (__name__ == "__main__"):
	main()

Basic Python IRC Op/Flood Bot (Manual)

My Home Cisco Router/Switch Setup

So some number of years ago, I purchased a Cisco series router and catalyst switch but I only messed around on them to learn and never really used them in “production”. So below are my configs and some pictures of my home network setup.

# cisco catalyst 3500

enable
configure terminal

# restore factory defaults

write erase
reload
show running-config
show version

# 802.1q vlan trunk

interface fastEthernet 0/1
switchport trunk encapsulation dot1q
switchport mode trunk
switchport trunk allowed vlan all
exit

# 802.1q vlan access

int fastEthernet 0/2
switchport access vlan 2
exit

# disable some stuff

no ip http server
no ip http secure-server
exit

# save the config

write memory

# cisco series 2600

enable
configure terminal

# restore factory defaults

write erase
reload
show running-config
show version

# 802.1q inter vlan routing

int fastEthernet 0/1
no shut
exit

int fastEthernet 0/1.1
encapsulation dot1Q 1 native
exit

int fastEthernet 0/1.2
encapsulation dot1Q 2
ip address 192.168.10.1 255.255.255.0
ip nat inside
exit

# enable dhcp client

int fastEthernet 0/0
no shut
ip address dhcp
ip nat outside
exit

# nat

int fastEthernet 0/0
ip access-list standard NAT
permit 192.168.10.0 0.0.0.255
ip nat inside source list NAT interface fastEthernet 0/0 overload
exit

# disable some random stuff

no ip http server
no ip http secure-server
exit

# save the config

write memory

# openwrt configurations

ssh 192.168.1.1

# wpa2-ccmp-eap-ttls

opkg update
opkg install `opkg list | grep -i 'freeradius' | awk '{ print $1 }'`
opkg install `opkg list | grep -i 'hostap' | awk '{ print $1 }'`
opkg install `opkg list | grep -i '802.1x' | awk '{ print $1 }'`
opkg remove wpad-mini
opkg install hostapd wpa-supplicant

# startup

uci set [email protected][0].encryption="wpa2+ccmp"
uci set [email protected][0].key="Drowssap1!"
uci set [email protected][0].server="1.2.3.4"
uci set [email protected][0].port="1812"
uci commit wireless
/sbin/wifi

# netgear wndr3700v2 vlans – port numbers are ordered in reverse above

# tplink wdr4300 vlans

# interface vlan addresses – assign them to the lan fw group

 

My Home Cisco Router/Switch Setup

A Basic Version Of scrypt() – Memory Hard Problems

The script below will unroll 1048576 (20-bits) x 32-bytes (32-megabytes) of SHA256 hash digests into memory and will perform 1048576 (20-bits) of array index look ups to get the final hash digest.

import hashlib
def tohex(h):
	o = ""
	for c in h:
		d = ord(c)
		f = ""
		if (d < 16):
			f = "0"
		d = hex(d)
		o += (f + d[2:])
	return o
def scrypt(p, r, m):
	h = hashlib.sha256(p).digest()
	#print(tohex(h))
	k = h
	l = []
	s = 0
	while (s < m):
		k = hashlib.sha256(k).digest()
		#print(s,tohex(k))
		l.append(k)
		s += 1
	k = h
	i = 0
	n = (m - 1)
	while (i < r):
		tt = ((ord(k[28]) << 24) | (ord(k[29]) << 16) | (ord(k[30]) << 8) | (ord(k[31]) << 0))
		j = (tt & n)
		#print(i,hex(tt),j,tohex(l[j]))
		k = l[j]
		i += 1
	return tohex(k)
s = scrypt("P@ssW0rd1!", 2**20, 2**20)
print(s)

cat /proc/cpuinfo | grep -i 'model.*name' | head -n 1 ; date ; python scrypt.py ; date
model name	: Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz
Sat Jan 25 13:20:42 EST 2014
3f26b65f9c3ae151c7113efd3abe57a5e7257ba9b9010ec53acde03112b5a9b1
Sat Jan 25 13:20:44 EST 2014
# cat /proc/cpuinfo | grep -i 'model.*name' | head -n 1 ; date ; python scrypt.py ; date
model name	: Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz
Sun Jan 26 19:18:13 UTC 2014
3f26b65f9c3ae151c7113efd3abe57a5e7257ba9b9010ec53acde03112b5a9b1
Sun Jan 26 19:18:16 UTC 2014
sysctl -n machdep.cpu.brand_string ; date ; python scrypt.py ; date
Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
Sat 25 Jan 2014 13:16:15 EST
3f26b65f9c3ae151c7113efd3abe57a5e7257ba9b9010ec53acde03112b5a9b1
Sat 25 Jan 2014 13:16:19 EST

and also, a random py script to generate random passwords:

import os
import random
import string
import sys
f = open(sys.argv[1], "r")
for l in f.readlines():
	l = l.strip()
	p = []
	for x in range(0, int(sys.argv[2])):
		if ((x % 4) == 0):
			p.append(random.choice(string.digits))
		elif ((x % 4) == 1):
			p.append(random.choice(string.uppercase))
		elif ((x % 4) == 2):
			p.append(random.choice(string.lowercase))
		elif ((x % 4) == 3):
			p.append(random.choice("~!@#$%^&*+"))
	random.shuffle(p)
	s = "".join(p)
	print(l + "," + s)
f.close()

A Basic Version Of scrypt() – Memory Hard Problems

MSCHAPv2 Is Over Complicated & $#!T, So I Propose MSCHAPv3

Some “brilliant” “engineer” at Microsoft got paid way too much money to invent this non-sense protocol below:


[ Video: https://www.youtube.com/watch?v=sIidzPntdCM by Moxie Marlinspike]

So here, I’ll propose a simpler version, based on better algorithms, for free! Let’s call it, I don’t know… MSCHAPv3 and here’s it’s RFC:

Client [username & password stored in brain]
Server [username & password stored in file_hash = username:pre_salt;sha256(pre_salt + password + post_salt);post_salt]
       [pre_salt = random_char(16) & post_salt = random_char(16)]

Client [client_nonce = random_byte(32)]
Client ---> client_nonce                ---> Server
                                             Server [server_nonce = random_byte(32)]
Client <--- server_nonce                 user_hash                   ---> Server
Client <--- pre_salt + ";" + post_salt   chap_hash                   ---> Server
                                             Server [chap_hash = sha256(client_nonce + file_hash + server_nonce) & auth_stat = (OK or NO)]
Client <--- auth_stat                   <--- Server

And here’s the Python/Pseudo Code:

import hashlib
import random
file_hash = "jon:[email protected]#$;086f15ae992ccf018f8b907681a855df80836448fd1240cad48f4fd4cd591c6a;%^&*"
client_nonce = str(random.getrandbits(32*8)) ; print("--->", client_nonce)
server_nonce = str(random.getrandbits(32*8)) ; print("", user_hash,"==",user_verify)
pre_salt = file_hash.split(":")[1].split(";")[0]
post_salt = file_hash.split(":")[1].split(";")[2] ; print("", chap_hash,"==",chap_verify)
auth_stat = ((user_hash == user_verify) and (chap_hash == chap_verify)) ; print("<---", auth_stat)

And here’s the public parts of the CHAP:

('--->', '56694872300446231399629229069920062364535355653875029722468457353192460920651')
('', 'e755ddaebc858e9cf681c07f875f10af57b2d824c3b3733d89811b7471997d22', '==', 'e755ddaebc858e9cf681c07f875f10af57b2d824c3b3733d89811b7471997d22')
('', '6d1f2bf581e65227f7d8ec88f7fe85090642e66a9bd754e3ee8bc4e7c185c431', '==', '6d1f2bf581e65227f7d8ec88f7fe85090642e66a9bd754e3ee8bc4e7c185c431')
('<---', True)
MSCHAPv2 Is Over Complicated & $#!T, So I Propose MSCHAPv3

The RSA Algorithm Equivalent Of The NSA’s Dual_EC_DRBG (The Danger Of Standardizing Magical Constants!)

  • Let’s pretend I am the NSA
  • Let’s pretend I wanted to influence or trick NIST along with the RSA (the organization, not the algorithm!) into approving:
    • A new, very slow! (slow means good right?), secretly backdoored, non-obvious, non-provable, plausibly deniable PRNG standard
    • Let’s also make it part of a mandatory suite so that it *must* be implemented in any software that’s requesting standards approval
  • I would probably want this standard to be based on a common asymmetric encryption algorithm, say RSA, so that it appears normal and good

 

  • First, I would calculate the following components in secret (and obviously with much larger, stronger numbers so that no one else can break our private key)
p=241 ; q=251
n = (p * q) ; n
phi = ((p - 1) * (q - 1)) ; phi
e = 239 ; n % e ; phi % e
print("http://www.wolframalpha.com/input/?i=multiplicative+inverse+of+"+str(e)+"+mod+"+str(phi)+" # obviously we must do this step in private locally but I'm too lazy to implement the math...")
d = 38159 ; (e * d) % phi
  • Then I declare the following algorithm and constants to be used publicly:

 

Define TwoBit_RSA_PRNG (or Dual_RSA_PRNG, sound familiar? :):

Defined Constants:

    let e be the prime integer used for exponentiation
    let n be the prime integer used as the modulus
    let ^ represent the exponentiation operator
    let % represent the modulus operator
    let & represent the binary AND operator
    let + represent the addition operator

Pseudo Code:

import sys
def powmod(a, b, c):
    return ((a ^ b) % c)
def Dual_RSA_PRNG(seed, init):
    e = 239;# Magic!
    n = 60491;# Magic!
    init = (init & 0xFFF)
    return powmod((seed + init), e, n)
def main(a, b):
    s = a
    r = Dual_RSA_PRNG(s, b)
    for x in range(0, 9):
        r = Dual_RSA_PRNG(s, r)
        sys.stdout.write(str(r)+" ")
    sys.stdout.write("\n")
main(int(sys.argv[1]), int(sys.argv[2]))
  • Example Output:
main(31337, 0) = 41308 34055 21755 59599 44528 47001 55179 46730 24863
  • So what does the above mean?
    • The output bytes above appear to be random and even acquiring them doesn’t leak the next set of bytes, assuming the seed stays secret
    • One should not be able to break the private key, assuming it is large and secure enough
    • Even if someone discovers the private key, they still cannot prove that we have the key, assuming we keep it secret
    • With the private key, we can determine the seed and predict the future stream of random bytes with a small amount of the random output

 

PRNG Predicition Python Code:

import sys
def predict(out0, out1):
    e = 239;# Magic!
    n = 60491;# Magic!
    d = 38159;# Private!
    b0 = (out0 & 0xFFF) ; b0
    b1 = ((out1 ** d) % n) ; b1
    s = (b1 - b0)
    print("Discovered seed: "+str(s))
    r = out1
    sys.stdout.write("PRNG prediction: ")
    for x in range(0, 9):
        r = (((s + (r & 0xFFF)) ** e) % n)
        sys.stdout.write(str(r)+" ")
    sys.stdout.write("\n")
predict(int(sys.argv[1]), int(sys.argv[2]))
$ python break.py 59599 44528
Discovered seed: 31337
PRNG prediction: 47001 55179 46730 24863 51524 37767 31388 49000 137
  • And now we can continue the original PRNG to see what “random” output would come next:
main(31337, 59599) = 47001 55179 46730 24863 51524 37767 31388 49000 137

 

Conclusion: And that folks is how great Dual_EC_DRBG is! We are paying these people millions in tax payer dollars to come up with these garbage algorithms practically equivalent to the one above. It’s kind of saddening to see…

The RSA Algorithm Equivalent Of The NSA’s Dual_EC_DRBG (The Danger Of Standardizing Magical Constants!)

Quick Blog Links

about   root @       
 
  MacOS Applications   [x-code + objective-c]  
 
  SSHPass Automation Program   [python]  
 
  VPN-Like Tunneled Interface & Traffic   [python  /  networking]  
 
  DHCP/ARP Relay-Bridge ~ Proxying   [c  /  networking]  
 
  Nginx Mod Hook for Stream Proxy Server   [c]  
 
written   Secure LAN Communication   [College Thesis]  
 
  College Project – Teaching Hacking!   [Course Paper]  
 
  ARM Assembly – A Basic Introduction…   [Blog Post]  
 
configs   WiFi Bridge ~ Network Diagram   Firewalling ~ eb|iptables  
 
  Cisco and OpenWRT   Ubiquiti and OpenWRT  
 
gear   Mac Mini   WiFi Networks  
 
 
# Note: github.com/fossjon <- I lost access due to missing 2fa, so now I'm using -> github.com/stoops
for p in `seq 1 3` ; do
  curl -sL "https://fossjon.com/feed/?paged=$p" | grep -Ei '<(title|link)>' \
    | sed -e '[email protected]<[email protected]~<[email protected]' | tr ' \t\r\n' ' ' | tr -s ' ' | tr '~' '\n' \
    | sed -e '[email protected]^.*<title>\(.*\)</title>.*<link>\(.*\)</link>.*[email protected]<a href="\2" style="text-decoration:none;font-family:monospace;">\1</a><br/>@' \
    | grep -i '/fossjon.com/'
done > blog.html
   
   pages  
   1   2   3   4   5   |  6   7   8   9   10   
 11   12   13   14   15   |  16   17   18   19   20 
Quick Blog Links

A Slight Modification Of The CPU-Based Random Number Generator

Just a little update of a previous script I posted here, it’s still very slow to run but it doesn’t rely on a hash function to create the final set of random data…

import signal
import sys

c = 0; f = 0
r = ""; t = 0; b = 0

def handler(signum, frame):
	global c, f
	global r, t, b
	f = 1
	s = str(c); m = len(s)
	if ((m % 2) == 1):
		s = s[1:]; m = len(s)
	#print(c)
	p = (m / 2)
	for x in range(0, p):
		d = ((int(s[x]) + int(s[x + p])) % 10)
		if (d > 7):
			if (int(s[x + p]) > 7):
				continue
			d = int(s[x + p])
		u = min(8 - b, 3)
		w = (3 - u)
		#print("\t(%s + %s) = (%d >> %d) <> w) <= 8):
			r += chr(t); t = 0; b = 0
		if (u < 3):
			u = (3 - u)
			w = ((2 ** u) - 1)
			#print("\t\t(%s + %s) = (%d & %d) << %d \t %d , %d" % (s[x], s[x + p], d, w, 8 - b - u, b, u))
			t += (((d & 7) & w) << (8 - b - u)); b += u

def srnd(size):
	global c, f
	global r, t, b
	r = ""; t = 0; b = 0
	signal.signal(signal.SIGALRM, handler)
	while (len(r) < size):
		signal.alarm(1)
		c = 0; f = 0
		while (f == 0):
			c += 1
		signal.alarm(0)
	o = r[0:size]
	c = 0; f = 0
	r = ""; t = 0; b = 0
	return o

def stoh(inpt):
	h = ""
	for d in inpt:
		a = hex(ord(d))
		a = a[2:]
		if (len(a) < 2):
			a = ("0" + a)
		h += a
	return h

e = stoh(srnd(32))
print(e)
$ python sigrnd.py > test.rnd
e178c23644435d209a98623f67b39bd94124c4a03bb3f8e2d871954330ffda40
2b566db93a55190affef100972cf54f42440f225fc1f0f2ebb14062485c1bd87
dd9de46a255410fe9925ac634c1c5d90b48511486700f3c9f4666d97610d7f96
1fb232f334d4a15404d97e72fa39bc0bd70831d558ee46420944ee1475dc33cf
9f8ac9c0668f5f0bf816560413eb8d465fdf86e07a1c3cd039f5c35ca65688a1
111ee2fcb3729e6886534b261a4b3d7afb0e62dc0e6c18153fc0cef15d161ff4
7ce0411de8f635d08b1b2a5f7080893f94279637c614aca13d4136bff17f9ba6
a1e7f3592a4d5c07c56c84d4f1448928b910d1051a8e4f7113b536e941ddea72
3433453f211492348e4154bd3427d079ac8f5e4d1522cdff323fe30aaa6bcda1
00f4ff6b5337690def4ec26e832a6a032cbb024ac7d9d224712422b2e4dc41fc
361cb649e81cbe5c9ad970db125cd2309f8e196140e28d4ec5f16ea1bd3551c8
7283d4e8c0a42c400fa5f5db3573df1f446a09779ddc30ffa2b84153a3ec4c7b
86ec7f80766be8d27b24c7db7b609288c7c0ac5e6345dcf6207555c605f9222d
6595417501a0df5c0339705e3c471d5bec7a880c81e1295556dd2db8c8104323
bf166eb924ad195a028dee22a36e87b487e5c83f2d9b1fa2a6ada5b35c0192c0
b5bdc471b5d7b2f0f6b08db4274e3e1ec1e2eb5b20e450bfa25b79e8e8059d19
6e0d5ba936fc630d257c25fd27c3b99c3616ce17e470066a107cf9f56d74ced7
aaa12055cc5e6629c2ef17fa398b5aaffe24ebb01cd81edde2c5b79b75b1a2ae
06c83d2d79c64d5ee206c48efe15841224a4b4279efbbca2f47dc1d8a40bc5bd
daf5cc2d164e3bae9fcc4a8e698169556e96d19e47eaae842f5fa77d0342f00d
57095f3ed4445c0331bff1b86f883fc589437dcc8b45a0900bee2cf44609da99
95c522a66f0984cb9382ff737f340a8cec5434fe573d3fb6c48f13133eea6f9f
3ef172617d41b1ca588ba7ff28e242dd6488bf5a9ba41b2a8834b9a3cf35f752
1135a16689629f2560a8c4390a908ec345d5bcd82f78210597c99ee34eb15e94
dc9d4be19a93b602cf3bdeb0baf913c5273d020f75162e30636dfb0fcb80d121
a214d021f98d2f028e780747deb7bc9a368ec36e9d226f029f89d85325d6cf02
3dfe96a7bef6c8dcff22b163d8407fee1f8d52ff39144433d72da6918ee6c853
4097d09af9abfeaecd46bf8eb49933c0e8a903719cb21a0688e4d5e544fd1e11
e1616e89980c450022236a9b9bf05dd2e03f15b5e0af17674ffca56e6138c9d3
78193776e694cac8a8c3a219b06cb70918ef29151e54828bbc4a05ad1b8598ff
1279d3a8090e0a037feebe271445e27617c0cc41165bfd8a1cfac7830d7149dc
ea3321da8408630db9dbaf945eca0e05c8dde069cf6669ed112593e7dd66573b
e0c384c87016c273a81d7001aa8977eb0d6d2447fcffae13e43c5f46a2eae4ee
c1584801c2183baf511058a8cc329f8da81455824b4a8a3f4e5c9ff891ac3466
84164902fe12ff530e7c4345fc793a695986f1edc8432a94f993c687edc31a9e
c3a195f8800150eb8c0098422fd4c31d6fdbee7bca4715ea0cde8b1b83579d47
5dc80e604deb964dfab71c8c206ac4dcf5922fb53a5824b3406c9399bbd7fcba
25bbd158ed7623fb42656d29e9b56e9a2d1a763b7a00fcca1b02d262479f5a48
20bcc8976207c0a06aba765f0aa768db58c6c1ac36f9734f57a12969f55d7297
7ab12a2982aa2974092df7ef0813c8f1827d2fabf781b4de3f8c7d42720783c1
68dc9f744bd8794919c7abcbb0a7b3737b9f0caf974e0d6a2688241aa0559cd4
731e9f253a0c8827a10639066169ac33dfc9c9a5ddb85e8def8ec151ab352469
096ac68f4d62eaac2476977a498a362b5b45e18e5dbbb0f78c5649ec94817e76
0245dd2c4ef49382546aa06c3929ba4e70f210af3bedfc4c5eebc46bd9391683
bf7110c1e15f178ab1171c5f938ab1e2d0a1b9b29677b9f362b3132ef56dabbf
1643830ba06963161eaa04b9f8e088a4687d09e438e41d2a5466d6f78b274c9e
c9def9205f496b010ce2892135fef94fe2deb7f62640dff9f30994fd5f46e4de
938d483ed34deb033207ed1ec4cadbf8c3d9e8d86f93717575b4cd17eeb725c1
f96f1a0e38c9f7a2fe6a623fb3b62a151dc9b0f51b34861b7730b4058b1ded9b
6c7e48582ded238178c1036be88b7583803ece4127781b3cded024925e4c9e6b
6810854b6219e191fff2f7623c0827045fa4f097e043277d45260aeeb512c128
3512bb2fa47c1b3808f9b1109bd5cdc1506d9f472534c89f0433ab2d286f5cdd
ab8a7ad4fea0b0391fd162dfb975dfc190dfb200a6e2f9b70959c3dc4147416e
1824ac1a6806ac85ec8618426173bf1f77004d51446dc0cae18df7bd4d9da3df
fff792348efa02f21f40af926f1cda6bc3b486623aff46d9c13a6e14309fe2dd
28005590a0639de926f891c5e805d252375dc4602b0579c1cf7e64d06d83ce7c
951757ab8747578b690e490a306e94265912e43b2302c5d7476f98c29b667e7a
a91a3aa632cb30320b6097ae58051b58be361ab1682b2ecde9d74592592d2f1f
9c528fd8ec7c03467239cca5394038c61986ffe9bb60afd4d315781d5b2a09ec
759b5d68c9a6d0b0204f38b0d65de468cd5578f5d864ceb7f41ef10fa1b62802

Edit: A Linux entropy command line tester: http://www.fourmilab.ch/random/

As you can see below, we got up to 7.90 bits of entropy per byte while generating less than 2048 bytes of random data. We also almost hit the arithmetic mean value of 127.5 by scoring a 125. This process, however, took a really long time to run, but, all that was needed was a CPU, a counter, and a alarm signal interrupt.

$ ./ent test.rnd 
Entropy = 7.900037 bits per byte.

Optimum compression would reduce the size
of this 1920 byte file by 1 percent.

Chi square distribution for 1920 samples is 262.13, and randomly
would exceed this value 36.60 percent of the times.

Arithmetic mean value of data bytes is 125.3578 (127.5 = random).
Monte Carlo value for Pi is 3.187500000 (error 1.46 percent).
Serial correlation coefficient is 0.013566 (totally uncorrelated = 0.0).
A Slight Modification Of The CPU-Based Random Number Generator

Grabbing a CA Cert with tcpdump/openssl and the built in WiFi Connection Interface

Here’s the source code first:

#!/usr/bin/python
import base64
import os
import re
import subprocess
import sys
import time
def writepem(certdata):
	f = ""
	e = base64.b64encode(certdata)
	x = 0; l = len(e)
	f += ("-----BEGIN CERTIFICATE-----\n")
	while (x < l):
		f += ("%s\n" % (e[x+0:x+64]))
		x += 64
	f += ("-----END CERTIFICATE-----\n")
	return f
def brutecert(pcapdata):
	l = 900
	while (l <= 1024):
		p = writepem(pcapdata[:l])
		#sys.stderr.write(p+"\n")
		try:
			certchk = subprocess.check_output("echo '%s' | openssl verify 2>&1 | grep '^OK$'" % (p), shell=True)
		except:
			certchk = ""
		if (certchk != ""):
			break
		l += 1
	if (certchk != ""):
		sys.stdout.write(p)
		return 1
	return 0
os.system("killall -9 tcpdump > /dev/null 2>&1 ; killall -9 tcpdump > /dev/null 2>&1")
os.system("rm -fv wifi.pcap > /dev/null 2>&1 ; tcpdump -i %s -w wifi.pcap -U > /dev/null 2>&1 &" % (sys.argv[1]))
sys.stderr.write("Note: If you want to interrupt this script, press Control+Z and killall -9 python\n")
r = 0
while (1):
	try:
		tcpout = subprocess.check_output("tcpdump -xr wifi.pcap 2> /dev/null | tr '\\t' ' ' | sed -e 's/^ [ ]*0x[0-9A-Fa-f][0-9A-Fa-f]*:[ ]*//'", shell=True)
		tcplist = tcpout.split("\n")
		eapdata = ""; eapindx = 0; eapsize = -16
		for x in range(0, len(tcplist)):
			if (eapindx < (eapsize + 4)):
				h = ""
				for c in tcplist[x].strip():
					if (not c in "0123456789ABCDEFabcdef"):
						continue
					h += c
					if (len(h) == 2):
						if (eapindx >= (eapsize + 4)):
							sys.stderr.write("EAP read error [%d] >= [%d]...\n" % (eapindx + 1, eapsize))
						else:
							if (eapindx >= 4):
								eapdata += chr(int(h, 16))
						eapindx += 1; h = ""
			else:
				z = re.match("^[0-9][0-9]:[0-9][0-9]:[0-9][0-9].* EAP packet.* v2.* len ([0-9]+)$", tcplist[x].strip(), re.I)
				if (z):
					eapindx = 0; eapsize = int(str(z.group(1)))
					sys.stderr.write("Possible EAP data: line [%d] len [%d]...\n" % (x, eapsize))
		p = 0; l = len(eapdata)
		tlsdata = ""; tlsindx = 0; tlssize = -16
		while (p < l):
			i = p; m = [["\x01","\x02"],[],[],[],["\x15"],[None],[],[],[],[]]
			for j in m:
				if (i >= l):
					pass
				elif (len(j) < 1):
					i += 1
				elif (None in j):
					if ((ord(eapdata[i]) & 0x80) > 0):
						i += 1
				else:
					for k in j:
						if (eapdata[i] == k):
							i += 1
			if (i == (p + len(m))):
				tlslen = ((ord(eapdata[p+2])<<8) + (ord(eapdata[p+3])<<0))
				tlsmlen = ((ord(eapdata[p+6])<<24) + (ord(eapdata[p+7])<<16) + (ord(eapdata[p+8])<<8) + (ord(eapdata[p+9])<<0))
				sys.stderr.write("Possible TLS data: index [%d] len [%d] mlen [%d]...\n" % (p, tlslen, tlsmlen))
				p += 10
				if (tlssize < 1):
					tlsindx = 0; tlssize = tlsmlen
				for x in range(0, tlslen - 10):
					if ((tlsindx >= tlssize) or (p >= l)):
						pass
					else:
						tlsdata += eapdata[p]
						p += 1
					tlsindx += 1
				if (tlsindx >= tlssize):
					if (tlsindx > tlssize):
						sys.stderr.write("TLS read error [%d] >= [%d]...\n" % (tlsindx, tlssize))
					tlsindx = 0; tlssize = -16
				p -= 1
			p += 1
		p = 0; l = len(tlsdata)
		while (p < l):
			if (r == 0):
				i = p; m = "\x30\x82\x03"
				for j in m:
					if (tlsdata[i] == j):
						i += 1
				if (i == (p + len(m))):
					sys.stderr.write("Possible CA data: index [%d]...\n" % (p))
					r = brutecert(tlsdata[p:])
			p += 1
	except:
		pass
	if (r != 0):
		break
	time.sleep(1)
os.system("killall -9 tcpdump > /dev/null 2>&1 ; killall -9 tcpdump > /dev/null 2>&1")

Then you run the command:

# python cagrab.py wlan0 | tee ca.crt
Note: If you want to interrupt this script, press Control+Z and killall -9 python
Possible EAP data: line [0] len [5]...
Possible EAP data: line [4] len [6]...
Possible EAP data: line [22] len [1024]...
Possible EAP data: line [90] len [1024]...
Possible EAP data: line [158] len [480]...
Possible EAP data: line [204] len [69]...
Possible EAP data: line [219] len [4]...
Possible TLS data: index [11] len [1024] mlen [2498]...
Possible TLS data: index [1035] len [1024] mlen [2498]...
Possible TLS data: index [2059] len [480] mlen [2498]...
Possible TLS data: index [2539] len [69] mlen [59]...
Possible CA data: index [74]...
Possible CA data: index [1006]...
-----BEGIN CERTIFICATE-----
MIIDtTCCAp2gAwIBAgIJAKhl2tXce/J4MA0GCSqGSIb3DQEBBQUAMHExCzAJBgNV
BAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMRAwDgYDVQQHDAdUb3JvbnRvMQ8wDQYD
VQQKDAZzdG9vcHMxEjAQBgNVBAMMCXJhZHNydi1jYTEZMBcGCSqGSIb3DQEJARYK
cm9vdEBsb2NhbDAeFw0xNDAzMjYwMTQ1MjJaFw0yNDAzMjMwMTQ1MjJaMHExCzAJ
BgNVBAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMRAwDgYDVQQHDAdUb3JvbnRvMQ8w
DQYDVQQKDAZzdG9vcHMxEjAQBgNVBAMMCXJhZHNydi1jYTEZMBcGCSqGSIb3DQEJ
ARYKcm9vdEBsb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMh2
sAnJApatDY+2IjWUmdvMuBmNBXP29FAKUfO6D6EY90MBVPShzaOsr/p4Il7oUDqy
rs3wdeCBRLvGV+cHsgyMBlHh2jS6PKHMvVEh3n2kaTb+BAXe6Q2dDdkpGz5BSr31
mYfGuDvBtDop7fE/HQH6NwMM7qHKv8yO433JPPN3E6l7ln1WXRberFkGS39CTA0j
dpAzjz2+J8Wfm2zGd/z22ggf1PGw2VukbC+o0TOQpKb05sprLQmqDykMmzv3V5N2
Sa9KUFtQNihGOjHgjRwmys5gniV52cJnAU0hSickMBiWDXp65MEXBaPCqaaqj3DM
eHkRArBOcCMnfL7KwWMCAwEAAaNQME4wHQYDVR0OBBYEFO3bA+BXWeWip7bIjvXq
vzi3AvshMB8GA1UdIwQYMBaAFO3bA+BXWeWip7bIjvXqvzi3AvshMAwGA1UdEwQF
MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJlRk1MPGGONHKmU8WnryvnrhFr+KPfO
5eBzn+7HOSjK27FEmCRoYM3gk6SJJbIX0BtLgtz6o/E+WX7A611Jf5jXbNNOOz1L
d8F9NxmcbA3nYXaeTm2/BBOIF4diizQjHIkNS8R+MMOchKMV6WpAb7Ia7W849IbM
pQ1I5RxoTMjMy6hdpr1YUYqbTeq6X8z2P9AxiH0cKHxshQVkXFan8JTp290l2IIX
tCzIzOCqPWBcScrrhCYTbJl+9YZ1CSRwdos5/XWpCvCHI9cRA9qPLjkoiaZ8ZCHY
pxnYlLauxJnCmyk2HW00V5bUJ1vIb1mDV78Y/1kekSwZAvhOW9M1Pag=
-----END CERTIFICATE-----

Then you attempt a real connection to the WPA Enterprise access point (with fake credentials!) and wait for the script above to write out the CA Certificate file (verify it against a hash first!). You can then move this file to a user’s directory and point to it with a Wi-Fi connection client. This helps because the built-in Wi-Fi clients on Linux don’t seem to present any server certificate when connecting initially which forces one to manually transfer it around everywhere which is annoying when you have no network connection to begin with!

Grabbing a CA Cert with tcpdump/openssl and the built in WiFi Connection Interface

Finally Able To Run My Own WPA2-AES EAP-TTLS FreeRADIUS Server (RasPi)

I should have posted these pre-steps: First download the latest stable freeradius source code, extract and change directory, ./configure && make, su and make install. Also, the post-config to run the service itself: /usr/local/sbin/radiusd

And here are my example configuration notes in case anyone else is interested:

cd /usr/local/etc/raddb/certs

export D=`pwd` ; export KEY_CONFIG=$D/openssl.cnf
cat /etc/ssl/openssl.cnf | tr '\t' ' ' | sed -e "[email protected]^dir .*\[email protected] = `pwd`@g" -e "[email protected]^countryName_default .*\[email protected]_default = [email protected]" -e "[email protected]^stateOrProvinceName_default .*\[email protected]_default = [email protected]" -e "[email protected]^0.organizationName_default .*\[email protected]_default = [email protected]" > openssl.cnf

sed -i -e '[email protected]@@g' -e '[email protected]/[email protected]@g' /usr/lib/ssl/openssl.cnf

rm -fv index.txt ; touch index.txt
rm -fv serial ; echo 01 > serial
mkdir -p ./newcerts

openssl dhparam -out dh 2048
openssl req -days 3650 -nodes -new -x509 -keyout ca.key -out ca.crt -config $KEY_CONFIG
openssl req -days 3650 -nodes -new -keyout server.key -out server.csr -config $KEY_CONFIG
openssl ca -extensions v3_ca -days 3650 -out server.crt -in server.csr -cert ca.crt -keyfile ca.key -config $KEY_CONFIG

cat ca.crt ca.key > ca.pem
cat server.crt server.key > server.pem


#cd /etc/freeradius/certs

#openssl genrsa -out server.key 2048
#openssl req -new -key server.key -out server.csr
#openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
#openssl dhparam -outform PEM -out dh 2048

#cat server.crt server.key > server.pem ; cat server.pem > ca.pem
#echo > ../acct_users
#( echo 'client 0.0.0.0/0 {' ; echo '  secret = "pwd"' ; echo '  shortname = "wifi"' ; echo '}' ) > ../clients.conf
#echo 'jon Cleartext-Password := "pwd"' > ../users
vim /usr/local/etc/raddb/eap.conf
vim /usr/local/etc/raddb/modules/inner-eap

eap {
    ...
    default_eap_type = ttls
    ...
    tls {
        ...
        private_key_file = ${certdir}/server.pem
        certificate_file = ${certdir}/server.pem
        CA_file = ${cadir}/ca.pem
        dh_file = ${certdir}/dh
        cipher_list = "DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA"
        ...
    }
    ...
    ttls {
        ...
        default_eap_type = mschapv2
        ...
    }
    ...
    mschapv2 {
        ...
    }
    ...
}
vim /usr/local/etc/raddb/clients.conf

client 0.0.0.0/0 {
    secret    = [long-secret-passphrase-here]
    shortname = homewifi
    nastype   = other
}

Authentication:

vim /usr/local/etc/raddb/users

"jon" Cleartext-Password := "[personal-password-here]"

or

vim /usr/local/etc/raddb/sites-{available,enabled}/{default,inner-tunnel}

authorize {
    ...
    unix
    ...
}

* Note: Make sure to publish/distribute the ca.crt file above for connecting clients to use, it should look something like this:

-----BEGIN CERTIFICATE-----
MIIDzTCCArWgAwIBAgIJAMML9s5w/d4oMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNV
BAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMRAwDgYDVQQHDAdUb3JvbnRvMQ8wDQYD
VQQKDAZzdG9vcHMxDTALBgNVBAsMBHdpZmkxDzANBgNVBAMMBnJhZHNydjEZMBcG
CSqGSIb3DQEJARYKcm9vdEBsb2NhbDAeFw0xMzEyMzAyMjE0MzBaFw0yMzEyMjgy
MjE0MzBaMH0xCzAJBgNVBAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMRAwDgYDVQQH
DAdUb3JvbnRvMQ8wDQYDVQQKDAZzdG9vcHMxDTALBgNVBAsMBHdpZmkxDzANBgNV
BAMMBnJhZHNydjEZMBcGCSqGSIb3DQEJARYKcm9vdEBsb2NhbDCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAMsYNqwP+Zd9szkwwEVjxgOPn+d7kIZKbKnh
ZJOhG2poxnlPcv2Ac67xPuJ4tuiU6Xni1+YElkx4uxNa4GNm9EF2M0MRAE/eAwxK
QN9Y4/KN3C3AU8VDyIUXMx+XN38HI48lgZIj1c9HhoB8llTHeL4jGRVDmzqGqOCl
GwSNMh9mCgedTODARyDyJ9tyEayU1D+WDqwQTFbBfvd7VYejCtzo7edjCoMt6Kap
HsB3eE1LRTcE/QWlaDmszBzdFk+jqp2rzP+eKLXNLvalZEPOJ0koGqy9BfI9+fqW
avy/fphcN5+5UhNXadRrYOYJuPBe/AC90NmlFn+ztYmiRwf+GtkCAwEAAaNQME4w
HQYDVR0OBBYEFPE09eFbbSvz8E4uY2F4cA0PJmreMB8GA1UdIwQYMBaAFPE09eFb
bSvz8E4uY2F4cA0PJmreMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
AFYN7lTdZjNhHohCul9HzP87vHFiiV0N47eCBeyoujvkKkQHm2fKunxKLfe0ySBa
xOXdHHEhfBiv7Qz1LgryaYjMeJ8OhbktPT3ahGIWnNgyeKJiM3eD0fNVFWxp0ZBO
OlVQh5NYbuHhWafnAP8DDyhgKB99uEpF5iS1KwfkCGBbynYOayqNZGIVIH0c0Bmb
Ps+qNYxLKHQRi3+dnv4/gKPwKFDDiccHrQxiAEMXY+iO0rnPjc35SPri2QMAKdYf
1Nv/lmEPwQutjns1EUHHSmNwuC4O/1AUR54iskxzHy3v3RafOQ9B5aO6fyaMVFQF
iYX2djQzSq9qfOj9lMz5Cww=
-----END CERTIFICATE-----

Note: You can run this command to decode the certificate above: openssl x509 -in ca.crt -text -noout

Edit: For some basic OpenSSH cipher choices: Ignore the randomness

Finally Able To Run My Own WPA2-AES EAP-TTLS FreeRADIUS Server (RasPi)

A Python TrueRand-Like Script Based On Signals, Alarms, Clocks, Counters, & SHA256

So I was watching some new Defcon videos from some of my favourite speakers (Jeff Moss, Bruce Schneier, Renderman, Dan Kaminsky, Moxie Marlinspike, Joshua Wright, Johnny Long, Charlie Miller, etc.) and Dan mentioned the ability to generate random numbers on a given system with nothing more than a CPU clock type device. I don’t understand it much but I think the basics includes setting an alarm trap signal and setting an infinite loop to increase a counter variable and then using that resulting integer as a source of randomness. You can repeat this process multiple times in a row to generate a larger amount of random data. Here’s my take on it, however, it is *very* slow and most likely mathematically/statistically wrong:

import hashlib
import signal

c = 0; f = 0
r = ""; l = 0
n = 3

def handler(signum, frame):
	global c, f
	global r, l
	global n
	f = 1
	s = str(c); m = len(s)
	if ((m % 2) == 1):
		s = s[1:]; m = len(s)
	#print(c)
	p = (m / 2)
	for x in range(0, p):
		d = ((int(s[x]) + int(s[x + p])) % 10)
		if (d > 7):
			if (int(s[x + p]) > 7):
				continue
			d = int(s[x + p])
		r += str(d); l += n

def srnd(size):
	global c, f
	global r, l
	global n
	signal.signal(signal.SIGALRM, handler)
	o = ""; m = 0
	while (m < size):
		r = ""; l = 0
		while (l < 256):
			signal.alarm(1)
			c = 0; f = 0
			while (f == 0):
				c += 1
			signal.alarm(0)
		print(r)
		h = hashlib.sha256(r).digest()
		for d in h:
			if (m < size):
				o += d; m += 1
	return o

def stoh(inpt):
	h = ""
	for d in inpt:
		a = hex(ord(d))
		a = a[2:]
		if (len(a) < 2):
			a = ("0" + a)
		h += a
	return h

e = stoh(srnd(32))
print(e)
$ python sigrnd.py 
003052717203640343422444177105135642455155135417632775634425154765734347724627720521226
c2638300e80d2fb7ab0230c4a6534191dda4b86b997508ff445adc577a7426c3
A Python TrueRand-Like Script Based On Signals, Alarms, Clocks, Counters, & SHA256

A small whois server and a nice holiday video

So here’s the most basic whois server in Python (connects to a PostgreSQL DB for the cached data):

Also, a funny holiday reminder that the NSA is spying on all of us!

ACLU NSA Vid [funny]

whois_limit

limiter.py

#!/usr/bin/python

import ast
import getpass
import hashlib
import os
import random
import re
import socket
import string
import sys
import time

def rstr(size):
	outp = ""
	for x in range(0, size):
		outp += random.choice(string.digits + string.ascii_uppercase + string.ascii_lowercase + "[email protected]#$%^&*-_=+?")
	return outp

fobj = open(sys.argv[1], "r")
conf = ast.literal_eval(fobj.read().strip())
fobj.close()

servport = conf["limiter"]["port"]
password = conf["limiter"]["pass"]
numtimes = conf["limiter"]["conn"]
timeouts = conf["limiter"]["time"]

prepad = rstr(8); pospad = rstr(8); cntrlist = []
addrlist = {}

sockobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sockobjc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sockobjc.bind(("", servport))
sockobjc.listen(1)

while (1):
	(sockconn, sockaddr) = sockobjc.accept()
	print("conn open:", sockaddr)
	try:
		sockconn.settimeout(1)
		datalist = sockconn.recv(1024).strip().split(" ")
		try:
			sendflag = 0
			scounter = datalist[0].strip()
			inetaddr = datalist[1].strip()
			authhash = datalist.pop()
			sharedsec = (prepad + " " + password + " " + pospad)
			temphash = hashlib.sha256(sharedsec + " " + " ".join(datalist) + " " + sharedsec).hexdigest()
			if (temphash != authhash):
				sockconn.send("0" + " " + prepad + " " + pospad)
				sendflag = 1
			else:
				if (len(cntrlist) >= 65536):
					prepad = rstr(8); pospad = rstr(8); cntrlist = []
				if (scounter in cntrlist):
					sockconn.send("1" + " " + scounter)
					sendflag = 1
				else:
					cntrlist.append(scounter)
					if (not inetaddr in addrlist.keys()):
						addrlist[inetaddr] = [0, 0]
					prestime = time.time()
					if ((prestime - addrlist[inetaddr][0]) >= timeouts):
						addrlist[inetaddr][0] = prestime
						addrlist[inetaddr][1] = 0
					print("conn info:", sockaddr, scounter, datalist, addrlist[inetaddr])
					if (addrlist[inetaddr][1] < numtimes):
						addrlist[inetaddr][1] += 1
						sockconn.send("2" + " " + "ok")
						sendflag = 1
			if (sendflag != 1):
				sockconn.send("2" + " " + "no")
		except:
			pass
	except:
		pass
	try:
		print("conn closed:", sockaddr)
		sockconn.shutdown(socket.SHUT_RDWR)
		sockconn.close()
	except:
		pass

whoiss.py

#!/usr/bin/python

import ast
import getpass
import hashlib
import os
import psycopg2
import random
import re
import socket
import string
import sys
import time

def sstr(inpt):
	outp = ""
	yesl = (string.digits + string.ascii_uppercase + string.ascii_lowercase + "-_.")
	for chrl in inpt:
		if (chrl in yesl):
			outp += chrl
	return outp

def rnum(size):
	random.seed(time.time())
	outp = ""
	for x in range(0, size):
		outp += random.choice(string.digits)
	return outp

def lims(connaddr):
	global limhost, limport
	global limpass, limpre, limpos
	x = 0
	limresp = ["-1"]
	try:
		while ((x < 8) and (limresp[0] != "2")):
			limnumb = rnum(8)
			limobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			limobjc.connect((limhost, limport))
			limdata = (limnumb + " " + connaddr)
			limsec = (limpre + " " + limpass + " " + limpos)
			limhash = hashlib.sha256(limsec + " " + limdata + " " + limsec).hexdigest()
			limobjc.sendall(limdata + " " + limhash)
			limresp = limobjc.recv(1024).strip().split(" ")
			limobjc.close()
			if (len(limresp) < 1):
				limresp = ["-1"]
			if (limresp[0] == "0"):
				limpre = limresp[1]
				limpos = limresp[2]
			elif (limresp[0] == "1"):
				pass
			print("recv limit:", limdata, limresp)
			x += 1
	except:
		pass
	return limresp

'''{
"db":{"host":"127.0.0.1", "user":"whois", "pass":"Siohw1!", "name":"dbname", "table":"whois_cache", "col":"text"},
"limiter":{"host":"127.0.0.1", "port":3434, "pass":"Limiter1!", "conn":1, "time":10},
"whois":{"port":4343},
}'''
fobj = open(sys.argv[1], "r")
conf = ast.literal_eval(fobj.read().strip())
fobj.close()

servport = conf["whois"]["port"]
childlist = []

limhost = conf["limiter"]["host"]
limport = conf["limiter"]["port"]
limpass = conf["limiter"]["pass"]
limpre = ""; limpos = ""

sqlshost = conf["db"]["host"]
sqlsuser = conf["db"]["user"]
sqlspass = conf["db"]["pass"]
sqlsdb = conf["db"]["name"]
sqlstbl = conf["db"]["table"]
sqlscol = conf["db"]["col"]

sockobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sockobjc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sockobjc.bind(("", servport))
sockobjc.listen(1)

while (1):
	for x in range(0, len(childlist)):
		try:
			os.waitpid(childlist[x], os.WNOHANG)
		except:
			childlist[x] = -1
	while (-1 in childlist):
		childlist.remove(-1)
	lims("127.0.0.1")
	(sockconn, sockaddr) = sockobjc.accept()
	print("conn open:", sockaddr)
	try:
		childpid = os.fork()
	except:
		childpid = -1
	if (childpid == 0):
		resplim = lims(sockaddr[0])
		try:
			sqldom = sockconn.recv(1024).strip()
			sqldom = sstr(sqldom.upper())
			connresp = ""
			print("conn data:", sockaddr, sqldom)
			if ((resplim[0] == "2") and (resplim[1] == "ok")):
				try:
					conn = psycopg2.connect("host='%s' dbname='%s' user='%s' password='%s'" % (sqlshost, sqlsdb, sqlsuser, sqlspass))
					curs = conn.cursor()
					curs.execute("SELECT %s FROM %s WHERE name = '%s';" % (sqlscol, sqlstbl, sqldom))
					rows = curs.fetchall()
					conn.close()
					leng = 0
					for rowo in rows:
						connresp = ("%s\n\n\n" % (rowo[0].strip()))
						leng += 1
						break
					if (leng < 1):
						connresp = ("NOT FOUND\n")
				except:
					connresp = ("SERVER ERROR (1)\n")
			else:
				connresp = ("LIMIT REACHED\n")
			sockconn.send(connresp)
		except:
			pass
		try:
			print("conn closed:", sockaddr)
			sockconn.shutdown(socket.SHUT_RDWR)
			sockconn.close()
		except:
			pass
		sys.exit(0)
	else:
		try:
			sockconn.close()
		except:
			pass
		childlist.append(childpid)

Limiter Notes:

  • The shared secret is padded with 2 random strings:
    • shared-secret = (pre-pad + common-password + post-pad)
    • These 2 strings are re-generated after 2^16 unique nonces are used
  • The message data is prefixed with a unique nonce string:
    • message-data = (uniq-nonce + message-body)
  • The limiter server uses sha256 hashing to authenticate data:
    • auth-message = sha256(shared-secret + message-data + shared-secret)
    • Can switch to a basic HMAC call if greater security is needed
  • The limiter server is a single process which communicates with any connecting clients
    • Can switch to a forked-child setup if faster connections are needed

Whois Notes:

  • The whois server uses forked-child processes to communicate with multiple clients at the same time
    • Each client process will make its own connection to the database server
A small whois server and a nice holiday video

A Simple Puppet Master/Node/Agent Starter Guide

If you’re looking for a simple, quick starter guide to setting up a basic Puppet master/agent between VM’s then you should take a look at this blog I came across from a Google search. I’m putting this here as a bookmark to myself:

http://www.6tech.org/2013/01/how-to-install-puppet-open-source-on-centos-6-3/

Edit:

Pushing an example shell script to some agents (puppetnode):

[master ~]# cat /etc/puppet/manifests/site.pp
node "puppetnode"
{
	file { "/usr/local/bin/repoconf.sh" :
		mode => 0755,
		owner => root,
		group => root,
		source => "puppet:///modules/bin/repoconf.sh"
	}
	exec { "/usr/local/bin/repoconf.sh" :
		require => File["/usr/local/bin/repoconf.sh"]
	}
	package { "nc" :
		ensure => latest,
		require => Exec["/usr/local/bin/repoconf.sh"]
	}
}
[master ~]# cat /etc/puppet/modules/bin/files/repoconf.sh
#!/bin/bash
echo `date` >> /tmp/custom.puppet.sh.log
[puppetnode ~]# puppet agent -t
Info: Retrieving plugin
Info: Caching catalog for puppetnode
Info: Applying configuration version '1386822999'
Notice: /Stage[main]/Main/Node[puppetnode]/File[/usr/local/bin/repoconf.sh]/ensure: defined content as '{md5}dfd896a6b7b57885fac7bac43f2bd263'
Notice: /Stage[main]/Main/Node[puppetnode]/Exec[/usr/local/bin/repoconf.sh]/returns: executed successfully
Notice: /Stage[main]/Main/Node[puppetnode]/Package[nc]/ensure: created
Notice: Finished catalog run in 6.84 seconds
A Simple Puppet Master/Node/Agent Starter Guide