您当前的位置:首页 > 网站建设 > php
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax | jQuery |

hexdec()、pack()等函数的研究

51自学网 2023-05-04 20:55:06
  php

关于hexdec()、pack()等函数的研究分析

先看一段简单的代码

<?php function Exec_Hex($data) { $len = strlen($data); for($i=0;$i < $len;$i+=2){ $newdata.=pack("C",hexdec(substr($data,$i,2))); } return $newdata; } $c_name = Exec_Hex('7777772e74686973646f6f722e636f6d'); echo $c_name; ?> 

hexdec — 十六进制转换为十进制";
pack把数据装入一个二进制字符串";

 

$newdata.=pack("C",hexdec(substr($data,$i,2))); 
等价于:
$newdata = $newdata . pack("C",hexdec(substr($data,$i,2))); 

最终输出的字符串就是www.thisdoor.com 能找到这个网址的相信你已经知道这个网址是干嘛的了,这就是一个后门提交的网址。
hexdec很好理解
pack下有很多可以说明的问题,用途也很广泛,记录一下,留着以后研究:

 

 

 

pack–压缩资料到位字符串之中。
语法:string pack(string format, mixed [args]…);
参数一:format参数表示资料用什么方式读取到
参数二:将要压缩的资料。

参数一 的种类
a 将字符串空白以 NULL 字符填满
A 将字符串空白以 SPACE 字符 (空格) 填满
h 十六进位字符串,低位在前
H 十六进位字符串,高位在前
c 有号字符
C 无号字符
s 有号短整数 (十六位,依计算机的位顺序)
S 无号短整数 (十六位,依计算机的位顺序)
n 无号短整数 (十六位, 高位在后的顺序)
v 无号短整数 (十六位, 低位在后的顺序)
i 有号整数 (依计算机的顺序及范围)
I 无号整数 (依计算机的顺序及范围)
l 有号长整数 (卅二位,依计算机的位顺序)
L 无号长整数 (卅二位,依计算机的位顺序)
N 无号短整数 (卅二位, 高位在后的顺序)
V 无号短整数 (卅二位, 低位在后的顺序)
f 单精确浮点数 (依计算机的范围)
d 倍精确浮点数 (依计算机的范围)
x 空位
X 倒回一位
@ 填入 NULL 字符到绝对位置

上面参数一得总结来自于网络,不知道是哪个翻译翻得,总之我个人不推荐看。下面是php手册上面的内容(全英文的,虽然我也看不懂,但是一个单词一个单词的翻译去理解,也比看上面的翻译强)

a — NUL-padded string
A — SPACE-padded string
h — Hex string, low nibble first
H — Hex string, high nibble first
c — signed char
C — unsigned char
s — signed short (always 16 bit, machine byte order)
S — unsigned short (always 16 bit, machine byte order)
n — unsigned short (always 16 bit, big endian byte order)
v — unsigned short (always 16 bit, little endian byte order)
i — signed integer (machine dependent size and byte order)
I — unsigned integer (machine dependent size and byte order)
l — signed long (always 32 bit, machine byte order)
L — unsigned long (always 32 bit, machine byte order)
N — unsigned long (always 32 bit, big endian byte order)
V — unsigned long (always 32 bit, little endian byte order)
f — float (machine dependent size and representation)
d — double (machine dependent size and representation)
x — NUL byte
X — Back up one byte
@ — NUL-fill to absolute position

====================H 和 h========================
————————-H — h ——————————
先看中文翻译
H 十六进位字符串,高位在前
h 十六进位字符串,低位在前

再看英文
h — Hex string, low nibble first 十六进制,低位在前以半字节为单位(上面的翻译少了半字节,这个半字节很重要,nibble就是半字节的意思)
H — Hex string, high nibble first 十六进制,高位在前以半字节为单位

方法:先转换为十进制,再转换为十六进制。进行pack方法的H前,必须先将字节补充完整。

