PHP技术问询:如何让pack()返回与普通字符串等效的字符串?
嘿,你的问题根源是对
pack('V')的误解! 你以为pack('V', 0x41)会生成单个"A"字符?其实不是——V格式代表32位无符号长整型(小端序),所以0x41(十进制65)打包后得到的是4字节序列:\x41\x00\x00\x00,也就是一个"A"后面跟着三个空字节。这就是所有困惑的起点。
为什么看起来和"A"一模一样?
- echo的“偷懒”输出:PHP的
echo碰到字符串里的空字节\x00就会停止输出,所以你只能看到开头的"A",但实际字符串长度是4,而普通的"A"长度只有1。随手跑个strlen(pack('V', 0x41))和strlen("A")就能验证,结果会是4和1,差异明显。 - mb_detect_encoding的局限性:这个函数只检查字节是否在目标编码的范围内,ASCII覆盖0-127,
\x41和\x00都符合,所以它会告诉你两者都是ASCII,但这完全不代表内容相同。
SQL查询为啥执行失败?
当你把这个4字节字符串拼进SQL语句后,实际生成的查询是:
SELECT item_name, item_description FROM items WHERE item_name LIKE 'A\x00\x00\x00%'
你的item_name字段里都是正常的无空字节的字符串,自然匹配不到任何记录,看起来就像查询“失败”了。而且有些数据库驱动在处理带空字节的字符串时,还可能出现解析异常,进一步导致查询出错。
结合你的CTF注入场景
这个空字节特性可是SQL注入里的经典玩法——空字节截断。比如如果你的代码有前缀过滤,攻击者可以用pack('V', ...)生成带空字节的payload,让数据库在处理时“忽略”空字节后的内容,或者绕过某些基于字符串长度的检查。举个例子,攻击者构造$querystr = pack('V', 0x41) . "' UNION SELECT flag, '' FROM flags -- ",空字节可以用来绕过部分WAF规则,或者在特定场景下截断SQL语句,从而触发注入漏洞。
最后给你个直观验证方法:用bin2hex()看两者的真实内容——bin2hex(pack('V',0x41))会输出41000000,而bin2hex("A")是41,一眼就能看出差异。
内容的提问来源于stack exchange,提问作者neatzsche
相关产品推荐
相关产品推荐

