Reconstruction of irremote.psiloc.com (Psiloc Irremote)

By dose | January 5, 2015
Under: Uncategorized
Comments: 4 Comments »

Motivation

As written in a previous blog post, I recently had to swap a defective HDD
of a Pioneer DVR recorder. After some reading in the Internet, I found out
that a user needs to have a special “Service Remote” to swap a HDD.
I finally fixed this problem by using the IrDA interface of my Notebook, as
written in the README of my project, but when thinking about how to do this,
I also thought about the IrDA interface of my Nokia N95 Symbian-based phone.
I remembered that somebody a few years ago mentioned Psiloc IrRemote for
remote control of various devices. So I searched for it and eventually found
out that the company Psiloc went out of business.
Fortunately, I found a release of the software by Googling around a
bit so that I was at least able to find a working copy of the software.
After installing the program on my phone, I was presented with a default list
of devices. Of course the remote that I was interested in, wasn’t available.

Remote definition file format

But I read that the software basically uses LIRC format for the remote
definitions and using web.archive.org revealed that there was a wizard that
was able to create IRRemote definition files online given a LIRC remote file.
So a user basically just had to map LIRC keys to preset templates for the
appropriate device type in the wizard and was then able to download a
definition file for the remote to import on his phone. These files have the
extension .ir and by executing them in the filemanager on the phone, they
are imported into the IRRemotes Remote-Database on the target phone.
But the wizard on the manufacturer’s homepage isn’t available anymore, so bad
luck for me and for most users of the application who paid for this…

But first I wanted to check the format of the remote definition files on the
phone, so I used the SISContents application to take a further look into the
directory structure of the installation package. The /private Directory is
interesting (That is a protected directory for AppData normally not accessible
to the user on Symbian phones):

./private/2000C3EC:
backup_registration.xml  database.dat  layouts  remotes

./private/2000C3EC/layouts:
layout_air.xml  layout_dvd.xml   layout_other.xml  layout_tv.xml
layout_amp.xml  layout_hifi.xml  layout_sat.xml   layout_vcr.xml
layout_cd.xml   layout_hometheatre.xml  layout_tuner.xml

./private/2000C3EC/remotes:
1017.xml  125.xml   1570.xml  1899.xml  2088.xml  2487.xml  465.xml  730.xml
1028.xml  1261.xml  1575.xml  18.xml 2094.xml  2488.xml  466.xml  739.xml
...

So first let’s have a look at the layouts-Files:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns="http://irremote.psiloc.com/schema/layout.xsd" 
  author="Mariusz Ostrowski" name="Minium" 
  graphicsfile="\resource\apps\irRemote9\layout%i.mif" type="Amp">
  <screen width="352" height="416" background="16384" 
   backgroundmask="16385" backgroundstretch="true">
    <text x="10" y="12" width="332" height="26" align="center" 
     valign="center" color="000000" name="Title"/>
    <button name="DEVNAME" width="338" height="36" x="7" y="7" 
     inactive="16676" inactivemask="16677"></button>
    <button name="DUMMY" width="129" height="65" x="111" y="50" 
     centerx="176" centery="145" inactive="16432" inactivemask="16433">
      <key>Up</key>
    </button>
    <button name="DUMMY" width="129" height="65" x="111" y="175" 
     centerx="176" centery="145" inactive="16434" inactivemask="16435">
      <key>Down</key>
    </button>
    <button name="AmpVolumeDown" width="65" height="129" x="81" y="80"
     centerx="176" centery="145" released="16486" releasedmask="16487" 
     pressed="16488" pressed="16488" pressedmask="16489"
     inactive="16436" inactivemask="16437">
      <key>Left</key>
    </button>
...

What can be seen is that there is a .xsd schema definition file referred.
The original Homepage is offline, so it’s not available anymore, but Wayback
machine has it.
The layout seems to be very simple to comprehend, basicaly there are buttons
which can then be assigned to a LIRC code.
So next let’s check a remote defintion file for reference.
Here is a simple example:

<?xml version="1.0" encoding="utf-8"?>
<remote xmlns="http://irremote.psiloc.com/schema/remote.xsd" name="STR-DE205" 
  bits="12" eps="30" aeps="100" phead="2530" shead="480" pone="1300" 
  sone="500" pzero="700" szero="500" gap="25061" minrepeat="2" type="Amp">
  <flags>
    <flag>SPACEENC</flag>
  </flags>
  <codes>
    <code name="AmpSourceVCR" data="441" />
    <code name="AmpSourceTV" data="561" />
    <code name="AmpSourceTape" data="c41" />
    <code name="AmpSourceCD" data="a41" />
    <code name="AmpSourceTuner" data="841" />
    <code name="AmpSourcePhono" data="41" />
    <code name="AmpSourceDat" data="896" />
    <code name="AmpSourceDVD" data="96" />
    <code name="AmpSourceAux" data="cd6" />
    <code name="AmpPower" data="8c6" />
    <code name="AmpVolumeMute" data="281" />
    <code name="AmpVolumeUp" data="481" />
    <code name="AmpVolumeDown" data="c81" />
  </codes>
</remote>

There also is a schema definition file which was also archived by the Wayback
machine. The format is indeed very simple, so when looking at various .xml
files, it’s easy the correlate the given fields to the ones from the LIRC file
format. The mapping is so obvious, that I won’t go into detail about that.
So my goal was to convert a LIRC file into a remote definition for IRRemote
by reconstructing the original Wizard from the irremote homepage.
For that goal I reimplemented the LIRC file parser in PHP, as it has to work
as web application.
But for a user to get a usable file that he can use with IRremote, it is
necessary to write a valid .ir definition file to be able to import it on the
phone. Therefore this format needs to be analyzed. So the first task is to get
some .ir files. Fortunately, I found a database of .ir files on the net that
I could analyze.
When looking at them, it seems that they are the .xml IR remote definition
files with a binary header.
Let’s have a look at a short and simple one:

Sony_RM~6189.ir:
00000000 99 12 68 13 │ 01 01 00 00 │ 00 01 00 00 │ 00 01 00 00 ..h.............
00000010 00 D9 16 00 │ 00 02 00 00 │ 00 54 56 04 │ 00 00 00 53 .Ù.......TV....S
00000020 6F 6E 79 0E │ 00 00 00 52 │ 4D 38 36 32 │ 5F 4B 56 32 ony....RM862_KV2
00000030 38 57 46 33 │ 45 49 1B 00 │ 00 2D 18 00 │ 00 D9 16 00 8WF3EI...-...Ù..
00000040 00 08 00 00 │ 00 59 6F 5F │ 6D 69 73 6D │ 6F 01 00 00 .....Yo_mismo...
00000050 00 2D 18 00 │ 00 8C 01 00 │ 00 3C 72 65 │ 6D 6F 74 65 .-.......<remote
00000060 20 78 6D 6C │ 6E 73 3D 22 │ 68 74 74 70 │ 3A 2F 2F 69  xmlns="http://i
00000070 72 72 65 6D │ 6F 74 65 2E │ 70 73 69 6C │ 6F 63 2E 63 rremote.psiloc.c
00000080 6F 6D 2F 73 │ 63 68 65 6D │ 61 2F 72 65 │ 6D 6F 74 65 om/schema/remote
00000090 2E 78 73 64 │ 22 20 6E 61 │ 6D 65 3D 22 │ 53 6F 6E 79 .xsd" name="Sony
000000A0 5F 52 4D 2D │ 38 36 32 2E │ 32 22 20 62 │ 69 74 73 3D _RM-862.2" bits=
000000B0 22 31 35 22 │ 20 65 70 73 │ 3D 22 33 30 │ 22 20 61 65 "15" eps="30" ae
000000C0 70 73 3D 22 │ 31 30 30 22 │ 20 70 68 65 │ 61 64 3D 22 ps="100" phead="
000000D0 32 34 30 30 │ 22 20 73 68 │ 65 61 64 3D │ 22 36 30 30 2400" shead="600
000000E0 22 20 70 6F │ 6E 65 3D 22 │ 31 32 30 30 │ 22 20 73 6F " pone="1200" so
000000F0 6E 65 3D 22 │ 36 30 30 22 │ 20 70 7A 65 │ 72 6F 3D 22 ne="600" pzero="
00000100 36 30 30 22 │ 20 73 7A 65 │ 72 6F 3D 22 │ 36 30 30 22 600" szero="600"
00000110 20 67 61 70 │ 3D 22 35 30 │ 30 30 30 22 │ 20 66 72 65  gap="50000" fre
00000120 71 75 65 6E │ 63 79 3D 22 │ 34 30 32 34 │ 34 22 20 74 quency="40244" t
00000130 79 70 65 3D │ 22 54 56 22 │ 20 3E 0D 0A │ 09 3C 66 6C ype="TV" >...<fl
00000140 61 67 73 3E │ 0D 0A 09 09 │ 3C 66 6C 61 │ 67 3E 53 50 ags>....<flag>SP
00000150 41 43 45 45 │ 4E 43 3C 2F │ 66 6C 61 67 │ 3E 0D 0A 09 ACEENC</flag>...
00000160 09 3C 66 6C │ 61 67 3E 52 │ 45 56 45 52 │ 53 45 3C 2F .<flag>REVERSE</
00000170 66 6C 61 67 │ 3E 0D 0A 09 │ 09 3C 66 6C │ 61 67 3E 43 flag>....<flag>C
00000180 4F 4E 53 54 │ 4C 45 4E 47 │ 54 48 3C 2F │ 66 6C 61 67 ONSTLENGTH</flag
00000190 3E 0D 0A 09 │ 3C 2F 66 6C │ 61 67 73 3E │ 0D 0A 09 3C >...</flags>...<
000001A0 63 6F 64 65 │ 73 3E 0D 0A │ 09 09 3C 63 │ 6F 64 65 20 codes>....<code
000001B0 6E 61 6D 65 │ 3D 22 54 56 │ 59 65 6C 6C │ 6F 77 22 20 name="TVYellow"
000001C0 64 61 74 61 │ 3D 22 35 32 │ 33 64 22 2F │ 3E 0D 0A 09 data="523d"/>...
000001D0 3C 2F 63 6F │ 64 65 73 3E │ 0D 0A 3C 2F │ 72 65 6D 6F </codes>..</remo
000001E0 74 65 3E 0D │ 0A 00 00 00 │ 00 00 00 00 │ 00 00 00 00 te>.............
000001F0 00 00 00 00 │ 00 00 00 00 │ 00 00 00 00 │ 00 00 00 00 ................

