Advertising (This ad goes away for registered users. You can Login or Register)

Understanding HBL inner workings (I)

This is the development forum of the half-byte loader project. For general Half Byte Loader questions, visit the Half Byte Loader forum.
Forum rules
This forum is for HBL Development discussions ONLY. For User support or HBL general discussions, go to viewforum.php?f=3 . Messages that are not development related will be deleted.
Locked
m0skit0
Guru
Posts: 3817
Joined: Mon Sep 27, 2010 6:01 pm

Understanding HBL inner workings (I)

Post by m0skit0 »

Since I'm stuck with fever at home and have nothing better to do, I'll start this topic about how HBL works. I'll be referencing latest revision at this time, r116. You can browse the code online here.

NOTE: this is not a C course, so please do not ask C-specific questions. Those can be answered in any decent C book.

First of all, HBL is not a normal homebrew. Since it was aimed to be run through a game exploit, it's designed to be compiled as a plain binary (hbl.bin). It's not an ELF and thus it's not a PRX. Not an EBOOT either. HBL is injected into memory when loading the exploit, ends up in main memory and finally gets executing. Since HBL is way too big to fit inside an exploit, we choose to do a double loading scheme: first the exploit loads a loader which in turn loads HBL in memory. I'll take a tour into HBL's loader in this chapter.

The HBL loader is mainly the file loader.c. Let's take a walk through it. The loader entry point is

Code: Select all

void _start() __attribute__ ((section (".text.start")));
The attribute defines this function to be first on the generated binary code.

The rest of the function is pretty well commented to be self-explanatory, except this part

Code: Select all

	if ((hbl_file = sceIoOpen(HBL_PATH, PSP_O_RDONLY, 0777)) < 0)
		exit_with_log(" FAILED TO LOAD HBL ", &hbl_file, sizeof(hbl_file));
	
	else
	{
		LOGSTR0("Loading HBL\n");
		load_hbl(hbl_file);
	
		LOGSTR0("Copying & resolving HBL stubs\n");
		copy_hbl_stubs();
        LOGSTR0("HBL stubs copied, running eLoader\n");
		run_eloader(0, NULL);
	}

	while(1)
		sceKernelDelayThread(100000);
So here we first open the HBL binary (hbl.bin) which path defined by the HBL_PATH macro. If we take a look at that macro, we'll find that it actually maps to ms0:/hbl/hbl.bin. So if this file opening succeeds, next we need to load it, which is what load_hbl function performs.

Code: Select all

tGlobals * g = get_globals();
I'm going to explain this line since it happens a lot in HBL. The HBL global variables are stored on the scratchpad (a small 4 KiB RAM). load_hbl is going to store some values there so they can be used later by HBL. Then we get HBL file size, we allocate memory with that size and then this line:

Code: Select all

run_eloader = sceKernelGetBlockHeadAddr(HBL_block);
Gets the allocated memory starting address. Keep in mind that sceKernelAllocPartitionMemory does not return a pointer (= memory address) but an SceUID (an 32-bits ID used by the kernel to identify system objects). Then we assign that address to run_eloader, which in fact is a pointer to a function. This function is called later to run HBL. This works because HBL's entry point is put at the start of the binary file, which is the same we did with the loader's entry point (void _start() __attribute__ ((section (".text.start")))).

The rest of the function is pretty well commented and self-explanatory. So when load_hbl ends executing, it's copy_hbl_stubs that comes next. This function resolves HBL imports. And what does this mean? It means it has to prepare HBL so it can execute system calls such as sceWhatever. When loaded HBL will not know where to find such calls, and the loader has to prepare it with a minimum so it can work on its own.

copy_hbl_stubs accesses a configuration file that stores information about HBL's imports, and where you can find the exploited game's stubs (system calls) among other stuff. You can easily follow the function since with all the comments and debugs it's self-explanatory. It first reads the location of the exploited game's stubs and compare them to HBL's stubs. If they match, the address of that stub is stored. Then it writes the resolved stubs to HBL's stubs (which are also stored into the scratchpad).

When copy_hbl_stubs ends run_eloader is next. As we saw before this transfers control to the hbl.bin file which starts HBL execution.

So this is all for now, hope you find it interesting. Any questions are welcome. On the next one I'll begin with the HBL proper.
Advertising
I wanna lots of mov al,0xb
Image
"just not into this RA stuffz"
wololo
Site Admin
Posts: 3621
Joined: Wed Oct 15, 2008 12:42 am
Location: Japan

Re: Understanding HBL inner workings (I)

Post by wololo »

Thanks. Despite working a lot on HBL, I feel it's very nice to remember how it works with a clear explanation rather than looking directly at the code.
Easy to understand and very detailed tutorial as usual, looking forward to the next one :)
Advertising
If you need US PSN Codes, this technique is what I recommend.

Looking for guest bloggers and news hunters here at wololo.net, PM me!
m0skit0
Guru
Posts: 3817
Joined: Mon Sep 27, 2010 6:01 pm

Re: Understanding HBL inner workings (I)

Post by m0skit0 »

Thanks for the cheering mate :lol:
I wanna lots of mov al,0xb
Image
"just not into this RA stuffz"
Locked

Return to “Half Byte Loader Development”