Firmware Analysis/Reverse Engineering -

Sam Losco

True & Honest Fan
kiwifarms.net
I have a Yamaha RX-V477 stereo. It has network capability. The default webui that loads when you just type in the IP only has network settings and firmware update. But you can access a "hidden" webui by going to IP/Setup/index.html. Setup is case sensitive.

So I wanted to pop open the firmware and see if I could find if there are any other hidden pages.

It's a bin file, so I tried to use binwalk to analyze and extract files. Except binwalk apparently doesn't see anything valid in it. A regular scan returns a blank output. However, if I use the -I option to show invalid results, it kicks out a shit ton of stuff. It looks like the firmware may be VxWorks because it lists a VxWorks symbol table? But it also lists various Linux ext file systems (invalid) and Windows executables. So I'm think that shit isn't actually there and that's why it only shows up with an -I option; it's trying to find known stuff where it doesn't actually exist?

Anyone have any experience with this?
 

Sam Losco

True & Honest Fan
kiwifarms.net
I love a challenge, can you upload the file or is it too big?
Doesn't look like the forum will let me upload it. You can get it here: https://usa.yamaha.com/support/updates/rx-v477_htr-4067.html

The only other time I've used binwalk was for a Korean IP camera I was trying to fix. I thought I might have to extract it out and write it to the flash like that. That went nowhere, but binwalk worked fine on that file.

The camera just had bad hardware. The network stopped working and it would reboot after the Linux watchdog triggered. Then one day it stopped doing that and I was able to spend as much time as I wanted in it via serial poking around trying to figure out what was wrong. I had to copy the firmware file to it's internal memory via micro SD and then, fumbling around, I managed to find out how it's webui trigger a firmware update, and I triggered that. It re-flashed but did not fix any of the problems. I'm pretty sure the flash chip was just going bad and fucking up Linux. Maybe other hardware issues as well because at the start, even if I got in fast enough to kill the watchdog process, it would still do a hard reboot after a few minutes.
 

Kosher Dill

Potato Chips
True & Honest Fan
kiwifarms.net
It seems like your file is compressed or encrypted. Take a look at the frequency of every byte and it's completely flat across the board. Blue is your file and orange is a random Windows executable I pulled to compare with.

1593067073100.png


7-Zip didn't know how to "decompress" it so I'm guessing encryption. I think you're going to have to find some clever way to extract the decrypted data from your system or something.
 

Sam Losco

True & Honest Fan
kiwifarms.net
Maybe you could catch firmware packets with https://www.ti.com/tool/PACKET-SNIFFER?
Your link is broken. WHatever that is, it requires a USB dongle and doesn't appear that it would in anyway help me.

I could capture traffic from Wireshark, but that won't help either. You upload the full bin through the webui and then the stereo extracts it and writes to flash itself, I can't see any of that.

It seems like your file is compressed or encrypted. Take a look at the frequency of every byte and it's completely flat across the board. Blue is your file and orange is a random Windows executable I pulled to compare with.

View attachment 1404788

7-Zip didn't know how to "decompress" it so I'm guessing encryption. I think you're going to have to find some clever way to extract the decrypted data from your system or something.
Yeah, I was thinking that it might mean it's encrypted. In the "invalid" output, I did see something about a "private key in DER format", whatever DER format is.

I guess a UART port for serial access is my only hope to poke around. I don't know how useful that'll even be though. I suspect this thing might be running VxWorks and I know jack shit about that. It's my main unit so I'm not sure I want to do that.

Edit - I no English too goood.
 

garakfan69

Mentally Enabled Schizoposter
kiwifarms.net
I guess a UART port for serial access is my only hope to poke around. I don't know how useful that'll even be though. I suspect this thing might be running VxWorks and I know jack shit about that. It's my main unit so I'm not sure I want to do that.
Maybe there's a JTAG interface you can access.
 

Kosher Dill

