Page 1 of 4

[Tutorial] Reverse Engineering C series

Posted: Tue Apr 01, 2014 2:24 pm
by sectroyer
If you are interested in debugging take a look here:
viewtopic.php?f=10&t=9658

To start reversing C exeDSP you have to understand one thing - in opposite to B, D, E and F there is "no" symbols on C :( At the beginning it makes our job much harder... However if you dig into assembly a little deeper you can notice some patterns. First of all on B, D, E and F when you are working on a patch you start by finding function with "interesting name" on C you have to work differently. First option is to use debug messages. They can help you identify interesting functions (sometimes even revealing function name) to start reversing the code. Second option is to memhook end of GetWString function (which is used for EVERY string on the screen :D). You can locate this function by locating "GetWString" text:

Code: Select all

00C67E9C
00C67E9C loc_C67E9C                              ; CODE XREF: CResourceManager::GetWString(int)+68j
00C67E9C                 MOV             R3, R5
00C67EA0                 MOV             R0, #0
00C67EA4                 MOV             R1, #3
00C67EA8                 LDR             R2, =aErrorCresourcemanagerGetwstringStringIdIsOutOfRange ; "[Error] CResourceManager::GetWString - "...
00C67EAC                 LDR             R4, =_ZN7CCDebug5PrintI9CCDebugBPEEvmmPKcz ; CCDebug::Print<CCDebugBP>(ulong,ulong,char  const*,...)
00C67EB0                 BLX             R4 ; sub_207C0EC
00C67EB4                 MOV             R0, #0
00C67EB8                 MOV             R1, R0
00C67EBC                 LDR             R2, =aAssertFuncS ; "ASSERT!, Func:%s"
00C67EC0                 LDR             R3, =aGetwstring ; "GetWString"
00C67EC4                 BLX             R4 ; sub_207C0EC
00C67EC8                 MOV             R4, #0
00C67ECC
In R0 you will have pointer to wide string (wchar_t*) which you can check using GDB and in LR will be the return address. For instance when I was working on Movie Delete Patch I hooked GetWString and pushed tools menu button. Then every string from the menu was logged and I immediately (thanks to value from LR) was able to locate function that was creating Movie Browser tools menu :)

The final way is to find a place to patch in D assembly (which has all symbols) and then locate the same place in C (which doesn't have symbols). It will work because it looks that C is just D without symbols :D In many cases you can find line by line same/similar assembly instructions :)

When you have successfully patched your version of exeDSP it's time to make it work on every version :) Dynamic patching on C is similar to B, D, E and F without one caveat. You have to find a way to dynamically locate the right function and then (as on B, D, E and F) right place to patch. I use two approaches for solving this problem.

First solution is to use my "find_func_by_string" and then (if it doesn't return 0) using find_function_start for find the function address:

Code: Select all

key_press_addr=find_func_by_string(pid, symtab, "_ZN9TDBuilder8GetTDiCPE16TDSourceObject_k", "SendKeyPressInput", F_SEEK_DOWN,-0x80000);
 if(key_press_addr)
      key_press_addr=find_function_start(pid,key_press_addr);
To this function you pass pid, symtab, name of one of the few exported functions that is the closest to function that you are looking for, string to look, search direction flag and search offset. This method returns the address of a place where the string is used so that's why we call find_function_start to return actual function address. In some cases the function we are looking doesn't use any hardcoded strings but the next/previous one does. It looks like the very stable is to check how far approximately the functions we are looking is from the string usage place. We don't have to be precise it is enough to "land" somewhere in interesting function. It is quite reliable for functions which are more than 20-30 assembly lines. Then sample usage looks like this:

Code: Select all

addr=find_func_by_string(pid, symtab, "CRYPTHW_SetIV", "t_SetItemToListCtrl", F_SEEK_DOWN);
if(adde)
{
      addr=addr-0x600;
      tools_menu_addr=find_function_start(pid,adde);
}
In some cases using method described above isn't possible (I have encountered this problem while working on samyGOrc. Solution was to locate a string close to vtable (you can check it on D assembly) and locate this string dynamically by starting with some exported symbol from rodata. After finding the string you add the static offset to locate the function pointer from vtable:

Code: Select all

unsigned long thread_addr=get_object_by_name(symtab,"_ZTI8PCThread");
if(debug)
     printf("PCThread: : 0x%x\n",(uint)thread_addr);
for(cur_addr=thread_addr+0x15000; cur_addr < (thread_addr+0x25000); cur_addr+=0x100)
{
     read_mem(pid,(void*)string_buf,0x120/4,cur_addr);
     for(i=0;i<0x120;i++)
     {
             if(!strcmp(string_buf+i,"15KeyInputCreator"))
             {
                      newKeyCommon=(void*)(cur_addr+i-6*4);
                      read_mem(pid,(void*)&newKeyCommon,1,(uint)newKeyCommon);
                      if(debug)
                      {
                              printf("String '15KeyInputCreator' found at: 0x%08x\n",(uint)(cur_addr+i));
                              printf("_ZN15KeyInputCreator12NewKeyCommonEv found at: 0x%08x\n",(uint)newKeyCommon);
                      }
             }
     }
}
EDIT:
I would like to thanks timoo for his great find:
timoo wrote:imho at least fw T-valdeuc 0000 have these 'symbols' - function names etc.
This find makes adding support for C with existing patches much simpler (all my new patches will support method described here). I attach two files C_find.py and C_exports.txt which you use together (you have to put path to C_exports.txt in C_find.py) like this:
1) Load 0000 firmware
2) Find function you want to support
3) Load C_find.py
4) Run this command: generate_c_case("FUNCTION_NAME")
and at the end you will get something like this:

