SDK initialization

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

SDK initialization

Post by m0skit0 »

Hi again everybody!

I've managed to run non-signed ELFs from the MoHH exploit by kgsws.

But I ran into a problem: the ELF execute properly (at least very simple ones) if it doesn't include the SDK initialization (when I manually code module_start(), create a new thread running main(), specify PSP_NO_MAIN_THREAD() macro, and of course I include necessary linking flags on the Makefile), but it does absolutely nothing if the SDK initialization is present (the screen keeps blank). Any ideas?

I already sought some people's help, but they really had no clue xD If you need the code I'm using or any reference I'll post it, just ask me.

Thanks a lot!
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

What code are you using? You need to place all sections to the right addresses, resolve stubs, THEN jump to the start of text section (0x0890000).
Can you post your code?

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

Post by m0skit0 »

Yes, I do that, otherwise I wouldn't be able to run a thing, wouldn't I? :P
You need to place all sections to the right addresses
Not ALL the sections. Only those marked as "must be allocated". And I think those are all in program section to make the loading faster (at least that's what the ELF standard paper I read said), so loading program section in the right address will suffice. Correct me if I'm wrong, but that way it works (partially as I said).
resolve stubs
Done. I get the stubs resolved from MoHH in a table and then load the program section from the ELF, locate the .lib.stub section and resolve the stubs. Of course, I can only resolve imports included in MoHH because they don't use fixed addresses or fixed syscalls numbers. If someone knows how can I get around this without accessing kernel mode, I'm all ears :D
THEN jump to the start of text section (0x0890000)
The entry point is specified by the ELF header, it's not a fixed address (although in PSP it's always the same, but just for safety I use the one specified in the ELF header). Btw, it's not 0x08900000 (you forgot a zero there :D), but 0x8900048 if I remember well (_start or module_start())

Here's the code; only the main function for brevity. If you need details about some function or data structure, just ask me I'll post it.

Code: Select all

tNIDResolver nid_table&#91;NID_TABLE_SIZE&#93;;

/* eloader entry point */
void start_eloader&#40;char *eboot_path&#41;
&#123;
	unsigned int num_nids, stubs_size, stubs_resolved;	
	tStubEntry* pstub_entry;		
	SceUID elf_file;
	unsigned int elf_size;
	Elf32_Ehdr elf_header;

	#ifdef DEBUG
		dbglog = sceIoOpen&#40;DEBUG_PATH, PSP_O_CREAT | PSP_O_WRONLY, 0777&#41;;
	#endif

	/* Extract resolved imports from game */
	if&#40;num_nids = build_nid_table&#40;&#40;tStubEntry *&#41; MOHH_LIBSTUB_ADDRESS, nid_table&#41;&#41;
	&#123;		
		/* Open ELF */
		elf_file = sceIoOpen&#40;eboot_path, PSP_O_RDONLY, 0777&#41;;

		/* Read ELF header */
		sceIoRead&#40;elf_file, &elf_header, sizeof&#40;Elf32_Ehdr&#41;&#41;;			
		
		/* Load ELF program section into memory */
		elf_size = elf_load_program&#40;elf_file, &elf_header&#41;;

		/* Locate ELF's .lib.stubs section */
		stubs_size = elf_find_imports&#40;elf_file, &elf_header, &pstub_entry&#41;;		
		
		/* Resolve ELF's stubs with game's stubs */
		stubs_resolved = resolve_imports&#40;pstub_entry, stubs_size, nid_table&#41;;
		
		/* No need for ELF file anymore */
		sceIoClose&#40;elf_file&#41;;

		/* Commit changes to RAM */
		sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
		
		/* Go for ELF! */
		execute_elf&#40;&#40;u32 *&#41;elf_header.e_entry&#41;;
	&#125;
	
	#ifdef DEBUG
		sceIoClose&#40;dbglog&#41;;
	#endif