When analyzing more files, the common header can be noticed: 99 12 63 13 01
I tried to import a file with such a header and interestingly, it was refused
by the phone (unknown file type). I did some research on the Internet and
found out that the first byte actually has to be 89, then it works, at least
with the version that I have.
It seems that the numbers in this file are organized in little endian DWORDs.
The next 3 DWORDs are all 1. I suspected that these are counters that enable
the user to import more than one definition for a certain remote, but I
didn’t find any file samples that showed how to pack multiple Remote
definitions into one file.
By reverse engineering the binaries lateron (see below), it was proven that
I was right (See the table description below for the tables):

1) Number of entries for DEVICES table
2) Number of entries for FILES table
3) Number of DEFINITION files

The meaning of the next DWORDs can be found out by comparing various files
and analyzing the structure behind them. It also helps to compare some .ir
files that refer to a device already in the database (database.dat) to find
some similarities. I noticed immediately that strings are stored by a DWORD
representing the length of the string followed by the string itself.
The numbers in the file actually represent a database consisting of 2 tables
and control files:

1) A Device table that identifies the device
2) A File table that links information about the XML definition file
and the device to control.

Why are there 2 tables?
Because there can be various devices using the same IR codes, this perfectly
makes sense.
The bytes following are representing (parts of) these 2 tables (they repeat
themselves the number of times given above):

D..DWORD
S..String
PK.Primary key
FK.Foreign Key

DEVICES
-------
D ID              [PK]
S Device Type     [Air Conditioner/Amp/...]
S Device Vendor
S Device Model

FILES
-----
D ID              [PK]
D File ID         [FK]
D Device ID       [FK]
S Author
D Rank

DEFINITIONS
-----------
D File ID         [PK]
S The xml file defining the IR definition.

When looking at these fields, it can be noticed that the File ID is actually
the same ID as the filenames in the ./2000C3EC/remotes directory of the
application, so this is how it is matched.
Now as previously mentioned, I also had a look at the database.dat to match
some values with .ir files in order to find out their meaning, therefore here
is the format of the database.dat, which is fairly simple as well. Dumping
the DB to plaintext with a simple C program helped to see all the values that
enabled me to make conclusions about their meaning:

D Database version? Always 1
D Number of device entries

DEVICES
-------
D ID            [PK]
S Device Type        [Air Conditioner/Amp/...]
S Device Vendor
S Device Model

D Number of file entries

FILES
-----
D ID            [PK]
D File ID
D Device ID        [FK]
S Author
S Filename of xml file
D Rank

I was unsure about the Rank-field but found out about it by checking the
archived copies of the irremote-site in the Wayback-machine. There was a rank
made up by some stars and when checking the range of this field, it can be
noticed that it ranges from -100 to 100 which would match best with this
field. As the UI of the application is also displaying the rank, it can be
concluded that it must be this field.