Potato Chips
True & Honest Fan
kiwifarms.net
I'm sure you've already tried this, but just in case - have you already looked through the known HTML, JS, etc. files' contents with a fine-toothed comb? You never know if some lazyman left something in and just commented it out.
 
  • Agree
Reactions: yahooligan

Sam Losco

True & Honest Fan
kiwifarms.net
Maybe there's a JTAG interface you can access.
Probably. I've never used a JTAG port though. Don't those usually require special debug software to use?

I'm sure you've already tried this, but just in case - have you already looked through the known HTML, JS, etc. files' contents with a fine-toothed comb? You never know if some lazyman left something in and just commented it out.
I have not. I'll take a look.

I originally knew the webui had hidden features back when I first got it. I found someone online that wrote some tampermonkey code or something that enabled basic controls in the default index.html. But I lost that when I stopped using Firefox I think. I just tonight found out about this Setup/index.html. It gives me control access but also settings that I don't think you can access anywhere else. It lets me set per speaker EQ, adjust audio levels per input, set volume memory, etc. All sorts of cool settings I've never seen on the unit front panel/IR remote or through the Android app.
 

Sam Losco

True & Honest Fan
kiwifarms.net
I'm sure you've already tried this, but just in case - have you already looked through the known HTML, JS, etc. files' contents with a fine-toothed comb? You never know if some lazyman left something in and just commented it out.
So the index page has access to every setting and value. It's 48,520 lines long!
Screenshot from 2020-06-25 01-24-46.png

Believe it or not, it's actually using a css file for that fantastic look.

It loads two js files, ajax.js and model_mask.js.

ajax.js appears to show two other directories but I'm not what they are used for.
Code:
var yncUrl = "/YamahaRemoteControl/ctrl";
function ajxCreateXMLHttpRequest(cbFunc, sync)
{
var XMLhttpObject = null;
try{
XMLhttpObject = new XMLHttpRequest();
}catch(e){
try{
XMLhttpObject = new ActiveXObject("MSXML2.XMLHTTP.6.0");
}catch(e){
try{
XMLhttpObject = new ActiveXObject("MSXML2.XMLHTTP.3.0");
}catch(e){
try{
XMLhttpObject = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
XMLhttpObject = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
return null;
}
}
}
}
}
if (XMLhttpObject) {
var ua = navigator.userAgent;
var safari = ua.indexOf("Safari")!=-1;
var konqueror = ua.indexOf("Konqueror")!=-1;
var mozes = ((a=navigator.userAgent.split("Gecko/")[1] )?a.split(" ")[0]:0) >= 20011128;
var mobile = ua.indexOf("Mobile")!=-1;
if(window.opera || safari || konqueror || mozes) {
XMLhttpObject.onload = function () { cbFunc(XMLhttpObject); }
}
else {
XMLhttpObject.onreadystatechange = function () { cbFunc(XMLhttpObject); }
}
try{
XMLhttpObject.open("POST", yncUrl, sync);
}catch(e){
return null;
}
XMLhttpObject.setRequestHeader("Content-Type" , "text/xml");
if(safari && mobile)
{
XMLhttpObject.setRequestHeader('Cache-Control', 'no-cache');
}
}
return XMLhttpObject;
}
function ajxCreateXMLObject()
{
var xml;
if (window.ActiveXObject) {
xml = new ActiveXObject("Microsoft.XMLDOM");
} else if (document.implementation) {
xml = document.implementation.createDocument("" , "" , null);
} else {
return null;
}
return xml;
}
function ajxSendData(httpObj, xml)
{
httpObj.send(xml);
}
function ajxRecvData(httpObj)
{
if ((httpObj.readyState == 4) && (httpObj.status == 200)) {
ReflectYncResponse(httpObj.responseXML, httpObj.responseText);
ajxCleanUpObj(httpObj);
}
}
function ajxCleanUpObj(httpObj)
{
var xmlData = httpObj.responseXML;
delete xmlData;
xmlData={};
xmlData=null;
if( navigator.userAgent.indexOf('MSIE') != -1 ){
httpObj.onreadystatechange = {};
}else{
httpObj.onload = {};
}
delete httpObj;
httpObj=null;
}
function sndYnc(yncUrl, data)
{
var httpObj = ajxCreateXMLHttpRequest(ajxRecvData, true);
if (httpObj) {
ajxSendData(httpObj, data);
}
}
function GenerateYncRequest(yncMethod, nodes, value)
{
var xmlTop = '<?xml version="1.0" encoding="utf-8"?><YAMAHA_AV cmd="'+yncMethod+'">';
var xmlBottom = '</YAMAHA_AV>';
for(var i = 0; i < nodes.length; i++)
{
xmlTop = xmlTop + '<' + nodes[i] + '>';
xmlBottom = '</' + nodes[i] + '>' + xmlBottom;
}
return xmlTop + value + xmlBottom;
}
I just noticed it says something about activex. I'll have to boot into Windows and open this in IE to see if anything happens.

