When you want your Controls to render Unicode text and improve support for international fonts, you always call Application.SetCompatibleTextRenderingDefault(false) (before any Form is created).
Setting false means that the rendering is not compatible with pre-Whidbey (.NET Fx 2.0) GDI+ rendering, using GDI (TextRenderer) with ClearType support instead.
I also suggest enabling Visual Styles by default, calling Application.EnableVisualStyles()
Specifying an active DpiAwareness may also improve the overall aspect.
Here I’m calling SetProcessDpiAwareness(), specifying PROCESS_PER_MONITOR_DPI_AWARE as the adopted mode. Modify or remove if not required / unwanted.
Note: if you’re using the Windows PowerShell ISE, this may not work when run from the IDE.
You have to execute the script through either powershell.exe or pwsh.exe
using namespace System.Drawing
using namespace System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
[System.Windows.Forms.Application]::SetCompatibleTextRenderingDefault($false)
$code = @" [System.Runtime.InteropServices.DllImport("Shcore.dll")] public static extern int SetProcessDpiAwareness(int dpiAwarenessMode);
"@
$PInvoke = Add-Type -MemberDefinition $code -Name "PInvoke" -PassThru
$null = $PInvoke::SetProcessDpiAwareness(2)
$form = [Form] @{ AutoScaleMode = [AutoScaleMode]::Dpi; ClientSize = [Point]::new(200, 200); StartPosition = [FormStartPosition]::CenterScreen; Text = "Visual Styles";
}
$button = [Button] @{ Font = [Font]::new("Segoe UI", 20) Location = [Point]::new(20, 20) Size = [Size]::new(40, 40) Text = [char]::ConvertFromUtf32(0x0001F6F3) UseVisualStyleBackColor = $true
}
$form.Controls.Add($button)
$form.ShowDialog()
In PowerShell, like many scripting languages, there is a set of escape characters that you can use within strings to represent certain characters that have a special meaning. Use escape characters to represent non-printable or reserved characters within strings. These characters are essential for handling special situations and ensuring your PowerShell scripts work as expected. They allow you to use special characters that would otherwise have special meaning or functionality. For example, using escape characters allows you to include quotation marks within a string without terminating the string.
In this post, we’ll explore the main escape characters available in PowerShell and how to use them effectively. We’ll cover:
- What escape characters are and why they are useful
- The most common escape character, backtick in PowerShell, and the backslash with RegEx
- Escaping quotation marks, newlines, tabs, and other special characters
- Using escape characters to encode Unicode characters
- Escaping regex special characters when using the -match operator
- Tips for correctly escaping strings in your PowerShell code
Understanding PowerShell’s escape characters will allow you to work with strings and include special characters you would normally be unable to use. By the end of this post, you’ll know how to escape any character in PowerShell.
What are Escape Characters?
The primary escape character in PowerShell is the backtick (`) character. When you need to include a special character like a double quote within a string, you can use the escape character to ensure that PowerShell interprets the double quote as part of the string, rather than the end of the string. It is a common requirement when working with text files, configuration files, or when passing arguments to other scripts or programs. By using escape characters, you can include things like quotation marks, newlines, tabs, etc., in strings without interfering with PowerShell’s parsing and execution.
For example, if you want to print a double quote inside a string, using an escape character will allow PowerShell to interpret it properly:
Write-host "She said, `"Hello World!`""
Here, the backtick ` escapes the double quote ” so that PowerShell doesn’t terminate the string early. It enables you to print special characters like double quotes and backslashes that have reserved meanings in PowerShell.

Alternatively, you can make double-quotation marks appear in a string, by enclosing the entire string in single quotation marks. For example:
Write-host 'As they say, "live and learn."'
In another case, I had to call an external program or batch file, with parameters passed from PowerShell. So, Here is how I escaped the double quote characters:
$cmd = "cmd /C echo `"Hello World`"" Invoke-Expression $cmd
Importance of escape characters in PowerShell
Escape characters are important in PowerShell scripting. They let you include special characters in strings, like quotes or parentheses, without causing conflicts or syntax errors. By using escape characters, you can ensure that PowerShell interprets these characters correctly and avoids any unwanted behavior
Escaping specific characters is essential when working with strings in PowerShell for several reasons:
- Including double quotes within a string without escaping them can lead to syntax errors or unexpected behavior in your script.
- Printing new lines, tabs, and other non-printable characters
- Escaping wildcards like
*and.to match them literally, so they don’t glob filenames - Handling paths and filenames with reserved characters
- Properly escaping double quotes allows you to create more complex and dynamic scripts. It lets you include string values with double quotes within other strings or commands.
- In many cases, like when working with JSON or XML data, you need to use double quotes for proper formatting. Escaping them ensures that your script handles these formats correctly.
Without escape characters, your PowerShell code often throws parsing errors or fails to work as intended. Properly escaping characters ensures that the system parses strings correctly.
Here’s a table of the common escape characters in PowerShell:
| Escape Sequence | Represents |
|---|---|
` | The escape character itself (a backtick) |
`0 | Null |
`a | Alert/Beep |
`b | Backspace |
`f | Form feed |
`n | New line |
`r | Carriage return |
`t | Horizontal tab |
`v | Vertical tab |
`" | Double quote |
`' | Single quote |
`$ | for the dollar sign ($) which denotes a variable in PowerShell |
`( | Represents an opening parenthesis. |
`) | Represents a closing parenthesis. |
`% | represents a percentage sign |
`{ | represents an opening curly brace. |
`} | represents a closing bracket. |
`] | represents a closing bracket. |
`[ | represents an opening bracket. |
Using these escape characters appropriately will ensure that your PowerShell scripts function as intended.
In any scripting language, it’s crucial to understand the concept of escape characters. An escape character is a character that allows the interpreter to treat the subsequent character as a different type of character. For example, when working with strings in a script, you might need to insert a special character, such as a double quote, inside the string itself. To do this, you would use an escape character to signal that the subsequent double quote should be treated as part of the string, rather than the end of the string.
Different methods to escape double quotes in PowerShell
Using backtick (`) character
$exampleString = "This is a `"double quote`" within a string." #Output: This is a "double quote" within a string.
In this example, the backtick is used to escape the double quotes, allowing them to be included within the string.
Using single quotes instead of double quotes
Another method to escape double quotes in PowerShell is to use single quotes as the string delimiters. When using single quotes, any double quotes within the string are treated as literal characters, without the need for an escape character:
$exampleString = 'This is a "double quote" within a string.'
However, using single quotes means that any variables or expressions within the string won’t be expanded. So, you might need to concatenate strings in such cases.
Using double double quotes
A third method for escaping double quotes in PowerShell is to use double double quotes. This can be particularly useful when working with strings containing multiple double quotes:
$exampleString = "This is a ""double quote"" within a ""string""."
In this example, each pair of double quotes is interpreted as a single, literal double quote character.
How to escape single quotes in PowerShell?
Single quotes are another way to define strings in PowerShell. However, if you need to include a single quote within a single-quoted string, you need to handle escape characters correctly.
Write-host 'This is a ''quoted'' string.'
You can use the double single quote if you want to include a single quote within a string like this:
Write-host 'This is a ''quoted'' string.'
Escaping Backslash
In PowerShell, the backslash (\) is not a special character in double-quoted strings, so it doesn’t usually need escaping. However, there are scenarios, especially when interfacing with other systems or regular expressions, where you might need to deal with escaping backslashes.
Here are some real-world examples where escaping backslashes can be pertinent:
# Escaping backslash
$Path = "C:\Users\John\Documents\file.txt"
$Components = $path -split '\\'
$components
#Another Example:
$string = "C:\Program Files\Some Software\file.txt"
if ($string -match "C:\\Program Files\\Some Software\\file.txt") { Write-Output "Match found!"
}You always need two backslashes to escape a single literal backslash. This is important when dealing with file paths and regex patterns.
"OldDomain\user" -replace "OldDomain\\", "Newdomain\"
Escaping $ in PowerShell
To use a literal $ character in a variable name in PowerShell, you can escape it with a backtick/grave accent. By default, Variable names preceded by a dollar sign ($) will be replaced with the variable’s value! To avoid the substitution of a variable value within a double-quoted string, utilize the backtick character (`), which serves as the escape character in PowerShell.
#Before Escape $i = 10 Write-host "The value of $i is $i." #After Escape Write-host "The value of `$i is $i."