&#125;
A few comments about the code:
  • I'm just considering static ELFs, not PRXs (by now). Just to simplify. If statics work, then relocation should be easy and would work without much problem (I hope xD)
  • I'm using fixed-size data structures because malloc() didn't work with the exploit's SDK. I didn't try to make it work neither. I'll check that later, it's just optimization.
  • Code is not optimized, just the first thought I got about it.
  • The aim is of course getting an EBOOT.PBP instead of an ELF. But I think that if I get the ELFs to work, extracting them from PBPs will be fairly easy.
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

Take a look at pspsdk/src/startup/crt0.c. That's the crt0 (initialization code) for ELF. try to use it in your application and check if it works. if it doesn't, try commenting out some things until it works. Then you'll know what prevent the ELF from loading.

EDIT: You said malloc doesn't work. Maybe it's a libc problem, in fact crt0 does some lib calls. have you tried the following in the Makefile of the elf?

Code: Select all

USE_KERNEL_LIBC = 1
USE_KERNEL_LIBS = 1
also try PSP_NO_CREATE_MAIN_THREAD().

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

Post by m0skit0 »

also try PSP_NO_CREATE_MAIN_THREAD().
I already said that the ELF execute if I put this macro :)

Thanks for the ideas, I'll try and report any news.
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

m0skit0 wrote:
also try PSP_NO_CREATE_MAIN_THREAD().
I already said that the ELF execute if I put this macro :)

Thanks for the ideas, I'll try and report any news.
you said:
m0skit0 wrote:when I manually code module_start(), create a new thread running main(), specify PSP_NO_MAIN_THREAD() macro, and of course I include necessary linking flags on the Makefile
i mean to use ONLY PSP_NO_MAIN_THREAD, without manually coding _start.

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

Post by m0skit0 »

Then you got an error: "module_start" not found :P
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

m0skit0 wrote:Then you got an error: "module_start" not found :P
ehhh??? but it's very strange!
from crt0.c:

Code: Select all

/**
 * Startup thread
 *
 * Creates the main program thread based on variables defined by the program.
 *
 * @param args - Size &#40;in bytes&#41; of arguments passed to the program by the kernel.
 * @param argp - Pointer to arguments passed by the kernel.
 */
int _start&#40;SceSize args, void *argp&#41;
&#123;
	void &#40;*_main_func&#41;&#40;SceSize args, void *argp&#41; = _main;
	void &#40;*_init_func&#41;&#40;void&#41; = _init;

	if &#40;&#40;&module_info != NULL&#41; && &#40;module_info.modattribute & 0x1000&#41;&#41; &#123;
		/* If we're running in kernel mode, the addresses of our _main&#40;&#41; thread
		   and _init&#40;&#41; function must also reside in kernel mode. */
		_main_func = &#40;void *&#41; &#40;&#40;u32&#41; _main_func | 0x80000000&#41;;
		_init_func = &#40;void *&#41; &#40;&#40;u32&#41; _init_func | 0x80000000&#41;;
	&#125;

	/* Call _init&#40;&#41; here, because an app may have code that needs to run in
	   kernel mode, but want their main&#40;&#41; thread to run in user mode.  If they
	   define "constructors" they can do any kernel mode initialization here
	   before their app is switched. */
	_init_func&#40;&#41;;

	if &#40;&sce_newlib_nocreate_thread_in_start != NULL&#41; &#123;
		/* The program does not want main&#40;&#41; to be run in a seperate thread. */
		_main_func&#40;args, argp&#41;;
		return 1;
	&#125;

	int priority = DEFAULT_THREAD_PRIORITY;
	unsigned int attribute = DEFAULT_THREAD_ATTRIBUTE;
	unsigned int stackSize = DEFAULT_THREAD_STACK_KB_SIZE * 1024;
	const char *threadName = DEFAULT_MAIN_THREAD_NAME;

	if &#40;&sce_newlib_priority != NULL&#41; &#123;
		priority = sce_newlib_priority;
	&#125;
	if &#40;&sce_newlib_attribute != NULL&#41; &#123;
		attribute = sce_newlib_attribute;
	&#125;
	if &#40;&sce_newlib_stack_kb_size != NULL&#41; &#123;
		stackSize = sce_newlib_stack_kb_size * 1024;
	&#125;
	if &#40;&sce_newlib_main_thread_name != NULL&#41; &#123;
		threadName = sce_newlib_main_thread_name;
	&#125;

	/* Does the _main&#40;&#41; thread belong to the User, VSH, or USB/WLAN APIs? */
	if &#40;attribute & &#40;PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_USBWLAN | PSP_THREAD_ATTR_VSH&#41;&#41; &#123;
		/* Remove the kernel mode addressing from the pointer to _main&#40;&#41;. */
		_main_func = &#40;void *&#41; &#40;&#40;u32&#41; _main_func & 0x7fffffff&#41;;
	&#125;

	SceUID thid;
	thid = sceKernelCreateThread&#40;threadName, &#40;void *&#41; _main_func, priority, stackSize, attribute, 0&#41;;
	sceKernelStartThread&#40;thid, args, argp&#41;;

	return 0;
