Patching SceHttp_Library

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

Moderators: cheriff, TyRaNiD

Post Reply
ixalon
Posts: 6
Joined: Mon Jul 17, 2006 11:39 pm

Patching SceHttp_Library

Post by ixalon »

Hi guys,

I'm pulling my hair out trying to patch an export in SceHttp_Library (libhttp.prx) from a kernel mode PRX.

libhttp.prx loads, I run through the nidtable and replace the function pointer with one to my PRX's version. All seems good.

However, when I fire up VSH and try the internet browser, it just displays the 'busy' blob for a few seconds and I'm just left in the XMB with no exceptions being shown over psplink

Anyone know what's going on? The trigger for this seems loading libhttp.prx as even when I don't patch its exports the same thing happens. If I don't load libhttp.prx the browser opens correctly.

Hope someone can enlighten me to my probably silly mistake!
Chris

Code: Select all

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <stdio.h>
#include <string.h>

#include "libs.h"

PSP_MODULE_INFO&#40;"httppatch", PSP_MODULE_KERNEL, 1, 1&#41;;
	
void Debug&#40;char *msg&#41; &#123;
	printf&#40;msg&#41;;
	int hFile;
	hFile = sceIoOpen&#40;"ms0&#58;/debug.txt", PSP_O_CREAT|PSP_O_APPEND|PSP_O_WRONLY, 0777&#41;;
	sceIoWrite&#40;hFile, msg,  sizeof&#40;msg&#41;&#41;;
	sceIoClose&#40;hFile&#41;; 
&#125;
int snprintf&#40;char *a, size_t b, const char * c, ...&#41; &#123;
	return 0;
&#125;

typedef int &#40;*sceHttpCreateTemplate_Delegate&#41;&#40;char *agent, int unknown1, int unknown2&#41;;
sceHttpCreateTemplate_Delegate sceHttpCreateTemplate_Orig = 0;
int ixHttpCreateTemplate&#40;char *agent, int unknown1, int unknown2&#41;
&#123;
	char buf&#91;100&#93;;
	sprintf&#40;buf, "sceHttpCreateTemplate&#40;%s, %d, %d&#41;\n", agent, unknown1, unknown2&#41;;
	Debug&#40;buf&#41;;
	return &#40;*sceHttpCreateTemplate_Orig&#41;&#40;agent, unknown1, unknown2&#41;;
&#125;

void* patchNIDTable&#40;SceModule *mod, char* lib, char* func, void *newProcAddr&#41; &#123;

	u32* ent_next = &#40;u32*&#41;mod->ent_top;
	u32* ent_end = &#40;u32*&#41;mod->ent_top + &#40;mod->ent_size >> 2&#41;;
	u32 nid = libsNameToNid&#40;func&#41;;

	while &#40;ent_next < ent_end&#41;
	&#123;
		SceLibraryEntryTable* ent = &#40;SceLibraryEntryTable*&#41;ent_next;
		if &#40;ent->libname && strcmp&#40;ent->libname, lib&#41; == 0&#41;
		&#123;
			int count = ent->stubcount + ent->vstubcount;
			u32* nidtable = &#40;u32*&#41;ent->entrytable;
			int i;
			for &#40;i = 0; i < count; i++&#41;
			&#123;
				if &#40;nidtable&#91;i&#93; == nid&#41;
				&#123;
					u32* procAddr =&#40;u32*&#41;nidtable&#91;count+i&#93;;
					if &#40;newProcAddr&#41; &#123;
						nidtable&#91;count+i&#93; = &#40;u32&#41;newProcAddr;
					&#125;
					return procAddr;
				&#125;
			&#125;
			return 0;
		&#125;
		ent_next += ent->len; // len in 32-bit words.
	&#125;
	return 0;
&#125;

void LoadAndStart&#40;char *lib, int w&#41; &#123;
	printf&#40;"Loading and starting %s... ", lib&#41;;
	int result = pspSdkLoadStartModule&#40;lib, w&#41;;
	printf&#40;"Done &#40;%08x&#41;\n", result&#41;;
&#125;
int main_thread&#40;SceSize args, void *argp&#41;
&#123;	
	sceKernelDelayThread&#40;10*100000&#41;;
	printf&#40;"main_thread running...\n"&#41;;	

	// load libraries
	//pspSdkInstallKernelLoadModulePatch&#40;&#41;; // causes crash
	pspSdkInstallNoDeviceCheckPatch&#40;&#41;;
	pspSdkInstallNoPlainModuleCheckPatch&#40;&#41;;

	printf&#40;"loading libs...\n"&#41;;	
	
	LoadAndStart&#40;"flash0&#58;/kd/ifhandle.prx", PSP_MEMORY_PARTITION_KERNEL&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/pspnet.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/pspnet_inet.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/pspnet_apctl.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/pspnet_resolver.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/libparse_uri.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/libparse_http.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/libhttp.prx", PSP_MEMORY_PARTITION_USER&#41;;
	
	// Hook function function
	SceModule *mod;
	mod = sceKernelFindModuleByName&#40;"SceHttp_Library"&#41;;
	if&#40;mod&#41; &#123;
		printf&#40;"found SceHttp_Library module - %d\r\n", mod->modid&#41;;		
		sceHttpCreateTemplate_Orig = patchNIDTable&#40;mod, "sceHttp", "sceHttpCreateTemplate", ixHttpCreateTemplate&#41;;
		if&#40;sceHttpCreateTemplate_Orig == 0&#41; &#123;
			printf&#40;"Could not hook sceHttpCreateTemplate function\n"&#41;;
			sceKernelTerminateDeleteThread&#40;0&#41;;
			sceKernelExitDeleteThread&#40;0&#41;;
		&#125;
		printf&#40;"patched old sceHttpCreateTemplate at %p with %p\r\n", &#40;u32&#41;sceHttpCreateTemplate_Orig, &#40;u32&#41;ixHttpCreateTemplate&#41;;
	&#125; else &#123;
		printf&#40;"SceHttp_Library module not found\r\n"&#41;;
	&#125;	
	
	sceKernelExitDeleteThread&#40;0&#41;;	
	return 0;