H是一次是4位的读取,一个十六位进制是占4位,所以H是一次4位,H2是一次8位(即一个字节)。
echo pack("H",0×4);
echo pack("H2",65);
echo pack("H2",0×41);
echo pack("H2",”41“);
echo pack("H2H2", 0×41, 0×42);
echo pack("h2h2", 0×41,0×42); `
echo pack("H3", 124);
echo pack("h3",124);

输出如下
@
e
e
A
ef
Vf

//第一行:pack("H",0×4);将一个十六进制(4位)以十六进制的方式读取然后写入到字符串中。因为0×4是4位,
0×4转化为十进制为4。而一个字节是8位,所以会自动补充位一个字节8位的长度,后面4位补充为0000(记住!但凡要进行pack方法的H前,必须先将字节补充完整)。所以十进制为40(为什么要转化为十进制去在读取,我也不知道,可能pack方法开发者就是这么写的),十进制40以H十六进制的方式读取,就是0×40,转换成ascii码就为@。

//第二行:pack("H2",65);65是十进制(H默认是读取读取十进制,以十六进制的方式读取),所以65被H后为0×65,转化为ascii码就是e。

//第三行:pack("H2",0×41);0×41是十六进制,H2表示一次读取8位(H默认是读取读取十进制,以十六进制的方式读取),0×41转化为十进制为65,65被H后为0×65,转化为ascii码就是e。

//第四行:pack("H2",”41“);"41"为字符串,H2表示读取1个8位,但是(H默认是读取读取十进制,以十六进制的方式读取,所以字符串41就被H默认转换为十进制41),十进制41被H后为0×41,转化为ascii码就是A。

//第五行:pack("H2H2", 0×41, 0×42);0×41和0×42一共是十六位,H2H2表示读取两个8位,转化为十进制为65和66,65被H后就是0×65,66被H就是0×66,转化为ascii码就是分别是ef。

//第六行:pack("h2h2", 0×41,0×42);0×41和0×42是两个八位,h十六进位字符串,低位在前。h和H是几乎是一样的只是一个前后排序的问题。H是高位在前,h是低位在前。0×41和0×42转化为十进制65和66,。这里读取后跟H不一样,h是低位在前,H是高位在前。这里来做一个比较,如下:

读取前十六进制 0×41 0×42
读取前十进制 65 66
H读取后十六进制 0×65 0×66
h读取后十六进制 0×56 0×66
H读取后二进制 01100101 01100110 高位在前 以一次H读取对象为基础,4位为单位,进行高低互换
h读取后二进制 01010110 01100110 低位在前 以一次h读取对象为基础,4位为单位,进行高低互换

h按16进制读取后分别为二进制01010110和01100110转化为十六进制56和66,转化为ascii码为Vf。

//第七行:pack("H3", 124);因为要首先要将字节补充完整,因此补充完整后为1240。1240是十进制(H默认是读取读取十进制,以十六进制的方式读取),所以1240被H以后打到的是0×1240,转换为2进制的话就为0001 0010 0100 0000,转换为16进制就是0×1240,而浏览器这里是以ascii码读取的,所以是8位一次的翻译,所以0×1240被分割成0×12和0×40,0×40是@,0×12在ascii表里可以看到是(device control 2) 设备控制2,这个东西在ie8中显示出来就是上下双向箭头。而在ie6,ie7浏览器上因为使用的不同的编码方式,而显示出不同的字符。

//第八行:pack("h3",124);因为h是低位在前,而且又是1个半字节(记住!但凡要进行pack方法的H前,必须先将字节补充完整),然后再,我们来对比一下h与H,
读取前十六进制 0x7C
读取前十进制 1240
H读取后十六进制 0×1240
h读取后十六进制 0×0421
H读取后二进制 0001001001000000 高位在前 以一次H读取对象为基础,4位为单位,进行高低互换
h读取后二进制 0000010000100001 低位在前 以一次h读取对象为基础,4位为单位,进行高低互换

0000 0100 0010 0001 或者 0×0421,分成0×04和0×21,在ie8中以ascii码表示出来就是如上所示

注意:

pack("H",0×41); 是不正确的,但不会报错

pack("HH",0×41); 是不正确,会报名错,需要两个参考

pack("H*",0×41); 是正确,为e。

=================V 和 N====v 和 n=======================
————————-V – N———————–
先看中文翻译
V 无号短整数 (卅二位, 低位在后的顺序)
N 无号短整数 (卅二位, 高位在后的顺序)

再看英文
V — unsigned long (always 32 bit, little endian byte order) 无符号长整型(总是32位,低地址存放最低有效字节)(根据金山词霸的解释)
N — unsigned long (always 32 bit, big endian byte order) 无符号长整形(总是32位,高地址存放最低有效字节)(根据金山词霸的解释)

下面解释 little endian 和 big endian
big endian — 是指低地址存放最高有效字节
little endian — 是指低地址存放最低有效字节

 

比如:a = 0×05060708
0×05060708
高端<—低端

在BIG-ENDIAN的情况下存放为:
因为低端地址存放高端有效字,08是最低有效字放在高端地址
字节号 0 1 2 3 ··· ···
低端地址 高端地址
—————————————–>
数据 05 06 07 08 ··· ···

在LITTLE-ENDIAN的情况下存放为:
因为低地址存放最低有效字节,08是最低有效字放在低端地址
字节号 0 1 2 3 ··· ···
低端地址 高端地址
—————————————–>
数据 08 07 06 05 ··· ···

因为内存都是从低端地址读起,因为读取内存数据一般使用地址指针,读一个地址在加一个偏移量。所以这个内存little-endian 与 big-endian 决定了数据读取出来的顺序,并不是想上面那个中文翻译的那样子(什么低位在后的顺序,我是服了,翻译的真让我受不了)。

下面举几个V的例子
echo "1 ".pack("V",0x65666768696A6B);echo "<br />";
echo "2 ".pack("V",0x666768696A6B6C);echo "<br />";
echo "3 ".pack("V",0x6768696A6B6C6D);echo "<br />";

显示出来为
// kjih 01101011 01101010 01101001 01101000
// k j i h
// lkji 01101100 01101011 01101010 01101001
// l k j i
// mlkj 01101101 01101100 01101011 01101010
// m l k j

N的例子
echo "4 ".pack("N",0x65666768696A6B);echo "<br />";
echo "5 ".pack("N",0x666768696A6B6C);echo "<br />";
echo "6 ".pack("N",0x6768696A6B6C6D);echo "<br />";

显示出来为
// hijk 01101000 01101001 01101010 01101011
// h i j k
// ijkl 01101001 01101010 01101011 01101100
// i j k l
// jklm 01101010 01101011 01101100 01101101
// j k l m

——————-v – n—————-
先看中文翻译
v 无号短整数 (十六位, 低位在后的顺序)
n 无号短整数 (十六位, 高位在后的顺序)

再看英文
v — unsigned short (always 16 bit, little endian byte order) 无符号短整型(总是16位,低地址存放最低有效字节)(根据金山词霸的解释)
n — unsigned short (always 16 bit, big endian byte order) 无符号短整形(总是16位,高地址存放最低有效字节)(根据金山词霸的解释)

不用举例子了,这个跟V和N的区别就是16位和32位的区别。


——————-关于V – N溢出的问题————————–

 

 

================ a ===================
先看中文翻译
a 一个填充空的字节串

再看英文翻译

a NUL-padded string
a NUL-padded string

a NUL – padded string

下面是例子:
echo pack("a",65)."<br />";
echo pack("a2",65)."<br />";
echo pack("a2",65,66)."<br />";
echo pack("a2a2",65,66)."<br />";
echo pack("a","65")."<br />";
echo pack("a2","65")."<br />";
echo pack("a",0×65)."<br />";
echo pack("a1",0×65)."<br />";
echo pack("a2",0×65)."<br />";
echo pack("a3",0×65)."<br />";

输出为:
6
65
"报错"
65
6
65
1
1
10
101

由上面例子可知,这个该死的a,是以十进制的方式读取的,不管是字符还是十六进制都是先转换为十进制读取的,a1是读取一位十进制(也不知道是多少位),a2是读取二位十进制(也不知道是多少位),a3是读取三位十进制(也不知道是多少位)。如果是十六进制,就先转换成十进制,如上面的0×65转换成101,然后用a3读取后显示出来就是101。

echo pack("cccc", 0×41, 0×42, 0×43, 0×44); // ABCD
echo pack("cccc", 65, 66, 67, 68); // ABCD
echo pack("c4", 0×41, 0×42, 0×43, 0×44); // ABCD
echo pack("c4", 65, 66, 67, 68); // ABCD

 


下载地址:
自适应移动端全屏竖屏小姐姐视频播放网站源码
带会员中心全网VIP视频解析源码
51自学网自学EXCEL、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。
京ICP备13026421号-1