首页
社区
课程
招聘
[原创]shellcode免杀框架内附SysWhispers2_x86直接系统调用
2021-1-28 19:17 27923

[原创]shellcode免杀框架内附SysWhispers2_x86直接系统调用

2021-1-28 19:17
27923

1、概述

之前分析CS4的stage时,有老哥让我写下CS免杀上线方面知识,遂介绍之前所写shellcode框架,该框架的shellcode执行部分利用系统特性和直接系统调用(Direct System Call)执行,得以免杀主流杀软(火绒、360全部产品、毒霸等),该方式也是主流绕过3环AV、EDR、沙箱的常用手段。Ps:感谢邪八Moriarty的分享课。

2、简要介绍

该框架主要由四个项目组成:
GenerateShellCode:负责生成相关功能的shellcode。
EncryptShellCode:负责以AES128加密所将执行的shellcode。
FunctionHash:负责计算shell中所用到函数的hash值。
XShellCodeLoader:负责执行加密后的shellcode。

2.1 GenerateShellCode

以简单弹窗messagebox生成的shellcode作介绍,定义的入口函数MyEntry(),先定义了GetProcAddr()、LoadLibaryA()和MessageBoxA()三个函数对应的hash,然后通过MyGetProcAddress()传入hash值和kernel32基址返回相关函数地址再进行调用。

 

自定义函数入口需在项目属性->链接器->入口点中进行设置:

 

通过GetKernel32Base()函数获得kernel32基址:

 

通过MyGetProcAddress()函数传入hash值找出对应的函数名,函数内容就是解析kernel32的导出表,遍历每个函数并计算出相应hash并与传入的hash作比较:

 

GetProcHash()把函数名转为相应的hash:

 

Release x86模式生成后exe程序后,010editor打开找到.text代码段,将其抠出后得到shellcode:

 

2.2、EncryptShellCode

首先打开已经抠出的shellcode文件,并将器读入内存:

 

AES循环加密0x10个字节AES加密的实现是WjCryptLib_Aes开源项目:

加密后保存到新文件:

2.3、FunctionHash

这个比较简单,计算所需要用到函数的hash值:

2.4、XShellCodeLoader

下面着重介绍下shellcode的执行实现,因为x86、x64进0环进3环的方式不同,在这里简单介绍下不同版本3环进0环的方式:
一、32位的程序在32位系统上运行有两种方式进0环,第一个是中断门int 02Eh,第二种是sysenter
二、32位的程序在64位系统上运行,通过FastSystemCall进0环
三、64位的程序在64位系统上运行,通过syscall进0环
这里用vs的Release x86来进行编译,所生成的32位exe程序在32位系统运行使用sysenter进0环,在64位系统则使用FastSystemCall进0环。

 

下面我们先以32位程序运行在32位系统的sysenter进行讲解:
首先自定义一个区段,该区段的属性最好只为read,一定不要read、write、execute全上,这种全属性在内存中会显得很可疑,区段名最好为系统常用的而这个程序又没用到的,如.edata,因为360杀毒可能会对不常见的区段名报毒,另外不建议使用#pragma section(".edata",read,execute,nopage) 该方式定义区段名,因为该方式生成的区段会出现在程序中所有区段的最前面,360杀毒报毒,特征较明显。使用以下方式去定义区段,区段的内容为已AES加密的shellcode:

然后通过遍历自身程序的区段查找出自定义的区段:

接着调用NtProtectVirtualMemory()修改自定义区段的属性为可读可写,即readwrite,

而NtProtectVirtualMemory()是由汇编所写的直接系统调用:

解析上述汇编,首先把001911B13h这个对应NtProtectVirtualMemory函数名的hash值压栈,然后调用SW2_GetSyscallNumber函数(后面解析syswhier框架时会提及),该函数会返回NtProtectVirtualMemory对应的系统调用号,mov ecx,5h是把函数个数赋值给ecx,再把NtProtectVirtualMemory()函数所传入的参数相继压栈,然后调用sysenter。

 

接着循环把自定义区段解密出来:

 

把自定义区段的属性还原到read、execute:

 

执行shellcode:

 

再来看看32位程序运行在64位系统的KiFastSystemCall,其主要区别只在于汇编部分:

 

Call internal_cleancall_wow64_gate,
internal_cleancall_wow64_gate的值为__readfsdword(0xC0),即FS[0xC0] WOW32Reserved

3、执行效果

3.1、实验环境:

Team server: Kali 2020 ip: 192.168.202.131
控制端:win7 32位 ip:192.168.202.134
受控端1:win 7 32位 ip: 192.168.202.140
受控端2:win10 1907位 ip: 192.168.202.1