&#125;

/* Entry point */
int module_start&#40;SceSize args, void *argp&#41;
&#123;	
	int thid;
 	thid = sceKernelCreateThread&#40;"httppatch", main_thread,  0x18, 0x10000, 0, NULL&#41;;
	if&#40;thid >= 0&#41;
	&#123;
		sceKernelStartThread&#40;thid, args, argp&#41;;
	&#125;
	return 0;
&#125;

/* Module stop entry */
int module_stop&#40;SceSize args, void *argp&#41;
&#123;
	return 0;
&#125;
Running the above gives:

Code: Select all

loading libs...
Loading and starting flash0&#58;/kd/ifhandle.prx... Done &#40;04ff8973&#41;
Loading and starting flash0&#58;/kd/pspnet.prx... Done &#40;04ff4f0b&#41;
Loading and starting flash0&#58;/kd/pspnet_inet.prx... Done &#40;04ff0421&#41;
Loading and starting flash0&#58;/kd/pspnet_apctl.prx... Done &#40;04fee435&#41;
Loading and starting flash0&#58;/kd/pspnet_resolver.prx... Done &#40;04fec449&#41;
Loading and starting flash0&#58;/kd/libparse_uri.prx... Done &#40;04fe8e5d&#41;
Loading and starting flash0&#58;/kd/libparse_http.prx... Done &#40;04fe6a71&#41;
Loading and starting flash0&#58;/kd/libhttp.prx... Done &#40;04fe3305&#41;
found SceHttp_Library module - 83768069
patched old sceHttpCreateTemplate at 9cbe388 with 8827d43c
moonlight
Posts: 567
Joined: Wed Oct 26, 2005 7:46 pm

Post by moonlight »

You are patching a user2user export to a kernel function!

That causes user code to jump to kernel code, and that's not allowed.
ixalon
Posts: 6
Joined: Mon Jul 17, 2006 11:39 pm

Post by ixalon »

Thanks moonlight... Knew I'd have made a glaringly simple error!

Still having problems though - stripping out all the nid table patching, if I do nothing more than load libhttp.prx in anything (kernel mode or user mode PRX) then the browser won't start.

e.g.

Code: Select all

...
PSP_MODULE_INFO&#40;"httppatch", 0, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;THREAD_ATTR_USER&#41;;
...
int main&#40;SceSize args, void *argp&#41;
&#123;	
	LoadAndStart&#40;"flash0&#58;/kd/ifhandle.prx", PSP_MEMORY_PARTITION_KERNEL&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/pspnet.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/pspnet_inet.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/pspnet_apctl.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/pspnet_resolver.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/libparse_uri.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/libparse_http.prx", PSP_MEMORY_PARTITION_USER&#41;;
	LoadAndStart&#40;"flash0&#58;/kd/libhttp.prx", PSP_MEMORY_PARTITION_USER&#41;;
	
	sceKernelExitThread&#40;0&#41;;
	return 0;
&#125;
moonlight
Posts: 567
Joined: Wed Oct 26, 2005 7:46 pm

Post by moonlight »

probably vsh will try to load those modules by itself, and since you have loaded them, they will return the exclusive load error to the vsh module calling the loadmodule function, and it will abort the browser load.
ixalon
Posts: 6
Joined: Mon Jul 17, 2006 11:39 pm

Post by ixalon »

Ack! :(

Is there any way to patch usermode library functions in a way that built-in VSH plugins use the patched versions?

Could I patch sceKernelLoadModule and all its variants to ignore exclusive load errors and just return the module id of the already loaded module? Or could I patch it to check for attempts to load flash0:/kd/libhttp.prx and redirect it towards say ms0:/mypatched_libhttp.prx
moonlight
Posts: 567
Joined: Wed Oct 26, 2005 7:46 pm

Post by moonlight »

Yes, i guess you can patch loadmodule to fake results, don't forget to patch startmodule too if necessary.

In case of loadmodule, you have to patch the user import, not the kernel import, that despites having same name is a different function. You may have to patch too sceKernelLoadModuleVSH, but I don't think those net modules are loaded with that function, but you never know.
Post Reply