&#125;
PSP_NO_CREATE_MAIN_THREAD is defined as:

Code: Select all

  #define PSP_NO_CREATE_MAIN_THREAD  	&#40;  	  	 &#41;   	   int sce_newlib_nocreate_thread_in_start = 1
so _start is still defined if PSP_NO_CREATE_MAIN_THREAD is used.
module_start is only an alias to _start, but it's defined ONLY when building prx (see crt0_prx.c). are you sure you aren't building with BUILD_PRX=1??? it seems strange to me...

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

Post by m0skit0 »

Ok, my mistake, I apologize! When I have some time I'll try playing with crt0.c to see what my ELF loader doesn't like from here. I'll answer as soon as I get some answers :)
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

Post by m0skit0 »

Can you give me some advice about why the modifications in crt0.c doesn't affect at all? I mean, I modify that file but that seems not to affect the initialization code in my app. How can I do to test a modified crt0.c?

Sorry for the n00bishness :P
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

m0skit0 wrote:Can you give me some advice about why the modifications in crt0.c doesn't affect at all? I mean, I modify that file but that seems not to affect the initialization code in my app. How can I do to test a modified crt0.c?

Sorry for the n00bishness :P
you'll have modify it from the pspsdk source, recompile pspsdk and try.
you can also include crt0.c in your application, then use -mno-crt0 in your makefile to tell the compiler to not include crt0.

EDIT: There's a third way. take pspsdk source, modfiy crt0, make (only startup directory). copy crt0.o in your pspsdk and try...

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

BTW, take a look at this message: http://forums.ps2dev.org/viewtopic.php?p=26585#26585

to jump to text segment, don't use j/jr, use jal or when crt0 exits it'll return to $ra, but $ra doesn't point to the end of your loader code, and it'll crash!!! :)

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

Post by m0skit0 »

Thanks for pointing out that link, very useful. I don't know I've not visited it earlier :P

The fact is that it seems that default stack allocation by SDK initialization is the problem. If I down the 256 KB reserved by default, it do work. So I'm considering freeing the MoHH reserved memory, but sincerly I've never used dynamic allocation on PSP. Which functions should I use? sceKernelAllocPartitionMemory() and the like? Any useful info about how to use such functions?

Thanks!
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

m0skit0 wrote:Thanks for pointing out that link, very useful. I don't know I've not visited it earlier :P

The fact is that it seems that default stack allocation by SDK initialization is the problem. If I down the 256 KB reserved by default, it do work. So I'm considering freeing the MoHH reserved memory, but sincerly I've never used dynamic allocation on PSP. Which functions should I use? sceKernelAllocPartitionMemory() and the like? Any useful info about how to use such functions?

Thanks!
I suggest you to dump all the UIDs for allocated memory blocks, so you'll see what's allocated by MoHH. But you can't do that in usermode, so we need to find another way. I suggest you to reverse MoHH, find the exitcallback registration function, reverse the exit callback and see what it does to free memory. That way you can free MoHH memory and get memory for your homebrew.

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
m0skit0
Posts: 191
Joined: Tue Jun 02, 2009 8:58 pm

Post by m0skit0 »

Yes, that's exactly what i'm doing right now :)
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

BTW, can you send me a PM with the source code of your loader? i'm very interested :)

Thanks!

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
Post Reply