From Vita Development Wiki
(Redirected from SELF Loading)
Jump to navigation Jump to search

SceKernelModulemgr is in charge of loading both user modules and kernel modules. SceSblAuthMgr facilitates the SELF decryption process and this library loads the ELF programs into memory along with linking with NIDs and relocation of ELF in position independent executables.



This module exists only in non-secure world. The SELF can be found in os0:kd/modulemgr.skprx.

Known NIDs

Version Name World Privilege NID
1.69 SceKernelModulemgr Non-secure Kernel 0xAFDA75C2
3.57 SceKernelModulemgr Non-secure Kernel 0x8FDDA3C0
3.60 SceKernelModulemgr Non-secure Kernel 0x726C6635
3.65 SceKernelModulemgr Non-secure Kernel 0x781C6F50


This module exports kernel and user libraries.

Known NIDs

Version Name World Visibility NID
1.69-3.60 SceModulemgrForKernel Non-secure Kernel 0xC445FA63
3.65 SceModulemgrForKernel Non-secure Kernel 0x92C9FFC2
1.69-3.65 SceModulemgrForDriver Non-secure Kernel 0xD4A60A52
1.69-3.65 SceModulemgr Non-secure User 0xEAED1616
3.57-3.60 SceBacktraceForDriver Non-secure Kernel 0x77CB3DD6
3.57-3.60 SceBacktrace Non-secure User 0xB07B6A3F


//these types are defined in elfutils
typedef Elf32_Ehdr Elf32_Ehdr;
typedef Elf32_Phdr Elf32_Phdr;

typedef struct SCE_header
	uint32_t magic;                 /* 53434500 = SCE\0 */
	uint32_t version;               /* header version 3*/
	uint16_t sdk_type;              /* */
	uint16_t header_type;           /* 1 self, 2 unknown, 3 pkg */
	uint32_t metadata_offset;       /* metadata offset */
	uint64_t header_len;            /* self header length */
	uint64_t elf_filesize;          /* ELF file length */
	uint64_t self_filesize;         /* SELF file length */
	uint64_t unknown;               /* UNKNOWN */
	uint64_t self_offset;           /* SELF offset */
	uint64_t appinfo_offset;        /* app info offset */
	uint64_t elf_offset;            /* ELF #1 offset */
	uint64_t phdr_offset;           /* program header offset */
	uint64_t shdr_offset;           /* section header offset */
	uint64_t section_info_offset;   /* section info offset */
	uint64_t sceversion_offset;     /* version offset */
	uint64_t controlinfo_offset;    /* control info offset */
	uint64_t controlinfo_size;      /* control info size */
	uint64_t padding;
} SCE_header;

typedef struct SCE_appinfo
   uint64_t program_authority_id;                /* program authority id */
   uint32_t vendor_id;             /* vendor id */
   uint32_t self_type;             /* app type */
   uint64_t version;               /* app version */
   uint64_t padding;               /* UNKNOWN */
} SCE_appinfo;

typedef struct segment_info
   uint64_t offset;
   uint64_t length;
   uint64_t compression; // 1 = uncompressed, 2 = compressed
   uint64_t encryption; // 1 = encrypted, 2 = plain
} segment_info;

typedef struct self_data_buffer
   SCE_header sce_header;
   SCE_appinfo sce_appinfo;
   Elf32_Ehdr elf_hdr;
   //... data goes
} self_data_buffer;

typedef struct self_data_ctx //size is 0x30
   self_data_buffer* self_header; // aligned buffer - based on (buffer_unaligned). 
                                  // points at SCE_header followed by SCE_appinfo
                                  // size is usually 0x1000
   uint32_t self_header_length;
   Elf32_Ehdr* elf_ptr; // pointer constructed with elf_offset
   Elf32_Phdr* phdr_ptr; // pointer constructed with phdr_offset

   uint8_t type; // ex: 2
   uint8_t init_completed;
   uint8_t unk_12;
   uint8_t unk_13;
   segment_info* section_info_ptr; // pointer constructed with section_info_offset
   void* buffer_unaligned; // SELF header data - size 0x103F - raw data read from file
   int sm_ctx; // obtained with sceSblAuthMgrSmStartForKernel

   SceSblSmCommContext130* context_130;
   SceUID fd; // file descriptor of SELF file - obtained with sceIoOpenForDriver
   SceUID pid;
   uint32_t max_size;
} self_data_ctx;