3.2、32位系统执行

火绒版本号:

静态查杀,未发现风险:

 

360安全管家及360杀毒版本号:

 

静态查杀,未发现风险:

 

执行均未拦截,运行上线:

 

卡巴斯基,静态扫描未发现风险:

执行时则被查杀:

原因是stage执行下载后的Beacon.dll在内存中反射调用时被卡巴斯基规则检测到,也有相应的解决办法,等下篇文章魔改cobalt strike再来相应解决。

3.3、64位系统执行

同样成功执行并上线(测试过程同上)

 

附上框架项目地址:
https://github.com/mai1zhi2/ShellCodeFramework

4、SysWhispers2项目简介

该项目较为简单,主要方法有三个:
一、SW2_HashSyscall()

该方法是计算传入的函数名的hash值。

 

二、SW2_PopulateSyscallList()
该函数中首先找到ntdll的基址:

遍历ntdll.dll的导出函数,并将其函数名对应的hash值和函数地址保存在SW2_SYSCALL_ENTRY结构体中:

将SW2_SYSCALL_ENTRY的列表按照函数地址进行从小到大冒泡排序:

 

三、SW2_GetSyscallNumber
该函数传入需要的函数hash值,遍历列表,返回对应的序号即系统调用号

 

原版只有64位程序运行在64系统的syscall,最后附上该项目修改后的32位程序运行在32位系统的sysenter和32位程序运行在64位系统的KiFastSystemCall版本,使用方法均与原版一致:
https://github.com/mai1zhi2/SysWhispers2_x86


[培训]《安卓高级研修班(网课)》月薪三万计划,掌 握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞8
打赏
分享
最新回复 (24)
雪    币: 0
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
会飞的鱼z 2021-1-28 22:30
2
0
大佬  请接受我的克隆头   学习了   以后还会关注你
雪    币: 292
活跃值: (153)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Dstlemoner 2021-1-29 00:08
3
0
以前免杀好火,后来不是中病毒,是中杀毒软件。。。哈哈哈哈哈 苦练免杀,结果大佬直接开后门进,跟进自己家一样。
雪    币: 3126
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
我来自南方 2021-1-29 09:08
4
0
你公开了,那么,免杀也就随之不免杀了
雪    币: 225
活跃值: (1487)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_0xC05StackOver 2021-1-29 10:55
5
1
我来自南方 你公开了,那么,免杀也就随之不免杀了
他这个方法免杀对于payload加载器来说其实是个非常好的思路,因为现在动态的对于syscall除了沙箱模拟跑这个行为之外,普通的进程注入拦截检测手段非常非常有限,在x64上也不能在内核挂钩ntprotect这个函数做检测了,所以整体来说个人认为效果还是不错的,但是这个syscall模拟在不同版本系统上的函数index不一样需要处理此外还需要处理32位的问题因为syswow64中间层拿到的不是真正的ntdll,而是wow64的,杀软可以在wow64上面做hook检测,所以32还需要涉及32->64天堂之门的段寄存器转换,要稍微麻烦点,还有一个不好的点在于这个shellcode没有做混淆,个人认为使用llvm编译这个shellcode在ir层做一次混淆效果会更好这样跑起来shellcode的内存特征就没有了
雪    币: 5435
活跃值: (11850)
能力值: ( LV12,RANK:312 )
在线值:
发帖
回帖
粉丝
一半人生 5 2021-1-29 19:46
6
0

不错的,免杀第一阶段静态+回连已经够了,这个和免杀壳效果大体一样。

过动态执行需要对cs(木马)操作,如创建文件几乎杀软都会拦截,有效的r3代码-shellcode可以绕过监控/回调及对象拦截比较困难,但也是很有价值的。

最后于 2021-1-29 19:47 被一半人生编辑 ,原因:
雪    币: 2865
活跃值: (8493)
能力值: ( LV13,RANK:390 )
在线值:
发帖
回帖
粉丝
快乐鸡哥 7 2021-1-29 21:15
7
0
wx_0xC05StackOver 他这个方法免杀对于payload加载器来说其实是个非常好的思路,因为现在动态的对于syscall除了沙箱模拟跑这个行为之外,普通的进程注入拦截检测手段非常非常有限,在x64上也不能在内核挂钩ntpro ...

高手竟在我身边

