📜 ⬆️ ⬇️

Siemens SGold: Hacking Through Java

Foreword


This article reveals a method for gaining access to the address space of any Siemens SGold phone processor through a single environment in which at least some code can be run, that is, via a Java machine.
The proposed method was invented by Comrade Chaos (Dmitry Zakharov), a person without whom, as they say, it was not possible to modify and debug the firmware on Siemens phones with a BB processor
SGoldLite and SGold-2 families. And I just expanded and systematized it.

What does this give in perspective?


This all makes it possible to modify the firmware directly from a phone without a computer and a Data cable, which cannot be found in our time, and there may be a lack of finance. For a simple user, this is an extension of the hardware (overclocking the processor, increasing performance, unlocking SDRAM, etc.) and software
(such as the legendary performer of the ELF format, Java hip increase, etc.) of opportunities, and for the programmer to practice writing ARM programs, working directly with hardware, a processor (which stands in IPhone 2, by the way), for this there are all the conditions. And naturally, this is for those who are interested and curious, who may have such a device lying around. Intrigued?
So give it a second life!

Source


I designed all the work with the address space into a separate class ASpace. Next, I will explain some of its details.

Initialization


Well, let's move on to the method.
As you guessed, this action takes place through Java-code, and, of course, ARM-assembler. Siemens Java machine has built-in classes for working with zip archives. It was then that the "vaunted fascist", oh, that is, German engineers, pierced themselves, overlooked the hole. This applies to all existing firmware (and new, unfortunately or to the joy, it is not necessary to wait).
Actually by the title, let's look at the code:
')
//    ZIP  public byte[] aspace_ziparray = {0,0,0,0}; //,   2,  public int[] mainarray = {0}; //   public static final int ASPACE_RET_SUCCESS = 1; public static final int ASPACE_RET_UNKNOWNERROR = 0; public static final int ASPACE_RET_NOZIPFILE = -1; public static final int ASPACE_RET_NOZIPENTRY = -2; public static final int ASPACE_RET_SIGNOFIND = -3; //     0xA8000000 (SDRAM)  0xB0000000 (Flash) private static final int ASPACE_OFFSET_SDRAM_TO_FLASH = 0x8000000; //    0x00000000 (  ) public static int mainarray_startindex = 0; /*     Flash */ //   ()   0xA0000030 private static final int[] aspace_sgold_flash_signature = { 0xA0000000, //0xA0000000 0x5FFFFFFF, //0x5FFFFFFF 0xA0000074, //0xA0000074 0x544B4A43 //CJKT Marker }; /*   ( ) */ public int ASpace_Init(String any_zipfile, String any_zipentryname) { try { //  ,       ZipFile zf = new ZipFile(any_zipfile); if (zf != null) { // ZipEntry      ZipEntry ze = zf.getEntry(any_zipentryname); if (ze != null) { //  InputStream zis = zf.getInputStream(ze); //   ,      , //     2 zis.read(aspace_ziparray, 4, 0x7FFFFFFF); // zip -  zf.close(); //    Flash //       //     0x0 int i = ASPACE_OFFSET_SDRAM_TO_FLASH/4; for (; i > 0; i--) { int j = 0; for (int k = 0; k < 4; k++) { if (mainarray[i + k] != aspace_sgold_flash_signature[k]) { j = 1; break; } } if (j == 0) { //    Flash mainarray_startindex = i - (aspace_sgold_flash_signature_offset/4); // ,    , .. 0x00 mainarray_startindex += ( 0x50000000/4 ); break; } } //,   if (i != 0) return ASPACE_RET_SUCCESS; //  else return ASPACE_RET_SIGNOFIND; //     } else return ASPACE_RET_NOZIPENTRY; //    } else return ASPACE_RET_NOZIPFILE; //  } catch (Exception e) { return ASPACE_RET_UNKNOWNERROR; } } 


I will describe what the Siemens address space map looks like:
0x00000000-0x00003FFF - Internal SRAM # 1 (inside the microcontroller)
0x00080000-0x00097FFF - Internal SRAM # 2 (inside the microcontroller)
0x00400000-0x0040FFFF - Internal BootROM (inside the microcontroller)
0xA0000000-0xA7FFFFFF - External Flash (sometimes 32 MB, 64 MB, 96 MB, 128 MB)
0xA8000000-0xA9FFFFFF - External SDRAM (sometimes 8 MB, 16 MB, 32 MB)
0xB0000000-0xB7FFFFFF - Flash Mirror with Write Access
0xF0000000-0xFFFFFFFF - I / O ports, embedded device registers in microns

The bottom line is that by reading the read 0x7FFFFFF byte method outside the aspace_ziparray array, we are in the area of ​​the mainarray array, thereby Java increases its length to 2 GB (0x7FFFFFFF). Since everything is within the rules, the exception about exiting from the boundaries of the array does not pop up. And the contents of this array is the address space,
starting at the physical address of this array in SDRAM.

Naturally, it is somewhere in the Java heap.
On the x65th models, this is around 0xA8000000-0xA8300000.
On the x75th models, this is around 0xA8500000-0xA8700000.

