前言

  RunAsDate是一个小工具,允许您在指定的日期和时间运行程序,不过有人用它来破解有时间限制了。此实用程序不会更改计算机的当前系统日期和时间,但只会将指定的日期/时间注入所需的应用程序。该软件是个免费软件,可以通过 官网 下载。有一天想看看它到底怎么实现的。经过分析是通过注入dllHook几个关于时间获取API实现的。32位的和64位的代码实现没啥区别,本篇以64位进行分析,32位感兴趣自行分析。

主角和工具

  • Detect it easy 1.01
  • IDA 7.5
  • X64Dbg
  • RunAsDate

探测

  我们先到官网下载原汁原味的程序,如下图所示进行下载:

  解压后,得到了3个文件:

  运行该软件,界面如下:

  为了检验工具的效果,先写一个获取时间的C代码(随便一个语言就可,不过代码需要自己写),如下:

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4. int main()
  5. {
  6. time_t t;
  7. time(&t);
  8. struct tm _t;
  9. errno_t err = localtime_s(&_t, &t);
  10. err ? puts("获取时间失败!!!") : printf_s("%d/%0.2d/%0.2d\n", _t.tm_year + 1900, _t.tm_mon + 1, _t.tm_mday);
  11. system("pause");
  12. return 0;
  13. }

  编译运行,获取得到当前时间:

  来试试工具有没有效果,注意把下图所示的红框框住的选项选中,否则没效果,然后点击运行,发现起作用:

初步分析

  既然工具咋用已经探测完毕了,我们来进入分析环节。先用Detect it easy 1.01探测一下:

  是C++写的,且没有任何加壳,为逆向分析降低了足够的难度。直接拖到IDA进行抄底。启动一个新进程的API函数有很多,有ShellExecuteEx系列函数、ShellExecute系列函数和CreateProcess系例函数。我们都给下上断点,来看看它到底是用哪个函数启动的,设置好点击运行,断点断到CreateProcessW,如下图所示。

  通过堆栈定位可以定位到调用地址,如下图所示:

  定位到IDA中,然后大体分析一下函数,重命名一些函数方便进一步分析,并发现一些可疑函数,命名好名字,关键伪代码如下面几张图所示:

  下图是执行上面子函数的主过程。有经验的一看就知道,这就是典型的远程线程注入过程。

  什么是远程线程注入呢?首先你准备一个待注入的Dll,假设名字为A.DLL。如果加载一个Dll,常规的办法就是用LoadLibrary函数加载。然而我是A进程,想让B进程调用函数,就必须启用一个线程,需要调用的API就是CreateRemoteThread函数,只能通过lpParameter传递一个参数。它们的函数原型如下:

  1. HANDLE WINAPI CreateRemoteThread(
  2. __in HANDLE hProcess,
  3. __in LPSECURITY_ATTRIBUTES lpThreadAttributes,
  4. __in SIZE_T dwStackSize,
  5. __in LPTHREAD_START_ROUTINE lpStartAddress,
  6. __in LPVOID lpParameter,
  7. __in DWORD dwCreationFlags,
  8. __out LPDWORD lpThreadId
  9. );
  10. HMODULE WINAPI LoadLibrary(
  11. _In_ LPCTSTR lpFileName
  12. );

  而每一个进程中,LoadLibrary函数地址都是一致的。故我需要通过一段ShellCode,将一些参数聚合起来直接传给它,让它负责分析传来的参数并实现注入功能。而ShellCode怎样写到B进程呢?通过VirtualAllocate(Ex)函数和WriteProcessMemory函数配合将ShellCode和待解析的参数一块写进去。从IDA分析结果可知,ShellCode就是sub_140006B3C,我们来看一下:

  为了方便阅读,伪C代码如下:

  从ShellCode很明显看出。a1就是通过CreateRemoteThread传来的参数。a1的地址加40偏移的值就是一个函数地址,在把a1的地址加上64的偏移作为参数传入得到返回值v2v3应该是一个函数地址,通过a1加上48的偏移,把v2和a1加上586的偏移作为参数传入得到返回值v3,如果返回值不为空调用v3,把a1加上620的偏移作为参数进行传入。只从ShellCode看不太出来是啥,如果有经验就应该大体能猜出来。具体分析一下它传过来的参数是如何包装的。

  从上图发现*(lpFileName + 66)就是所谓待注入进程调用ShellCode的参数。而从Buffer存储写进去,但遗憾的是,我压根不知道Buffer里面的内容到底是啥,看前面的伪代码也看不出来,只看到它的首地址被清零。这个就是F5插件的缺陷。它反编译成伪C代码不是准确的,甚至是错误的,比如函数调用的参数有时会有错误,或者直接JMPOUT,还是看汇编准确。不过我们可以看一下BufferIDA识别为char,但明显看到使用该变量的函数告诉咱们这个是大小至少为0x288char数组。故我们可以看看Buffer的堆栈来进行修正。

  从堆栈可以明显看出所谓是fucs就是属于Buffer的,所以上面的部分就是给参数打包的过程。我们直接改Buffer,将它改为char Buffer[288]。然后重新F5,看一下代码的变化:

  反编译出来的伪C代码就看起来正常了,虽然看起来还是比较别扭,不过包装参数的过程比较明晰了。然后我们把它拖到X64Dbg,来进行验证一下过程,我们先通过下VirtualAllocEx断点获取它们返回的申请到的物理页虚拟首地址,把它记录下来。

  然后在CreateRemoteThread下断点,停住创建的待注入的程序。然后另起一个X64Dbg附加上,直接看一下记录的地址的内容。首先我看的是参数部分,直接在内存窗口选好0x288字节保存到文件,方便一一对应,如下图所示:

  下图就是所谓的ShellCode,在函数头部下一个断点:

  然后放开RunAsDate程序,被注入的程序就停在上一步下的断点上,然后我们一步一步的跟,看看调用的是什么函数,先跟到第一个,发现是LoadLibraryW函数:

  其次就是GetProcAddress函数,用来获取DllInitDate函数地址:

  然后校验获取是否成功,传参FILETIME结构体调用InitDate函数:

  根据IDA和X64Dbg的分析,每个数据的对应如下图所示:

深入分析

  通过初步分析我们知道了这个软件的基本原理。但功能实现全部在所谓的dateinjo1_64.dll当中。我们可以在注入的程序时,直接从临时文件夹薅出来。在之前函数分析也知道它是直接把资源释放出来的,直接用资源编辑工具也能提取出来,这我就不继续描述了,直接开始分析。具体分析过程就不详细描述了,完全凭自己的正向开发经验,这个Dll很简单,最后命名好名字后如下图所示:

  综上可以看出,它是通过对GetLocalTimeGetSystemTimeGetSystemTimeAsFileTime这三个函数进行挂钩子。怎么挂钩子的可以在详细介绍一下:

  可以看出,它是通过构造一个movjmp+死地址进行Hook,感觉不直观,来看一下下面一个被RunAsDate注入的被挂钩的函数:

  通过上图,知道为什么代码要这样构造了吧?

总结与思考

  • RunAsDate并不高大上,原理很简单,其实本质就是用了远程线程注入+Hook所有获取时间函数的API的方式实现时间的控制。
  • 有些人利用RunAsDate,来破解一些软件时间使用限制。想要保护自己商业软件的合法权益,可以通过它的实现原理,检查是否程序模块有没有它的Dll,有的话直接退出程序或者修复Hook。也可以检查函数是否被Hook的方式进行反制。
  • 使用IDA时,不要过于依赖F5,虽然直观方便,但它反编译出的伪C代码并不是完全正确的,甚至是错误的,如果想弄对必须进行修改调整。
  • 软件的Hash值:EF847F60C02856AB013438D7A55A6CC1
  • 64位的注入的Dll的IDA分析结果:蓝奏云下载 —— 密码:f854

羽夏逆向破解日记簿——RunAsDate的实现原理分析的更多相关文章

  1. 羽夏逆向指引—— Hook

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你的, ...

  2. CrackMe005-下篇 | 逆向破解分析 | 160个CrackMe(视频+图文)深度解析系列

    作者:逆向驿站微信公众号:逆向驿站知乎:逆向驿站 CrackMe005,上篇说了具体方法,下篇来发逆向分析过程,看看老夫是如何得到上篇的具体方法的! 准备 [环境和工具] win7/xp虚拟机环境 C ...

  3. 跟羽夏学 Ghidra ——工具

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  4. 跟羽夏学 Ghidra ——引用

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  5. 跟羽夏学 Ghidra ——导航

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  6. 2018-2019-2 20165312《网络攻防技术》Exp1 PC平台逆向破解

    2018-2019-2 20165312<网络攻防技术>Exp1 PC平台逆向破解 一.Exp1.1 直接修改程序机器指令,改变程序执行流程 知识要求:Call指令,EIP寄存器,指令跳转 ...

  7. 羽夏看Win系统内核——简述

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  8. 羽夏看Win系统内核——SourceInsight 配置 WRK

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  9. 羽夏看Win系统内核——系统调用篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

随机推荐

  1. 【编程语言】Matlab 学习记录

    title: Matlab Learning Record date: 2020-05-23 20:11:26 author: liudongdong1 img: https://gitee.com/ ...

  2. 【java web】过滤器、拦截器、监听器的区别

    一.对比: 1.1 过滤器和拦截器的区别: ①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对actio ...

  3. C# 单元测试,测试资源管理器里面没有需要的单元测试

    已经创建了单元测试,却无法运行,更改引用的程序集,将TestPlatform换位QualityTools.UnitTestFramework.具体原因尚未分析,随笔记录.

  4. 一个基于activiti审批流程示例,如何与系统整合

    前言 目前市场上有很多开源平台没有整合工作流,即使有,也是价格不菲的商业版,来看这篇文章的估计也了解了行情,肯定不便宜.我这个快速开发平台在系统基础功能(用户管理,部门管理-)上整合了工作流,你可以直 ...

  5. Linux下cat命令的使用

    1.普通用法-->查看文件内容 cat file_name 查看文件时的相关参数: 1.cat f1.txt,查看f1.txt文件的内容. 2.cat -n f1.txt,查看f1.txt文件的 ...

  6. javascript(2)运算符

    ### js运算符 1.运算符 1.typeof 获取当前变量类型 运算符(特殊) 2.= 赋值运算符 3.== 简要比较运算符(忽略变量的类型) 4.=== 标准比较运算符(严格变量的类型.判断是否 ...

  7. jvm学习笔记:程序计数器

    程序计数器(PC Register) The Java Virtual Machine can support many threads of execution at once (JLS §17). ...

  8. Spring全自动AOP和项目加入jar包

    一.jar可以引进项目中,复制到路下后,要add as library,加载到工作空间中才能引入: 也jar包放在硬盘的项目目录外面,可以多个项目引入共用: 二.xml配置 1.aop全自动配置 2. ...

  9. Dockerfile 自动制作 Docker 镜像(一)—— 基本命令

    Dockerfile 自动制作 Docker 镜像(一)-- 基本命令 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 CentOS 7.0 云服务器 c. 上一篇:手动制作Do ...

  10. 手动制作Docker镜像

    手动制作 Docker 镜像 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 CentOS 7.0 云服务器(用来用去感觉 Windows 的 Docker 出各种问题,比如使用 ...