最后于 2021-1-29 21:20 被快乐鸡哥编辑 ,原因:
雪    币: 15
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ﺭ并亲了你一下ﺭ荒 2021-1-31 15:08
8
0
mark 免杀
雪    币: 1556
活跃值: (2122)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
killleer 2021-1-31 17:46
9
0
Dstlemoner 以前免杀好火,后来不是中病毒,是中杀毒软件。。。哈哈哈哈哈 苦练免杀,结果大佬直接开后门进,跟进自己家一样。
以前的人死脑筋,现在的人真TM心狠手辣,无所不用其极
雪    币: 2190
活跃值: (926)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
rushmaster 1 2021-1-31 21:03
10
0
感谢分享。。
雪    币: 2674
活跃值: (2304)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
低调putchar 1 2021-2-1 11:12
11
0
好帖子!值得参考!
雪    币: 4150
活跃值: (702)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Hades一KXXY 2021-2-3 09:18
12
0
雪    币: 23
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
Tupler 2021-2-18 11:38
13
0
mark
雪    币: 324
活跃值: (529)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
newu 2021-3-1 15:21
14
0
嘤嘤嘤,刚编译好就被火绒杀了...
雪    币: 3028
活跃值: (1458)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
MsScotch 2021-3-1 17:10
15
0
看到好长一段时间炒 syscall方式绕杀软的,为什么不去重新map一份 ntdll、kernel32 ?map之后需要修复的地方比较少,而且稳定。
雪    币: 225
活跃值: (1487)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_0xC05StackOver 2021-3-3 14:33
16
1
MsScotch 看到好长一段时间炒 syscall方式绕杀软的,为什么不去重新map一份 ntdll、kernel32 ?map之后需要修复的地方比较少,而且稳定。
因为这个地方 如果调用原生的x64的syscall 除非是用类似于qemu的仿真沙箱 不然不好检测
雪    币: 242
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_hgrbqfun 2021-10-20 16:57
19
0
mb_plkoupkf 可以加Q交流一下吗 852056282
你怎么一直在发这个叫别人加qq,是广告狗吗,到处都有你
雪    币: 428
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hehehero 2021-10-21 20:01
20
0
感谢分享。。
雪    币: 4132
活跃值: (2609)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
linghaien 2022-1-9 01:46
21
0
那个取peb的汇编是通杀win 系统吗。我看到几个版本的这种,都有一点区别,但是有些是部份电脑会崩
雪    币: 6
活跃值: (546)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
大佬求关照 2022-1-11 21:53
22
0
这个易语言好像有类似的源码叫KiFastSystemCall,帖子说的是一个基于Baby大佬改的,但不知道github上有没有
那个是通过读系统DLL文件,从EAT定位到代码,然后取到NT函数的SSDT号,再调用
雪    币: 763
活跃值: (2707)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tmflxw 2022-3-25 14:00
23
0
我测试wow NtAllocateVirtualMemory,在win10成功,在win7 x64调用失败呢?
雪    币: 8
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
echotxl 2022-6-8 14:50
24
0
我在win7 x64测试的结果也失败了
雪    币: 4919
活跃值: (2806)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
ezre 2023-7-11 15:29
25
0

最后那个SysWhispers2_x86_WOW64Gate,看了一下,在win7 x64下似乎有些问题

比如NtWriteVirtualMemory函数 

NtWriteVirtualMemory PROC

push ebp

mov ebp, esp

push 0B018A6B4h        ; Load function hash into ECX.

call SW2_GetSyscallNumber

lea esp, [esp+4]

mov ecx, 5h

push_argument:

dec ecx

push [ebp + 08h + ecx * 4]

jnz push_argument

push ret_address_epilog ;ret address

call dword ptr internal_cleancall_wow64_gate ; call KiFastSystemCall

lea esp, [esp+4]

ret_address_epilog:

mov esp, ebp

pop ebp

ret

NtWriteVirtualMemory ENDP


ntdll.dll中的汇编代码是:

mov eax,37

xor ecx,ecx

lea edx,dword ptr ss:[esp+4]

call dword ptr fs:[C0]

add esp,4

ret 14


源代码好像少了lea edx,dword ptr ss:[esp+4]这一行,加上就执行成功了

NtWriteVirtualMemory PROC

push ebp

mov ebp, esp

push 0B018A6B4h        ; Load function hash into ECX.

call SW2_GetSyscallNumber

lea esp, [esp+4]

mov ecx, 5h

push_argument:

dec ecx

push [ebp + 08h + ecx * 4]

jnz push_argument

push ret_address_epilog ;ret address

lea edx,dword ptr ss:[esp+4];!!!!!!!!!!!!

call dword ptr internal_cleancall_wow64_gate ; call KiFastSystemCall

lea esp, [esp+4]

ret_address_epilog:

mov esp, ebp

pop ebp

ret

NtWriteVirtualMemory ENDP



最后于 2023-7-11 15:30 被ezre编辑 ,原因:
游客
登录 | 注册 方可回帖
返回