typedef int(segment_decrypt_callback_t)(void* unk);

typedef struct self_decrypter_ctx //size is unknown
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t unk_8;
   uint32_t unk_C;
   uint32_t unk_10;
   uint32_t unk_14;
   uint32_t unk_18;
   uint32_t unk_1C;
   self_data_ctx* data_ctx;
   SceUID evid; // SceModuleMgrSelfDecryptComm event flag
   SceUID tid; // SceModuleMgrSelfDecrypter thread
   uint32_t unk_2C;
   uint32_t unk_30;
   uint32_t unk_34;
   uint16_t segment_number;
   uint16_t unk_3A;
   uint32_t unk_3C; // = 0x10
   uint32_t unk_40;
   uint32_t unk_44;
   segment_decrypt_callback_t* dec_callback;
   //... data goes on
} self_decrypter_ctx;

Data segment layout

Offsets are for FW 3.60.

Offset Size Description
0x0000 0x340 unknown
0x0340 at least 0x4C self_decrypter_ctx data
? ? unknown

Loading Sequence

When loading a module the sequence creates a SceModule structure to represent it.

typedef struct
    const char *filename; // 0x64
    Elf32_Ehdr ehdr;        // 0x74
    Elf32_Phdr phdr;        // 0xA8
    void *text_addr;        // 0x108
    SceUID text_uid;        // 0x10C
    u32 text_size;          // 0x110
    void *kernel_addr;      // 0x114
    SceUID kernel_uid;      // 0x118
    unsigned int parent_pid; // 0x3E4
    SceSblSmCommContext130* context_130;
} SceModule;

SELF Decryption

The following code can decrypt a SELF located at path. Set user to 1 if decrypting a user module else 0 for kernel. Set pathid to 0 if you're decrypting the SELF at the right location (for example decrypting sysmem.skprx located in os0:). If you have copied the SELF elsewhere, you need to set the pathid to the right value for where the real path was. usecdram is for modules that are too large and won't fit in contiguous regular memory.

