Backdooring Portable Executables

Prepping for OSCE, lots of shellcoding and debugging going on. Shellcoding is particularly frustrating today so to change gears for a bit I’m going to write up backdooring PEs. Examples are x86, tested on Windows XP SP3, using the x86 putty executable available here. I also used Stud_PE, Immunity Debugger, and a great blog post over at Sector876 that helped me get the basics down. There’s a couple of different methods, let’s start with the first, we’ll add a section.

First, let’s start by opening the program in Stud_PE. Select the Sections tab and you can see all of the sections present in the executable. Right click and choose “New Section” and adjust the size. Ensure you’ve added enough space to fit your shellcode in, and select the option to fill the space with null bytes. After you save, run the executable to ensure it still functions and nothing is broken.

adding a section with Stud_PE

Open the executable in the debugger and inspect the sections, in Immunity this is easily found in the Memory Map tab. If you inspect the section, you should find it filled with null bytes. Note the memory address that the section starts at, in this instance we see 0x004c3000.

our new section, all filled with nulls

We will need to redirect program execution to this address, where we will eventually put shellcode. For now, note the existing instructions at the program’s entry point. We will need these for redirecting back to normal execution for the program.

our initial instructions

After saving these addresses, it is time to redirect execution. In Immunity we do this by right clicking the instruction and selecting Assemble, then inputting our jump instruction. We want to jump to 0x004c3000 in this case.

assembling our jmp instruction

After assembling the instruction should update in the debugger to exactly what we need.

jmp to…

Hit F7 in Immunity to move to the next instruction and you should see the new section we added, filled with nulls.

nulls, nulls everywhere

The first thing that should be done at this point is to save the executable. After saving, in the new section overwrite the first two instructions with PUSHAD and PUSHFD instructions. This saves the program state before we pass it our shellcode. Press F7 twice to move ahead and then note the location of ESP. We will need this location after the shellcode to adjust the stack prior to normal program execution. In this instance, ESP is at 0x0012FFA0 following the two instructions added.

ready for shellcode now

Use msfvenom to create shellcode. In this instance we’re creating a reverse tcp shell for Windows in hex format, no bad chars specified. In Immunity, this is placed in the executable by selecting enough memory locations to hold our shellcode starting with the instruction following the PUSHFD, then right clicking and performing a binary paste.

generating shellcode

Once the shellcode is pasted in, place a breakpoint on the last instruction of the shellcode and press F9 to continue execution. Note that if the shellcode is a reverse shell, unless you have a listener set up it will take execution off into an exception, and that you’ll have to close the listener to hit your breakpoint. Once at the breakpoint, note the address at ESP. In this case it is 0x0012fd9c.

ESP location after shellcode execution

The determine the ESP offset, we subtract the initial ESP value from the ending value, so 12ffa0 – 12fd9c, and our offset is 0x204. in order to get ESP back where it belongs for normal program execution, we need to add 0x204 to ESP, so we right click the instruction immediately following the shellcode and input ADD ESP, 0x204. The next two instructions should be POPFD followed by POPAD to resume the program’s saved state from before the shellcode.

Perfect! Or was it…

At this point, it doesn’t work. You get your shell, the program doesn’t open, you close your shell, the program crashes. Frustrating. What we want is for the program to open and for you to get your shell at the same time. And for it to not crash when we close out of our shell. First things first. The opening issue has already been solved for us.

The offending code

So we found it. It’s near the bottom, in the blog linked above he links to the metasploit github where you can find it for yourself. So we update it…

Easy enough

Still not quite right though, normal program execution doesn’t happen. Over at the metasploit github page, you can view the code for the exitfunc portion. This code is appended to the end of your msfvenom-generated code even if you choose EXITFUNC=none, right at the end. Check out this part is particular:

very last line of your shellcode

If you trace it in the debugger, your shellcode calls EBP which takes it off back into the shellcode and eventually out into ntdll.KiFastSystemCallRet which… ok, turning into a rabbit hole. Researching this, figuring out why it is doing this, is a priority. But for right now, quick and dirty, oh so dirty, just overwrite that call with NOPs and it works.

this is a gross solution and I should feel bad…

On the agenda is creating a backdoor using existing null space within the application and figuring out this business with the EXITFUNC in msfvenom.

program’s running…
shell’s working… it’s still gross though