Now that I knew how to read the file formats, I also dug up some database.dat
which was filled with more remotes than the default ones on the internet
together with the corresponding .xml files.
As I also knew the format of the 2 tables making up the required information,
I wrote some scripts to import them into a MySQL DB. I added some fields which
may be interesting for the site that is presenting the data and ended up with
the following structure. As I wasn’t able to reconstruct the whole database by
this, I set the auto increment values high enough so that future additions
hopefully don’t collide with old data, should I get some from you.
If you also have databases that help me to reconstruct the original database
on irremote.psiloc.com, feel free to contact me and send me your dumps!
You can do this by dumping the /private/2000C3EC folder of your phone, zipping
its contents and send them to me.

 

CREATE TABLE `DEVICES` (
  `ID` int(11) NOT NULL auto_increment,
  `DEVICE` varchar(16) NOT NULL,
  `VENDOR` varchar(32) NOT NULL,
  `MODEL` varchar(64) NOT NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=100000 ;

CREATE TABLE `FILES` (
  `ID` int(11) NOT NULL auto_increment,
  `FILEID` int(11) NOT NULL,
  `DEVID` int(11) NOT NULL,
  `AUTHOR` varchar(16) default NULL,
  `FILE` varchar(16) NOT NULL,
  `RANK` tinyint(4) default '0',
  `DOWNLOADS` int(11) default '0',
  `NAME` varchar(32) default NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=120000;

The DOWNLOADS-field is a download counter which was present on the original
page. Of course, this information wasn’t available in any dumps, so it’s zero.
The name of the .ir files is also quite simple, it’s just
VENDOR_MODEL_FILEID.ir
I added the NAME-field to store the name of the original LIRC file into the
DB. I did this to help identifying possible duplicates. Because when looking
at the original DB, I found many duplicates which grew the database
unnecessarily. The name can be found in the .xml definition files
in tag <remote>. Of course it is valid to do different mappings from the same
LIRC input file, but when people want to upload a remote definition, they
may not know that it already exists (especially as the naming in the current
DB is really chaotic).

For reconstrution, I didn’t only use the database.dat dump, but also a
dump of .ir files that I found.
If you are interested in the database, just contact me.

Reconstructing the Webservice

Now that I reconstructed the database, the next task was to get them into
the IRremote application.
Importing every single .ir file would have been a tedious task and by the time
I tried this I wasn’t aware how to put multiple definitions into one .ir file,
because I didn’t find any example for it out there.
How did normal users of the application get the most current database?
When looking at the application, I found that it has an online update feature.
The user just needs to press “Refresh” on a screen and the list gets updated
via some webservice running on irremote.psiloc.com.
So the first task was to find out what functions it calls. To accomplish that,
I made use of the hosts-file from Symbian and redirected the host
irremote.psiloc.com to my machine.
This isn’t so easy, as the hosts-file is also located in the inaccessible
/private folder.
Informations about it can be foundhere.
To access that folder, you first need the CapsOnOff program. There are
various descriptions on how to install this on the Internet, just google
for it. i.e. this site.
Once the hosts file redirects the application to the server, the following
Requests can be seen:

http://irremote.psiloc.com/WebService.asmx/GetVendors
http://irremote.psiloc.com/WebService.asmx/GetModels
http://irremote.psiloc.com/WebService.asmx/GetRanks
http://irremote.psiloc.com/WebService.asmx/GetRemote
http://irremote.psiloc.com/WebService.asmx/SetRank
http://irremote.psiloc.com/WebService.asmx/AddVendor

Now by putting some logging code to these scripts, it’s not really hard to
get the input data for each call, but the severe problem that arises is, that
it is unknown which answer the application expects.
So at this point, it is only possible to get the desired information by
disassembling the Application and taking a look at its inner working by
reverse engineering. Unfortunately, this isn’t that easy.
For reversing Symbian binaries, first the headers need to be restored. This
is done by the petran.exe tool available from Nokia.
But unfortunately, when loading irRemote9.exe into the disassembler, it
just has some loader stub code which passes a pointer to some packed/crypted
chunk of code to another background application called “DRM Common Solutions“.
This was one of Psiloc’s products that they not only used for their own
applications, but also tried to sell as DRM solution for other Symbian apps.
So I first had to take a look at the core DLL that the IrRemote9.exe
calls into for loading: DRMCommonSignerCore.dll
This DLL itself is crypted/packed and has its own loading routine. So it took
me quite some time to figure out, how their “protection” works. I don’t want
to bother you with alle the details, but I wrote an unpacker for their files:

The header structure of the packed/crypted data is as follows:

#define MAGIC 0x6FCB73E7
typedef struct
{
        unsigned long magic;
        unsigned long cbCompressed;
        unsigned long cbUncompressed;
        unsigned long CRC;
        char key1[128];
        char key2[64];
} TYP_HDR;

So it starts with a magic and contains info about the compressed and
uncompressed length of the data (because the data is also compressed), as
well as a CRC checksum for verification and 2 keys for decryption.

1) It has some static table in it. This gets “decrypted” with RC4 decode
with an also hardcoded key.
However the RC4 decode is a modified version of RC4 which does a 3x
indirection of the decoder table (look at my sources for clearification).
2) It does a public RSA decrypt of key1 with the RC4-decrypted
modulus and the well known public exponent 65537 (0x10001) (no padding).
3) It is searching the decrypted key1 for the first NULL byte.
4) Starting at the offset after the NULL-Byte, it RSA decryptes key2 with
the data after the NULL-Byte as modulus and the well known public
exponent 65537 (0x10001) (no padding).
5) Is repeats 3) for key2
6) It does its special RC4 decode on the actual data with the data from
5) after the offset 0 as a key.
7) The resulting decrypted buff is zlib uncompressed into memory and
finally executed.

Now that stuff only ran through for the DRMCommonSignerCore.dll, but when
using it on IrRemote9.exe, it doesn’t work. It turns out that for protected
executables it executes, there are other rc4-Tables and keys for step 1,
but the unpacking process is fortunately the same.

The resulting buffer gets executed, however it doesn’t have a standard
EPOC header, but a special header on its own, which contains informations for
the loader. So even though one can load up the decrypted code parts into the
disassembler, there are no valid references, sections etc. making the
resulting code quite hard to analyze.
So the header also needs to be rebuilt to be a valid EPOC header. By looking
at the binary output, some offsets can be guessed and matched to the fields
in a normal EPOC header. So I tried to do this as it can be seen in my
unpacker and finally, I got something usable (still not all fields are clear
to me, but I don’t care, as the original goal has been accomplished).

Now using the disassembled output, the request and response for the various
calls revealed (the input arrays are always the POST-Parameters sent to the
Webservice call):

GetRanks:
---------
Array
(
    [deviceId] => 1521
    [hash] => 993317623
)
-->
<ArrayOfRankInfo>
        <RankInfo>
                <RankId>[rank id]</RankId>
                <Rank>[rank value]</Rank>
                <RemoteId>[remote id]</RemoteId>
                <Author>[author]</Author>
        </RankInfo>
</ArrayOfRankInfo>

GetModels:
----------
Array
(
    [deviceTypeName] => Air Conditioner
    [vendor] => Mitsubishi
    [hash] => 2634342403
)
-->
<ArrayOfDeviceInfo>
        <DeviceInfo>
                <DeviceId>[id]</DeviceId>
                <Model>[model name]</Model>
        </DeviceInfo>
</ArrayOfDeviceInfo>


GetVendors:
-----------
Array
(
    [deviceTypeName] => Air Conditioner
    [hash] => 3112346557
)

->
<ArrayOfString>
        <string>[Vendor]</string>
    ...
</ArrayOfString>


GetRemote
---------
Array
(
    [remoteId] => 1933
    [hash] => 862864718
)
->
The XML file for the remote definition with a prepended EFBBBF BOM in the 
beginning.

AddVendor
---------
Array
(
    [deviceTypeName] => Air Conditioner
    [vendor] => Mitsubishi
    [model] => RM561Vx
    [remoteId] => 2077
    [imei] => xxxxxxxxxxxxxxx
    [uid] => 536882564
    [method] => 0
    [hash] => 3916498465
)

SetRank
-------
Array
(
    [rankId] => 1933
    [imei] => xxxxxxxxxxxxxxx
    [uid] => 536882564
    [rankValue] => Yes
    [method] => 0
    [hash] => 402398422
)

The Setter-Functions let the user rank a remote, if the definition file is
actually working (remember the Rank-Field in the DB), whereas the AddVendor
call adds another device name to an already existing Remote definition file,
to signify that it also works with that vendor/remote.

One interesting field here is the hash-Field given in every request. It seems
to be some security-by-obscurity feature supposedly to prevent the webservice
from being spammed.
I was able to reverse the calculation of these values for the calls that
only used DWORDs and documented them in this source file, however I wasn’t
able to find out how an INT64 is represented on the symbian phone so that
the hashes for the Setter-functions containing the IMEI can also be calculated
correctly. Maybe you have an idea?