Code: Select all

	C_CASE(_ZN10TCChNumber7SetTypeEi)
		addr=find_nth_func_from_export(h,"_ZN12TCChannelKeyC1Ei",13);
		C_FOUND(addr);
	C_RET(addr);
5) Use one of my (new) patches (or write your own on the basis of libSchedulePVR) and copy C_support.c/h and C_find.h files to patch directory and set C_SUPPORT to 1 in Makefile
6) Add generated C_CASE to C_find.h and voila :)

You can see all this in action here:
viewtopic.php?f=75&t=9038&p=73842&hilit ... PVR#p73842

I have attached C exeDSP signature file, so you can use it for auto naming functions :)

Re: [Tutorial] Reverse Engineering C series

Posted: Tue Apr 01, 2014 8:59 pm
by greenhorn
awesome

Re: [Tutorial] Reverse Engineering C series

Posted: Tue Apr 01, 2014 9:02 pm
by sectroyer
greenhorn wrote:awesome
Glad you like it :) Hope it will be helpful :)

Re: [Tutorial] Reverse Engineering C series

Posted: Sat Apr 05, 2014 11:55 am
by FilipeAmadeuO
Nice :)
Do you think it could be possible to patch/acess exeDSP in order to use Oscam as used in E and F series (by juuso) ?

Re: [Tutorial] Reverse Engineering C series

Posted: Sat Apr 05, 2014 1:42 pm
by juusso
not by me, but yes, this way could be possible.

Re: [Tutorial] Reverse Engineering C series

Posted: Sat Apr 05, 2014 2:46 pm
by FilipeAmadeuO
juuso - Thanks
sectroyer - Can you please check if it?s posibe to extend oscam to other Samsung series ? This would a very nice feature :)

Re: [Tutorial] Reverse Engineering C series

Posted: Sat Apr 05, 2014 3:13 pm
by zoelechat
I wonder why nobody asked it before :mrgreen:

Re: [Tutorial] Reverse Engineering C series

Posted: Sat Apr 05, 2014 8:32 pm
by sectroyer
FilipeAmadeuO wrote:juuso - Thanks
sectroyer - Can you please check if it?s posibe to extend oscam to other Samsung series ? This would a very nice feature :)
No way :) Why?
1) I don't have access to any paid/encrypted tv channels.
2) I don't know how :)
3) Don't ask ever again :D

Re: [Tutorial] Reverse Engineering C series

Posted: Tue May 06, 2014 8:43 pm
by sectroyer
I found another way for finding good places to patch. Althought (almost) all symbols are missing on ARM C they are present on Trident/Mips :) Many features are not availabe for these TVs (timeshift, pvr, etc. ) but for other patches look at their assembly often is a good idea ;)

Re: [Tutorial] Reverse Engineering C series

Posted: Sun Mar 01, 2015 10:19 pm
by sectroyer
sectroyer wrote:I found another way for finding good places to patch. Althought (almost) all symbols are missing on ARM C they are present on Trident/Mips :) Many features are not availabe for these TVs (timeshift, pvr, etc. ) but for other patches look at their assembly often is a good idea ;)
Confirmed. I was able to find functions in same places :) Just in one window I open C MIPS find function copy name and in second window I find same place in C ARM rename some "sub_xxxxx" to correct name and voila :) Of course you still have to make it dynamic but that's another storry ;)