Windows PowerShell中栈溢出内存覆盖异常:高十六进制值无法按预期写入
栈溢出攻击中高十六进制值内存覆盖异常的原因与解决办法
问题场景
下述C程序存在栈溢出漏洞,可实施内存覆盖攻击,但在Windows PowerShell中执行攻击命令时,输入\xaa\xbb\xcc\xdd这类高位十六进制值无法覆盖预期内存地址;而输入\x11\x22\x33\x44这类低位十六进制值时,能正常完成预期覆盖。
程序代码
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { int value = 5; char buffer_one[8], buffer_two[8]; strcpy(buffer_one, "one"); /* Put "one" into buffer_one. */ strcpy(buffer_two, "two"); /* Put "two" into buffer_two. */ printf("[BEFORE] buffer_two is at %p and contains '%s'\n", buffer_two, buffer_two); printf("[BEFORE] buffer_one is at %p and contains '%s'\n", buffer_one, buffer_one); printf("[BEFORE] value is at %p and is %d (0x%08x)\n", &value, value, value); printf("\n[STRCPY] copying %d bytes into buffer_two\n\n", strlen(argv[1])); strcpy(buffer_two, argv[1]); /* Copy first argument into buffer_two. */ printf("[AFTER] buffer_two is at %p and contains '%s'\n", buffer_two, buffer_two); printf("[AFTER] buffer_one is at %p and contains '%s'\n", buffer_one, buffer_one); printf("[AFTER] value is at %p and is %d (0x%08x)\n", &value, value, value); }
执行命令
.\a.out $(python -c "print('A'*16 + '\xaa\xbb\xcc\xdd')")
异常输出
[BEFORE] buffer_two is at 0061FF0C and contains 'two' [BEFORE] buffer_one is at 0061FF14 and contains 'one' [BEFORE] value is at 0061FF1C and is 5 (0x00000005) [STRCPY] copying 20 bytes into buffer_two [AFTER] buffer_two is at 0061FF0C and contains 'AAAAAAAAAAAAAAAA¼+ªª' [AFTER] buffer_one is at 0061FF14 and contains 'AAAAAAAA¼+ªª' [AFTER] value is at 0061FF1C and is -1499059284 (0xa6a62bac)
原因分析
- PowerShell编码转换干扰:PowerShell默认以UTF-8或UTF-16处理字符串,当Python输出包含高位ASCII字节(值>0x7F,如
0xaa、0xbb)时,这些字节不符合UTF-8的有效编码规则,PowerShell会自动将其替换为Unicode替换字符�(十六进制0xFFFD)。后续控制台代码页(如CP936)的转义进一步改变了字节值,最终传递给程序的不是原始的十六进制字节,导致内存覆盖结果异常。 - 低位十六进制值无干扰:
0x11、0x22这类低位值属于ASCII控制字符,是UTF-8的有效单字节编码,PowerShell不会对其进行修改,因此能正常传递给程序完成预期覆盖。
解决办法
方法1:用Python输出字节流并通过管道传递(需修改程序)
修改程序从标准输入读取 payload,然后用Python直接输出原始字节流,避免PowerShell的编码转换:
# 修改后的程序读取stdin示例(替换原strcpy(buffer_two, argv[1])) # fread(buffer_two, 1, 20, stdin); python -c "import sys; sys.stdout.buffer.write(b'A'*16 + b'\xaa\xbb\xcc\xdd')" | .\a.out
方法2:用PowerShell直接构造字节数组转换为字符串
通过PowerShell的字节数组构造原始payload,再用ASCII编码强制转换为字符串,避免编码替换:
$payload = [byte[]]((0x41)*16 + 0xaa, 0xbb, 0xcc, 0xdd) $payloadStr = [System.Text.Encoding]::ASCII.GetString($payload) .\a.out $payloadStr
方法3:改用WSL执行
在Windows Subsystem for Linux的bash环境下运行原命令,WSL的字符串处理不会干扰原始字节传递:
./a.out $(python -c "print('A'*16 + '\xaa\xbb\xcc\xdd')")
内容的提问来源于stack exchange,提问作者SUD pythonism
相关产品推荐
相关产品推荐