Given the database and the knowledge about the Webservice calls, I now managed
to reimplement the webservices based on the MySQL DB that I created.
Via the host-file redirection, I was able to fetch the remote definitions
conveniently via the application.

Using the webservice on your phone

As previously mentioned, you have to put a valid hosts-file for redirecting
the calls on your phone.
So if you have a phone with platform security on, you first need to get
access to your private-Folder via CapsOff. I mirrored the tools needed for
this here.
An instruction can be found here.
Then put this hosts-file into the appropriate directory (C:\private\10000882)
or modify your existing hosts file to contain the entries from the file.
More informatios about the host-file can be found here.
Then Psiloc IrRemote should be able to access the Webservices from this
mirror site.

Reconstructing the Webpage

Next step was to reconstruct the web interface so that also other users can
gain access to the remote definition files again and – more important – to
be able to create new remote definitions based on LIRC files on their own,
so that also I can finally use it the way I intended to.
I fetched what I could get via the Wayback machine and added my own PHP
code for DB access to it. The original was ASP.NET, but I don’t like that,
PHP is more portable and easier to implement.
As for the Wizard, I wasn’t able to find out how it originally worked, as I
only found the starting page, so I made up my own interface for mapping a
layout (based on the layout XML files) to LIRC keys from a LIRC file.
I also saw that there were options to import CCF files, but that would
involve converting CCF files to pronto codes which then can be easily
converted to a LIRC input file. I actually ported pronto2lirc.py to PHP, so
you can input raw pronto codes in the composing-Wizard, but converting CCF
files has to be done via CCFTools and they are currently only available
for Windows.
I tried to contact the author, but I didn’t get any response and there is no
sourcecode publically available. So my only bet would be to reverse CCFtools
to port it to Posix, but that is quite a lot of work and I don’t know if it’s
worth it. If you think, that this would generally be a good idea, I may do
this, but it seems to be too much work for me if the only benefit from it is
to get another wizard working on my irremote-Site.

Conclusion

So finally I put up a mirror of the old irremote site with my database in
background at http://irremote.0wnz.at
Feel free to use it and use the Wizard to add your own remote definition
files. If you want to get the whole database onto your phone, you have to
patch your host file as mentioned above. Maybe someone with Symbian expertise
can write an installation package to do this, I can only give you the
instruction above on how to do this manually.
If you have an IRRemote DB on your phone, please send it to me (including the
remote definition XML files, so basically a dump of your /private/2000C3EC
directory, accessiable also via CapsOnOff) so that I can reconstruct even more
of the original remotes database.
Also contact me, if you want to have my sources or are otherwise interested in
the project to revive this application.

So I hope that this revived page is useful for the remaining IrRemote users so
that I didn’t only do this for myself.

Pioneer DVR recorder harddisk recovery

By dose | November 14, 2014
Under: Uncategorized
Comments: 7 Comments »

I recently was asked if I could take a look at a Pioneer DVR-633H Harddisk-Recorder as it always booted up with the “Hdd Error” message. So this was quite obvious: A dying harddisk.
When I opened up the case, I found a Seagate 250GB IDE drive in it and after finally dismounting it and connecting it to a PC, I was happy to see that it was still accessible. There were bad sectors on it, for example the first 2 sectors were bad, but I was lucky: A lot of sectors of the harddisk were still readable!
So next I searched the internet to check how to recover data from it.
I found a few scripts that people wrote to recover their harddisks, for example this one by Mike Knoop and – even better – this one by Stefan Haliner that supports multiple recorders.

However, I wasn’t really satisfied with the results. Both scripts just dump consecutive MPEG-chunks to files and leave the task of manually merging them to the user.
The first one spit out over 1700 chunks, reassembling them would have been a tedious task. Most notably the splitting was often also wrong. The second one was a bit better, there weren’t so many chunks left, but it also required me to look through all the chunks and merge/split them to reconstruct the movies.

So these solutions didn’t really satisfy me, I didn’t want to have so much work just to recover data from them. Therefore I decided to analyze the disk image myself with a Hex-editor. I found out that there are some block directories on it that looked like pointers to the blocks a movie is made of. This encouraged me to look further and after some days of analysis, I finally found out how data is stored on these drives and was able to write a litte Windows-program that parses the drive structure and dumps the movies together with their names and their recording date.

I hope that this is also useful for other users suffering from the same problem. Of course it’s written entirely in C, no scripting languages needed. If you want me to port it to Linux, just write a comment or send me an e-mail. I explained the recovery procedure and the technical deatils about the on-disk format in the README file.
You can find everything here: >> Download <<.

