2

All,

I have been trying to figure this out for a couple of days now and I need some help.

For a research project for work I have written some custom malware, the malware itself is not the issue here and I won't share any code, but I do need some help on the actual injector.

I have some problems trying to fully understand how and when I need to perform manual relocations. I am not relocating at the moment and using a random address from virtualallocex, and everything just works. My malware exe runs and I have no issues UNLESS the memory location where the remote process PE is loaded at overlaps with my malware PE preferred base address.

I am not using NtUnmapViewOfSection as it gets detected by AntiVirus and basically is just a crap function that randomly doesn't work, so my plan is to just use a random address provided by VirtualAllocEx and relocate if need be (which I don't understand, see questions hereunder).

This is my current working method (unless target process overlaps with preferredbase):

  1. Download malware exe and place in buffer
  2. CreateProcess to start victim process
  3. Suspend the thread right after (I'm not using CREATE_SUSPENDED flag as this does not work in win10)
  4. Get necessary header info from the buffer (PIMAGE_DOS_HEADER, PIMAGE_NT_HEADERS), also get the ImageBase address from remote process PEB
  5. Allocate memory in target process (VirtualAllocEx), using NULL for lpAddress so virtualAllocEx can choose the location
  6. Write PE headers and sections to the memory location
  7. Protect Memory
  8. Change EAX to new entrypoint
  9. Change PEB to new baseAddress
  10. ResumeThread
  11. Profit

So please help me understand the following:

  1. Why does this work without doing any manual relocations, is there some magic PE loader in the background that does this even though I'm injecting?

  2. Why doesn't it work when the target process overlaps with the preferred base address. The PE image itself is copied in a non-overlapping memory location, so how in the hell is that any different from my working solution when the target process doesn't overlap. It should just do the magic relocation thing from my first question.

  3. Why do I see so many people change the preferredBaseAddress in the image before writing it to memory? To my knowledge this field is only used to map PE to their preferredbaseaddress, if they can't do that the PE loader performs the relocations. Seeing as injection code usually performs its own manual relocations I have no idea why they would change this.

Hopefully somebody can help me understand, because this is driving me nuts :).

Best regards!

yannickwe87
  • 105
  • 7
  • All, I created my own relocation code and it works now, but I do have to change the preferredBaseAddress in the image before copying it to memory. Still figuring out why it worked without the relocation code and why I need to change the preferredbase as well as the PEB – yannickwe87 Mar 04 '17 at 14:38

1 Answers1

1

1: It is because of the way assembly code works. Most jmp's are relative to the current address, and thus will work no matter where the code is located. The problems arrise as soon as you want to look up variables / resolve dll import addresses from the IAT. This is because these operations require MOV instructions, and generally compilers will hardcore an address as the source operand for these functions. The problem then is that it will be pointing to some random location, and thus will either result in an access violation / undefined behaviour.

What I think is the case for you, is that both the host process, and the payload, have the same preferred base address. This means that it doesn't fail with an access violation, because there just happens to be some random data at that location.

If you always load the payload at it's preferred base address, you won't need to do manual relocations.

2: Not sure what you mean

3: For normal simple applications, you won't have to change the preferred base address. The problem arrises when your payload needs to access it's relocation table (for example, when deploying a rootkit or w/e). It kind of depends on how the virus was built. There shouldn't be any problems if the preferred base address is compared to the actual base address.

To your CREATE_SUSPENDED problem: I had this exact same problem a few weeks back. It seems that as soon as you resume a thread created with CREATE_SUSPENDED, it overwrites it's registers or w/e. I couldn't figure out why this problem arrises. What you can do to overcome this though, is never resume the main thread at all. Instead, simply create a new thread with CreateRemoteThreadEx.

EDIT: After reading one of your other questions, you actually solved this problem for me. I was changing EIP instead of EAX. I didn't know the PE loader called eax instead of just resuming the code at the instruction pointer.

If you ever need any help with this, HMU. I've done a whole ton of research on malware development, and love to share the knowledge.

user2073973
  • 564
  • 6
  • 21