Model_mask.js has a bunch of memory addresses that I think it's pulling current settings values from and then some different model numbers. I can post it if you want, but it's over the character limit in this post.

I don't see anything commented out anywhere.

Edit to avoid double post:
You can try poking at it with OpenOCD. It's likely using just some ARM as core.
If I decide to open it up, I'll give that a look.
 
  • Like
Reactions: yahooligan

Kosher Dill

Potato Chips
True & Honest Fan
kiwifarms.net
I just noticed it says something about activex. I'll have to boot into Windows and open this in IE to see if anything happens.
No, that's just creating a COM object in JS. Using the code you posted, you now know how their control messages are put together and how you could write your own code to control the stereo.

You probably want to look at who's calling GenerateYncRequest, the "yncMethod" values are going to be your selection of features.
 

SickNastyBastard

::::::::::::::::::::::::::::::::::::::::::::::::::
True & Honest Fan
kiwifarms.net
Your link is broken. WHatever that is, it requires a USB dongle and doesn't appear that it would in anyway help me.

I could capture traffic from Wireshark, but that won't help either. You upload the full bin through the webui and then the stereo extracts it and writes to flash itself, I can't see any of that.
Bummer, the article made it look like it would just capture the internal info coming from your system. Otherwise id say i think Samy Kamkar has infor on firmware sniffing boards, but i doubt youd want to break apart your shit to do that
 

yahooligan

Get ready for a surprise!
kiwifarms.net
I originally knew the webui had hidden features back when I first got it. I found someone online that wrote some tampermonkey code or something that enabled basic controls in the default index.html. But I lost that when I stopped using Firefox I think. I just tonight found out about this Setup/index.html. It gives me control access but also settings that I don't think you can access anywhere else. It lets me set per speaker EQ, adjust audio levels per input, set volume memory, etc. All sorts of cool settings I've never seen on the unit front panel/IR remote or through the Android app.
Another thing you might consider is having a look at that Tampermonkey script itself. It's likely to be shorter and a bit easier to figure out what's going on in it.

Edit: reading that script you posted further, it looks like the first half is pretty generic "if this browser, do this, otherwise, do that" type workarounds. It gets more interesting once you get to the "Ync" stuff -- I assume that's something like Yamaha Network Control or somesuch. The function mentioned, ajxSendData, seems to be what's doing some of the actual messaging. Have a further look at that, or consider intercepting the ajax messages with something like https://www.codexworld.com/how-to/monitor-ajax-requests-google-chrome/ . Without knowing what Tampermonkey script you're using, my first guess would be that it's just sending out ajax requests in the form the receiver is expecting. I think that's your lowest-hanging fruit right there, getting the bulk of the Tampermonkey script to work in another browser or environment.

I know this doesn't answer your first question looking for hidden shit, but it's one step closer to understanding your receiver.
 
Last edited:

дядя Боря