Here is another example:
Escape characters to Encode Unicode characters
# Unicode for the copyright symbol © is U+00A9
$unicodeString = "Hello World `u{00A9} 2023"
Write-Output $unicodeStringPlease note, that this is available only after PowerShell 6.
PowerShell Here-Strings
In PowerShell, a here-string allows for the creation of multi-line string literals, without the need for manual line breaks or extensive quoting. They are especially useful for embedding complex, multi-line data directly within scripts.
Here’s the basic syntax:
@<quote> <your multi-line string> <same quote at>
Where <quote> is either a single (') or double (") quote, depending on whether or not you want the string to support variable interpolation and escape sequences.
Here are some examples:
Simple Here-String with Single Quotes:
This will take everything literally between the delimiters.
$herestring = @' This is a multi-line string where everything is taken "literally", including special characters like `t or `n. It preserves all whitepsace and line breaks. '@ Write-Output $herestring
Here-String with Double Quotes:
This will interpret variables and escape sequences.
$name = "Alice" $herestringInterpolated = @" Hello, $name. This is an interpolated multi-line string. A tab looks like this: `tSee? "@ Write-Output $herestringInterpolated
Escaping special characters in strings with PowerShell
Sometimes, you may need to include special characters within strings in PowerShell. To do this, use escape characters to ensure that the system interprets these characters correctly.
For example, if you want to include a double quote within a string, you can use either the escape character ` before the double-quote:
Write-host "This is a `"quoted`" string."
How to escape all special characters in a PowerShell string?
Although you don’t always need to escape all special characters within a PowerShell string, you should do so to avoid any potential issues or confusion. To escape all special characters in a string, we can use the -replace operator with a regular expression pattern that matches any special character and replaces it with the escaped version.
# Source String
$OriginalString = "This is a .^$*+?{}[]\|() sample string with special characters."
# Regular expression pattern to match special characters
$Pattern = "([\.\^\$\*\+\?\{\}\[\]\\\|\(\)])"
$EscapedString = $originalString -replace $Pattern, '`$1'
Write-host $EscapedStringThis code uses a regular expression pattern to match any special character and replaces it with the escaped version using the backtick. In case, you are looking to remove or replace all special characters from a string, refer to:
Escaping Parentheses in PowerShell scripts
Parentheses are commonly used in PowerShell for grouping and capturing. However, if you need to include literal parentheses within a PowerShell script, you need to escape them.
In Strings
When using parentheses as literals in a string, they typically don’t need to be escaped:
$message = "Hello (World)!" Write-Output $message
This will output: Hello (World)!
However, it’s good to be aware of how you use them, especially within double-quoted strings, to ensure they’re not evaluated as part of an expression or sub-expression.
In Regular Expressions
When working with regex in PowerShell, parentheses have a special role. They are used to define capturing groups. Therefore, if you want to match parentheses literally, you need to escape them.
Let’s say you want to match the string “Hello (World)!” using regex:
$pattern = 'Hello \(World\)!' "Hello (World)!" -match $pattern
In the $pattern, the backslashes (\) are used to escape the parentheses, ensuring they are matched as literal characters and not interpreted as regex capturing groups.
Within Code Blocks or Expressions
In scenarios where you’re using sub-expressions within strings, you might want to ensure that parentheses are used correctly:
$name = "John" $message = "Hello $($name)!" Write-host $message
Here, $($name) is a sub-expression that evaluates the variable $name inside the string. The output will be: Hello John!
PowerShell escape quotes in string examples
Escaping double quotes within a string
Here’s an example of how to escape double quotes within a string using the backtick (`) character:
$exampleString = "The wise man said, `""To be or not to be.`"" Write-Host $exampleString
The wise man said, "To be or not to be."
Escaping double quotes in a script
When writing a PowerShell script, you may need to escape double quotes when passing arguments to another script or program. Here’s an example of how to do that:
$argument = 'This is a "test" argument.' $scriptPath = "C:\Scripts\Script.ps1" Invoke-Expression "& `"$scriptPath`" `"$argument`""
In this example, the backticks are used to escape the double quotes surrounding the script path and the argument, ensuring that they are both passed as single arguments to the Invoke-Expression cmdlet.
Escaping double quotes in a function
When working with functions in PowerShell, you may need to escape double quotes when passing values to the function. Here’s an example of how to do that:
function Test-Function { param ( [string]$inputString ) Write-Host "You entered: $inputString"
}
$exampleString = 'This is a "test" string.'
Test-Function -inputString $exampleStringIn this example, you use single quotes to define the string containing the double quotes, ensuring that the system does not interpret the double quotes as the end of the string.
Using escape characters with regular expressions in PowerShell
For example, if you want to match a literal dot character in a regular expression, you would need to escape it like this: ..\
$string = 'C:\folder\file.txt'
if ($string -match 'C:\\folder\\file\.txt') { "Match found!"
}# Escaping regex metacharacters "$25" -match "^`$" "25.5" -match "\."
This ensures regex matches them literally instead of their special meaning. Here is another example:
"Hello (World)" -match "Hello \(World\)"
Please note, The primary escape character in PowerShell is the backtick (`), and in regex, it’s typically the backslash ().
Applications of PowerShell escape double quote in real-world scenarios
- Configuration file management: Escaping double quotes is essential when working with configuration files, such as JSON or XML, that require double quotes for proper formatting.
- Log file parsing and analysis: When analyzing log files that contain double quotes, escaping them correctly ensures accurate parsing and processing of the data.
- Data extraction and manipulation: When working with data from databases, APIs, or other sources that contain double quotes, mastering PowerShell escape double quote techniques is crucial for accurate extraction, manipulation, and storage of the data.
Common issues and solutions when working with PowerShell double quotes in a string
- Forgetting to escape double quotes: When working with strings containing double quotes in PowerShell, it’s essential to remember to escape them using the backtick (`) character, single quotes, or double double quotes. Failing to do so can result in syntax errors or unexpected behavior in your script.
- Using the wrong escape character: The escape character in PowerShell is the backtick (`) character. Using a different character, such as the backslash, will not produce the desired result when attempting to escape double quotes in a string.
- Misusing single quotes and double quotes: When using single quotes to define a string, variables and expressions within the string will not be expanded. If you need to include variables within a string containing double quotes, you will need to use one of the other methods for escaping double quotes, such as the backtick (`) character or double quotes.
- Incorrectly concatenating strings with escaped double quotes: When concatenating strings that include escaped double quotes, be sure to use the correct method for concatenation, depending on whether you are using single quotes, double quotes, or a combination of both.
Best practices for using PowerShell escape quotes
- Consistency: Choose a method for escaping double quotes and stick with it throughout your script for better readability and maintainability.
- Use single quotes for static strings: When working with strings that do not require variable or expression expansion, use single quotes to minimize the need for escape characters.
- Comment your code: Include comments in your script to explain any non-obvious uses of escape characters, especially when working with complex strings or multiple levels of escaping.
- Escape all special characters: Although you do not always need to, you should escape all special characters within strings and regular expressions to ensure clarity and avoid potential issues.
- Test your script: Always test your script thoroughly to ensure that escaping double quotes and other special characters are functioning as expected.
Wrapping up
Escape characters are essential for handling strings and text in PowerShell. Used properly, they can overcome a whole class of errors and issues. Mastering the art of PowerShell escape double quote is an essential skill for any PowerShell scripter. In this comprehensive guide, We discussed their importance, common use cases, and best practices for handling them effectively. You can create more efficient and effective scripts and avoid common pitfalls by understanding the various methods for escaping special characters, such as using the backtick (`) character, single quotes, or double quotes. Remember that the escape character has no effect unless it is used before a special character, and it is not recognized at all in single-quoted strings (which are literal strings in PowerShell).
What is an escape character in PowerShell?
How do I handle double quotes within a string using escape characters in PowerShell?
To include double quotes within a string, you can either use single quotes around the entire string or escape the double quotes with a backtick. For Example: $message = "She said, `"Hello, world!`""
Can I use escape characters to include special symbols like $ in a string?
Yes, you can use the backtick escape character to include special symbols within a string. For example: $text = "The price is `$10 per item"
How can I split a long command across multiple lines using escape characters?
What is the difference between single quotes and double quotes in terms of escaping?
In PowerShell, single quotes and double quotes have different behavior when it comes to escaping: Single quotes (‘) treat everything inside them as literal characters, so you don’t need to escape special characters. Double quotes (“) allow variable expansion and expression evaluation, so you must use escape characters to include special characters or prevent expansion.
How do I escape a backtick character itself?
To use a literal backtick character within a string, you need to escape it with another backtick. For example: $string = "This is a backtick: ``"

Introduction — from CVE-2021–28958 to CVE-2021–33055
// Commands from this string were then executed in PowerShell
Analysis of the
After verifying the patch, we’ve asked ourselves: Is it possible to do something malicious if we can’t use any character from the list above? Another RCE via PowerShell injection?
Well, yes, it’s possible — in other case, I wouldn’t write this article or mention another CVE ID, right?
Unicode’s General Punctuation block — quotes come in many flavors
character, as showed below:
Script execution revealed that
quotes were interpreted as valid string enclosing symbols:
Next, we tried using
In this case quotes were not interpreted as string enclosing symbols and were printed by the script:
So far, we confirmed that at least one special character (
To our surprise, PowerShell had no problem with both cases:
Since PowerShell (Core version) is open source, it was possible to verify whether this behavior was intended or not. In CharTraits.cs file, we can find
internal static class SpecialChars
// Uncommon whitespace
internal const char NoBreakSpace = (char)0x00a0;
internal const char NextLine = (char)0x0085;
// Special dashes
internal const char EnDash = (char)0x2013;
internal const char EmDash = (char)0x2014;
internal const char HorizontalBar = (char)0x2015;
// Special quotes
internal const char QuoteSingleLeft = (char)0x2018; // left single quotation mark
internal const char QuoteSingleRight = (char)0x2019; // right single quotation mark
internal const char QuoteSingleBase = (char)0x201a; // single low-9 quotation mark
internal const char QuoteReversed = (char)0x201b; // single high-reversed-9 quotation mark
internal const char QuoteDoubleLeft = (char)0x201c; // left double quotation mark
internal const char QuoteDoubleRight = (char)0x201d; // right double quotation mark
internal const char QuoteLowDoubleLeft = (char)0x201E; // low double left quote used in german.
This class is self-explanatory, but why is it possible to use different quotes to enclose a single string? Functions
from the mentioned above file answer this question:
// Return true if the character is any of the normal or special
// single quote characters.
internal static bool IsSingleQuote(this char c)
return (c == ‘\’’
// Return true if the character is any of the normal or special
// double quote characters.
internal static bool IsDoubleQuote(this char c)
return (c == ‘“‘
To sum it up, in PowerShell, we can end the string using a different quote character, as long as it’s one of the characters defined in
class and that both quotes (starting and ending) have the same type (two single quotes or two double quotes). Since
PoShI — vulnerable web server PoC
parameter in GET query, e.g.:
GET /date?format=dd HTTP/1.0
Get-Date -Format “FORMAT_QUERY_PARAMETER_IS_INJECTED_HERE”
function (which sanitizes the same characters as
function from ADSSP did). When you run the application, make sure to start it like this:
java -Dfile.encoding=UTF-8 poshi.jar
The web server should listen on port 8000 and return the current date:
# ASCII double quote and U+201D quote are used here
As shown in the previous section, this code is perfectly fine in PowerShell and should lead to execution of
command. Unexpectedly, our Python script shows that it did not work (“whoami” part was not interpreted as a command, so we did not manage to escape from the string):
Well, that’s awkward ¯\_(ツ)_/¯
Finding the culprit
The result of the last PoC execution indicates that for some reason, PowerShell did not interpret our
Note: some registry keys might not exist — they must be added manually.
From now on, code executed by PowerShell will be stored in events (code 4104). Let’s execute Python PoC again and inspect events in Event Viewer:
Applications and Services Logs > Microsoft > Windows > PowerShell > Operational
One of the events with code 4104 should contain
command executed by PoShI:
As it can be seen, our
quote was broken down into three symbols:
It looks like we’ve encountered some problems with encoding — but which one?
Code pages
After some digging, it turned out that when our Java code sends bytes to PowerShell, those are converted to characters using the OEM code page. In Windows, we can check the currently used code page with the
As it can be seen, the CP437 code page is used in my version of Windows (English US). Is it a culprit that destroyed the
quote? Let’s see — in UTF-8 this symbol is represented by three bytes:
0xE2 0x80 0x9D
Let’s see what characters we would get from those bytes with the CP437 code page:
Those characters are exactly the same ones that we saw in Event Viewer, in a place where
quote was supposed to be. In order to perform a PowerShell injection, we would have to send some bytes in
GET query parameter, which would be mapped to
quote in the CP437 code page.
Unluckily, the CP437 code page has neither a
quote nor any other special quote from the General Punctuation that could bypass sanitization and perform code injection — we came to a dead end. Changing the code page manually did not seem interesting. It would ruin an idea of remote exploitation, and if we could change the code page on the remote system, we would probably already have code execution on it. But what exactly determines which OEM code page is used? System locale — which depends on Windows’ language.
In the Region settings of Windows, we can change the current system locale:
In my case, the system locale is set to “English (United States)” — which was predictable since I’m using the English US Windows version. What if we changed it to something else, let’s say “French (France)”? After the system reboot, everything seems to be the same, but
command result indicates that the code page has changed to CP850:
for x in range(3000):
This script attempts to encode
character using various code pages, from CP1 to CP3000 (most of them do not even exist, and some do not have
character — exception handler takes care of it and just skips to the next code page). The script execution result is shown below:
As you can see, multiple code pages contain
UINT GetCodePageForLocale(LCID lcid)
int sizeInChars = sizeof(acp) / sizeof(TCHAR);
bool IsInterestingCodePage(UINT cp)
for (int x = 0; x < sizeof(interestingCodePages); ++x)
for (int x = 1; x < 65536; ++x)
UINT codePage = GetCodePageForLocale(x);
LCIDToLocaleName(x, (LPWSTR)langName, LOCALE_NAME_MAX_LENGTH, 0);
printf(“Code page for %d (‘%S’) -> %d\n”, x, langName, codePage);
How does it work? With the
WinAPI function, it is possible to retrieve the original OEM code page associated with locale ID (LCID). Full LCID structure is described here, but the most interesting part for our case is shown below:
LCID is a 4-byte value, in which the first 12 bits are always zero, and the next 4 bits are zeros in most cases. Because of that, it seems reasonable to start with brute-force of only the last 16 bits — “candidate” LCIDs would be integers from 0 to 65535. If
returns a code page that contains
character (we got list of those code pages using Python script), then we know that this locale ID is interesting. Windows with this locale will have a default code page containing
character and we should be able to exploit our PoShI server. But it’s only an ID — how do we map it into a locale name? Using
Result of this app execution is shown below:
There are some potentially interesting results — let’s focus on “ja-JP” locale, which has CP932 set as the default code page. We can guess that it’s a default locale for the Japanese Windows systems — which is correct:
Checkpoint time! Let’s sum it up:
- we know that the CP932 code page contains
- U+201D
- character, potentially allowing us to conduct a PowerShell injection attack against PoShI
- CP932 is a default OEM code page for ja-JP locale
- ja-JP locale is used by default in the Japanese Windows systems
Final attack
If PoShI were running on the Japanese Windows, we would be able to inject
character into the PowerShell script by sending specially crafted bytes in the HTTP request. But what bytes do we have to send? Again — let’s use Python:
bytes (“h” in ASCII is represented by
byte) will be interpreted as
quote in CP932. To check this out, let’s change our english Windows locale to “Japanese (Japan)” in Region settings and reboot it. Then, execute modified Python PoC (with
bytes instead of
Something went wrong — why? Well, we’re sending UTF8 encoded data (and PoShI expects UTF8 as well), but
bytes do not represent a valid character in UTF8. By adding one more byte, we can make it a valid sequence for UTF8 — e.g.,
0xC2 0x81 0x68
. But won’t it foil our exploitation attempt when those bytes get converted using CP932? Let’s have a look at the CP932 table:
In CP932, characters are encoded using one or two bytes. As we can see,
maps to ツ character in Japanese Katakana (single-byte character). The
indicates that a character is encoded using two bytes — as we checked earlier
maps to a single
quote character. So
0xC2 0x81 0x68
in CP932 — but how would the final PowerShell command look after the injection?
part looks suspicious, but PowerShell won’t have a problem with that. Let’s modify our PoC again:
command result in response — and Event Viewer confirms that this time
quote was injected successfully:



