push 4C2h
call esp
It's a 7-byte NOP. I leave it to you to figure out how it works.
executes from stack no?, and is a simple c2 04 00 00 (ret 4)...
not really usable in this day and age with dep, and so on.....
It’s not usable at all. I think what is happening is that pushing the return address for the call changes the value in ESP, so the call destination ends up being the location on the stack where the return address is stored, and the return address is not likely to be a workable instruction. This version will work:
push 4c2h
mov eax, esp
call eax
But a slow 9-byte nop that changes a register value is probably not too useful.
I didn't say it was useful :green but it shows that the stack is an executable segment under Windows, which is occasionally useful (a substitute for the hazardous practice of self-modifying code). The local heap is also executable.
Here are some faster NOP's:
db 8Dh,49h,0
db 66h,8Dh,49h,0
db 8Dh,89h,0,0,0,0
MichaelW makes a good point, that esp is ambiguous (or at least, looks ambiguous) in the instruction CALL ESP. In real life I use
   mov eax,esp
  push eax
instead of
  push esp
for the same reason. On the earliest Intel chips, after the instruction PUSH ESP, the value on the stack would be the NEW esp value, rather than the previous value, as it is on all the newer chips that I know of. To be safe, I never push esp directly.
update: The original PUSH 4C2h / CALL ESP does return properly, and the execution continues with no problem, at least on this Pentium 4.
It works fine on my P4, but on my P3 the CALL ESP is causing an exception because the destination address is the value of ESP after the return address is pushed.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  include \masm32\include\masm32rt.inc
  include \masm32\include\debug.inc
  includelib \masm32\lib\debug.lib
  DBGWIN_EXT_INFO = 1
  DBGWIN_DEBUG_ON = 1
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  .data
  .code
EH:
  ret
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  TrapException <offset EH>
  push 4c2h
  mov ebx, esp
  print "esp =      "
  print uhex$(ebx),13,10,13,10
  inkey "Press any key to continue..."
  print chr$(13,10)
  call ebx
  push 4c2h
  mov ebx, esp
  print "esp =      "
  print uhex$(ebx),13,10,13,10
  inkey "Press any key to continue..."
  print chr$(13,10)
  call esp
  inkey "OK"
  exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
esp =Â Â Â Â Â Â 0012FFB8
Press any key to continue...
esp =Â Â Â Â Â Â 0012FFB8
Press any key to continue...
=====================[EXCEPTION INFORMATION]====================
Exception code: EXCEPTION_ACCESS_VIOLATION
Location: , 0
eax=00000000 ebx=0012FFB8 ecx=0012FFBC edx=00000001 esi=00000000
edi=00000002 ebp=0012FFF0 esp=0012FFB4 eip=0012FFB5
CS=001B DS=0023 SS=0023 ES=0023 FS=0038 GS=0000Â o d I S z a P c
----------------------------------------------------------------
I wonder if this change in behavior is documented somewhere.
MichaelW,
Your code doesnt run on my P4 - Windows XP, SP2. Is there any reason ?
Quote from: RuiLoureiro on December 10, 2007, 04:52:34 PM
MichaelW,
        Your code doesnt run on my P4 - Windows XP, SP2. Is there any reason ?
I would guess the reason is
DEP (http://support.microsoft.com/kb/875352). What happens when you run it?
It hangs, doesnt do anything
The attachment includes the source and the EXE.
[attachment deleted by admin]
Quote from: MichaelW on December 10, 2007, 06:21:59 PM
The attachment includes the source and the EXE.
When i saw your .asm i said: Console Assemble & Link.
It gives the same resulsts for ESP and at the end OK.
Have a nice night/day
Rui
Surprising that a P3 and a P4 differ in this way, but I don't blame Intel for not documenting such an obscure thing.
Here's another demo of (safer) code in the stack, using CPEEK, which is available here:
http://www.masm32.com/board/index.php?topic=8135.msg59649#msg59649
;Build file:
;\masm32\bin\ml /c /coff stack.asm
;\masm32\bin\polink /SUBSYSTEM:CONSOLE stack.obj
;;;;;;;;;;;;;;;; STACK.ASM:
.586
.model flat, stdcall
option casemap:none
.data
ExitAddress dd ?
.code
include cpeek.inc
@cpeek
Start:
pop ExitAddress
xor eax,eax
call regs     ;regs is a function in cpeek.dll
push 0E3FF40h  ;inc eax, jmp ebx
mov ebx,offset wherenext
jmp esp
wherenext:
add esp,4
call regs   ;observe that eax is now 1 and esp is the same as before
jmp ExitAddress
end Start
Quote from: MichaelW on December 10, 2007, 10:54:11 AM
I wonder if this change in behavior is documented somewhere.
It is actually a documented erratum (Specification Update 244460-004).
QuoteG15. Near CALL to ESP Creates Unexpected EIP Address
IMPLICATION: Due to this erratum, the processor may transfer control to an unintended address. Results are
unpredictable, depending on the particular application, and can range from no effect to the unexpected
termination of the application due to an exception. Intel has observed this erratum only in a focused testing
environment. Intel has not observed any commercially available operating system, application, or compiler that
makes use of or generates this instruction.
Quote from: MazeGen on December 11, 2007, 10:27:08 AM
It is actually a documented erratum (Specification Update 244460-004).
Thank you for finding this. The problem was apparently known in 1999, with no plans to fix it.
Quote
Problem: As documented, the CALL instruction saves procedure linking information in the procedure stack and jumps to the called procedure specified with the destination (target) operand. The target operand specifies the address of the first instruction in the called procedure. This operand can be an immediate value, a general purpose register, or a memory location. When accessing an absolute address indirectly using the stack pointer (ESP) as a base register, the base value used is the value in the ESP register before the instruction executes. However, when accessing an absolute address directly using ESP as the base register, the base value used is the value of ESP after the return value is pushed on the stack, not the value in the ESP register before the instruction executed.
Time for some more Kinky Kode. Today we look at jumping to a nonexistent label.
;Build file:
;\masm32\bin\ml /c /coff phantom.asm
;\masm32\bin\polink /SUBSYSTEM:CONSOLE phantom.obj
;;;;;;;;;;;;;;;; PHANTOM.ASM:
.586
.model flat, stdcall
option casemap:none
include \masm32\include\kernel32.inc  ;only cpeek needs these.
includelib \masm32\lib\kernel32.lib
include cpeek.inc
@cpeek
.code
  db 66h  ;operand size override prefix
testlabel:
  inc eax
  call regs  ;Behold, ax but not eax has been incremented :D
  xor eax,eax
  jmp ebx   ;equivalent to ExitThread with return code in eax
Start:
  pop ebx
  mov eax,-1
  jmp testlabel-1
end Start
hows it non existant then, its (offset) testlabel -1...
so you just jump to the db 66h....
Quote from: evlncrn8 on December 12, 2007, 05:37:28 PM
hows it non existant then, its (offset) testlabel -1...
so you just jump to the db 66h....
I dramatised it a bit :bg. The code just shows that the assembler understands "testlabel-1". So, we don't need to think up a new name for a jump destination if we know how far it is from some other named label. The trick also works for local labels, e.g. "jc @F+2".