• 加密与解密 读书笔记


    加密与解密,可作为经常查阅的工具书,比如查各种jmp的机器码,除法的编译,虚表详述。书中用源代码-无优化-有优化的对比来叙述。有优化这块算是盲区了,比如连续switch会编译成跳表,不连续的也会做衰减判断(自动调整为从小号到大号的顺序),lea可以拿来做算数加法,等等。

    趋势

    私人壳往往被当作病毒处理。商用壳则有兼容性问题。所以现在正经软件的保护一般不加壳,而是靠序列号设计。

    虚拟机壳

    虚拟机壳的设计思路是提高分析成本。将x86指令替换成自己的字节码,然后执行虚拟机解释字节码。
    效率换安全,一条指令会膨胀几十上百倍。一般只对关键代码做保护。
    VMProtect的使用有两种方式,一种是直接指定要保护的起止地址。另一种是SDK方法,开发的时候加个关键字VMProtectbegin和VMProtectend标记,然后用VMProtect打开编译后的exe实施保护。
    这是目前最流行的趋势。

    压缩引擎

    压缩可以慢,解压必须快。常见的压缩引擎包括aPLib,JCALG1,LZMA。

    CC保护

    跟卖服务器的CC保护不是一个意思,他们那个说的是DDoS。
    将子进程中所有跳转指令换成INT 3指令(CC)。父进程负责截获异常,并计算正确的跳转地址。

    加壳的一般过程

    • 保存入口参数
    • 加载加壳需要的API。如果DLL不在就loadLibrary,如果在了就直接getModuleHandle。然后是getProcAddress(有的会自己实现)获取输入函数地址。这三个很重要。
    • 按区块解密原代码,放在内存中合适的位置
    • 填写IAT,因为壳的IAT顶替了原来的IAT被PE装载器加载,所以需要做恢复工作
    • 重定位修复,exe可以不做修复,dll要做修复
    • hook api,按书中描述,这一步我个人理解和IAT修复好像是一样的?
    • 跳转到OEP,简单情况下壳与OEP之间有明显的分界线,但有的壳会将OEP代码段搬到外壳的地址空间,然后擦除这段代码(stolen bytes),从而消去这条分界线。

    在调试器中,看见的都是call 立即数,call [ebp+x],很容易茫然。书中给了一个例子,流程如下:

    • 调用getProcAddress,获取virtualAlloc的地址
    • 调用virtualAlloc,为壳的第二部分申请空间
    • 调用解压函数
    • 跳转到壳的第二部分
    • 解压各区块,写回
    • 重建IAT
    • 反DUMP
    • 返回OEP

    脱壳的一般过程

    最终目标是文件能够正常运行。

    • 找OEP
    • dump内存
    • 重建可执行文件

    一种方法是,从壳的开始处跟踪,直至到达代码段。

    脱壳后无法运行的一种可能原因:附加数据

    感觉这是一种不错的反调试方法。在可执行文件的末尾附加上一段数据,这段数据不会被映射进内存,块表里也看不见。所以脱壳时dump内存,结果无法正常运行(信息损失了)。
    除了将附加数据粘贴到脱壳结果,代码上可能也需要修改文件指针的偏移量,总之最终要确保能读取附加数据。

    “完美”脱壳的评价标准

    基本标准是可以运行。完美则不止于此。

    • 输入表存储位置最好与原来相同。重建时不讲究的话可以存在新增区块。原位置的推测主要是要熟悉各种编译器会把输入表存在哪。
    • 图标等不应当随壳一起被脱掉。需要去外壳中找回来,然后放回rsrc段。资源修复工具如DT_ResFix。
    • 区块调整。删除一些不用的区块(既在块表中删,也删实际内容)。
    • PE文件头修复。

    一种强行下断的方法

    将汇编指令改为EB FE,就能简单实现一个死循环。FE是-2。

    upx魔改相关

    魔改的目的是,用最少的劳动阻止upx -d官方脱壳。
    upxpr,只修改了两个地方(块名和upx!),手工改回来即可。判断时或许可以看段总数和段名。
    upxfix_by_diken,这个在看雪上能找到,据说能把魔改壳改回普通壳。

    aspack的手脱

    upx破坏了输入表和重定位表,并且会合并区块。而aspack则都不会。
    aspack直接对text段的实际内存地址(imagebase+text voffset)下写断点,就能等到解压完毕。

    asprotect的原理

    用得比较广泛、研究得也比较多的加密壳。

    • 外壳校验。这加大了脱壳难度。权宜之计是在想要修改的地方下断点,然后修改eip。
    • emulate standard system function。把标准api的开头代码移到壳里,然后把标准api调用代码改为壳调用代码。对抗时,用patch覆盖上述过程,在IAT表中搜索当事api,然后把当事api地址写回原来的代码。
    • stolen bytes。将代码变形,然后搬进外壳段。

    寻找oep的经验

    dll的oep可以在载入时找,也可以在退出时找。退出时找更容易,书中示例也都是退出时找。

    od中patch

    可以patch任意一条指令而做到只添加不删除。
    比如将or al,al指令修改为jmp,
    在jmp的目标位置先做想做的事(先pushad,最后popad),此过程中可以用hideOD这样的插件来分配空间,
    然后最后or al,al,再jmp回原来or al, al的下一条指令。

    beingdebugged的连串反应

    beingdebugged为true,为影响ntglobalflag,进一步影响heap flag,影响堆的填充内容。如果不从源头上消灭,会留下很多痕迹。

    加密之道

    任何单个的反调试手段,破解起来都不困难。将常见的手段组合起来,就能拖垮耐心。

    检测调试器的存在

    除了检查窗口名称和进程名称,其实还有很多方法。
    windows提供了进程间互访内存的函数,readprocessmemory和writeprocessmemory。用virtualprotect函数设置权限之后,就能读写进程的地址空间。

    • 特征码法。枚举当前运行的进程,检查每个进程特定位置的内容。此法版本敏感。
    • 检测进程是否加载dbghelp.dll。
    • 检查进程是否具有sedebugprivilege权限。
    • 父进程检测。正常启动时父进程一般是cmd、explorer、services。
    • 两次汇编指令RDTSC之间的时间差。

    dll劫持

    类似Linux的preload library,但只能劫持非核心系统库DLL,比如网络应用程序中的ws2_32.dll和游戏中的d3d8.dll,以及大部分应用程序都会用的lpk.dll。

    特别的反调试思路

    • 攻击调试器。比如向调试器发送格式化字符串。
    • 双进程保护。一个进程只能有一个调试器。

    附加

    如果不方便用调试器启动,可以先启动目标进程,然后附加。调试游戏时一般附加。

    软件保护相关

    切记,试用版不能包含重要功能的代码。
    序列号机制的本质是,对比用户输入序列号和内置算法生成序列号。
    较为简单的注册机的本质是正向(而非逆向)抠出了内置生成算法,此算法一般的输入是用户名、机器信息等。
    “期望的用户输入”在任何时候都不应该出现在内存中。生成端再复杂都没用,关键是用户输入端。CTF中也是如此,以strcmp为界,其实只有输入一侧需要研究。
    如果使用对称加密的话,用户输入的注册码应作为密钥,而不是明文。否则密钥就只能硬编码,硬编码的结果就是别人容易写出注册机。对称加密的秘密是密钥。
    如果使用非对称加密的话,生成算法不放在软件本地,版权方用私钥签名来生成。输入端需要输入一个能被公钥成功验签的内容。
    针对各类签名算法的软件保护,都可以用patch n的方法来攻击。有点打包重签名的意思。修改算法中的大数n,自己制定私钥,写出注册机,一起重新发布即可。

    取证相关

    PC取证

    取证标准要求不能开机。硬盘被系统挂载时会有数据写入,导致污染。
    不能拆机时,使用linux可启动光盘启动目标计算机,然后用dd命令复制硬盘。
    能拆机时,可以借助硬盘复制机连接src和dst,或者用另一台取证计算机(linux用dd,windows用winhex)。

    手机取证

    手机自带的闪存芯片焊在主板上,部分手机会用SD卡。前者可以用热风枪吹下来(chip-off,但有损坏风险),后者直接用读卡器即可。
    自带存储的取证可以用JTAG法,通过跳线将手机置于调试模式。
    对于已root、开启usb调试的手机上,将/system分区以读写模式重新挂载,把busybox装进/system/xbin,然后nc、dd。
    移动设备中不能被用户使用的分区有很多。正常情况下,只有/data和/mnt/sdcard以读写模式挂载,因此大多数取证操作中只需要检查这两个分区就可以了。

  • 相关阅读:
    简单三步 用GPT-4和Gamma自动生成PPT PDF
    C语言01、数据类型、变量常量、字符串、转义字符、注释
    连接池及Druid(德鲁伊) 数据库连接池
    安卓毕业设计源码基于Uniapp+SSM实现的校园心理健康APP
    软件设计模式(六):迭代器、访问者、建造者模式
    Spark 3.0 - 8.ML Pipeline 之决策树原理与实战
    16【数据库的范式】
    GBase 8s的封锁技术的基本介绍
    太强了,用Excel玩机器学习
    推荐系统(业务侧)小结
  • 原文地址:https://blog.csdn.net/weixin_42100211/article/details/127266508