Reconstruction of (Psiloc Irremote)

By dose | January 5, 2015
Under: Uncategorized


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 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):

backup_registration.xml  database.dat  layouts  remotes

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

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="" 
  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">
    <button name="DUMMY" width="129" height="65" x="111" y="175" 
     centerx="176" centery="145" inactive="16434" inactivemask="16435">
    <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">

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="" 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">
    <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" />

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:
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):

PK.Primary key
FK.Foreign Key

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

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

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

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

D Number of file entries

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, 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.


  `ID` int(11) NOT NULL auto_increment,
  `DEVICE` varchar(16) NOT NULL,
  `VENDOR` varchar(32) NOT NULL,
  `MODEL` varchar(64) NOT NULL,

  `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,

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
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
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 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:

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];

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):

    [deviceId] => 1521
    [hash] => 993317623
                <RankId>[rank id]</RankId>
                <Rank>[rank value]</Rank>
                <RemoteId>[remote id]</RemoteId>

    [deviceTypeName] => Air Conditioner
    [vendor] => Mitsubishi
    [hash] => 2634342403
                <Model>[model name]</Model>

    [deviceTypeName] => Air Conditioner
    [hash] => 3112346557


    [remoteId] => 1933
    [hash] => 862864718
The XML file for the remote definition with a prepended EFBBBF BOM in the 

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

    [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 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.


So finally I put up a mirror of the old irremote site with my database in
background 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.

10 comments | Add One


  1. Linas - 02/10/2015 at 18:21

    Hi, I have Psiloc irremote installed and gained accsess to system folders on my nokia E51. But database`s of remote`s I downloaded from russian site. Date of files in database ending 2007.11.21. I installed this program and updated Samsung`s TV database on another E-51 till 2010. I can get theese file`s from that phone I think. Do You need them ? If I could help somehow – i will do it, just say. Sorry for my english, I`m Lithuanian and I`m not well speaking , but You can contact me in skype “meskiuukas” (vatican city). .

  2. MrFe - 04/5/2015 at 12:09

    You sir are a hero 🙂 I have A nokia E51 and still use the software. Back in the day i made a .ir file for a PCI webtuner. i still have it . i tried to upload it but some error appeared.
    More, when the site was still active a have downloaded all the file that were available. If you need them just contact me. They are even sorted.

  3. Ecrazy - 04/19/2015 at 03:01

    Man, what a job.
    Good work, i was trying to use my n98 as remote and the error trying to “refresh” the list bring me here. I wish you get done your job.

    Peace 🙂

  4. Towfiq - 05/7/2016 at 13:06

    I was googling for this app for a long time and found your site. I have a nokia E71. everytime I install the app either it doesn’t have a reg no. or doesn’t respond. can you help please?


  5. Hong Son - 04/2/2018 at 06:21

    Today, I still use this approval to remote some devices.
    Thank you so much.

  6. Cong Hung - 01/31/2019 at 15:59

    Thanks for your effort.
    I’m using this application to remote via Nokia 5700 Xpress Mucsic.
    Thanks again.

  7. Wilcon Barro - 06/11/2019 at 00:26

    Can you create a win32 application that converts .lirc file to .ir so that we can use it even when the site is offline

  8. hristo - 07/15/2019 at 17:17

    have you file for philips pfh 4100/88

  9. Evan R - 12/15/2020 at 20:47

    When you run use the files on the nokia app are you able to actually see the codes list? I have the .ir file for the remote I need but don’t have a nokia to open the file.

  10. hey - 04/27/2022 at 23:43

    Thanks foe this, DRM Common Solutions unpacker is very handy :p


Leave a Comment


E-Mail :

Subscribe :
Website :

Comments :