From 1b4809f70b1332ab7a94c310a6ec433d4acc440d Mon Sep 17 00:00:00 2001 From: zefie Date: Wed, 14 Jul 2021 08:54:54 -0400 Subject: [PATCH] proper nodejs versioning, encryption working --- .gitignore | 3 +- hacktv_updsrv/.gitignore | 366 ++++++++++++++++++ hacktv_updsrv/README.md | 22 +- ...sted wtv-log requests will appear here.txt | 0 .../ServiceVault/htv-update/upd/update.txt | 7 - .../ServiceVault/htv-update/upd/updater.html | 48 --- .../ServiceVault/wtv-1800/finish-prereg.js | 11 +- .../ServiceVault/wtv-1800/preregister.js | 30 +- .../ServiceVault/wtv-flashrom/get-lc2-page.js | 98 +++++ .../wtv-flashrom/lc2-download-failed.html | 50 +++ .../wtv-flashrom/lc2-download-failed.js | 53 +++ .../ServiceVault/wtv-flashrom/willie.js | 20 + .../wtv-head-waiter/finalize-security.js | 8 +- .../wtv-head-waiter/login-stage-two.js | 10 +- .../ServiceVault/wtv-head-waiter/login.js | 16 +- .../ServiceVault/wtv-head-waiter/test.js | 2 +- hacktv_updsrv/ServiceVault/wtv-home/home.js | 18 +- .../ServiceVault/wtv-home/splash.txt | 5 +- hacktv_updsrv/ServiceVault/wtv-log/log.js | 11 +- .../ServiceVault/wtv-log/phone-log.js | 10 - .../wtv-star/images/HackTVLogo.gif | Bin 0 -> 16880 bytes .../wtv-star/images/HackTVLogoJewel.gif | Bin 0 -> 5845 bytes .../wtv-star/images/WebTVLogoJewel.gif | Bin 0 -> 7459 bytes .../ServiceVault/wtv-tricks/blastcache.txt | 14 + .../ServiceVault/wtv-tricks/go-offline.js | 42 ++ .../wtv-update/content/diskmaps/htvupdate.txt | 10 + .../content/htvupdate/Games}/Games.html | 2 +- .../content/htvupdate/Games}/cSetup.html | 0 .../htvupdate/MattMan/Tricks}/tricks.html | 0 hacktv_updsrv/ServiceVault/wtv-update/sync.js | 36 ++ .../{htv-update => wtv-update}/update.html | 12 +- .../updatesuccess.txt | 1 + hacktv_updsrv/app.js | 226 +++++++---- hacktv_updsrv/hacktv_updsrv.njsproj | 41 +- hacktv_updsrv/package-lock.json | 21 +- hacktv_updsrv/package.json | 3 +- hacktv_updsrv/services.json | 5 +- hacktv_updsrv/wtvsec.js | 8 +- 38 files changed, 988 insertions(+), 221 deletions(-) create mode 100644 hacktv_updsrv/.gitignore create mode 100644 hacktv_updsrv/ServiceLogPost/client-posted wtv-log requests will appear here.txt delete mode 100644 hacktv_updsrv/ServiceVault/htv-update/upd/update.txt delete mode 100644 hacktv_updsrv/ServiceVault/htv-update/upd/updater.html create mode 100644 hacktv_updsrv/ServiceVault/wtv-flashrom/get-lc2-page.js create mode 100644 hacktv_updsrv/ServiceVault/wtv-flashrom/lc2-download-failed.html create mode 100644 hacktv_updsrv/ServiceVault/wtv-flashrom/lc2-download-failed.js create mode 100644 hacktv_updsrv/ServiceVault/wtv-flashrom/willie.js delete mode 100644 hacktv_updsrv/ServiceVault/wtv-log/phone-log.js create mode 100644 hacktv_updsrv/ServiceVault/wtv-star/images/HackTVLogo.gif create mode 100644 hacktv_updsrv/ServiceVault/wtv-star/images/HackTVLogoJewel.gif create mode 100644 hacktv_updsrv/ServiceVault/wtv-star/images/WebTVLogoJewel.gif create mode 100644 hacktv_updsrv/ServiceVault/wtv-tricks/blastcache.txt create mode 100644 hacktv_updsrv/ServiceVault/wtv-tricks/go-offline.js create mode 100644 hacktv_updsrv/ServiceVault/wtv-update/content/diskmaps/htvupdate.txt rename hacktv_updsrv/ServiceVault/{htv-update/upd => wtv-update/content/htvupdate/Games}/Games.html (95%) rename hacktv_updsrv/ServiceVault/{htv-update/upd => wtv-update/content/htvupdate/Games}/cSetup.html (100%) rename hacktv_updsrv/ServiceVault/{htv-update/upd => wtv-update/content/htvupdate/MattMan/Tricks}/tricks.html (100%) create mode 100644 hacktv_updsrv/ServiceVault/wtv-update/sync.js rename hacktv_updsrv/ServiceVault/{htv-update => wtv-update}/update.html (69%) rename hacktv_updsrv/ServiceVault/{htv-update => wtv-update}/updatesuccess.txt (76%) diff --git a/.gitignore b/.gitignore index 9491a2fd..4a8a2dea 100644 --- a/.gitignore +++ b/.gitignore @@ -360,4 +360,5 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +FodyWeavers.xsd +/hacktv_updsrv/ServiceLogPost/1626307222_warning_812bf30600b002bb diff --git a/hacktv_updsrv/.gitignore b/hacktv_updsrv/.gitignore new file mode 100644 index 00000000..9e06e212 --- /dev/null +++ b/hacktv_updsrv/.gitignore @@ -0,0 +1,366 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# ServiceLogPost Posted Logs +ServiceLogPost/*_* + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd +/hacktv_updsrv/ServiceLogPost/1626307222_warning_812bf30600b002bb diff --git a/hacktv_updsrv/README.md b/hacktv_updsrv/README.md index 19772a65..6d21e995 100644 --- a/hacktv_updsrv/README.md +++ b/hacktv_updsrv/README.md @@ -1,3 +1,23 @@ -# hacktv_updsrv +# wtv minisrv node.js +The ***wtv minisrv***, or "***hacktv_updsrv***" project is an ambitious node.js project to have a mini WebTV server that supports wtv-encryption for advanced level access. +This open source server is not yet ready for public use, but is available for anyone wanting to try to help advance it. + +Current status: +- Can encrypt and decrypt SECURE ON and arbitrary encrypted data +- Can handle psuedo encryption (box sends SECURE ON but does not encrypt) +- Can handle client "relogin" and "reconnect" events + +Current issues: +- Probably can't handle more than one box at a time +- Power cycling box and re-connecting via ConnectSetup may invalidate encryption until server is restarted +- wtv-update:/update does not yet function as intended + +Feature Todo: +- Test and enable flashrom flashing functionality (at least for LC2 and higher) +- Proper wtv-star (generic service error page) support. +- (maybe) implement HTTP proxy (needs to be able to defluff most of the web, think retro WAP converter) +- (maybe) enable "internet mode" (let user outside of minisrv) +- (maybe) wtvchat stuff +- (probably not) url tokenizer \ No newline at end of file diff --git a/hacktv_updsrv/ServiceLogPost/client-posted wtv-log requests will appear here.txt b/hacktv_updsrv/ServiceLogPost/client-posted wtv-log requests will appear here.txt new file mode 100644 index 00000000..e69de29b diff --git a/hacktv_updsrv/ServiceVault/htv-update/upd/update.txt b/hacktv_updsrv/ServiceVault/htv-update/upd/update.txt deleted file mode 100644 index 4a771cc2..00000000 --- a/hacktv_updsrv/ServiceVault/htv-update/upd/update.txt +++ /dev/null @@ -1,7 +0,0 @@ -GROUP name=hacktv version=!VERS! root=file://Disk/Browser/ service-owned - display Updating HackTV Files... - sync Games/Games.html Games.html - sync Games/cSetup.html cSetup.html - sync Games/updater.html updater.html - sync MattMan/Tricks/tricks.html tricks.html -END-GROUP diff --git a/hacktv_updsrv/ServiceVault/htv-update/upd/updater.html b/hacktv_updsrv/ServiceVault/htv-update/upd/updater.html deleted file mode 100644 index bd4058be..00000000 --- a/hacktv_updsrv/ServiceVault/htv-update/upd/updater.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - Retrieving Files - - - - - - - -
- - - - - - -
- Retrieving Files -
-
-
-
- - - -
- - - Your HackTV Box is downloading updates from zefie's server. -