I’d love to hear from you if this possibly also works for other recorders or even other brands.. Who knows, maybe it’s a standardised format, it mostly looks a bit like something from the DVD-Standard.

Crack für Indiana Jones 3 (Der letzte Kreuzzug) / Deutsch

By dose | October 19, 2014
Under: Uncategorized
Comments: No Comments »

Und weiter geht’s in der Serie über das Cracken von alten LucasFilm Adventures.
Nachdem ich mir ja schon Loom vorgenommen habe, funktioniert Indy 3 nach genau demselben Schema:

Wenn man nicht will, dass Indy nach dem “heiligen Kran” sucht, vergleicht man wieder die Operationen bei Erfolg und Fehler. Wie auch Loom sind die .LFL DAteien mit 0xFF verXORt.

Fehlerfall:

Script 204, offset 0x39f5: [88] o5_isNotEqual()
Script 204, offset 0x39fc: [1A] o5_move()
Script 204, offset 0x3a01: [18] o5_jumpRelative()
Script 204, offset 0x3a04: [46] o5_increment()
Script 204, offset 0x3a07: [48] o5_isEqual()
Script 204, offset 0x3a0e: [A8] o5_notEqualZero()
Script 204, offset 0x3a13: [46] o5_increment()
Script 204, offset 0x3a16: [A] o5_startScript()

Erfolgsfall:

Script 204, offset 0x39f5: [88] o5_isNotEqual()
Script 204, offset 0x3a01: [18] o5_jumpRelative()
Script 204, offset 0x3a04: [46] o5_increment()
Script 204, offset 0x3a07: [48] o5_isEqual()
Script 204, offset 0x3a0e: [A8] o5_notEqualZero()
Script 204, offset 0x3a39: [1A] o5_move()
Script 204, offset 0x3a3e: [80] o5_breakHere()

Eigentlich dasselbe Schema wie bei LOOM. Also wieder die Kommandos in der Datei 92.LFL ansehen:

3A0D: A8 E4 85 26 00 46 6B 00 0A

Wenn Variable E4 85 nicht 0 ist, dann wiederholt sich die Abfrage, sonst springt er raus und alles ist gut. Selbe Lösung wie bei LOOM: Variable auf 0 setzen und raus springen, den Offset kann man wieder anhand der Position und der Angabe von oben berechnen, ergibt somit:

3A0D: 1A E4 85 00 00 18 23 00

Das Ganze wieder mit 0xFF verXORen, fertig ist der Crack 🙂

 

Windows Mobile cabwiz.exe bug and fix

By dose | September 30, 2014
Under: Uncategorized
Comments: No Comments »

I recently had to create a SmartDevice project of a VB.NET application (Yuck!) with multiple localized resources in it. So that means that there is a subdirectory for each language that contains a lang.dll file holding the language ressourcesin the appropriate language.
When creating the setup project, everything works fine, but when trying to deploy the application, I saw that the .dll file was the same in every directory installed. It seems that sabwiz.exe has a bug that prevents you from adding multiple files with the same filename to a project, even though they go to different target directories. After googling a bit, i found this blog post that explains the issue and also contains a fix for that.
The fix offered there works fine, but its code is overly complicated and not available in source form. Now as I had to modify other things in the .inf file too, I just wanted to add my postprocessing to the fixer-Application.
So I wrote my own fixer that is smaller in size (only 6kb!) and doesn’t depend on ugly .NET framework, but is native Win32 code. Feel free to use it,  source code can be found here. Precompiled executable can be found here.
To install, just:

cd [Visual Studio Dir]\SmartDevices\SDK\SDKTools\
move cabwiz.exe ___cabwiz.exe
move cabwizfix.exe cabwiz.exe

I hope it’s useful to you.

Alternative to netstat -p

By dose | September 11, 2014
Under: Uncategorized
Comments: No Comments »

On SuSe Linux SLES 10.2, netstat -a -p for some reason doesn’t output any PID that belongs to a socket. This old trick helps:

netstat -a -e  # Shows the inode-number for the process
lsof | grep <inode number>

Windows XP Updates

By dose | September 3, 2014
Under: Uncategorized
Comments: No Comments »

In case you missed the news: There are still XP Updates available after official end of support:

https://sebijk.com/community/board9-community/board5-pc/2984-xp-updates-weiterbeziehen/

 

Booting Memtest86+ from Harddisk