int decrypt_self(const char *path, const char *outprefix, int pathid, int usecdram, int user)
    char outpath[256];
    int ctx;
    int ret;
    int pid;
    int fd = 0, wfd = 0;
    char *somebuf = NULL;
    char *hdr_buf = NULL, *hdr_buf_aligned;
    char *data_buf = NULL, *data_buf_aligned;
    int phdr;

    unsigned int hdr_size;

    // set up SBL decrypt context
    ret = SceSblAuthMgrForKernel_0xA9CD2A09(&ctx);
    printf("SceSblAuthMgrForKernel_0xA9CD2A09: 0x%08X, CTX: 0x%08X\n", ret, ctx);
    if (ret < 0)
        return 1;

    // set up this weird buffer
    somebuf = sceKernelLoadcoreKallocForKernel(0x10005, 0x130);
    printf("Weird buffer: 0x%08X\n", somebuf);
    if (somebuf == NULL)
        goto fail;
    memset(somebuf, 0, 0x130);
    if (ret < 0)
        goto fail;
    *(int *)(somebuf + 0x4) = user;
    *(u64_t *)(somebuf + 0x8) = 0x2808000000000001LL;
    *(u64_t *)(somebuf + 0x10) = 0xF000C000000080LL;
    *(u64_t *)(somebuf + 0x18) = 0xFFFFFFFF00000000LL;
    *(u64_t *)(somebuf + 0x30) = 0xC300003800980LL;
    *(u64_t *)(somebuf + 0x38) = 0x8009800000LL;
    *(u64_t *)(somebuf + 0x48) = 0xFFFFFFFF00000000LL;

    if (pathid)
        *(int *)(somebuf + 0x128) = pathid;
        ret = SceIofilemgrForDriver_0x9C220246(0x10005, path, 1, somebuf + 0x128);
        printf("SceIofilemgrForDriver_0x9C220246: 0x%08X\n", ret);
        if (ret < 0)
            goto fail;

    // read header
    fd = sceIoOpenForDriver(path, 1, 0);
    printf("sceIoOpenForDriver: 0x%08X\n", fd);
    if (fd < 0)
        goto fail;
    hdr_buf = sceKernelLoadcoreKallocForKernel(0x10005, 0x1000+63);
    hdr_buf_aligned = (char *)(((int)hdr_buf + 63) & 0xFFFFFFC0);
    printf("Header buffer: 0x%08X, aligned: 0x%08X\n", hdr_buf, hdr_buf_aligned);
    if (hdr_buf == NULL)
        goto fail;
    ret = sceIoReadForDriver(fd, hdr_buf_aligned, 0x1000);
    printf("Header read: 0x%08X\n", ret);
    hdr_size = *(unsigned int *)(hdr_buf_aligned + 0x10);
    if (hdr_size > 0x1000)
        printf("Header too large: 0x%08X\n", hdr_size);
        goto fail;
    ret = sceIoLseekForDriver(fd, 0LL, 0);
    printf("Header rewind: 0x%08X\n", ret);

    // set up SBL decryption for this SELF
    ret = SceSblAuthMgrForKernel_0xF3411881(ctx, hdr_buf_aligned, hdr_size, somebuf);
    printf("SceSblAuthMgrForKernel_0xF3411881: 0x%08X\n", ret);
    if (ret < 0)
        goto fail;

    // set up read buffer
    data_buf = sceKernelLoadcoreKallocForKernel(0x10005, 0x10000+63);
    data_buf_aligned = (char *)(((int)data_buf + 63) & 0xFFFFFFC0);
    printf("Data buffer: 0x%08X, aligned: 0x%08X\n", data_buf, data_buf_aligned);
    if (data_buf == NULL)
        goto fail;

    // get sections
    int elf_offset = *(int*)(hdr_buf_aligned + 0x40);
    int num_segs = *(short*)(hdr_buf_aligned + elf_offset + 0x2C);
    printf("Number of segments to read: 0x%04X\n", num_segs);
    int info_offset = *(int*)(hdr_buf_aligned + 0x58);
    struct seg_info *segs = (struct seg_info *)(hdr_buf_aligned + info_offset);
    int phdr_offset = *(int*)(hdr_buf_aligned + 0x48);
    struct e_phdr *phdrs = (struct e_phdr *)(hdr_buf_aligned + phdr_offset);

    // decrypt sections
    int i;
    int total, to_read, num_read, off;
    int aligned_size;
    int blkid = 0;
    void *pgr_buf;
    for (i = 0; i < num_segs; i++)
        sprintf(outpath, "%s.seg%u", outprefix, i);
        wfd = sceIoOpenForDriver(outpath, 0x602, 6);
        printf("sceIoOpenForDriver(%s): 0x%08X\n", outpath, wfd);
        if (wfd < 0)

        if (blkid)
        aligned_size = (phdrs[i].p_filesz + 4095) & 0xFFFFF000;
        if (usecdram)
            blkid = sceKernelAllocMemBlockForKernel("self_decrypt_buffer", 0x40404006, 0x4000000, NULL);
            blkid = sceKernelAllocMemBlockForKernel("self_decrypt_buffer", 0x1020D006, aligned_size, NULL);
        printf("sceKernelAllocMemBlockForKernel: 0x%08X, size: 0x%08X\n", blkid, aligned_size);
        ret = sceKernelGetMemBlockBaseForKernel(blkid, &pgr_buf);
        printf("sceKernelGetMemBlockBaseForKernel: 0x%08X, base: 0x%08X\n", ret, pgr_buf);
        if (ret < 0)

        // setup buffer for output
        ret = SceSblAuthMgrForKernel_0x89CCDA2C(ctx, i, (u32_t)segs[i].length, pgr_buf, phdrs[i].p_filesz);
        printf("SceSblAuthMgrForKernel_0x89CCDA2C: 0x%08X\n", ret);
        if (ret < 0)

        ret = sceIoLseekForDriver(fd, segs[i].offset, 0);
        printf("sceIoLseekForDriver(0x%08X): 0x%08X\n", (u32_t)segs[i].offset, ret);
        if (ret < 0)
        total = (u32_t)segs[i].length;
        to_read = total > 0x10000 ? 0x10000 : total;
        off = 0;
        while (total > 0 && (num_read = sceIoReadForDriver(fd, data_buf_aligned+off, to_read)) > 0)
            off += num_read;
            total -= num_read;
            if (num_read < to_read)
                to_read -= num_read;

            ret = SceSblAuthMgrForKernel_0xBC422443(ctx, data_buf_aligned, off); // decrypt buffer
            printf("SceSblAuthMgrForKernel_0xBC422443: 0x%08X\n", ret);
            if (ret < 0)
                printf("!!! ERROR !!!\n");
            ret = SceSblAuthMgrForKernel_0x15248FB4(ctx, data_buf_aligned, off); // copy buffer to output
            printf("SceSblAuthMgrForKernel_0x15248FB4: 0x%08X\n", ret);
            if (ret < 0)
                printf("!!! ERROR !!!\n");

            off = 0;
            to_read = total > 0x10000 ? 0x10000 : total;

        // write buffer
        off = 0;
        while ((off += sceIoWriteForDriver(wfd, pgr_buf+off, phdrs[i].p_filesz-off)) < phdrs[i].p_filesz);
    if (blkid)

    if (fd)
    if (somebuf)
    if (hdr_buf)
    if (data_buf)
    return 1;