Since the array is int, one cell is 4 bytes, i.e. moving the index by 1, we move 4 bytes each. Though our array is int, it doesn’t see more than 2 GB, so we have half of SDRAM, mirror Flash, I / O ports and all internal memory at our disposal.
The rest, so to speak, "behind the scenes." Next, you need to shift the index so that it is in the Flash mirror area, and lead it to the beginning, checking the aspace_sgold_flash_signature signature along the way, which indicates that we are at the beginning of Flash. As we found it, we jump to the starting address, writing down the index of the mainarray array, corresponding to the address 0x00, in the variable mainarray_startindex.
Everything, initialization is passed.

Read and write


Using the mainarray array, moving its index relative to mainarray_startindex, we can both read and write to the SRAM / SDRAM / I / O ports.
This is what the methods do:

 //   32    public int ASpace_readword(int address); //   16    public int ASpace_readhwrd(int address); //    public int ASpace_readbyte(int address); //   32    public int ASpace_writeword(int address, int value); //   16    public int ASpace_writehwrd(int address, int value); //    public int ASpace_writebyte(int address, int value); 


Execution of the ARM code


Indeed, all this is good, but how to execute the ARM-code?
There is a method of installing the performer of machine code processor.
In the SRAM / SDRAM of the phone there are a lot of different pointers (who do not know, read C / C ++ textbooks) for any procedures that are periodically called, and if you load your code in the free space (and there are also full ones) and change the pointer to then the firmware itself will call it. But we must do everything correctly so that the system does not fall. For example, this is how the executor of the ARM code looks for our method:

  /* ARM Caller -  ARM - */ //    public final int aspace_sgold_armcaller_newpointer = 0x803F8; //    ARM Caller'a public final int aspace_sgold_armcaller_bodyaddress = 0x8E010; //       public final int aspace_sgold_workcode_bodyaddress = 0x8E100; //    private static final int ASPACE_ARMCALLER_STATE = 16; private static final int ASPACE_ARMCALLER_OLDPROC = 17; private static final int ASPACE_ARMCALLER_RUNPROC = 18; private static final int ASPACE_ARMCALLER_PARAM0 = 19; private static final int ASPACE_ARMCALLER_PARAM1 = 20; private static final int ASPACE_ARMCALLER_PARAM2 = 21; private static final int ASPACE_ARMCALLER_PARAM3 = 22; private static final int ASPACE_ARMCALLER_RETURN = 23; //  private static int aspace_armcaller_repaddress = 0; //   ARM Caller'a private static int aspace_armcaller_bodyaddress = 0; //     ARM  private static int[] aspace_armcaller = { 0xE92D401F, // ; STMFD SP!, {R0-R4,LR} 0xE59F0038, // ; LDR R0, =old_proc 0xE12FFF30, // ; BLX R0 0xE59F002C, // ; LDR R0, =state 0xE3500000, // ; CMP R0, #0 0x08BD801F, // ; LDMEQFD SP!, {R0-R4,PC} 0xE59F002C, // ; LDR R0, =param0 0xE59F102C, // ; LDR R1, =param1 0xE59F202C, // ; LDR R2, =param2 0xE59F302C, // ; LDR R3, =param3 0xE59F4018, // ; LDR R4, =run_proc 0xE12FFF34, // ; BLX R4 0xE58F0024, // ; STR R0, [PC,#0x24] ; ret 0xE3A00000, // ; MOV R0, #0 0xE58F0000, // ; STR R0, [PC,#0x00] ; state 0xE8BD801F, // ; LDMFD SP!, {R0-R4,PC} 0x00000000, // ; state 0x00000000, // ; old_proc 0x00000000, // ; run_proc 0x00000000, // ; param0 0x00000000, // ; param1 0x00000000, // ; param2 0x00000000, // ; param3 0x00000000 // ; ret }; 


Changing the body of the program, we can set the parameters, make sure that with one command the code is called only once. After installation, you can run ARM-procedures, set up to 4 parameters and get the return value.
Methods that serve our performer:

  /*   / ARM Caller'a (   ) */ // ARM Caller'a public int ASpace_InstallArmCaller(int replace_address, int body_address); // ARM Caller'a public int ASpace_DeInstallArmCaller(); /*     */ public int ASpace_RunArmCode(int address, int arg0, int arg1, int arg2, int arg3); 


Additional methods


Well, what is listed above is the core, the basis. But there are other methods in the class.
They are collected on their basis. Some use ARM code:

 /*    / ARM  Data Abort */ public void ASpace_DisableDataAbort(); public void ASpace_EnableDataAbort(); /*    SDRAM  0xB8000000 (  ARM Caller) */ public void ASpace_SDRAMRemap(); /*          */ public int ASpace_SearchFunction(int search_address, int search_size, int[] pattern, int offset); /*          */ public int ASpace_SearchFunctionByWords(int search_address, int search_size, int[] pattern, int offset); 


Conclusion


Above, I mentioned perspective. A ready-made implementation of one of her ideas already exists,
and, of course, is an example of working with this class.
You can find the source and ready midlet here:

Siemens SGold Service Tool .

Source: https://habr.com/ru/post/149068/


All Articles