在学习中存在问题,在此记录下来
本次实现旨在了解病毒重定位的语句,和如何找到kernel32.dll的基地址。
本实验仿照编写具有自我重定位功能的64位代码并注入其他进程 - JackNoire's Blog 这篇文章,但最后并未成功注入。实现效果如下:

问题:在命令行运行后,结果显示注入成功。但系统中PID为“33732”的进程立刻停止运行。问过ai,但无法解决,ai回答如下:

若老师有空,希望指点一二。
病毒代码.c文件
一、编写c代码
![]()

在mb.c文件中,编写了一个无限循环的弹窗,效果如下:

我希望在目标程序运行时,可以出现这个关不掉的弹窗。
通过VS自带的cl命令,使用X64的编译器,得到了mb.c的汇编代码(mb.asm文件):

![]()
基于得到的.asm文件进行简化:
原版本如下:


修改后版本如下:

修改内容:
- 添加了user32.lib动态链接库来使用“MessageBox”函数
- 减少了开头的描述性文件
- 将数据段中的数据定义写入代码段中

- 删掉了pdata和xdata段
- 为MessageBo的参数使用mov传入寄存器(如果是lea指令,则这里使用的是相对寻址,不需要进行重定位的操作。为了说明重定位的原理,将其修改为mov指令,从而让这里使用绝对寻址。)
|
|
|
二、生成exe文件


这一步使得mb.exe的文件缩小

三、.asm文件中添加重定位代码
上边这张图是原来的代码,下边这张图是添加重定位的代码
|
(之前的代码) |
|
(添加重定位功能的代码) |
重定位功能使用“call reloc”命令,该命令自动在栈中存入“call reloc”这条指令的下一地址。因此在调用的reloc函数中“pop rbp”将里边在运行时的真实地址放入rbx。将静态编译得到的reloc函数地址,放入rax。rbx与rax的差值即为运行前后地址的差值。用差值与Caption变量的静态编译的地址相加,即可得到运行时的Caption地址。这个操作也就是重定位。
因为Caption变量中装的是“MessageBox”字符串,因此他的长度为10。通过这个前提可以算出下一个变量Text的地址为Caption变量的地址rbx+11(10个字符串再加结束字符“00”)。
四、用Kernel32.dll加载user32.dll
“MessageBoxA是user32.dll提供的一个函数。但是,并不是所有进程都会加载user32.dll,对于那些没有加载user32.dll的进程,注入的代码是无法正常运行的。不过,几乎所有进程都会加载kernel32.dll,而kernel32.dll中又包含LoadLibraryA和GetProcAddress,可以利用它们加载user32.dll并获取MessageBoxA的地址。”
修改的完整代码如下:

修改的内容:
- 动态链接库替换为“INCLUDELIB kernel32.lib”,链接两个函数
|
|
|
- 使用kernel3dll中的函数来调用“MessageBoxA”函数

五、kernel32.dll中的两个函数调用改为动态调用
下图是代码中调用LoadLibraryA和GetProcAddress函数的语句:

“将代码注入目标进程后,这两条语句就有可能不奏效了,因此把这两条语句处理一下。 “
首先找到LoadLibraryA和GetProcAddress的地址,可以写一个很简单的C语言程序来找:

运行结果为:

因此,对这两条语句作如下修改:
mov rax, 00007FFAB81C2D80H ;LoadLibraryA入口地址
call rax
mov rax, 00007FFAB81B3C70H ;GetProcAddress入口地址
call rax
得到代码:

生成exe文件

将exe文件用IDA pro将代码部分导出为c语言数组形式


编写注入程序
首先,要处理LoadLibraryA和GetProcAddress的地址。之前用的是本机预设的地址,在注入目标程序时候要获取真实地址:

完整注入代码如下:


运行测试

显示注入成功,但进程立刻被杀死,并没有执行病毒


如图,运行的进程强制结束了,并没出现弹窗。





650

被折叠的 条评论
为什么被折叠?