This may take a while. - -

- -

- - - -
- - diff --git a/hacktv_updsrv/ServiceVault/wtv-1800/finish-prereg.js b/hacktv_updsrv/ServiceVault/wtv-1800/finish-prereg.js index 1e607636..325faf39 100644 --- a/hacktv_updsrv/ServiceVault/wtv-1800/finish-prereg.js +++ b/hacktv_updsrv/ServiceVault/wtv-1800/finish-prereg.js @@ -1,7 +1,7 @@ if (socket_session_data[socket.id].ssid != null && !sec_session[socket_session_data[socket.id].ssid]) { - sec_session[socket_session_data[socket.id].ssid] = new WTVNetworkSecurity(); + sec_session[socket_session_data[socket.id].ssid] = new WTVSec(); sec_session[socket_session_data[socket.id].ssid].IssueChallenge(); - sec_session[socket_session_data[socket.id].ssid].set_incarnation(initial_headers['wtv-incarnation']); + sec_session[socket_session_data[socket.id].ssid].set_incarnation(request_headers['wtv-incarnation']); } var contype = "text/tellyscript"; @@ -20,9 +20,10 @@ Connection: Keep-Alive wtv-initial-key: ` + issueWTVInitialKey(socket) + ` Content-Type: `+ contype + ` wtv-service: reset -`+getServiceString('wtv-star')+` -`+getServiceString('wtv-head-waiter')+` -`+getServiceString('wtv-flashrom')+` +` + getServiceString('wtv-1800') + ` +` + getServiceString('wtv-star') + ` +` + getServiceString('wtv-head-waiter') + ` +` + getServiceString('wtv-flashrom') + ` wtv-boot-url: wtv-1800:/preregister?relogin=true wtv-visit: wtv-head-waiter:/login? wtv-client-time-zone: GMT -0000 diff --git a/hacktv_updsrv/ServiceVault/wtv-1800/preregister.js b/hacktv_updsrv/ServiceVault/wtv-1800/preregister.js index 41ef0928..bd9909f4 100644 --- a/hacktv_updsrv/ServiceVault/wtv-1800/preregister.js +++ b/hacktv_updsrv/ServiceVault/wtv-1800/preregister.js @@ -2,33 +2,13 @@ var gourl = "wtv-1800:/finish-prereg?"; if (query['relogin']) gourl += "relogin=true"; -if (query['reconnect']) { - headers = `200 OK +if (request_headers['wtv-ticket']) { + gourl = "wtv-head-waiter:/login-stage-two?"; +} + +headers = `200 OK Connection: Keep-Alive wtv-expire-all: wtv- -wtv-expire-all: htv-` - - if (sec_session[initial_headers['wtv-client-serial-number']].ticket_b64) { - headers += "wtv-encrypted: true\n"; - headers += "wtv-ticket: " + sec_session[initial_headers['wtv-client-serial-number']].ticket_b64 + "\n"; - } - - headers += `wtv-client-time-zone: GMT -0000 -wtv-client-time-dst-rule: GMT -wtv-client-date: `+ strftime("%a, %d %b %Y %H:%M:%S", new Date(new Date().toUTCString())) + ` GMT -Content-type: text/html`; -} else { - - if (initial_headers['wtv-ticket']) { - gourl = "wtv-head-waiter:/login-stage-two?"; - } - - headers = `200 OK -Connection: Keep-Alive -wtv-expire-all: wtv- -wtv-expire-all: htv- wtv-open-isp-disabled: false wtv-visit: `+ gourl + ` Content-type: text/html`; - -} \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/wtv-flashrom/get-lc2-page.js b/hacktv_updsrv/ServiceVault/wtv-flashrom/get-lc2-page.js new file mode 100644 index 00000000..dd5ff305 --- /dev/null +++ b/hacktv_updsrv/ServiceVault/wtv-flashrom/get-lc2-page.js @@ -0,0 +1,98 @@ +headers = `200 OK +Content-type: text/html` + +data = ` + + +Updating + + + + + + + + + +
+ + + + + +
+Updating now... +
+
+
+
+
+ + + + + + + + + + + +
+
+ + + +Your Internet Receiver is being
updated automagically. +

+This will take forever, and then
your WebTV will reboot.

+
+

+ + + + + +
    Receiving part `+flashrom_part+` of `+totalprts+`v`+flashrom_version+` (`+flashrom_type+`)    
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +` \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/wtv-flashrom/lc2-download-failed.html b/hacktv_updsrv/ServiceVault/wtv-flashrom/lc2-download-failed.html new file mode 100644 index 00000000..19abc99a --- /dev/null +++ b/hacktv_updsrv/ServiceVault/wtv-flashrom/lc2-download-failed.html @@ -0,0 +1,50 @@ + + + +Updating failed + + + + + + + + + +
+ + + + + + + + +
+Updated failed +
+
+
+
+ +
+ + + + + + + + + + + +
+
+ + + +Update failed, gomennasai. + + \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/wtv-flashrom/lc2-download-failed.js b/hacktv_updsrv/ServiceVault/wtv-flashrom/lc2-download-failed.js new file mode 100644 index 00000000..de953f1f --- /dev/null +++ b/hacktv_updsrv/ServiceVault/wtv-flashrom/lc2-download-failed.js @@ -0,0 +1,53 @@ +headers = `200 OK +Content-type: text/html` + +data =` + + +Updating failed + + + + + + + + + +
+ + + + + + + + +
+Updated failed +
+
+
+
+ +
+ + + + + + + + + + + + +
+ + + +Update failed, gomennasai. + +` \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/wtv-flashrom/willie.js b/hacktv_updsrv/ServiceVault/wtv-flashrom/willie.js new file mode 100644 index 00000000..2e5eef92 --- /dev/null +++ b/hacktv_updsrv/ServiceVault/wtv-flashrom/willie.js @@ -0,0 +1,20 @@ +// willie is just a graphical frontend to a list of ROMs +// the rest of the scripts should work if you manually link to a ROM, and actually have it. + + +const options = new URL('http://wtv.zefie.com/willie.php?flash='+getSessionData(socket_session_data[socket.id].ssid, 'wtv-client-rom-type')) +var data_ready = false; +data = ''; +const req = http.request(options, res => { + console.log(`statusCode: ${res.statusCode}`) + + res.on('data', d => { + data += d; + }) + + res.on('end', function () { + data_ready = true; + }); +}); + +headers = "200 OK\nContent-type: text/html"; \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/wtv-head-waiter/finalize-security.js b/hacktv_updsrv/ServiceVault/wtv-head-waiter/finalize-security.js index ea99b6e5..ec678b8c 100644 --- a/hacktv_updsrv/ServiceVault/wtv-head-waiter/finalize-security.js +++ b/hacktv_updsrv/ServiceVault/wtv-head-waiter/finalize-security.js @@ -2,10 +2,10 @@ var challenge_response, challenge_header = ''; var gourl; if (socket_session_data[socket.id].ssid !== null) { - if (initial_headers['wtv-ticket']) { - if (initial_headers['wtv-ticket'].length > 8) { - DecodeTicket(initial_headers['wtv-ticket']); - sec_session[socket_session_data[socket.id].ssid].ticket_b64 = initial_headers['wtv-ticket']; + if (request_headers['wtv-ticket']) { + if (request_headers['wtv-ticket'].length > 8) { + DecodeTicket(request_headers['wtv-ticket']); + sec_session[socket_session_data[socket.id].ssid].ticket_b64 = request_headers['wtv-ticket']; //socket_session_data[socket.id].secure == true; } } else if (sec_session[socket_session_data[socket.id].ssid].ticket_b64 == null) { diff --git a/hacktv_updsrv/ServiceVault/wtv-head-waiter/login-stage-two.js b/hacktv_updsrv/ServiceVault/wtv-head-waiter/login-stage-two.js index 9c2f99be..27d81232 100644 --- a/hacktv_updsrv/ServiceVault/wtv-head-waiter/login-stage-two.js +++ b/hacktv_updsrv/ServiceVault/wtv-head-waiter/login-stage-two.js @@ -3,15 +3,15 @@ var gourl; if (socket_session_data[socket.id].ssid !== null) { if (sec_session[socket_session_data[socket.id].ssid].ticket_b64 == null) { - if (initial_headers['wtv-ticket']) { - if (initial_headers['wtv-ticket'].length > 8) { - sec_session[socket_session_data[socket.id].ssid].DecodeTicket(initial_headers['wtv-ticket']); - sec_session[socket_session_data[socket.id].ssid].ticket_b64 = initial_headers['wtv-ticket']; + if (request_headers['wtv-ticket']) { + if (request_headers['wtv-ticket'].length > 8) { + sec_session[socket_session_data[socket.id].ssid].DecodeTicket(request_headers['wtv-ticket']); + sec_session[socket_session_data[socket.id].ssid].ticket_b64 = request_headers['wtv-ticket']; //socket_session_data[socket.id].secure = true; } } else { challenge_response = sec_session[socket_session_data[socket.id].ssid].challenge_response; - var client_challenge_response = initial_headers['wtv-challenge-response'] || null; + var client_challenge_response = request_headers['wtv-challenge-response'] || null; if (challenge_response && client_challenge_response) { //if (challenge_response.toString(CryptoJS.enc.Base64).substring(0,85) == client_challenge_response.substring(0,85)) { if (challenge_response.toString(CryptoJS.enc.Base64) == client_challenge_response) { diff --git a/hacktv_updsrv/ServiceVault/wtv-head-waiter/login.js b/hacktv_updsrv/ServiceVault/wtv-head-waiter/login.js index 7ae2ae77..8c8ead24 100644 --- a/hacktv_updsrv/ServiceVault/wtv-head-waiter/login.js +++ b/hacktv_updsrv/ServiceVault/wtv-head-waiter/login.js @@ -1,16 +1,16 @@ var challenge_response, challenge_header = ''; if (socket_session_data[socket.id].ssid !== null) { - if (initial_headers['wtv-ticket']) { + if (request_headers['wtv-ticket']) { if (sec_session[socket_session_data[socket.id].ssid].ticket_b64 == null) { - if (initial_headers['wtv-ticket'].length > 8) { - sec_session[socket_session_data[socket.id].ssid].DecodeTicket(initial_headers['wtv-ticket']); - sec_session[socket_session_data[socket.id].ssid].ticket_b64 = initial_headers['wtv-ticket']; + if (request_headers['wtv-ticket'].length > 8) { + sec_session[socket_session_data[socket.id].ssid].DecodeTicket(request_headers['wtv-ticket']); + sec_session[socket_session_data[socket.id].ssid].ticket_b64 = request_headers['wtv-ticket']; } } } else { challenge_response = sec_session[socket_session_data[socket.id].ssid].challenge_response; - var client_challenge_response = initial_headers['wtv-challenge-response'] || null; + var client_challenge_response = request_headers['wtv-challenge-response'] || null; if (challenge_response && client_challenge_response) { if (challenge_response.toString(CryptoJS.enc.Base64).substring(0,85) == client_challenge_response.substring(0,85)) { console.log(" * wtv-challenge-response success for "+socket_session_data[socket.id].ssid); @@ -25,9 +25,9 @@ if (socket_session_data[socket.id].ssid !== null) { } /* -if (initial_headers) { +if (request_headers) { var cookiedata = {}; - Object.keys(initial_headers).forEach(function (k) { + Object.keys(request_headers).forEach(function (k) { switch (k) { case "wtv-capability-flags": case "wtv-system-version": @@ -36,7 +36,7 @@ if (initial_headers) { case "wtv-system-chipversion": case "wtv-system-sysconfig": case "wtv-system-cpuspeed": - cookiedata[k] = initial_headers[k]; + cookiedata[k] = request_headers[k]; break; } }); diff --git a/hacktv_updsrv/ServiceVault/wtv-head-waiter/test.js b/hacktv_updsrv/ServiceVault/wtv-head-waiter/test.js index 93abf3d0..14640344 100644 --- a/hacktv_updsrv/ServiceVault/wtv-head-waiter/test.js +++ b/hacktv_updsrv/ServiceVault/wtv-head-waiter/test.js @@ -1,2 +1,2 @@ -var wtvtest = new WTVNetworkSecurity(); +var wtvtest = new WTVSec(); wtvtest.Test(); \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/wtv-home/home.js b/hacktv_updsrv/ServiceVault/wtv-home/home.js index b8abbdb7..42cc642e 100644 --- a/hacktv_updsrv/ServiceVault/wtv-home/home.js +++ b/hacktv_updsrv/ServiceVault/wtv-home/home.js @@ -4,7 +4,7 @@ wtv-expire-all: wtv-home:/splash wtv-expire-all: htv- Content-type: text/html` -if (initial_headers['psuedo-encryption']) { +if (getSessionData(socket_session_data[socket.id].ssid, 'box-does-psuedo-encryption')) { var cryptstatus = "Psuedo-encrypted"; } else { var cryptstatus = ((socket_session_data[socket.id].secure === true) ? "Encrypted" : "Not Encrypted") @@ -13,7 +13,8 @@ if (initial_headers['psuedo-encryption']) { data =` - +Home for minsrv + -

Encryption Status: `+cryptstatus+`

` +

Welcome to `+ z_title + `

+

Encryption Status: `+cryptstatus+`

` if (socket_session_data[socket.id].secure) { data += 'Encryption Key (Server): ' + sec_session[socket.id].session_key2.toString(CryptoJS.enc.Hex)+'
'; data += 'Encryption Key (Client): ' + sec_session[socket.id].session_key1.toString(CryptoJS.enc.Hex)+'


'; } -data += `client:relog (via text/url)
-client:relog (direct)
-HackTV Updater Test
- +data += `client:relog (direct)
+Clear Cache
+HackTV Updater Test
+Ultra Willies
+Disconnect and go to HackTV Home
+ ` \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/wtv-home/splash.txt b/hacktv_updsrv/ServiceVault/wtv-home/splash.txt index c97f3d67..123e8313 100644 --- a/hacktv_updsrv/ServiceVault/wtv-home/splash.txt +++ b/hacktv_updsrv/ServiceVault/wtv-home/splash.txt @@ -4,8 +4,9 @@ wtv-expire-all: htv- Content-type: text/html +Engaging zefie... - +
- +

diff --git a/hacktv_updsrv/ServiceVault/wtv-log/log.js b/hacktv_updsrv/ServiceVault/wtv-log/log.js index 9a515fec..ec6b8c30 100644 --- a/hacktv_updsrv/ServiceVault/wtv-log/log.js +++ b/hacktv_updsrv/ServiceVault/wtv-log/log.js @@ -1,4 +1,13 @@ -// dummy page, we could handle the logs here. +// write posted log data to disk. should be decrypted by this point (if it was encrypted) if the crypto stream didn't break + +if (request_headers['post_data']) { + var fullpath = __dirname + "/ServiceLogPost/" + Math.floor(new Date().getTime() / 1000) + "_" + query['type']; + if (socket_session_data[socket.id].ssid) fullpath += "_" + socket_session_data[socket.id].ssid; + + fullpath = fullpath.replace(/\\/g, "/"); + fs.writeFileSync(fullpath, request_headers['post_data'].toString(CryptoJS.enc.Hex), "Hex"); + console.log("Wrote POST log data from", socket_session_data[socket.id].ssid, "to", fullpath, "on", socket.id); +} headers = `200 OK Connection: Keep-Alive diff --git a/hacktv_updsrv/ServiceVault/wtv-log/phone-log.js b/hacktv_updsrv/ServiceVault/wtv-log/phone-log.js deleted file mode 100644 index 78cd7415..00000000 --- a/hacktv_updsrv/ServiceVault/wtv-log/phone-log.js +++ /dev/null @@ -1,10 +0,0 @@ -// dummy page, we could handle the logs here. - -headers = `200 OK -Connection: Keep-Alive -wtv-visit: wtv-home:/splash? -Content-length: 0`; - -data = ''; - - diff --git a/hacktv_updsrv/ServiceVault/wtv-star/images/HackTVLogo.gif b/hacktv_updsrv/ServiceVault/wtv-star/images/HackTVLogo.gif new file mode 100644 index 0000000000000000000000000000000000000000..7df200353d74824c577df2a10f948bad8c60df38 GIT binary patch literal 16880 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 z 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 literal 0 HcmV?d00001 diff --git a/hacktv_updsrv/ServiceVault/wtv-star/images/HackTVLogoJewel.gif b/hacktv_updsrv/ServiceVault/wtv-star/images/HackTVLogoJewel.gif new file mode 100644 index 0000000000000000000000000000000000000000..07a0f4b89f69c09aeab54c2d11da99fef40b5ca7 GIT binary patch literal 5845 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 XA&c5qT{hU11bMt+0g}mu259~tK^*wd literal 0 HcmV?d00001 diff --git a/hacktv_updsrv/ServiceVault/wtv-tricks/blastcache.txt b/hacktv_updsrv/ServiceVault/wtv-tricks/blastcache.txt new file mode 100644 index 00000000..d25940c4 --- /dev/null +++ b/hacktv_updsrv/ServiceVault/wtv-tricks/blastcache.txt @@ -0,0 +1,14 @@ +200 OK +wtv-noback-all: wtv- +wtv-expire-all: wtv- +Content-type: text/html + + + + + + + \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/wtv-tricks/go-offline.js b/hacktv_updsrv/ServiceVault/wtv-tricks/go-offline.js new file mode 100644 index 00000000..f43dad67 --- /dev/null +++ b/hacktv_updsrv/ServiceVault/wtv-tricks/go-offline.js @@ -0,0 +1,42 @@ +headers = `200 OK +wtv-noback-all: wtv- +wtv-expire-all: wtv- +Content-type: text/html +wtv-service: reset +`+getServiceString('wtv-1800'); + + +// HackTV Homepage is default +var url="file://Disk/Browser/Games/Games.html"; + +if (query['url']) { + url = query['url']; +} + +data = ` + +Going offline... + + + +

+` +if (query['title']) { + data += "Going offline and loading "+decodeURI(query['title'])+", please wait!"; +} else { + data += "Please wait a moment."; +} + +data += "\n"; diff --git a/hacktv_updsrv/ServiceVault/wtv-update/content/diskmaps/htvupdate.txt b/hacktv_updsrv/ServiceVault/wtv-update/content/diskmaps/htvupdate.txt new file mode 100644 index 00000000..d2d97268 --- /dev/null +++ b/hacktv_updsrv/ServiceVault/wtv-update/content/diskmaps/htvupdate.txt @@ -0,0 +1,10 @@ +GROUP name=Browser version=!VERS! root=file://Disk/Browser/Games/ + display Updating HackTV Files... + sync Games.html content/htvupdate/Games/Games.html + sync cSetup.html content/htvupdate/Games/cSetup.html +END-GROUP + +GROUP name=Browser version=!VERS! root=file://Disk/Browser/MattMan/ + display Updating HackTV Files... + sync Tricks/tricks.html content/htvupdate/MattMan/Tricks/tricks.html +END-GROUP \ No newline at end of file diff --git a/hacktv_updsrv/ServiceVault/htv-update/upd/Games.html b/hacktv_updsrv/ServiceVault/wtv-update/content/htvupdate/Games/Games.html similarity index 95% rename from hacktv_updsrv/ServiceVault/htv-update/upd/Games.html rename to hacktv_updsrv/ServiceVault/wtv-update/content/htvupdate/Games/Games.html index 1acd2e95..a76fca83 100644 --- a/hacktv_updsrv/ServiceVault/htv-update/upd/Games.html +++ b/hacktv_updsrv/ServiceVault/wtv-update/content/htvupdate/Games/Games.html @@ -81,7 +81,7 @@ if (document.images) {
  • HTML Viewer
  • HackTV Tricks
  • Connect Setup -
  • Test +
  • NEW! Check for Updates
  • diff --git a/hacktv_updsrv/ServiceVault/htv-update/upd/cSetup.html b/hacktv_updsrv/ServiceVault/wtv-update/content/htvupdate/Games/cSetup.html similarity index 100% rename from hacktv_updsrv/ServiceVault/htv-update/upd/cSetup.html rename to hacktv_updsrv/ServiceVault/wtv-update/content/htvupdate/Games/cSetup.html diff --git a/hacktv_updsrv/ServiceVault/htv-update/upd/tricks.html b/hacktv_updsrv/ServiceVault/wtv-update/content/htvupdate/MattMan/Tricks/tricks.html similarity index 100% rename from hacktv_updsrv/ServiceVault/htv-update/upd/tricks.html rename to hacktv_updsrv/ServiceVault/wtv-update/content/htvupdate/MattMan/Tricks/tricks.html diff --git a/hacktv_updsrv/ServiceVault/wtv-update/sync.js b/hacktv_updsrv/ServiceVault/wtv-update/sync.js new file mode 100644 index 00000000..55195a58 --- /dev/null +++ b/hacktv_updsrv/ServiceVault/wtv-update/sync.js @@ -0,0 +1,36 @@ +var content_dir = service_dir + '/content/'; +var diskmap_dir = content_dir + '/diskmaps/'; + + +if (query['diskmap']) { + if (fs.lstatSync(diskmap_dir + query['diskmap'] + ".txt")) { + var diskmap_data = fs.readFileSync(diskmap_dir + query['diskmap'] + ".txt").toString(); + // try to parse diskmap and get an accurate timestamp for webtv versioning + // check all files in the diskmap and return the timestamp of the most recently modified + + data = ''; + var latest_file_ts = 0; + diskmap_data.split("\n").forEach(function (v) { + if (v.indexOf(" sync ") != -1) { + v = v.trim(); + var vcon = v.substring(v.indexOf("content/")); + vcon = vcon.replace("content/", content_dir) + var vconstat = Math.floor(fs.lstatSync(vcon).mtimeMs / 1000); + if (vconstat > latest_file_ts) { + latest_file_ts = vconstat + } + // todo read client post and only give whats needed + // instead of all that is available + // vconstat has the mtime of each file, we need to parse the post_data + data += v + "\n"; + } else { + data += v + "\n"; + } + }); + //data = diskmap_data.replace("!VERS!", latest_file_ts); + } +} + +headers = `200 OK +Content-type: text/download-list` + diff --git a/hacktv_updsrv/ServiceVault/htv-update/update.html b/hacktv_updsrv/ServiceVault/wtv-update/update.html similarity index 69% rename from hacktv_updsrv/ServiceVault/htv-update/update.html rename to hacktv_updsrv/ServiceVault/wtv-update/update.html index b07096b7..7c2cf193 100644 --- a/hacktv_updsrv/ServiceVault/htv-update/update.html +++ b/hacktv_updsrv/ServiceVault/wtv-update/update.html @@ -2,10 +2,10 @@ - - Retrieving Files + + HackTV Updater @@ -18,7 +18,7 @@
    - Retrieving Files + Download HackTV Updates
    @@ -31,7 +31,7 @@ @@ -40,7 +40,7 @@

    - Your HackTV Box is downloading updates from zefie's server. + Your HackTV Unit is downloading updates.

    This may take a while.

    diff --git a/hacktv_updsrv/ServiceVault/htv-update/updatesuccess.txt b/hacktv_updsrv/ServiceVault/wtv-update/updatesuccess.txt similarity index 76% rename from hacktv_updsrv/ServiceVault/htv-update/updatesuccess.txt rename to hacktv_updsrv/ServiceVault/wtv-update/updatesuccess.txt index 5d3cf0cf..9655cb3d 100644 --- a/hacktv_updsrv/ServiceVault/htv-update/updatesuccess.txt +++ b/hacktv_updsrv/ServiceVault/wtv-update/updatesuccess.txt @@ -1,3 +1,4 @@ +200 OK Content-Type: text/url client:ShowAlert?message=HackTV%20Update%20was%20successful%21&buttonlabel2=Go%20to%20HackTV&action2=file%3A%2F%2FDisk%2FBrowser%2FGames%2FGames.html&buttonlabel1=Okay&buttonaction1=client:goback&image=file://disk/browser/Games/hacktv2.gif&noback=true \ No newline at end of file diff --git a/hacktv_updsrv/app.js b/hacktv_updsrv/app.js index 40c8a5e3..dce6d78f 100644 --- a/hacktv_updsrv/app.js +++ b/hacktv_updsrv/app.js @@ -7,13 +7,16 @@ const strftime = require('strftime'); const net = require('net'); const CryptoJS = require('crypto-js'); const mime = require('mime-types'); -var WTVNetworkSecurity = require('./wtvsec.js'); +const crc16 = require('node-crc16'); +var WTVSec = require('./wtvsec.js'); -var zdebug = true; +var zdebug = false; var pubip = "192.168.11.8"; var ports = []; +var service_vault_dir = __dirname + "/ServiceVault"; + //pubip = getPublicIP(); function getServiceString(service) { @@ -37,6 +40,8 @@ var sec_session = new Array(); var socket_buffer = new Array(); var socket_session_data = new Array(); +var script_processing_timeout = 10; // seconds + var overrides = new Array(); //overrides['initial_key'] = "CC5rWmRUE0o="; //overrides['challenge'] = "0kjyqIYAu0ziFBbSERN6DGaZ6S0fT+DBUCtpHCJ4lpuM7CbXdAm+x83BIDoJYztd1Z+5KFZ7ghmb3LJCT/6mhWUYkqqKOyfPRW8ZIdbICK/CV+Kxm8EUjRXZSk/97tsmFpH3hcCJ7C2TBw+TX38uQQ=="; @@ -108,8 +113,8 @@ function doErrorPage(code) { var headers, data = null; switch (code) { case 404: - data = "The resource you requested could not be found."; - headers = "HTTP/1.1 404 Not Found\r\n"; + data = "The service could not find the requested page."; + headers = "404 "+data+"\r\n"; headers += "Content-Type: text/html\r\n"; break; case 400: @@ -128,7 +133,15 @@ function doErrorPage(code) { return new Array(headers, data); } -function processPath(socket, path, initial_headers = new Array(), query = new Array()) { +function getConType(path) { + // custom contype for flashrom + if (path.indexOf("wtv-flashrom") && (path.substring(path.length - 4, path.length) == ".rom" || path.substring(path.length - 5, path.length) == ".brom")) { + return "binary/x-wtv-flashblock"; + } + return mime.lookup(path); +} + +async function processPath(socket, path, request_headers = new Array(), query = new Array(), service_name) { var headers, data = null; var request_is_direct_file = false; path = path.replace(/\\/g, "/"); @@ -145,32 +158,36 @@ function processPath(socket, path, initial_headers = new Array(), query = new Ar if (request_is_direct_file) { // file exists, read it and return it console.log(" * Found " + path + " to handle request (Direct File Mode) [Socket " + socket.id +"]"); - var contype = mime.lookup(path); + var contype = getConType(path); data = fs.readFileSync(path).buffer; headers = "200 OK\n" headers += "Content-Type: " + contype; } else if (fs.existsSync(path + ".txt")) { // raw text format, entire payload expected (headers and content) console.log(" * Found " + path + ".txt to handle request (Raw TXT Mode) [Socket " + socket.id +"]"); - var fdat = fs.readFileSync(path + ".txt").toString(); - if (fdat.indexOf("\n\n") > 0) { - var fdata = fdat.split("\n\n"); - headers = fdata[0]; - fdata.shift(); - data = fdata.join("\n"); - } else if (fdat.indexOf("\r\n\r\n") > 0) { - var fdata = fdat.split("\r\n\r\n"); - headers = fdata[0].replace(/\r/g, ""); - fdata.shift(); - data = fdata.join("\r\n"); + var file_raw = fs.readFileSync(path + ".txt").toString(); + if (file_raw.indexOf("\n\n") > 0) { + var file_raw_split = file_raw.split("\n\n"); + headers = file_raw_split[0]; + file_raw_split.shift(); + data = file_raw_split.join("\n"); + } else if (file_raw.indexOf("\r\n\r\n") > 0) { + var file_raw_split = file_raw.split("\r\n\r\n"); + headers = file_raw_split[0].replace(/\r/g, ""); + file_raw_split.shift(); + data = file_raw_split.join("\r\n"); + } else { + headers = fdat; } } else if (fs.existsSync(path + ".js")) { // js scripting, process with vars, must set 'headers' and 'data' appropriately. // loaded script will have r/w access to any JavaScript vars this function does. // any query args are in an array named 'query' - console.log(" * Found " + path + ".js to handle request (JS Interpreter mode) [Socket "+socket.id+"]"); - var fdat = fs.readFileSync(path + ".js").toString(); - eval(fdat); + console.log(" * Found " + path + ".js to handle request (JS Interpreter mode) [Socket " + socket.id + "]"); + var service_dir = service_vault_dir.replace(/\\/g,"/") + "/" + service_name; + socket_session_data[socket.id].starttime = Math.floor(new Date().getTime() / 1000); + var jscript_eval = fs.readFileSync(path + ".js").toString(); + eval(jscript_eval); } else if (fs.existsSync(path + ".html")) { // Standard HTML with no headers, WTV Style console.log(" * Found " + path + ".html to handle request (HTML Mode) [Socket " + socket.id +"]"); @@ -194,6 +211,8 @@ function processPath(socket, path, initial_headers = new Array(), query = new Ar var errpage = doErrorPage(400); headers = errpage[0]; data = errpage[1]; + console.log(" * Scripting or Data error: Headers were not defined. (headers,data) as follows:") + console.log(headers,data) } if (data === null) { data = ''; @@ -214,53 +233,56 @@ function processPath(socket, path, initial_headers = new Array(), query = new Ar return new Array(headers, data); } -function processURL(socket, initial_headers) { - if (initial_headers === null) { +async function processURL(socket, request_headers) { + if (request_headers === null) { return; } var shortURL, headers, data = ""; var query = new Array(); - if (initial_headers['request_url']) { - if (initial_headers['request_url'].indexOf('?') >= 0) { - shortURL = initial_headers['request_url'].split('?')[0]; - var qraw = initial_headers['request_url'].split('?')[1]; + if (request_headers['request_url']) { + if (request_headers['request_url'].indexOf('?') >= 0) { + shortURL = request_headers['request_url'].split('?')[0]; + var qraw = request_headers['request_url'].split('?')[1]; if (qraw.length > 0) { qraw = qraw.split("&"); for (let i = 0; i < qraw.length; i++) { - query[qraw[i].split("=")[0]] = qraw[i].split("=")[1]; - } - if (zdebug) { - console.log("URL Request has query arguments:") - console.log(query); + var k = qraw[i].split("=")[0]; + if (k) { + query[k] = qraw[i].split("=")[1]; + } } + + console.log(" * Request query:", query); } } else { - shortURL = initial_headers['request_url']; + shortURL = request_headers['request_url']; } if (shortURL.indexOf(':/') >= 0) { var ssid = socket_session_data[socket.id].ssid; if (ssid == null) { - ssid = initial_headers['wtv-client-serial-number']; + ssid = request_headers['wtv-client-serial-number']; } var reqverb = "Request"; - if (initial_headers['encrypted'] || initial_headers['secure']) { + if (request_headers['encrypted'] || request_headers['secure']) { reqverb = "Encrypted " + reqverb; } - if (initial_headers['psuedo-encryption']) { + if (request_headers['psuedo-encryption']) { reqverb = "Psuedo-encrypted " + reqverb; } if (ssid != null) { - console.log(" * "+reqverb+" for " + initial_headers['request_url'] + " from WebTV SSID " + ssid, 'on', socket.id); + console.log(" * "+reqverb+" for " + request_headers['request_url'] + " from WebTV SSID " + ssid, 'on', socket.id); } else { - console.log(" * "+reqverb+" for " + initial_headers['request_url'], 'on', socket.id); + console.log(" * "+reqverb+" for " + request_headers['request_url'], 'on', socket.id); } // assume webtv since there is a :/ in the GET - var urlToPath = __dirname + "/ServiceVault/" + shortURL.split(':/')[0] + "/" + shortURL.split(':/')[1]; - if (zdebug) console.log(initial_headers); - var result = processPath(socket, urlToPath, initial_headers, query); + var service_name = shortURL.split(':/')[0]; + var urlToPath = service_vault_dir.replace(/\\/g, "/") + "/" + service_name + "/" + shortURL.split(':/')[1]; + console.log(request_headers); + var result = await processPath(socket, urlToPath, request_headers, query, service_name); if (result[0] == null) { + // error processing path var errpage = doErrorPage(404); headers = errpage[0]; data = errpage[1]; @@ -278,6 +300,7 @@ function processURL(socket, initial_headers) { } } } else { + // error reading headers (no request_url provided) var errpage = doErrorPage(400); headers = errpage[0]; data = errpage[1]; @@ -315,7 +338,8 @@ function processURL(socket, initial_headers) { headers_obj = moveObjectElement('Connection','http_response', headers_obj); } - if (initial_headers['psuedo-encryption']) { + if (request_headers['psuedo-encryption'] || getSessionData(socket_session_data[socket.id].ssid, 'box-does-psuedo-encryption')) { + request_headers['psuedo-encryption'] = true; headers_obj['wtv-encrypted'] = true; headers_obj = moveObjectElement('wtv-encrypted', 'Connection', headers_obj); } @@ -411,20 +435,24 @@ function headersAreStandard(string, verbose) { // we can better process it with the raw base64 data in processHeaders() below. var test = /^([A-Za-z0-9\+\/\=\-\.\,\ \;\:\?\&\r\n\(\)\%\<\>\_]{8,})$/.test(string); if (verbose) { - if (zdebug) console.log("request is ascii: " + test); - if (zdebug) console.log("request is SECURE ON: " + /^SECURE ON/.test(string)); + if (zdebug) console.log(" # Request is ascii: " + test); + if (zdebug) console.log(" # Request is SECURE ON: " + /^SECURE ON/.test(string)); } return test; } -function processHeaders(socket, data_hex, returnHeadersBeforeSecure = false, encryptedRequest = false) { +async function processHeaders(socket, data_hex, returnHeadersBeforeSecure = false, encryptedRequest = false) { var url = ""; var data = CryptoJS.enc.Latin1.stringify(CryptoJS.enc.Hex.parse(data_hex)); var headers = new Array(); if (typeof data === "string") { if (data.length > 1) { - data = data.split("\r\n\r\n")[0]; + if (data.indexOf("\r\n\r\n") != -1) { + data = data.split("\r\n\r\n")[0]; + } else { + data = data.split("\n\n")[0]; + } if (headersAreStandard(data, (!returnHeadersBeforeSecure && !encryptedRequest))) { data.split('\n').forEach(function (d) { if (d.length > 0) { @@ -444,29 +472,29 @@ function processHeaders(socket, data_hex, returnHeadersBeforeSecure = false, enc } }); } else if (!returnHeadersBeforeSecure) { + // if its a POST request, assume its a binary blob and not encrypted (dangerous) if (!encryptedRequest) { - // failed the headersAreStandard test, so we think this is a binary blob + // its not a POST and it 1failed the headersAreStandard test, so we think this is an encrypted blob if (socket_session_data[socket.id].secure != true) { // first time so reroll sessions - sec_session[socket.id] = new WTVNetworkSecurity(); + sec_session[socket.id] = new WTVSec(); sec_session[socket.id].IssueChallenge(); - console.log(" [ UNEXPECTED BINARY BLOCK ] First sign of encryption, re-creating RC4 sessions for socket id",socket.id); + if (zdebug) console.log(" # [ UNEXPECTED BINARY BLOCK ] First sign of encryption, re-creating RC4 sessions for socket id",socket.id); sec_session[socket.id].SecureOn(); socket_session_data[socket.id].secure = true; } var enc_data = CryptoJS.enc.Hex.parse(data_hex.substring(header_length * 2)); if (enc_data.sigBytes > 0) { var dec_data = CryptoJS.lib.WordArray.create(sec_session[socket.id].Decrypt(0,enc_data)); - var dec_data_text = dec_data.toString(CryptoJS.enc.Latin1); - var secure_headers = processHeaders(socket, dec_data.toString(CryptoJS.enc.Hex), true, true); + var secure_headers = await processHeaders(socket, dec_data.toString(CryptoJS.enc.Hex), true, true); headers['encrypted'] = true; - console.log("Encrypted Request (Decrypted):", dec_data.toString(CryptoJS.enc.Latin1),"on",socket.id); Object.keys(secure_headers).forEach(function (k, v) { headers[k] = secure_headers[k]; }); } } } + if (headers['wtv-client-serial-number'] != null) { socket_session_data[socket.id].ssid = headers['wtv-client-serial-number']; } @@ -484,13 +512,14 @@ function processHeaders(socket, data_hex, returnHeadersBeforeSecure = false, enc } if (returnHeadersBeforeSecure) { + headers = await checkForPostData(socket, headers, data, data_hex, returnHeadersBeforeSecure); return headers; } if (headers['secure'] === true) { if (!sec_session[socket.id]) { - console.log("Starting new WTVNetworkSecurity instance on socket", socket.id); - sec_session[socket.id] = new WTVNetworkSecurity(); + console.log(" * Starting new WTVSec instance on socket", socket.id); + sec_session[socket.id] = new WTVSec(); sec_session[socket.id].DecodeTicket(headers['wtv-ticket']); sec_session[socket.id].ticket_b64 = headers['wtv-ticket']; if (getSessionData(socket_session_data[socket.id].ssid, 'incarnation')) { @@ -500,7 +529,7 @@ function processHeaders(socket, data_hex, returnHeadersBeforeSecure = false, enc } if (socket_session_data[socket.id].secure != true) { // first time so reroll sessions - console.log(" [ SECURE ON BLOCK ("+socket.id+")]"); + if (zdebug) console.log(" # [ SECURE ON BLOCK ("+socket.id+")]"); socket_session_data[socket.id].secure = true; } if (!headers['request_url']) { @@ -516,16 +545,18 @@ function processHeaders(socket, data_hex, returnHeadersBeforeSecure = false, enc if (enc_data.sigBytes > 0) { if (headersAreStandard(enc_data.toString(CryptoJS.enc.Latin1), (!returnHeadersBeforeSecure && !encryptedRequest))) { // some builds (like our targeted 3833), send SECURE ON but then unencrypted headers - console.log("Psuedo-encrypted Request (SECURE ON)", "on", socket.id); + if (zdebug) console.log(" # Psuedo-encrypted Request (SECURE ON)", "on", socket.id); // don't actually encrypt output headers['psuedo-encryption'] = true; + setSessionData(socket_session_data[socket.id].ssid, 'box-does-psuedo-encryption', true); socket_session_data[socket.id].secure = false; - var secure_headers = processHeaders(socket, enc_data.toString(CryptoJS.enc.Hex), true); + var secure_headers = await processHeaders(socket, enc_data.toString(CryptoJS.enc.Hex), true); } else { // SECURE ON and detected encrypted data + setSessionData(socket_session_data[socket.id].ssid, 'box-does-psuedo-encryption', false); var dec_data = CryptoJS.lib.WordArray.create(sec_session[socket.id].Decrypt(0, enc_data)) - var secure_headers = processHeaders(socket, dec_data.toString(CryptoJS.enc.Hex), true); - console.log("Encrypted Request (SECURE ON)", "on", socket.id); + var secure_headers = await processHeaders(socket, dec_data.toString(CryptoJS.enc.Hex), true); + if (zdebug) console.log(" # Encrypted Request (SECURE ON)", "on", socket.id); } // Merge new headers into existing headers object Object.keys(secure_headers).forEach(function (k, v) { @@ -534,6 +565,7 @@ function processHeaders(socket, data_hex, returnHeadersBeforeSecure = false, enc } } } + headers = await checkForPostData(socket, headers, data, data_hex); return headers; } else { // socket error, terminate it. @@ -543,9 +575,59 @@ function processHeaders(socket, data_hex, returnHeadersBeforeSecure = false, enc return null; } +async function checkForPostData(socket, headers, data, data_hex) { + if (headers['request']) { + if (headers['request'].substring(0, 4) == "POST") { + if (data_hex.indexOf("0d0a0d0a") != -1) { + // \r\n\r\n + var header_length = data.length + 4; + } else if (data_hex.indexOf("0a0a") != -1) { + // \n\n + var header_length = data.length + 2; + } + if (socket_session_data[socket.id].secure == true) { + var enc_data = CryptoJS.enc.Hex.parse(data_hex.substring(header_length * 2)); + if (enc_data.sigBytes > 0) { + if (headersAreStandard(enc_data.toString(CryptoJS.enc.Latin1))) { + // some builds (like our targeted 3833), send SECURE ON but then unencrypted headers + if (zdebug) console.log(" # Psuedo-encrypted POST Content (SECURE ON)", "on", socket.id); + // don't actually encrypt output + headers['psuedo-encryption'] = true; + setSessionData(socket_session_data[socket.id].ssid, 'box-does-psuedo-encryption', true); + socket_session_data[socket.id].secure = false; + headers['post_data'] = await processHeaders(socket, enc_data.toString(CryptoJS.enc.Hex), true); + } else { + // SECURE ON and detected encrypted data + setSessionData(socket_session_data[socket.id].ssid, 'box-does-psuedo-encryption', false); + headers['post_data'] = CryptoJS.lib.WordArray.create(sec_session[socket.id].Decrypt(0, enc_data)) + if (zdebug) console.log(" # Encrypted POST Content (SECURE ON)", "on", socket.id); + } + } + } else { + if (zdebug) console.log(" # Unencrypted POST Content", "on", socket.id); + headers['post_data'] = CryptoJS.enc.Hex.parse(data_hex.substring(header_length * 2)); + } + } + } + return headers; +} -function handleSocket(socket) { - socket.id = Math.floor(Math.random() * 100000); +async function cleanupSocket(socket) { + try { + console.log(" * Destroying old WTVSec instance on disconnected socket", socket.id); + delete socket_buffer[socket.id]; + delete socket_session_data[socket.id]; + delete sec_session[socket.id]; + socket.end(); + } catch (e) { + console.log(" # Could not clean up socket data for socket ID", socket.id, e); + } +}; + + +async function handleSocket(socket) { + // create unique socket id with client address and port + socket.id = parseInt(crc16.checkSum(Buffer.from(String(socket.remoteAddress) + String(socket.remotePort), "utf8")).toString("hex"),16); socket_session_data[socket.id] = []; socket.setEncoding('hex'); //set data encoding (either 'ascii', 'utf8', or 'base64') socket.on('data', function (data_hex) { @@ -557,28 +639,26 @@ function handleSocket(socket) { } }); - socket.on('timeout', function () { + socket.on('timeout', async function () { socket.setTimeout(0); - processURL(this, processHeaders(this, socket_buffer[socket.id].toString(CryptoJS.enc.Hex))); + var phead = await processHeaders(this, socket_buffer[socket.id].toString(CryptoJS.enc.Hex)); + processURL(this, phead); socket_buffer[socket.id] = null; }); - socket.on('error', (err, socket) => { + socket.on('error', (err) => { console.log(" * Client disconnected unexpectedly"); + cleanupSocket(socket); + }); socket.on('end', function () { - console.log(" * Destroying old WTVNetworkSecurity instance on socket", socket.id); - delete socket_buffer[socket.id]; - delete socket_session_data[socket.id]; - delete sec_session[socket.id]; + cleanupSocket(socket); }); } -var z_version = "0.5.1a"; -var z_title = "zefie's wtv minisrv v" + z_version; +var z_title = "zefie's wtv minisrv v" + require('./package.json').version; console.log("**** Welcome to " + z_title + " ****"); - console.log(" *** Reading service configuration..."); var services_configured = JSON.parse(fs.readFileSync(__dirname + "/services.json")); Object.keys(services_configured.services).forEach(function (k) { @@ -605,7 +685,11 @@ Object.keys(services_configured.services).forEach(function (k) { var initstring = ''; ports.sort(); -ports.forEach(function (v) { + +// de-duplicate ports in case user configured multiple services on same port +const bind_ports = [...new Set(ports)] + +bind_ports.forEach(function (v) { try { var server = net.createServer(handleSocket); server.listen(v, '0.0.0.0'); diff --git a/hacktv_updsrv/hacktv_updsrv.njsproj b/hacktv_updsrv/hacktv_updsrv.njsproj index 0c783daf..4111df51 100644 --- a/hacktv_updsrv/hacktv_updsrv.njsproj +++ b/hacktv_updsrv/hacktv_updsrv.njsproj @@ -28,18 +28,31 @@ true + Code - + + + + + + + + + + + + + + + + Code + + - - - - - - + @@ -48,7 +61,6 @@ - Code @@ -57,12 +69,21 @@ - - + + + + + + + + + + + \ No newline at end of file diff --git a/hacktv_updsrv/package-lock.json b/hacktv_updsrv/package-lock.json index 7af7441a..29ba1225 100644 --- a/hacktv_updsrv/package-lock.json +++ b/hacktv_updsrv/package-lock.json @@ -1,9 +1,14 @@ { "name": "hacktv_updsrv", - "version": "0.0.0", + "version": "0.5.2", "lockfileVersion": 1, "requires": true, "dependencies": { + "buffer-factory": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/buffer-factory/-/buffer-factory-1.0.8.tgz", + "integrity": "sha512-EkUcaWsg7Vw+bfpGrpqzDIV4u3FksbHy0I0x9IZogqtCh9rZ5IHPTs/1QtZNNm/8BOeznUKTXIA72sVXEmFREQ==" + }, "crypto-js": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", @@ -27,6 +32,20 @@ "mime-db": "1.48.0" } }, + "node-addon-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz", + "integrity": "sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==" + }, + "node-crc16": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/node-crc16/-/node-crc16-2.0.7.tgz", + "integrity": "sha512-dbLudH39wvydMXsT5E/jdyEP0t/kO3EOFQawVeBk3cJP23+jL4feoCWF2kMThEvijrEt2isFx2XzYjLkf0h8+g==", + "requires": { + "buffer-factory": "1.0.8", + "node-addon-api": "3.0.0" + } + }, "strftime": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.0.tgz", diff --git a/hacktv_updsrv/package.json b/hacktv_updsrv/package.json index 26eb241a..bf401f16 100644 --- a/hacktv_updsrv/package.json +++ b/hacktv_updsrv/package.json @@ -1,6 +1,6 @@ { "name": "hacktv_updsrv", - "version": "0.0.0", + "version": "0.5.2", "description": "hacktv_updsrv", "main": "app.js", "author": { @@ -10,6 +10,7 @@ "crypto-js": "^4.0.0", "endianness": "^8.0.2", "mime-types": "^2.1.31", + "node-crc16": "^2.0.7", "strftime": "^0.10.0" } } diff --git a/hacktv_updsrv/services.json b/hacktv_updsrv/services.json index 19194250..82d4a766 100644 --- a/hacktv_updsrv/services.json +++ b/hacktv_updsrv/services.json @@ -14,8 +14,9 @@ "flags": "0x00000001", "connections": 1 }, - "htv-update": { + "wtv-update": { "port": 1619, + "flags": "0x04", "connections": 3 }, "wtv-log": { @@ -27,7 +28,7 @@ "flags": "0x00000010" }, "wtv-tricks": { - "port": "1602", + "port": 1602, "flags": "0x00000004" }, "wtv-flashrom": { diff --git a/hacktv_updsrv/wtvsec.js b/hacktv_updsrv/wtvsec.js index f4315de7..c23b2d8c 100644 --- a/hacktv_updsrv/wtvsec.js +++ b/hacktv_updsrv/wtvsec.js @@ -2,7 +2,7 @@ const CryptoJS = require('crypto-js'); const endianness = require('endianness'); var crypto = require('crypto'); -class WTVNetworkSecurity { +class WTVSec { //initial_shared_key = CryptoJS.lib.WordArray.random(8); initial_shared_key_b64 = "CC5rWmRUE0o="; initial_shared_key = null; @@ -19,7 +19,7 @@ class WTVNetworkSecurity { hRC4_Key2 = null; RC4Session = new Array(); - zdebug = true; + zdebug = false; constructor(wtv_incarnation = 1) { this.zdebug = true; @@ -215,7 +215,7 @@ class WTVNetworkSecurity { SecureOn(rc4session = null) { - console.log("Generating RC4 sessions with wtv-incarnation: " + this.incarnation); + if (this.zdebug) console.log(" # Generating RC4 sessions with wtv-incarnation: " + this.incarnation); var buf = new Uint8Array([0xff & this.incarnation, 0xff & (this.incarnation >> 8), 0xff & (this.incarnation >> 16), 0xff & (this.incarnation >> 24)]); endianness(buf, 4); @@ -297,4 +297,4 @@ class WTVNetworkSecurity { } } -module.exports = WTVNetworkSecurity; \ No newline at end of file +module.exports = WTVSec; \ No newline at end of file