Module decryption and signature checks ("HENkaku patches" on 1.60)

See also SELF_Loading to see how these SceSblAuthMgr function are used to decrypt SELFs.

The code below will patch signature checks and bypass module decryption and allow homebrew to run. The idea is to hook SceSblAuthMgr* calls that are imported to SceKernelModulemgr. The offsets are from 1.60, you will probably need to modify functions defines (set to addresses of functions) and INSTALL_HOOK second arguments (set to addresses of imports in SceKernelModulemgr). For old FWs like 1.60, as there is no kASLR, you can set hardcoded addresses, else take HENkaku code. As a bonus there's also patch_npdrm functions that patches SceNpDrm to bypass some DRM checks and allow unsigned packages to be installed, which you also need to modify addresses. See SceNpDrm#Package_integrity_checks.

// hardcoded addresses for 1.60
#define G_OUR_EBOOT *(unsigned*)(0x01e60000 - 20)
#define G_BUF *(unsigned*)(0x01e60000 - 12)
#define G_WRITTEN *(unsigned*)(0x01e60000 - 16)

#define Func(addr) ((unsigned(*)())(addr))

// Hardcoded addresses for 1.60
#define sceSblAuthMgrAuthHeaderForKernel Func(0x4BC6C9)
#define sceSblAuthMgrLoadSegmentForKernel Func(0x4BC851)
#define sceSblAuthMgrLoadBlockForKernel Func(0x4BC909)
#define sceSblAuthMgrLoadSegmentInternalForKernel Func(0x4BCA89)

// setup file decryption
unsigned sceSblAuthMgrAuthHeaderForKernel_patched(unsigned a1, unsigned a2, unsigned a3, unsigned a4) {
    unsigned res = sceSblAuthMgrAuthHeaderForKernel(a1, a2, a3, a4);

    if (res == 0x800f0624 || res == 0x800f0616 || res == 0x800f0024) {
        G_OUR_EBOOT = 1;

        // patch somebuf so our module actually runs
        unsigned *somebuf = (unsigned*)a4;
        somebuf[42] = 0x40;

        return 0;
    } else {
        G_OUR_EBOOT = 0;
    return res;

// setup output buffer
unsigned sceSblAuthMgrLoadSegmentForKernel_patched(unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5) {
    G_BUF = a4;
    G_WRITTEN = 0;
    if (G_OUR_EBOOT == 1) {
        return 0;
    return sceSblAuthMgrLoadSegmentForKernel(a1, a2, a3, a4, a5);

// decrypt
unsigned sceSblAuthMgrLoadBlockForKernel_patched(unsigned a1, unsigned a2, unsigned a3) {
    if (G_OUR_EBOOT == 1) {
        return 0;
    return sceSblAuthMgrLoadBlockForKernel(a1, a2, a3);

// copy to output - not present on 3.60
unsigned sceSblAuthMgrLoadSegmentInternalForKernel_patched(unsigned a1, unsigned a2, unsigned a3) {
    if (G_OUR_EBOOT == 1) {
        memcpy((void*)(G_BUF + G_WRITTEN), (void*)a2, a3);
        G_WRITTEN += a3;
        return 0;
    return sceSblAuthMgrLoadSegmentInternalForKernel(a1, a2, a3);

#define INSTALL_HOOK(func, addr) \
    { unsigned *target; \
    target = (unsigned*)addr; \
    *target++ = 0xE59FF000; /* ldr pc, [pc, #0] */ \
    *target++; /* doesn't matter */ \
    *target = (unsigned)func; \

// hardcoded addresses for 1.60
void hook_install(void) {
    INSTALL_HOOK(sceSblAuthMgrLoadBlockForKernel_patched, 0x5BAA0C);
    INSTALL_HOOK(sceSblAuthMgrLoadSegmentInternalForKernel_patched, 0x5BA9CC);
    INSTALL_HOOK(sceSblAuthMgrAuthHeaderForKernel_patched, 0x5BAA1C);
    INSTALL_HOOK(sceSblAuthMgrLoadSegmentForKernel_patched, 0x5BA9DC);

unsigned get_module_base(const char *name) {
    int * modlist[MOD_LIST_SIZE];
    int modlist_records;
    int res;
    SceModInfo modinfo;

    memset(modlist, 0, sizeof(modlist));
    modlist_records = MOD_LIST_SIZE;
    sceKernelGetModuleListForKernel(0x10005, 0x7FFFFFFF, 1, modlist, &modlist_records);

    for(int j = 0; j < modlist_records; j++) {
        memset(&modinfo, 0, sizeof(modinfo));
        res=sceKernelGetModuleInfoForKernel(modlist[j], &modinfo);
        if (strcmp(, name) == 0)
            return (unsigned)modinfo.module_top;
    return 0;

// Hardcoded addresses for 1.60
void patch_npdrm(unsigned base) {
    unsigned *patch;
    // check where check_func[0] is called
    patch = (unsigned*)(base + 0x310);
    *patch = 0x47702001;
    // check where check_func[1] is called
    patch = (unsigned*)(base + 0xaa4);
    *patch = 0x47702001;

    // always return 1 in install_allowed
    patch = (unsigned*)(base + 0x2d64);
    *patch = 0x47702001;
    // patch error code 0x80870003
    patch = (unsigned*)(base + 0x4856);
    *patch = 0x2500;
    // second same error code
    patch = (unsigned*)(base + 0x35fe);
    *patch = 0x2600;

// call this from a thread
int hook(void) {
    fprintf("Hook start\n");

    unsigned prev_dacr;
    __asm__ volatile("mrc p15, 0, %0, c3, c0, 0" : "=r" (prev_dacr));
    __asm__ volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (-1));

    unsigned base_npdrm = get_module_base("SceNpDrm");
    fprintf("SceNpDrm base: 0x%08x\n", base_npdrm);


    __asm__ volatile("MCR    p15, 0, %0, c7, c5, 0" : : "r" (0)); // flush icache
    __asm__ volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (prev_dacr));


    return 0;



Version NID
0.990 0x37C2A1A5


Version NID
0.990 0x0751F162


Version NID
0.990-3.60 0x2C2618D9

Used by sceKernelPrintBacktraceForDriver.

int SceModulemgrForKernel_2C2618D9(SceUID pid, void *a2, void *a3);


Version NID
0.990-3.60 0x0053BA4A
// a2 is the a1 of SceModulemgrForDriver_1D9E0F7E
int SceModulemgrForKernel_0053BA4A(SceUID pid, int a2);


Version NID
0.990 0xC72CA412
3.60 not present


Version NID
0.990-3.60 0x448810D5


Version NID
0.990-3.60 0xB4A1DE31
uint32_t sceKernelLoadcoreKallocForKernel(SceUID pid, uint32_t size);


Version NID
0.990-3.60 0xFDD7F646
void *sysroot_buffer = sceKernelGetSysrootBuffer;
kbl_modid = *(_DWORD *)(SceSysrootForKernel_CD70C9D7(sysroot_buffer) + 0x38);
unk = *(_DWORD *)(SceSysrootForKernel_CD70C9D7(sysroot_buffer) + 0x34);
// then does other things with other sysroot functions
void sceKernelFinalizeKblForKernel(void);


Version NID
3.60 0xB427025E
3.65-3.68 0x2E4A10A0
void sceKernelRegisterSyscallForKernel(uint32_t num, void *function);


Version NID
0.990-3.60 0x448810D5
int sceKernelDecryptSelfByPathForKernel(const char *path, int e_phnum, void *buffer, uint32_t bufsize, int zero_unk, uint32_t *bytes_read);

This is an easy way of decrypting SELFs but you are limited to the kinds of SELFs you can load in the current context (for example, you can't load user libraries from kernel context). It is also susceptible to limitations of where the SELF can be loaded from. For example, you are not allowed to load SELFs found in os0 from ux0. This is because it checks the PathId.


Version NID
1.60-3.60 0x97CF7B4E
int sceKernelGetModuleListForKernel(SceUID pid, int flags1, int flags2, SceUID *modids, size_t *num);


Version NID
3.60 0x410E1D2E

Found by Princess


Version NID
3.60 0x3B93CF88

Found by Princess


Version NID
3.60 0x1FDEAE16

Found by Princess


Version NID
3.60 0xD269F915


Version NID
3.60 0x6A655255

Found by Princess


Version NID
3.60 0xFE303863

Temp name was sceKernelGetModuleInternalForKernel.

int sceKernelGetModuleInternalForKernel(SceUID modid, void **module);


Version NID
3.60 0xD4BF409C

Found by Princess


Version NID
3.60 0x20A27FA9
 * @brief Get the main module for a given process.
 * @param pid The process to query.
 * @return the UID of the module else < 0 for an error.
SceUID sceKernelGetProcessMainModuleForKernel(SceUID pid);


Version NID
3.60 0x779A1025

Found by Princess


Version NID
3.60 0x01360661


Version NID
3.60 0x9C838A6B


Version NID
3.60 0xFA21D8CB


Version NID
3.60 0x6DF745D5


Version NID
3.60 0x7BB4CE54


Version NID
3.60 0x5972E2CC


Version NID
1.69-3.60 0x3AD26B43

Was wrongly named sceKernelLoadStartDefaultSharedModulesForPidForKernel.

This loads the default shared modules for a process (only the ones that are actually imported). This includes, for example, SceLibKernel. Modules are loaded with flags 0x10000000 meaning that text pages can be shared. If dipsw 210 is set, then flag 0x1000 is set, meaning that if the existing page is found, do not share it but instead make a copy.

int sceKernelLoadPreloadingModulesForKernel(int pid, void *unk_buf, int flags);


Version NID
0.990-3.60 0xAC4EABDB


Version NID
0.990-3.60 0x0E33258E


Version NID
0.990-1.60 0xF4B2D8B8

Calls sceKernelFreeHeapMemoryForDriver.


Version NID
0.990 0x829E1C94


Version NID
0.990 0x1100A1B8



Version NID
0.990-3.60 0x1D9E0F7E

Calls SceModulemgrForKernel_0053BA4A.


Version NID
0.990-3.60 0x861638AD


Version NID
0.990-3.60 0x0975B104


Version NID
1.69 0x36585DAF
3.60 moved to SceModulemgrForKernel


Version NID
3.60 0xBBE1771C


Version NID
0.940-3.60 0x5182E212


Version NID
1.69 0x912AEB73
3.60 non existent


Version NID
1.69-3.60 0x189BFBBB
int sceKernelLoadStartModuleForDriver(const char *path, SceSize args, void *argp, int flags, SceKernelLMOption *option, int *status);


Version NID
3.60 0x9D953C22
ceUID sceKernelLoadStartModuleForPidForDriver(SceUID pid, const char *path, SceSize args, void *argp, int flags, SceKernelLMOption *option, int *status);


Version NID
3.60 0xE2ADEF8D
SceUID sceKernelLoadStartSharedModuleForPidForDriver(SceUID pid, const char *path, SceSize args, void *argp, int flags, SceKernelLMOption *option, int *status);

sceKernelLoadModuleWithoutStartForDriver / sceKernelLoadModuleForDriver

Version NID
1.69-3.60 0x86D8D634
int opt = 4; // must be set
SceUID sceKernelLoadModuleForDriver(const char *path, int flags, SceKernelLMOption *option);

Returns int modid (to use with sceKernelStartModuleForDriver).


Version NID
1.69-3.60 0x0675B682
// flags must be 0
// opt can be null
int sceKernelStartModuleForDriver(SceUID modid, SceSize args, void *argp, int flags, SceKernelLMOption *option, int *status);


Version NID
1.69-3.60 0x03B30B7E
// flags must be 0
// opt can be null
int sceKernelStopUnloadModuleForDriver(SceUID modid, SceSize args, void *argp, int flags, SceKernelULMOption *option, int *status);


Version NID
3.60 0x49A3EDC7
int sceKernelStopUnloadModuleForPidForDriver(SceUID pid, SceUID modid, SceSize args, void *argp, int flags, SceKernelULMOption *option, int *status);


Version NID
3.60 0x02D3D0C1
int sceKernelStopUnloadSharedModuleForPidForDriver(SceUID pid, SceUID modid, SceSize args, void *argp, int flags, SceKernelULMOption *option, int *status);


Version NID
1.69-3.60 0x100DAEB9
int sceKernelStopModuleForDriver(SceUID modid, SceSize args, void *argp, int flags, SceKernelULMOption *option, int *status);


Version NID
1.69-3.60 0x728E72A6
// flags must be 0
int sceKernelUnloadModuleForDriver(SceUID modid, int flags, SceKernelULMOption *option);



Version NID
1.69 0xA4E6DA4D
3.60 non existent


Version NID
1.69 non existent
3.60 0xB4C5EF9E


Version NID
1.69 non existent
3.60 0x60647592


Version NID
1.69 0x1FD99C9F
3.60 non existent


Version NID
1.69 non existent
3.60 0x72CD301F


Version NID
1.69 0xBA49EA5C
3.60 non existent


Version NID
1.69 non existent
3.60 0x086867A8


Version NID
1.69 non existent
3.60 0x86EAEA0A


Version NID
1.69 0xE439E26B
3.60 non existent


Version NID
1.69 non existent
3.60 0x8E4A7716


Version NID
0.990-1.69 0x9C2A9A49
3.60 non existent


Version NID
1.69 non existent
3.60 0x9D674F45


Version NID
1.69 0x5303C52F
3.60 non existent


Version NID
1.69 non existent
3.60 0x849E78BE


Version NID
0.940-1.69 0x4D76CF9E
3.60 non existent


Version NID
1.69 0x9D2FE122
3.60 non existent


Version NID
0.940-3.60 0x5182E212


Version NID
1.69 0x912AEB73
3.60 non existent


Version NID
1.69-3.60 0x4397FC4E


Version NID
1.69-3.60 0x2EF2581F


Version NID
1.69-3.60 0xF5798C7C


Version NID
1.69-3.60 0x36585DAF


Version NID
1.69-3.60 0xEAEB1312


Version NID
1.69 non existent
3.60 0x85E6D2BB


Version NID
1.69 non existent
3.60 0x6CED1F63

Added somewhere between 3.30 an 3.60 to prevent loading Sysmodules from webbrowser (see Vitasploit 2.00-3.36 and h-encore 3.65-3.68 writeup).



Version NID
0.990-3.60 0x166B9C8C
// a4 size = 0x10
int sceKernelBacktraceForDriver(int a1, int a2, int a3, char* a4);


Version NID
0.990 0xC5608386
3.60 0x7C878F90


Version NID
0.990 0xCECD5584
3.60 0x888E99B8



Version NID
3.60 0xBF371A98

Calls sceKernelBacktraceForDriver.

// a4 size = 0x10
int _sceKernelBacktrace(int a1, int a2, int a3, char* a4);


Version NID
0.990 0x21F00CF2

Calls sceKernelPrintBacktraceForDriver.