Simple Reverse in the Real World

害, 人菜瘾大, 学了一点点逆向之后就想要来干点大的. 虽然平时 见到的软件一个也不会逆向 – 因为太大了, 并且也不知道如何下手.

不过最近可是让我搞到了一个好的练手的项目: 故事类似于这样

aq: [File] U.exe
aq: 来个逆向
aq: 阶教大厅中的病毒 belike
me: 中
me: 乐
...

这个 “病毒” 和以前高中里面办公室里面的十分类似, 一个简单的 表现就是会将周围 (比如 U 盘) 里面的文件隐藏起来, 然后生成 一堆奇怪的 .exe 文件, 诱导受害者点击这些程序, 以为自己在 打开正常的文件 – 最后继续传播.

一个简单的恢复方法就是直接使用 attrib 的命令来更改被隐藏的 文件, 然后删除掉那些奇怪的 .exe 文件. 我记得应该是 -s -h 属性标签. (具体可以参考Microsoft Doc).

Ghidra

因为之前都没怎么解除 Windows 的逆向程序, (因为没有 Windows 可以用)… 所以去学了一点点, 现学现卖了属于是.

WINAPI 与虚拟内存

首先出现的一个 Boss 就是 Windows API, 和在 Linux 中的东西不一样, Windows 有 Windows 自己的一套 “黑话”. 比如 GetCommandLineA 等函数, 虽然光看 GetCommandLine 确实容易理解 – 顾名思义嘛, 但是后面的 A 是什么东西? 尤其是当你在查文档的时候还会看到类似的 W 结尾的东西, 有时候就更奇怪了. ( 好吧, 没准只有我这种菜狗才会 觉得奇怪… 比如在 unix 那里, 如果名字稍微有点不一样的话, 一般 属于是那种稍微有点不同的函数) 在 Windows 这边, 好像这样的 AW 则表示的是函数的参数传递的方式是 ANSI 还是 Widechars 的区别. 虽然不是很了解, 但是我认为这样的操作应该是为了兼容旧的电脑的操作.

如果想要查找 Windows API 的话, 可以跑到微软的 文档 那里看.

至于虚拟内存, 感觉不太理解.

入口

扔到 Ghidra 中, 然后在 entry 中, 可以看到:

void entry() {
  __set_app_type(_GUI_APP);
  _mainCRTStartup();
}

entry 里面指定了程序的类型(_GUI_APP, _CONSOLE_APP, _UNKNOWN_APP, 可以在 internal.h 中查看… )

然后用了一个函数 (_mainCRTStartup, 名字是我改的, 之后到 Windows 上面之后再多练习一些… ) 来启动 main 函数, 也叫作启动函数. 所以尽管在 _mainCRTStartup 里面有一堆乱七八糟的东西, 但是程序的返回值肯定应该是要和 main 有关的, 所以在 uExitCode 的地方, 对应的应该就是 _main 函数: (uExitCode = _main())

Function in MAIN

用类似于伪代码一样的方法来写就是:

void _main() {
  // ... 两个比较奇怪的函数
  cmd_line = GetCommandLineA();
  GetStartupA(&startupinfo);
  // 应该是一串处理文件路径的操作, 其中有关键字符 '\t', ' '
  execute();
}

其中 execute() 中在最后有两行:

  ShellExecuteA((HWND)0x0,"open","explorer.exe", file_name,"",1);
  ShellExecuteA((HWND)0x0,"open","System Volume Information\\banana.exe","","",1);

这个应该算是一个比较合理的一个结果了: 执行真正的文件, 顺带执行 banana.exe, 即应该是病毒的本体. 关于 banana.exe, 在网络上搜索了之后, 发现是一个类似于挖矿病毒的东西. 但是我好像找不到这个东西. 之前在高中里面删除这玩意的时候也没有见到过. 所以就很奇怪.

隐藏文件和修改图标的操作 (待定)

不太理解 Windows 的文件管理 (其实 Unix 的也不太会, 但是至少了解一些些的 chmod667 之类的东西. ), 只是在代码里面看到了一些比较有意思的, 好像有点东西:

  puVar1 = (undefined4 *)&stack0x00000004;
  for (; 0xfff < in_EAX; in_EAX = in_EAX - 0x1000) {
    puVar1 = puVar1 + -0x400;
    *puVar1 = *puVar1;
  }

也不知道这个 0x400 对应的是什么文件权限, 还是别的什么东西… 不过凭直觉, 感觉应该是文件权限的操作. (具体还得要再试试, 如果网线到了的话就好了… )

然后是一堆 if 语句:

    if ((uVar4 & 0x100) != 0) {
      DAT_00404030 = DAT_00404030 | 1;
    }
    if ((uVar4 & 0x8000) != 0) {
      DAT_00404030 = DAT_00404030 | 2;
    }
    if ((uVar4 & 0x800000) != 0) {
      DAT_00404030 = DAT_00404030 | 4;
    }

猜测应该和图标有关, 类似于更改图表的属性呢? 差不多吧.

然后

目前还有的问题

  • 找不到本体, 以及本体的传播路径和方法. (总不能真的是全靠人 们拷贝复制吧? 病毒这么民风淳朴的么. )
  • 一些特殊的操作不太确定, 比如隐藏文件的操作. 对应的代码没有 找到. 所以想要尝试来调试一下.

感谢

感谢 aq 大佬整的样本. 感觉在 Windows 下的逆向有点不太会, 之后 可能会去那个方向多试试… (麻了, 实在是菜爆了. )

不过目前都是无调试的单单看 Ghidra 的输出的判断, 感觉还是需要 把程序跑起来看才可以. 在 Ghidra 里面有很多的反编译做得并不是特别好, mac m1 下的虚拟机目前(2022/9/11: UTM 3.2.4)又对非 arm 架构的支持得 不是很好. 所以我向一个学长整了台烂机子跑 Windows.

(等过几天网线到了, 我就把这个 post 更新一下. 害, 疫情真是狗. 外地能进的, 本地的就进不得, 总不能是嫌我网线太便宜了吧… )

关于样本

关于样本… 我不知道该不该把它放上去… 如果放的话, 万一有谁把我 反手举报了, 说我传播… 如果不放的话, 就有那么点不太合理. 有违 共享信息的原则… 所以我就做了一些防呆措施, 即将下载的连接隐藏了, 并且还将文件压缩了, 所以真的出了问题, 请不要指责我. 最后, 病毒样本就在下方的图片里面:

example