kiwifarms.net
if your firmware is VxWorks, it's a proprietary OS and you won't be able to dick around with it too much. That index file is more like a config file, whatever functionality is being exposed to you is whatever you got, but that's technically not the firmware level. I would not go crazy trying to wireshark the comms over network. Unless it's some simple JSON, you'll go crazy trying to reverse engineer this shit. If want to just blow off some time, help Null, he needs help.
 
  • Like
Reactions: lemmiwinks

Kosher Dill

Potato Chips
True & Honest Fan
kiwifarms.net
Anyway I say just post up all the rest of the HTML and JS, zip it and attach it to a post here. Probably whatever's in there is all that's going to be practical to work with.
 

Sam Losco

True & Honest Fan
kiwifarms.net
Another thing you might consider is having a look at that Tampermonkey script itself. It's likely to be shorter and a bit easier to figure out what's going on in it.

Edit: reading that script you posted further, it looks like the first half is pretty generic "if this browser, do this, otherwise, do that" type workarounds. It gets more interesting once you get to the "Ync" stuff -- I assume that's something like Yamaha Network Control or somesuch. The function mentioned, ajxSendData, seems to be what's doing some of the actual messaging. Have a further look at that, or consider intercepting the ajax messages with something like https://www.codexworld.com/how-to/monitor-ajax-requests-google-chrome/ . Without knowing what Tampermonkey script you're using, my first guess would be that it's just sending out ajax requests in the form the receiver is expecting. I think that's your lowest-hanging fruit right there, getting the bulk of the Tampermonkey script to work in another browser or environment.

I know this doesn't answer your first question looking for hidden shit, but it's one step closer to understanding your receiver.
I haven't had the script in years and have no idea where I got it. I'd have to go find it again.
Anyway I say just post up all the rest of the HTML and JS, zip it and attach it to a post here. Probably whatever's in there is all that's going to be practical to work with.
Done. And I missed a js file. There is one called app.js that initiates ajax.js and model_mask.js.
 

Attachments

yahooligan

Get ready for a surprise!
kiwifarms.net
There's a few URLs here, but you can access these all normally it looks like?

Code:
 switch(cat)
 {
 case 'Source Device':
 urlchar = '/Setup/source_device.html';
 break;
 case 'Multi Zone':
 urlchar = '/Setup/multi_zone.html';
 break;
 case 'Trigger Out':
 urlchar = '/Setup/trigger_out.html';
 break;
 case 'Network':
 urlchar = '/Setup/network.html';
 break;
 case 'Display':
 urlchar = '/Setup/display.html';
 break;
 case 'Advanced Setup':
 urlchar = '/Setup/advanced_setup.html';
 break;
 case 'Memory Guard':
 urlchar = '/Setup/memory_guard.html';
 break;
 case 'Model Information':
 urlchar = '/Setup/model_information.html';
 break;
 case 'Power':
 urlchar = '/Setup/power.html';
 break;
 case 'Volume':
 urlchar = '/Setup/volume.html';
 break;
 case 'Input/Output':
 urlchar = '/Setup/input_output.html';
 break;
 case 'Scene':
 urlchar = '/Setup/scene.html';
 break;
 case 'Surround':
 urlchar = '/Setup/surround.html';
 break;
 case 'Speaker':
 urlchar = '/Setup/speaker.html';
 break;
 case 'Sound/Video':
 urlchar = '/Setup/sound_video.html';
 break;
 case 'Video Adjustment':
 urlchar = '/Setup/video_adjustment.html';
 break;
 case 'HDMI':
 urlchar = '/Setup/hdmi.html';
 break;
 default:
 return;
 }
 window.location.href = urlchar;
}
The only other URL is "/YamahaRemoteControl/ctrl" and that's probably where the ajax goes.
Try looking in each of the directories shown, i.e. 192.168.1.28/Receiver Web Setup_files or 192.168.1.28/YamahaRemoteControl and see if it serves up anything legible.

If it is indeed a VxWorks device, take a look at https://github.com/PAGalaxyLab/vxhunter perhaps.
 

