状态
Done

一、SMC简介:

SMC,即Self Modifying Code,动态代玛加密技术,简单来说就是将一段正常的代码加密保存,在需要运行这段代码时调用解密函数对该加密代码进行解密,等运行完这段代码后又调用加密函数将代码重新加密保存,这样做的好处就是当对该段代码进行静态分析时啥也看不出来,以此达到保护代码的效果。

二、SMC技术实现:

ASC CODE
 

三、SMC逆向:

题目附件
tips:将后缀改回exe即可
以HWS的一道讲题为例,先运行程序可以看到提示要输入授权码:
notion image
放到EXEinfope,64位程序,无壳:
notion image
用IDA打开,搜索字符串Authorize:,定位其所在函数:
notion image
下方调用了两个函数,函数一:
notion image
函数二:
notion image
函数二没啥好分析 的就是输入一堆字符串,主要分析函数一:
notion image
稍微调整一下变量名,主要加密逻辑在40到48行的for循环,输入的flag和key值经过42行的运算得到的值和cipher数组要相同,想要获得flag的值在简单的办法就是考虑通过枚举的方式来求解,脚本如下:
运行脚本得出结果:
notion image
Caucasus@s_ability
得到这串字符串,打开终端尝试运行:
notion image
发现程序运行后什么也显示就退出程序了,这里是程序中有检测调试器的函数,还是shift+f12查看字符串:
notion image
可以看到有以下几个调试工具的字符串查看其交叉引用:
notion image
这里调用了GetWindowTextAAPI,如果窗口标题为上图几个逆向工具则将a2赋值为1,它作为返回值,返回到下图,作为是否退出程序的依据。
notion image
patch掉这个exit:
notion image
再次运程序,就可以正常运行了:
notion image
但是新的问题又来了,输入完授权码之后只是将前面函数二的内容输出就又退出程序了,这里可以回到函数一,发现一些端倪:
notion image
接收用户输入的变量flag并不是在该函数定义的,它是一个全局变量,查看其交叉引用:
notion image
flag变量在另外一个函数也被调用了,更过去看一下:
notion image
VirtualProtect()函数参数
参数介绍:
  • lpAddress:需要修改权限的内存起始地址
  • dwSize:需要修改的区域大小
  • flNewProtect:需要修改的内存权限
    • 具体参数:
      • 常量/值
        说明
        PAGE_EXECUTE0x10
        启用对已提交页面区域的执行访问。
        PAGE_EXECUTE_READ0x20
        启用对页面已提交区域的执行或只读访问。
        PAGE_EXECUTE_READWRITE0x40
        启用对页面已提交区域的执行、只读或读/写访问权限。
        PAGE_EXECUTE_WRITECOPY0x80
        启用对文件映射对象的映射视图执行、只读或复制写入访问。
        PAGE_NOACCESS0x01
        禁用对页面已提交区域的所有访问。
        PAGE_READONLY0x02
        启用对页面已提交区域的只读访问。
        PAGE_READWRITE0x04
        启用对已提交页面区域的只读或读/写访问权限。
        PAGE_WRITECOPY0x08
        启用对文件映射对象的映射视图的只读或复制写入访问权限。
        PAGE_TARGETS_INVALID0x40000000
        将页面中的所有位置设置为 CFG 的无效目标。
        PAGE_TARGETS_NO_UPDATE0x40000000
        当 VirtualProtect 的保护更改时,区域中的页面不会更新其 CFG 信息。
  • lpflOldProtect:指向一个变量的指针,该变量接收页面指定区域中第一页的上一个访问保护值
返回值:
  • 如果该函数成功,则返回值为非零值。
  • 如果函数失败,则返回值为零。
这个函数的作用为某段数据解密并赋予运行权限。在for循环之后下断点就可以查看到被加密的函数,但是在此之前还需要看一下该函数的交叉引用,因为需要找到程序直接退出的原因,找到调用该函数的上层函数:
notion image
查看该函数调用的第二个函数,大概逻辑是如果运行该程序时有图形窗口就退出程序,这个也很好理解,该程序本身是在命令行中运行,不需要图
notion image
notion image
形界面,这也算另外一种检查是否被调试的方法。这里依然是将其patch掉。
notion image
patch掉exit后,程序就正常显示出来之后的内容了,回到SMC处在For循环之后下断点:
notion image
运行调试器,定位到加密代码:
notion image
选中加密的代码按c转换为汇编代码,然后按p转换为函数,最后F5就可以看到伪代码了
notion image
这里还提供另外一种常见的解密方法,就是利用IDAPython对代码直接解密具体的解密脚本为:
查看解密后的代码:
解密的逻辑和之前一样还是暴力破解:
notion image
flag{Thousandriver_is_1000%_stronger_than_zero-one}

实例程序:

  1. 简单的SMC:
    1. 📖
      实例一
  1. Linux下的SMC:
    1. 🕵️
      实例二