I'm trying to understand the exploit for SLMail 5.5.

Here is the basic flow :

  1. I'm able to control EIP and point to an instruction "JMP ESP"
  2. ESP is pointing to the exact start position of my shellcode. (Shell code is encoded with shikata_ga_nai encoder in msfvenom)
  3. As ESP is pointing to the exact location which I want, I feel I don't think nop slide is required.But i'm seeing wired results when nop is not used.I hope some can shed some light on this.

4) Below are the first few instructions that my shellcode has without NOP slide, as soon as the highlighted weird instruction is executed, the instructions in the memory are getting changed (So weird!!)

0159A128   BF A849F49D      MOV EDI,9DF449A8
0159A12D   D9E5             FXAM
0159A12F   D97424 F4        FSTENV (28-BYTE) PTR SS:[ESP-C] <-- Weird instruction
0159A133   5B               POP EBX
0159A134   33C9             XOR ECX,ECX
0159A136   B1 52            MOV CL,52
0159A138   317B 12          XOR DWORD PTR DS:[EBX+12],EDI
0159A13B   83EB FC          SUB EBX,-4
0159A13E   03D3             ADD EDX,EBX

My memory looks this after the execution of the highlighted instruction:

0159A12F   0100             ADD DWORD PTR DS:[EAX],EAX
0159A131   0000             ADD BYTE PTR DS:[EAX],AL
0159A133   0000             ADD BYTE PTR DS:[EAX],AL <--Jumping here after the weird instruction
0159A135   00FF             ADD BH,BH
0159A137   FF31             PUSH DWORD PTR DS:[ECX]
0159A139   7B 12            JPO SHORT 0159A14D
0159A13B   83EB FC          SUB EBX,-4
0159A13E   03D3             ADD EDX,EBX

But with NOP slide appended to the shellcode, the below instruction which is actually in the line of execution gets excuted weithouit any hassle and making the exploit to work....

0159A133   5B               POP EBX

Can anyone explain why I need NOP slide to stop this weird behavior. Thank You.

  • why did you put FSTENV in your shellcode? – Igor Skochinsky Jul 2 '17 at 9:11
  • oh, you used the encoder. I guess it screwed up somehow. – Igor Skochinsky Jul 2 '17 at 9:12

Let's look up what the "weird instruction" does:

Saves the current FPU operating environment at the memory location specified with the destination operand, and then masks all floating-point exceptions. The FPU operating environment consists of the FPU control word, status word, tag word, instruction pointer, data pointer, and last opcode

In our case, the destination is ESP-C, which is 12 bytes before the start of the code (if code starts at ESP). Since the FPU state is 28 bytes, it goes further and overwrites the beginning of shellcode with the FPU values. If you add a NOP sled, the sled gets overwritten which has no effect because it won't be executed again. Without the sled, the currently executing instructions are overwritten which breaks the shellcode.

Apparently FSTENV is used as a part of the "getpc" primitive (one of the values stored is the current EIP) and it requires some stack space for the environment. So you need to ensure that either you have free space around ESP or add a NOP sled for padding. Or you can try modifying the encoder to use a more common call $+5/pop ebx sequence which would overwrite only one dword at ESP.

  • Had to log in to upvote this. Nice observation. – shebaw Jul 5 '17 at 19:38
  • the technique is described in the "Shellgames" presentation on my site. [esp-0c] allows a pop instruction to be used to return EIP in the popped register. However, you need the stack pointer to be far enough from the code to avoid being overwritten. – peter ferrie Jul 14 '17 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.