Ok, i will explain in detail, but first i will quote erdem_ua:
If you download a program, EULA will say something about "disassembling, decompiling, reverse engineering is prohibited".
But there is no string about on firmware download pages of Samsung. And again no such a string in Firmware image or inside of exeDSP (A.F.A.I.K). So Samsung doesn't say a word about it. [..] is free software and we don't sell this content with money. We also don't distribute Samsung's modified firmware too. Only thing we made is researching and trying to fix our devices.
What's the goal:
Let exeDSP output the current time into a file that can be read via any script.
What tools/resources did i use:
HxD
IDA 6.4 Demo
Windows calculator
ARM ? Architecture Reference Manual ARM ? v7-A and ARM ? v7-R edition (ARM DDI 0406B)
Procedure Call Standard for the ARM ? Architecture (ARM IHI 0042E)
a famous search web page
Some hints:
ATM this is for devs only!
In this post i have posted my code only (no original code).
Remember that IDA adds an offset of 0x8000 to .text section (or all?) relativ to the real file offset in hex editor.
Using the IDA demo version you are not able to save modifications (you can modify instructions using the menu 'Edit->Patch Program->Change Byte'). So i changed the machine code using 'Change byte' in IDA and checked IDA's resolved asm instruction. If correct i used a hex editor to apply the patched machine code in exeDSP (remember the 0x8000 offset).
How to start:
Look at the original exlink output excerpt when recording is started (
on unlimited channels at digital channels allowing to record the current broadcast/show) via tv's remote:
Code: Select all
!!------!![SSPVR_ERROR][SsPvrManager.cpp:RenameRecordFile():5136] Error : IsFileExist() failed
[PvrAppDrm] Current = 1391798775, Fri Feb 7 18:46:15 2014
[PvrAppDrm] Uri = 0
[PvrAppDrm] Able to Record (emi = 0)
[PvrDRM] Send ci info ( SSPvrManager --> PvrDrmManager ) filename(/dtv/usb/sdb/CONTENTS/20140207194613.tmp)
_______ REC STR OPEN (/dtv/usb/s#########SETTING THE CODEC TYPE 0
db/CONTENTS/20140207194613.tmp, 1, 5b)
The second line already shows what i wanted to get.
How to go on:
I fired up IDA and set up the ARM architecture options using the infos from
http://www.arm.com/products/processors/ ... fications+ related to the processor i got from the file /sys/selp/vd/lspinfo/board_name:
Also i enabled all options except
ARM specific options: 'Disable pointer dereferencing', 'Enable Macros', 'No automatic ARM-THUMB switch', 'Disable BL jumps detection',
options 1: 'Delete instructions with no xrefs', 'Convert 32bit instruction operand to offset', 'Create offset if data xref to seg32 exists' and
options 2: 'Control flow to data segment is ignored'.
Then i let it run A WHOLE DAY until the green 'LED' below menu 'Help' turned green (see screenshots, working while its yellow is annoying as IDA takes a lot of cpu processing time/ressources). BTW i didn't shutdown my laptop since that day, just used hibernating to prevent form stressing my pc once more
Looking for '[PvrAppDrm] Current =' you'll find one string with two reference to subs. I concentrated on the sub also using the string '[PvrAppDrm] Uri ='. The
pseudo c code of the relavant code (i don't want to post original code here) is:
Code: Select all
char* sTime;
ulong* rawTime;
GetSystemInfoTime(rawTime, 0);
sTime = asctime(localtime(rawTime));
// in asm here is register and stack handling
printf("[PvrAppDrm] Current = %llu, %s", *(ulonglong*)(&rawTime), sTime); // notice the format specifier of 'Current' is '%llu', that specifies a 64 bit value (two registers)
// in asm here is register and stack handling
printf("[PvrAppDrm] Uri = %d", some_register);
// in asm here is register and stack handling
loc_13BCD24();
// UNMODIFIED FROM HERE, but limiting broadcast recording 'feature' is implemented here
// in asm here is register and stack handling
// two compares in a row
// if not equal jump to loc_13BCD14 and print '[PvrAppDrm] Able to Record (emi = %d)'
// else print '[PvrAppDrm] NOT able to Record (emi = %d)'
In asm there's a lot of register handling for assigning function arguments and saving return values, which i reduced. The second printf() was unneccessary and could be modified. Also i removed a following branch to 'loc_13BCD24' where something is ignored only: '[PvrAppDrm] ignore default uri (0x%.2x) value and set copy-free value(0x%.2x)'. This string was only used there and this very small function was referenced only once, so i reused its string as filepath of the new file. So i finally had exactly 10 instructions for modifying.
The main information here is: There's a class method 'GetSystemInfoTime' that writes the current time at the address the first argument (i.e. 'rawTime') points to.
How to implement:
The main part was replacing the first printf() with fprintf(). fprintf() writes a string buffer into a file. As no file was opened in this sub i had to do that. Creating a file implies fopen() and fclose(). fopen() needs two arguments (string pointer): filepath and open mode. Therefor i used some strings being used in failure cases only. The returned FILE pointer is used by fclose() and fprintf(). The difference from printf() to fprintf() is that fprintf() has one additional argument being the first one and followed by the same arguments as printf()'s. So the modified pseudo code looks like this:
Code: Select all
char* sTime;
ulong* rawTime;
GetSystemInfoTime(rawTime, 0);
sTime = asctime(localtime(rawTime));
// reduced asm register handling: not assigning value of registers for '%llu'
fopen(<static_filepath>, <static_mode>); // return value is stored in R5
fprintf(R0/R5, "[PvrAppDrm] Current = %llu, %s", *(ulonglong*)(&rawTime), sTime); // hint: value of R0 and R5 are the same before this call
fclose(R5);
// reduced asm register handling
// no call to loc_13BCD24() anymore (so in this sub 6 more instruction were free to use)
// UNMODIFIED FROM HERE, but limiting broadcast recording 'feature' is implemented here
// in asm here is register and stack handling
// two compares in a row
// if not equal jump to loc_13BCD14 and print '[PvrAppDrm] Able to Record (emi = %d)'
// else print '[PvrAppDrm] NOT able to Record (emi = %d)'
Finally the resulting asm code looks like this (see comments):
record_sub_patched.png
(the main part was calculating the machine code for the new asm instruction, especially the offsets for the branch calls)
The equivalent machine code looks like this (one instruction is 4 Byte, little endian):
record_sub_patched_machine.png
From now on any time recording is started the new file is created containing the string created by asctime().
How to run at boot:
The next goal was creating this file automatically (in best case during boot before SamyGO scripts start). So i combed through the exlink boot output once more to find a good place for calling the modified code. Finally i found and used the following:
Code: Select all
+----------------------------------------------------------+
| |
| Congratulations : All RUIS threads are terminated!!! |
| |
+----------------------------------------------------------+
Here i had 10 instructions to modify (5 times loading a register and branching to puts()). But to see that this stuff was still called/working i wanted to keep the puts() of string containing 'Congratulations'. So 8 instruction were left to modify. What i had to do was calling the function already modified AND branching back. The latter one was the hard part is i had just one instruction left to modify in the already modified funtion. So that line had to be a branch to the 'Congratulations' sub and the 'Congratulations' sub had to decide whether to branch back (recording) or proceed executing (boot process). See the following illustration:
process_flow.png
The decission whether to branch back (recording) or proceed booting is done via the value of R8.:
At booting when entering the 'Congratulations' sub i assign the value 0xAB to R8. Then its branched in the recording sub (but not at its top) where R8 is NOT modified anymore. After fprinting and branching back to the 'Congratulations' sub R8 is still 0xAB. So we know it's the booting process and don't branch back to the recording function.
At recording the recording sub in its beginning assigns something to R8 (which is most probably not 0xAB; above the my modified code). After fptinting and branching to the 'Congratulations' sub R8 is NOT 0xAB, so it's branched back to the next instruction in the recording function and the original code is processed as before.
The asm code looks like this:
congratulations_sub_patched.png
The equivalent machine code looks like this:
congratulations_sub_patched_machine.png
I hope this is at least al little bit comprehensible!
(It's really hard to write down the learning progress and it's result of nearly two weeks)
PS: Tomorrow i will post how to fail safe test the patched exeDSP (edit: need more time to describe how to modify /mtd_exe)
PPS: if you look at my pseudo code and i tell you that the
limiting channel 'feature' limiting broadcast recording 'feature' results in printing '[PvrAppDrm] NOT able to Record (emi = 3)' then you could know which 'bne' (xx xx xx 1A) i talked about in my first post to replace with a 'b' (xx xx xx EA)
EDIT: attached dif file to first post (dif is without patched
limiting channel 'feature' limiting broadcast recording 'feature')
You do not have the required permissions to view the files attached to this post.