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

[Eloader] 6. Resolving stubs

Forum rules
Forum rule Nº 15 is strictly enforced in this subforum.
Post Reply
User avatar
Posts: 3817
Joined: Mon Sep 27, 2010 6:01 pm

[Eloader] 6. Resolving stubs

Post by m0skit0 » Mon Sep 27, 2010 2:43 pm

Originally posted by m0skit0 on

So now we know what a stub is, and also how it looks like. Time to see how we can resolve the stubs for the ELF program we already loaded.

To do this, we can simply use the game's already resolved imports and subtitute the right stub with the right call from the game's stubs. To do this, I would first backup all game's stubs in a data structure, so we don't lost them if they're going to be overwritten by the homebrew ELF we loaded. So, as I said, first we need to backup the game's stubs before loading the ELF program section. This can easily be done using the information I gave on the previous chapter.

I personally prefer saving memory and not include the whole stubs, but only the effective call associated with a NID. For example this struct:

Code: Select all

// Struct holding all NIDs imported by the game and their respective jump/syscalls
typedef struct
   u32 nid;   // NID
   u32 call;   // Syscall/jump associated to the NID
} tNIDResolver;
Here I will store the function NID and its real call, that is, the jump instruction if it's a user mode system call, or the syscall if it's a kernel mode system call. This way I only need half the size of the stubs, as the other instruction needed for each system call mode is always the same (nop for user mode, jr $ra for kernel mode). The little problem with this approach is knowing when to take first instruction as real call (user mode) or the second one (kernel mode). Here a refresh about user/kernel mode system calls:

User mode system call:

Code: Select all

   0x08C92974: 0x0A200020 ' . .' - j          loc_08800080
   0x08C92978: 0x00000000 '....' - nop 
Kernel mode system call:

Code: Select all

   0x08C92984: 0x03E00008 '....' - jr         $ra
   0x08C92988: 0x00088A8C '....' - syscall    0x222A
This can easily be solved by bitwise checking the stub's first instruction:

Code: Select all

#define SYSCALL_MASK_IMPORT 0x01000000

// Return real instruction that makes the system call (jump or syscall)
u32 get_good_call(u32* call_pointer)
   // Dirty hack here but works
   if(*call_pointer & SYSCALL_MASK_IMPORT)
   return *call_pointer;
This function receives a pointer to the stub. You can see that *call_pointer & SYSCALL_MASK_IMPORT in fact checks if the bit 24 is set (thus the instruction is a JR) or reset (thus the instruction is a J). So if the first stub instruction is a JR, we need to take the stub's second instruction (the syscall), else we just return the first one (the jump). Then just store the effective call on the tNIDResolver data structure.

To resolve the ELF stubs, we just do the inverse process: check the effective call we have on the tNIDResolver data structure, then recreate the stub's missing instruction. Here's an example:

Code: Select all

#define JR_RA_OPCODE 0x03E00008

#define NOP_OPCODE 0x00000000

/* Subsitutes the right instruction */
void resolve_call(u32 *call_to_resolve, u32 call_resolved)
   /* SYSCALL */
   if(!(call_resolved & SYSCALL_MASK_RESOLVE))
      *call_to_resolve = JR_RA_OPCODE;
      *(++call_to_resolve) = call_resolved;

   /* JUMP */
      *call_to_resolve = call_resolved;
      *(++call_to_resolve) = NOP_OPCODE;
But as some of you may have noticed, this will only allow us to resolve the ELF imports that are also the game's imports... But what if the ELF imports are not the same? What if there's an ELF import that is not imported by the game? Well, that's another matter, maybe I shall discuss a solution to this problem later :mrgreen:
I wanna lots of mov al,0xb
"just not into this RA stuffz"

Posts: 111
Joined: Mon Sep 27, 2010 4:35 pm

Re: [Eloader] 6. Resolving stubs

Post by tbg » Tue Sep 28, 2010 8:32 am

Translated into Spanish...
TBG : Team Extraction member

Post Reply

Return to “Programming and Security”