Kosher Dill

Potato Chips
True & Honest Fan
kiwifarms.net
There's a few URLs here, but you can access these all normally it looks like?
It sort of looks like all of these will serve up the same page, just with different tabs shown/hidden based on what the supposed URL is.

Notice the code in onCheckLocationAndSetCatPos which checks what the page's URL is and runs logic based off of that.

If it is indeed a VxWorks device, take a look at https://github.com/PAGalaxyLab/vxhunter perhaps.
This seems to run on unencrypted firmware - if you check the example .bin file they use you can even just open it up in Notepad and read out strings if you really want to. Most likely this won't help with the file we have available.

I'm thinking it's unlikely that we'll find anything more than what's available in the web page. @Sam Losco, I think this page would probably work just fine from a local copy, if you change yncUrl in ajax.js to use your stereo's full URL rather than a relative one, and adjust all the other relative links to the JS files as appropriate. Then you could edit the HTML to show just the controls you're interested in, etc.
 

Sam Losco

True & Honest Fan
kiwifarms.net
I'm thinking it's unlikely that we'll find anything more than what's available in the web page. @Sam Losco, I think this page would probably work just fine from a local copy, if you change yncUrl in ajax.js to use your stereo's full URL rather than a relative one, and adjust all the other relative links to the JS files as appropriate. Then you could edit the HTML to show just the controls you're interested in, etc.
Agreed. Now that I've thought about it more, with the options this page gives me, that I've never seen anywhere else, I don't think I'd even gain anything by poking around in the firmware. It's a stereo, what else could I even want it to do? The per speaker EQ settings are still the coolest I've seen. Best I can do is pretty up the page design. I can try that with CSS. I already have a browser add-on for doing custom CSS.

I went and found a Tampermonkey userscript that enables basic controls in the default index that loads. This is just IP/index.html

Code:
// ==UserScript==
// @name        RX-V475 WebControl Restore
// @namespace   https://userscripts-mirror.org/users/benh57
// @include     http://192.168.*
// @version     1
// @run-at document-start
// @grant       GM_addStyle
// ==/UserScript==

(function(open) {
      unsafeWindow.XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {

      this.origOnload = this.onload;
      this.onload = function (httpObj) {
      var xmlData = this.responseXML;

      if (xmlData) {

            var Cmd = ["Service","System", "Main_Zone", "Zone_2", "Zone_3", "Zone_4",
"Tuner", "USB", "HD_Radio" , "NET_RADIO" , "SERVER" , "SiriusXM" ,
"Rhapsody" , "Napster" , "Pandora" , "AirPlay","iPod_USB"];

        var cmdname = "";
        for ( var i = 0; i < Cmd.length; i++ ) {
            var zone = xmlData.getElementsByTagName(Cmd[i]);
            if (zone.length == 1) {
            cmdname = Cmd[i];
            break;
            }
        }

        if (cmdname == "System") {
             var Val = xmlData.getElementsByTagName("Model_Name");
                if (Val.length) {
                if (Val[0].firstChild) {
                    Val[0].firstChild.nodeValue = "RX-V677";
                }
            }
        }
        }
        this.origOnload();
      }
        open.call(this, method, url, async, user, pass);
      };
    })(unsafeWindow.XMLHttpRequest.prototype.open);
I don't think this is the same one I used before because the script I found actually didn't work until I changed the model number form V675 to V677, which is a model listed in the model_mask.js. This works but it also enables options this model doesn't have, like using WiFi. I am curious to know how it would handle trying to set WiFi when it doesn't actually have it... but not enough to actually try it since it might break it. Again, main, in use unit. Not looking to break it.

Without the script:
Screenshot from 2020-06-26 11-21-38.png

With the script:
Screenshot from 2020-06-26 11-21-55.png


Attached in the zip is the page without the script (RX-V477) and with the script loaded (RX-V677).
 

Attachments

Tags
None