By dose | August 2, 2014
Under: Uncategorized
Comments: No Comments »

If there is no bootable media available, you can easily boot memtest86+ also via Windows boot.ini using GRUB4DOS. You just need to follow the instructions from this post.
In case this gets lost somehow, here are the step-by-step instructions:

1) Download current grub4dos package and extract grldr to c:\
2) Download current memtest86 Pre-compiled bootable binary and extract it to c:\memtest.bin
3) Create c:\menu.lst with the following content:

color black/cyan yellow/cyan
timeout 2
default 0

title start Memtest86+
kernel /memtest.bin

title Back to NTDLR
chainloader /ntldr

title Restart machine
reboot

4) Add the line

c:\grldr="Memtest86+"

to the [operating systems] section of your c:\boot.ini, it may read something like that:

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /fastdetect /NoExecute=Opt
c:\grldr="Memtest86+"

5) Reboot and start memtest86.

Android auf Motorola Milestone 2

By dose | July 21, 2014
Under: Uncategorized
Comments: No Comments »

Unlängst habe ich Android auf einem Motorola Milestone 2 Mobiltelefon auf ein CanogenMod 9 aktualisiert, um es als Testgerät für QT-Entwicklung verwenden zu können.
Das hat schlussendlich auch geklappt, aber ich habe ein paar kleinere Probleme damit gehabt, daher eine kleine Anleitung, wie es klappt:

Diese Installationsanleitung für CM9 befolgen.
Wenn man cm5.zip flasht kommt der bootloader aber nicht automatisch, wenn das
blaue Licht zu blinken beginnt, Volume-Down Knopf drücken!
Sonst wie in der Anleitung angegeben vorgehen.

Nach der Installation hat man ein Problem mit adb shell, weil
von einem Farbterminal ausgegangen wird, daher hat man dann
die Escape-Sequenzen für Farbe in der Ausgabe z.B. bei LS
Hier kann man das colored-Putty verwenden.

Man kann nun keine Programme mehr mit adb install installieren.
Um das zu beheben:

adb shell
vi /data/local/userinit.sh

Eintragen:

ln -s /system/bin/ /bin

Telefon neu starten.

Reading the version number of a .NET assembly in plain C

By dose | July 15, 2014
Under: Uncategorized
Comments: No Comments »

I recently was assigned the task to write an Autoupdater application for Windows Mobile 6.5. Now my idea was to read the version resource from the application and determine its version and depending on the version propose an update to it or not. Now we all know that this is easy using the GetFileVersionInfo API. So I tried that and then notices that this works well for normal, native applications, but not for .NET Applications. It seems, that they don’t automatically create a Version Info resource section but instead just write the version to some structure that is called “Assembly”.
So I was in need for an API to read that information from the file. After some research, I found an API called Fusion that can be used to read Assembly informations from .NET executables. As it is a COM interface, it can be used from C code. Here is some C++ code that shows how to use this interface for this purpose.
But I wasn’t able to use it on Windows Mobile, because there is no such API on that operating system. This article explains how it works von Windows Mobile. So I finally ended up with parsing the file format and extracting the needed information. It’s not really hard to find the location in the PE file which contains all that tables that also contain Assembly information, but unfortunately, the tables have to be walked and processed according to their size information in order to find the real offset, as there are no RVA-pointers stored in the file that act as an index into the tables, but instead only variable size information is provided. For more information about the format, see this description.
Fortunately I found out that the WINE project already wrote an Assembly parser. So I stripped down the parser to the bare minimum required for getting the version info and packed it into a module that is easy to use. You can download it here.

Reenable UDMA on IDE-Channels in WinXP

By dose | June 29, 2014
Under: Uncategorized
Comments: No Comments »

I reently had the problem that there was a controller error on the Bus where I attached my SATA-Drivers (which are running in IDE compatibility mode) and Windows XP has the bad behaviour to reset the channel to PIO in that case and not set it back to UDMA.

Microsoft Knowledge Base suggests to reinstall the IDE Channel drivers in such a case, but due to another bug in gpt_loader.sys, this action results in a BSOD.
So there is a description how to reenable UDMA on the channels without the need to delete them (Basically delete “MasterIdDataChecksum” for the IDE master and “SlaveIdDataChecksum” for the IDE slave on the appropriate IDE channel
in HKLM\SYSTEM\CurrentControlSet\Control\Class\
{4D36E96A-E325-11CE-BFC1-08002BE10318}

Note that the subkeys under that reg key can be a lot and you hve to pick the correct one that corresponds to your IDE channel.