做这个东西,是因为看到了乌云网友写的一篇文章 (http://drops.wooyun.org/tips/14568)。
文章提供了一个数据传输的思路。在一台不能连网的虚拟机中运行软件,虚拟机只提供包含软件运行时的截图的分析报告。也就是说虚拟机的数据能通过图片显示出来,于是把虚拟机的文件写入到图片像素中,从而得到虚拟机的数据。
看到这文章时感到好惊艳,以前压根就没想过数据能以rgb三个颜色通道写三个字节的形式写到图片中。好像开启一片天地一样惊奇,实在增长见识。于是就想用php写一个这样的程序:能把文件数据写到图片中,也能从图片中还原文件。
程序和图片如下。先读取rar的数据然后进行base64加密,然后再逐个字符转为十进制,一个像素由rgb三个颜色通道组成,可以写三个字符 。一个1.83M的rar压缩文件写成的图片有2.12M大,如下图。不过数据越大生成的图片越大,数据处理起来也比较慢。
由此联想到数据都是0和1组成的,也就是说只要能体现两种不同状态的事物都可以做为传输介质,联想到之前看到新闻,说有黑客通过电脑发热盗取电脑数据,这也很好理解了。然后又联想到量子传输,好像也是这个原理的。
/**
* 从图片中按象素读数据
* @param type $file
*/
function getDataFromPic( $file ) {
$image = imagecreatefrompng( $file );
$aY = imagesy( $image );
$aX = imagesx( $image );
$aData = array();
$str = '';
for ( $x = 0; $x < $aX; $x++ ) {
for ( $y = 0; $y < $aY; $y++ ) {
$aRgb = imagecolorsforindex( $image, imagecolorat( $image, $x, $y ) );
$str .= chr( $aRgb['red'] );//十进制数据转为字符
$str .= chr( $aRgb['green'] );
$str .= chr( $aRgb['blue'] );
}
}
$data = base64_decode( $str );
return $data;
}
/**
* 把数据写到图片像素中
* @param max $binData 数据
* @param string $picfile 生成图片路径
*/
function createpic( $binData, $picfile ) {
$a = base64_encode( $binData );
$len = strlen( $a );
$w = $h = ceil( sqrt( ceil( $len/3 ) ) );//图片长宽
$im = imagecreatetruecolor( $w, $h );
$x = $y = 0;
$aData = array();
for ( $i = 0; $i < $len; $i++ ) {
$s = ord( $a{$i} );//转为十进制数据
$aData[] = $s;
if ( count( $aData ) == 3 ) {
$red = $aData ? $aData[0] : 255;
$green = $aData ? $aData[1] : 255;
$blue = $aData ? $aData[2] : 255;
$col = imagecolorallocate( $im, $red, $green, $blue );
imagesetpixel( $im, $x, $y, $col );
$y++;
if( $y >= $w ){
$y=0;
$x++;
}
$aData = array();
}
}
//header( 'Content-type: image/png' );
imagepng( $im, $picfile );
imagedestroy( $im );
}
$file = './1.rar';
$file2 = './2.rar';
set_time_limit(0);
$binData = file_get_contents( $file );
//$binData = '123456789';
createpic( $binData, './2.png' );
$data = getDataFromPic( './2.png' );
//echo $data;
file_put_contents($file2, $data);
exit;