mirror of
https://github.com/fail0verflow/letterbomb.git
synced 2024-11-16 15:39:18 +01:00
Initial commit
This commit is contained in:
commit
87154280a8
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
.*
|
||||
!.gitignore
|
||||
log/*
|
||||
!log/.keep
|
||||
bundle/*
|
||||
!bundle/.keep
|
||||
*.pyc
|
||||
tmp
|
||||
*.old
|
||||
config.py
|
||||
|
16
README.md
Normal file
16
README.md
Normal file
@ -0,0 +1,16 @@
|
||||
## LetterBomb web service implementation
|
||||
|
||||
This is the LetterBomb Wii System Menu 4.3 exploit implementation running on
|
||||
https://please.hackmii.com/. Requires Python 2.7, Flask, and geoip2.
|
||||
|
||||
In case you're wondering, `country_regions.txt` is based on reporting data
|
||||
from Homebrew Channel updates. This was implemented because we found out
|
||||
that about 30% of our users are stupid and won't pick the correct system
|
||||
menu version (and then complain that it doesn't work), so we use GeoIP to
|
||||
guess the right default for them. Similarly, the MAC address check was
|
||||
implemented because people would type in garbage for the MAC address and
|
||||
then complain that it doesn't work.
|
||||
|
||||
This does not include the HackMii Installer bundle. Those files would go
|
||||
in `bundle/`.
|
||||
|
164
app.py
Normal file
164
app.py
Normal file
@ -0,0 +1,164 @@
|
||||
import os, zipfile, StringIO, hashlib, hmac, struct, logging, urllib, random, json
|
||||
import geoip2.database
|
||||
from logging.handlers import SMTPHandler
|
||||
from datetime import datetime, timedelta
|
||||
from flask import Flask, request, g, render_template, make_response, redirect, url_for
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object("config")
|
||||
|
||||
TEMPLATES = {
|
||||
'U':"templateU.bin",
|
||||
'E':"templateE.bin",
|
||||
'J':"templateJ.bin",
|
||||
'K':"templateK.bin",
|
||||
}
|
||||
|
||||
BUNDLEBASE = os.path.join(app.root_path, 'bundle')
|
||||
#BUNDLE = [(name, os.path.join(BUNDLEBASE,name)) for name in os.listdir(BUNDLEBASE)]
|
||||
|
||||
#OUI_LIST = [i.decode('hex') for i in open(os.path.join(app.root_path, 'oui_list.txt')).read().split("\n") if len(i)==6]
|
||||
|
||||
COUNTRY_REGIONS = dict([l.split(" ") for l in open(os.path.join(app.root_path, 'country_regions.txt')).read().split("\n") if l])
|
||||
|
||||
#gi = pygeoip.GeoIP(os.path.join(app.root_path, 'GeoIP.dat'))
|
||||
gi = geoip2.database.Reader('/usr/share/GeoIP/GeoLite2-Country.mmdb')
|
||||
|
||||
class RequestFormatter(logging.Formatter):
|
||||
def format(self, record):
|
||||
s = logging.Formatter.format(self, record)
|
||||
try:
|
||||
return '[%s] [%s] [%s %s] '%(self.formatTime(record), request.remote_addr, request.method, request.path) + s
|
||||
except:
|
||||
return '[%s] [SYS] '%self.formatTime(record) + s
|
||||
|
||||
if not app.debug:
|
||||
mail_handler = SMTPHandler(app.config['SMTP_SERVER'],
|
||||
app.config['APP_EMAIL'],
|
||||
app.config['ADMIN_EMAIL'], 'LetterBomb ERROR')
|
||||
mail_handler.setLevel(logging.ERROR)
|
||||
app.logger.addHandler(mail_handler)
|
||||
|
||||
handler = logging.FileHandler(os.path.join(app.root_path, 'log', 'info.log'))
|
||||
handler.setLevel(logging.INFO)
|
||||
handler.setFormatter(RequestFormatter())
|
||||
app.logger.addHandler(handler)
|
||||
|
||||
app.logger.setLevel(logging.INFO)
|
||||
app.logger.warning('Starting...')
|
||||
|
||||
def region():
|
||||
try:
|
||||
country = gi.country(request.remote_addr).country.iso_code
|
||||
app.logger.info("GI: %s -> %s", request.remote_addr, country)
|
||||
return COUNTRY_REGIONS.get(country, 'E')
|
||||
except:
|
||||
app.logger.exception("GeoIP exception")
|
||||
return 'E'
|
||||
|
||||
def _index(error=None):
|
||||
g.recaptcha_args = 'k=%s' % app.config['RECAPTCHA_PUBLICKEY']
|
||||
rs = make_response(render_template('index.html', region=region(), error=error))
|
||||
#rs.headers['Cache-Control'] = 'private, max-age=0, no-store, no-cache, must-revalidate'
|
||||
#rs.headers['Etag'] = str(random.randrange(2**64))
|
||||
rs.headers['Expires'] = 'Thu, 01 Dec 1983 20:00:00 GMT'
|
||||
return rs
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return _index()
|
||||
|
||||
|
||||
def captcha_check():
|
||||
try:
|
||||
oform = {
|
||||
#"privatekey": app.config['RECAPTCHA_PRIVATEKEY'],
|
||||
"secret": app.config['RECAPTCHA_PRIVATEKEY'],
|
||||
"remoteip": request.remote_addr,
|
||||
#"challenge": request.form.get('recaptcha_challenge_field',['']),
|
||||
#"response": request.form.get('recaptcha_response_field',[''])
|
||||
"response": request.form.get('g-recaptcha-response',[''])
|
||||
}
|
||||
|
||||
#f = urllib.urlopen("http://api-verify.recaptcha.net/verify", urllib.urlencode(oform))
|
||||
f = urllib.urlopen("https://www.google.com/recaptcha/api/siteverify", urllib.urlencode(oform))
|
||||
|
||||
#result = f.readline().replace("\n","")
|
||||
#error = f.readline().replace("\n","")
|
||||
d = json.load(f)
|
||||
result = d["success"]
|
||||
f.close()
|
||||
|
||||
if not result:# != 'true':
|
||||
#if error != 'incorrect-captcha-sol':
|
||||
app.logger.info("ReCaptcha fail: %r, %r", oform, d)
|
||||
#g.recaptcha_args += "&error=" + error
|
||||
return False
|
||||
|
||||
except:
|
||||
#g.recaptcha_args += "&error=unknown"
|
||||
return False
|
||||
return True
|
||||
|
||||
@app.route('/haxx', methods=["POST"])
|
||||
def haxx():
|
||||
OUI_LIST = [i.decode('hex') for i in open(os.path.join(app.root_path, 'oui_list.txt')).read().split("\n") if len(i)==6]
|
||||
g.recaptcha_args = 'k=%s' % app.config['RECAPTCHA_PUBLICKEY']
|
||||
dt = datetime.utcnow() - timedelta(1)
|
||||
delta = (dt - datetime(2000, 1, 1))
|
||||
timestamp = delta.days * 86400 + delta.seconds
|
||||
|
||||
try:
|
||||
mac = ''.join([chr(int(request.form[i],16)) for i in "abcdef"])
|
||||
template = TEMPLATES[request.form['region']]
|
||||
bundle = 'bundle' in request.form
|
||||
except:
|
||||
return _index("Invalid input.")
|
||||
if not captcha_check():
|
||||
return _index("Are you a human?")
|
||||
|
||||
if mac == "\x00\x17\xab\x99\x99\x99":
|
||||
app.logger.info('Derp MAC %s at %d ver %s bundle %r', mac.encode('hex'), timestamp, request.form['region'], bundle)
|
||||
return _index("If you're using Dolphin, try File->Open instead ;-).")
|
||||
|
||||
if not any([mac.startswith(i) for i in OUI_LIST]):
|
||||
app.logger.info('Bad MAC %s at %d ver %s bundle %r', mac.encode('hex'), timestamp, request.form['region'], bundle)
|
||||
return _index("The exploit will only work if you enter your Wii's MAC address.")
|
||||
|
||||
|
||||
key = hashlib.sha1(mac+"\x75\x79\x79").digest()
|
||||
|
||||
blob = bytearray(open(os.path.join(app.root_path, template),'rb').read())
|
||||
blob[0x08:0x10] = key[:8]
|
||||
blob[0xb0:0xc4] = "\x00"*20
|
||||
blob[0x7c:0x80] = struct.pack(">I", timestamp)
|
||||
blob[0x80:0x8a] = "%010d"%timestamp
|
||||
blob[0xb0:0xc4] = hmac.new(key[8:], str(blob), hashlib.sha1).digest()
|
||||
|
||||
path = "private/wii/title/HAEA/%s/%s/%04d/%02d/%02d/%02d/%02d/HABA_#1/txt/%08X.000" % (
|
||||
key[:4].encode('hex').upper(), key[4:8].encode('hex').upper(),
|
||||
dt.year, dt.month-1, dt.day, dt.hour, dt.minute, timestamp
|
||||
)
|
||||
|
||||
zipdata = StringIO.StringIO()
|
||||
zip = zipfile.ZipFile(zipdata, 'w')
|
||||
zip.writestr(path, str(blob))
|
||||
BUNDLE = [(name, os.path.join(BUNDLEBASE,name)) for name in os.listdir(BUNDLEBASE) if not name.startswith(".")]
|
||||
if bundle:
|
||||
for name, path in BUNDLE:
|
||||
zip.write(path, name)
|
||||
zip.close()
|
||||
|
||||
app.logger.info('LetterBombed %s at %d ver %s bundle %r', mac.encode('hex'), timestamp, request.form['region'], bundle)
|
||||
|
||||
rs = make_response(zipdata.getvalue())
|
||||
zipdata.close()
|
||||
rs.headers.add('Content-Disposition', 'attachment', filename="LetterBomb.zip")
|
||||
rs.headers['Content-Type'] = 'application/zip'
|
||||
return rs
|
||||
|
||||
application=app
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run('0.0.0.0', 10142)
|
0
bundle/.keep
Normal file
0
bundle/.keep
Normal file
13
config.py.sample
Normal file
13
config.py.sample
Normal file
@ -0,0 +1,13 @@
|
||||
# -!- coding: utf-8 -!-
|
||||
|
||||
# for cookies and stuff, nobody really cares
|
||||
SECRET_KEY = 'fillme'
|
||||
|
||||
RECAPTCHA_PUBLICKEY = "fillme"
|
||||
RECAPTCHA_PRIVATEKEY = "fillme"
|
||||
|
||||
DEBUG = False
|
||||
ADMIN_EMAIL = ['foo@bar.com']
|
||||
SMTP_SERVER = '127.0.0.1'
|
||||
APP_EMAIL = 'foo@bar.com'
|
||||
|
209
country_regions.txt
Normal file
209
country_regions.txt
Normal file
@ -0,0 +1,209 @@
|
||||
E
|
||||
A1 U
|
||||
A2 E
|
||||
AW U
|
||||
AO E
|
||||
AI U
|
||||
AX E
|
||||
AL E
|
||||
AD E
|
||||
AN U
|
||||
AP J
|
||||
AE U
|
||||
AR U
|
||||
AM U
|
||||
AS U
|
||||
AG U
|
||||
AU E
|
||||
AT E
|
||||
AZ E
|
||||
BE E
|
||||
BJ E
|
||||
BF E
|
||||
BD U
|
||||
BG E
|
||||
BH U
|
||||
BS U
|
||||
BA E
|
||||
BY E
|
||||
BZ U
|
||||
BM U
|
||||
BO U
|
||||
BR U
|
||||
BB U
|
||||
BN U
|
||||
BW E
|
||||
CF E
|
||||
CA U
|
||||
CH E
|
||||
CL U
|
||||
CN U
|
||||
CI E
|
||||
CM E
|
||||
CD E
|
||||
CO U
|
||||
CV E
|
||||
CR U
|
||||
CU U
|
||||
KY U
|
||||
CY E
|
||||
CZ E
|
||||
DE E
|
||||
DJ E
|
||||
DM U
|
||||
DK E
|
||||
DO U
|
||||
DZ E
|
||||
EC U
|
||||
EG U
|
||||
ER E
|
||||
ES E
|
||||
EE E
|
||||
EU E
|
||||
FI E
|
||||
FJ E
|
||||
FK E
|
||||
FR E
|
||||
FO E
|
||||
FM U
|
||||
GA E
|
||||
GB E
|
||||
GE U
|
||||
GG E
|
||||
GH E
|
||||
GI E
|
||||
GP E
|
||||
GQ E
|
||||
GR E
|
||||
GD U
|
||||
GL E
|
||||
GT U
|
||||
GU U
|
||||
GY U
|
||||
HK J
|
||||
HN U
|
||||
HR E
|
||||
HT U
|
||||
HU E
|
||||
ID U
|
||||
IM E
|
||||
IN U
|
||||
IO U
|
||||
IE E
|
||||
IR U
|
||||
IQ U
|
||||
IS E
|
||||
IL E
|
||||
IT E
|
||||
JM U
|
||||
JE E
|
||||
JO U
|
||||
JP J
|
||||
KZ E
|
||||
KE E
|
||||
KG U
|
||||
KH U
|
||||
KN U
|
||||
KR K
|
||||
KW U
|
||||
LA U
|
||||
LB U
|
||||
LY E
|
||||
LC U
|
||||
LI E
|
||||
LK E
|
||||
LT E
|
||||
LU E
|
||||
LV E
|
||||
MO J
|
||||
MF E
|
||||
MA E
|
||||
MC E
|
||||
MD E
|
||||
MG E
|
||||
MV U
|
||||
MX U
|
||||
MH U
|
||||
MK E
|
||||
ML E
|
||||
MT E
|
||||
MM U
|
||||
ME E
|
||||
MN U
|
||||
MP U
|
||||
MZ E
|
||||
MR E
|
||||
MQ E
|
||||
MU E
|
||||
MW E
|
||||
MY U
|
||||
NA E
|
||||
NC E
|
||||
NE E
|
||||
NF E
|
||||
NG E
|
||||
NI U
|
||||
NL E
|
||||
NO E
|
||||
NP U
|
||||
NZ E
|
||||
OM U
|
||||
PK U
|
||||
PA U
|
||||
PE U
|
||||
PH U
|
||||
PG E
|
||||
PL E
|
||||
PR U
|
||||
PT E
|
||||
PY U
|
||||
PS U
|
||||
PF E
|
||||
QA U
|
||||
RE E
|
||||
RO E
|
||||
RU E
|
||||
SA U
|
||||
SD U
|
||||
SN E
|
||||
SG U
|
||||
SV U
|
||||
SM E
|
||||
PM E
|
||||
RS E
|
||||
SR U
|
||||
SK E
|
||||
SI E
|
||||
SE E
|
||||
SZ E
|
||||
SC U
|
||||
SY U
|
||||
TC U
|
||||
TG J
|
||||
TH U
|
||||
TJ U
|
||||
TK U
|
||||
TM E
|
||||
TL E
|
||||
TT U
|
||||
TO E
|
||||
TR E
|
||||
TW J
|
||||
TZ U
|
||||
UG U
|
||||
UA E
|
||||
UY U
|
||||
US U
|
||||
UZ U
|
||||
VA U
|
||||
VC U
|
||||
VE U
|
||||
VG U
|
||||
VI U
|
||||
VN U
|
||||
VU E
|
||||
YE U
|
||||
YT E
|
||||
ZA E
|
||||
ZM U
|
||||
ZW E
|
6
letterbomb.fcgi
Executable file
6
letterbomb.fcgi
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/python2
|
||||
from flup.server.fcgi import WSGIServer
|
||||
from app import app
|
||||
|
||||
if __name__ == '__main__':
|
||||
WSGIServer(app, debug=False).run()
|
59
oui_list.txt
Normal file
59
oui_list.txt
Normal file
@ -0,0 +1,59 @@
|
||||
0009BF
|
||||
001656
|
||||
0017AB
|
||||
00191D
|
||||
0019FD
|
||||
001AE9
|
||||
001B7A
|
||||
001BEA
|
||||
001CBE
|
||||
001DBC
|
||||
001E35
|
||||
001EA9
|
||||
001F32
|
||||
001FC5
|
||||
002147
|
||||
0021BD
|
||||
00224C
|
||||
0022AA
|
||||
0022D7
|
||||
002331
|
||||
0023CC
|
||||
00241E
|
||||
002444
|
||||
0024F3
|
||||
0025A0
|
||||
002659
|
||||
002709
|
||||
0403D6
|
||||
182A7B
|
||||
2C10C1
|
||||
34AF2C
|
||||
40D28A
|
||||
40F407
|
||||
582F40
|
||||
58BDA3
|
||||
5C521E
|
||||
606BFF
|
||||
64B5C6
|
||||
78A2A0
|
||||
7CBB8A
|
||||
8C56C5
|
||||
8CCDE8
|
||||
9458CB
|
||||
98B6E9
|
||||
9CE635
|
||||
A438CC
|
||||
A45C27
|
||||
A4C0E1
|
||||
B87826
|
||||
B88AEC
|
||||
B8AE6E
|
||||
CC9E00
|
||||
CCFB65
|
||||
D86BF7
|
||||
DC68EB
|
||||
E00C7F
|
||||
E0E751
|
||||
E84ECE
|
||||
ECC40D
|
BIN
static/letterbomb_icon.png
Normal file
BIN
static/letterbomb_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
57
static/mac.css
Normal file
57
static/mac.css
Normal file
@ -0,0 +1,57 @@
|
||||
body {
|
||||
font: 1.0em "Trebuchet MS", Verdana, Arial, sans-serif;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
input.button {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
|
||||
-moz-box-shadow: 2px 2px 3px #666;
|
||||
-webkit-box-shadow: 2px 2px 3px #666;
|
||||
box-shadow: 2px 2px 3px #666;
|
||||
|
||||
font-size: 20px;
|
||||
padding: 4px 7px;
|
||||
outline: 0;
|
||||
-webkit-appearance: none;
|
||||
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
input.buttonr:enabled {
|
||||
border-color:red;
|
||||
}
|
||||
input.buttonb:enabled {
|
||||
border-color:blue;
|
||||
}
|
||||
|
||||
input.box {
|
||||
border: 1px solid #ccc;
|
||||
|
||||
text-transform:uppercase;
|
||||
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
|
||||
-moz-box-shadow: 2px 2px 3px #666;
|
||||
-webkit-box-shadow: 2px 2px 3px #666;
|
||||
box-shadow: 2px 2px 3px #666;
|
||||
|
||||
font-size: 20px;
|
||||
padding: 4px 7px;
|
||||
outline: 0;
|
||||
-webkit-appearance: none;
|
||||
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
input.box:focus {
|
||||
border-color: #339933;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 0;
|
||||
}
|
BIN
templateE.bin
Normal file
BIN
templateE.bin
Normal file
Binary file not shown.
BIN
templateJ.bin
Normal file
BIN
templateJ.bin
Normal file
Binary file not shown.
BIN
templateK.bin
Normal file
BIN
templateK.bin
Normal file
Binary file not shown.
BIN
templateU.bin
Normal file
BIN
templateU.bin
Normal file
Binary file not shown.
95
templates/index.html
Normal file
95
templates/index.html
Normal file
@ -0,0 +1,95 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>LetterBomb</title>
|
||||
<link rel="stylesheet" type="text/css" href="/static/mac.css" />
|
||||
<script type="text/javascript">
|
||||
captcha_passed = false;
|
||||
function keyHandler(e, obj, next) {
|
||||
if (window.event) { // IE
|
||||
keynum = e.keyCode;
|
||||
} else if(e.which) { // sane browsers
|
||||
keynum = e.which;
|
||||
}
|
||||
if (keynum == 0x08 || keynum == 0x09 || (keynum >= 96 && keynum <= 105))
|
||||
return true;
|
||||
keychar = String.fromCharCode(keynum);
|
||||
if (keychar.match(/[0-9A-F]/) == null) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
function check() {
|
||||
var ids = ["a","b","c","d","e","f"];
|
||||
for (var i = 0; i < 6; i++) {
|
||||
var val = document.getElementById(ids[i]).value;
|
||||
if (val.match(/[0-9a-fA-F][0-9a-fA-F]/) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return captcha_passed;
|
||||
}
|
||||
function update() {
|
||||
var ok = check();
|
||||
document.getElementById('submit_btn').disabled = !ok;
|
||||
document.getElementById('submit_btn2').disabled = !ok;
|
||||
}
|
||||
function doNext(obj, next) {
|
||||
if (obj.value.length == 2 && next != null) {
|
||||
document.getElementById(next).value = '';
|
||||
document.getElementById(next).focus();
|
||||
}
|
||||
update();
|
||||
}
|
||||
function captcha_ok() {
|
||||
captcha_passed = true;
|
||||
update();
|
||||
}
|
||||
function captcha_expired() {
|
||||
captcha_passed = false;
|
||||
update();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<img src='/static/letterbomb_icon.png' style="margin-bottom: -30px;"/>
|
||||
<h1>LetterBomb</h1>
|
||||
<form method="POST" action="{{ url_for('haxx') }}">
|
||||
<p>
|
||||
<h2>System Menu Version</h2>
|
||||
<input type='radio' name='region' value='U' {% if region=='U' %}checked{% endif %}>4.3U
|
||||
<input type='radio' name='region' value='E' {% if region=='E' %}checked{% endif %}>4.3E
|
||||
<input type='radio' name='region' value='J' {% if region=='J' %}checked{% endif %}>4.3J
|
||||
<input type='radio' name='region' value='K' {% if region=='K' %}checked{% endif %}>4.3K
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h2>MAC Address</h2>
|
||||
<input type='text' maxlength='2' size='2' name='a' id='a' class='box' onkeydown="return keyHandler(event);" onkeyup="doNext(this, 'b');" placeholder='AA' />
|
||||
<input type='text' maxlength='2' size='2' name='b' id='b' class='box' onkeydown="return keyHandler(event);" onkeyup="doNext(this, 'c');" placeholder='BB' />
|
||||
<input type='text' maxlength='2' size='2' name='c' id='c' class='box' onkeydown="return keyHandler(event);" onkeyup="doNext(this, 'd');" placeholder='CC' />
|
||||
<input type='text' maxlength='2' size='2' name='d' id='d' class='box' onkeydown="return keyHandler(event);" onkeyup="doNext(this, 'e');" placeholder='DD' />
|
||||
<input type='text' maxlength='2' size='2' name='e' id='e' class='box' onkeydown="return keyHandler(event);" onkeyup="doNext(this, 'f');" placeholder='EE' />
|
||||
<input type='text' maxlength='2' size='2' name='f' id='f' class='box' onkeydown="return keyHandler(event);" onkeyup="update();" placeholder='FF' />
|
||||
<br />Necessary to create and sign the correct file
|
||||
</p>
|
||||
<p>
|
||||
<input type='checkbox' name='bundle' value='1' checked /> <b>Bundle the HackMii Installer for me!</b>
|
||||
</p>
|
||||
<div style="float: center; display: inline-block;" class="recaptcha">
|
||||
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
|
||||
<div class="g-recaptcha" data-sitekey="{{ config.RECAPTCHA_PUBLICKEY }}" data-callback="captcha_ok" data-expired-callback="captcha_expired"></div>
|
||||
</div>
|
||||
{% if error %}
|
||||
<div style="color: red; font-weight: bold; font-size: 18pt;">{{ error }}</div>
|
||||
{% endif %}
|
||||
<div style="color: red; font-weight: bold; font-size: 18pt;" id="nojs">You must have JavaScript enabled to use this site.</div>
|
||||
<script>document.getElementById("nojs").style.display = "none";</script>
|
||||
<p>
|
||||
<input type='submit' value='Cut the red wire' id='submit_btn' class='button buttonr' disabled /> <input type='submit' value='Cut the blue wire' id='submit_btn2' class='button buttonb' disabled />
|
||||
</p>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
5
update_oui.sh
Executable file
5
update_oui.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
wget -O - http://standards.ieee.org/develop/regauth/oui/oui.txt | grep -i nintendo | grep base\ 16 | awk '{print $1}' | sort > oui_list.txt.new || exit 1
|
||||
diff -urN oui_list.txt oui_list.txt.new
|
||||
mv oui_list.txt oui_list.txt.old
|
||||
mv oui_list.txt.new oui_list.txt
|
Loading…
Reference in New Issue
Block a user