Python實(shí)現(xiàn)向好友發(fā)送微信消息優(yōu)化篇
前言
之前說(shuō)了怎么寫(xiě)機(jī)器碼到內(nèi)存,然后調(diào)用?,F(xiàn)在說(shuō)說(shuō)怎么優(yōu)化。
第二次優(yōu)化
再看一遍c語(yǔ)言的代碼
void SendText( wchar_t* wsTextMsg) { // 發(fā)送的好友,filehelper是文件傳輸助手 wchar_t wsWxId[0x10] = L"filehelper"; WxBaseStruct wxWxid(wsWxId); // 發(fā)送的消息內(nèi)容 WxBaseStruct wxTextMsg(wsTextMsg); wchar_t** pWxmsg = &wxTextMsg.buffer; char buffer[0x3B0] = { 0 }; char wxNull[0x100] = { 0 }; DWORD dllBaseAddress = (DWORD)GetModuleHandleA("WeChatWin.dll"); // 發(fā)消息的函數(shù)call地址 DWORD callAddress = dllBaseAddress + 0x521D30; __asm { lea eax, wxNull; push 0x1; push eax; mov edi, pWxmsg; push edi; lea edx, wxWxid; lea ecx, buffer; call callAddress; add esp, 0xC; } }
上面的代碼真正發(fā)消息的是asm里面的代碼,之前的c代碼都是在組裝內(nèi)存數(shù)據(jù)。那我們是不是可以用Python組裝數(shù)據(jù),只講下面的匯編轉(zhuǎn)為機(jī)器碼寫(xiě)入內(nèi)存調(diào)用,這樣就少了很多無(wú)用的機(jī)器碼。
改完的SendText函數(shù)如下
wchar_t wsWxId[0x10] = L"filehelper";
wchar_t wsTextMsg[0x100] = L"test";
WxBaseStruct wxWxid(wsWxId);
WxBaseStruct wxTextMsg(wsTextMsg);
wchar_t** pWxmsg = &wxTextMsg.buffer;
char buffer[0x3B0] = { 0 };
char wxNull[0x100] = { 0 };
DWORD dllBaseAddress = (DWORD)GetModuleHandleA("WeChatWin.dll");;
DWORD callAddress = dllBaseAddress + 0x521D30;
void SendText() {
__asm {
lea eax, wxNull;
push 0x1;
push eax;
mov edi, pWxmsg;
push edi;
lea edx, wxWxid;
lea ecx, buffer;
call callAddress;
add esp, 0xC;
}
}
匯編代碼:
[]里面包含的類(lèi)型和變量名其實(shí)就是地址,只需要將地址改成用Python構(gòu)造的地址就可以了
完整代碼如下:
import os import pymem import ctypes import time def convert_addr(addr): if isinstance(addr, int): addr = hex(addr) if addr.startswith("0x") or addr.startswith("0X"): addr = addr[2:] if len(addr) < 8: addr = (8-len(addr))*'0' + addr tmp = [] for i in range(0, 8, 2): tmp.append(addr[i:i+2]) tmp.reverse() return ''.join(tmp) def WxBaseStruct(process_handle, content): struct_address = pymem.memory.allocate_memory(process_handle, 20) bcontent = content.encode('utf-16le') content_address = pymem.memory.allocate_memory(process_handle, len(bcontent)+16) pymem.ressources.kernel32.WriteProcessMemory(process_handle, content_address, bcontent, len(bcontent), None) pymem.memory.write_int(process_handle, struct_address, content_address) pymem.memory.write_int(process_handle, struct_address+0x4, len(content)) pymem.memory.write_int(process_handle, struct_address+0x8, len(content)*2) pymem.memory.write_int(process_handle, struct_address+0xC, 0) pymem.memory.write_int(process_handle, struct_address+0x10, 0) return struct_address, content_address def start_thread(process_handle, address, params=None): params = params or 0 NULL_SECURITY_ATTRIBUTES = ctypes.cast(0, pymem.ressources.structure.LPSECURITY_ATTRIBUTES) thread_h = pymem.ressources.kernel32.CreateRemoteThread( process_handle, NULL_SECURITY_ATTRIBUTES, 0, address, params, 0, ctypes.byref(ctypes.c_ulong(0)) ) last_error = ctypes.windll.kernel32.GetLastError() if last_error: pymem.logger.warning('Got an error in start thread, code: %s' % last_error) pymem.ressources.kernel32.WaitForSingleObject(thread_h, -1) return thread_h def main(wxpid, wxid, msg): process_handle = pymem.process.open(wxpid) wxNull_address = pymem.memory.allocate_memory(process_handle, 0x100) buffer_address = pymem.memory.allocate_memory(process_handle, 0x3B0) wxid_struct_address, wxid_address = WxBaseStruct(process_handle, wxid) msg_struct_address, msg_address = WxBaseStruct(process_handle, msg) process_WeChatWin_handle = pymem.process.module_from_name(process_handle, "WeChatWin.dll") call_address = process_WeChatWin_handle.lpBaseOfDll + 0x521D30 call_p_address = pymem.memory.allocate_memory(process_handle, 4) pymem.memory.write_int(process_handle, call_p_address, call_address) format_code = ''' 57 8D05 {wxNull} 6A 01 50 8D3D {wxTextMsg} 57 8D15 {wxWxid} 8D0D {buffer} FF15 {callAddress} 83C4 0C 5F C3 ''' shellcode = format_code.format(wxNull=convert_addr(wxNull_address), wxTextMsg=convert_addr(msg_struct_address), wxWxid=convert_addr(wxid_struct_address), buffer=convert_addr(buffer_address), callAddress=convert_addr(call_p_address)) shellcode = bytes.fromhex(shellcode.replace(' ', '').replace('\n', '')) shellcode_address = pymem.memory.allocate_memory(process_handle, len(shellcode)+5) pymem.ressources.kernel32.WriteProcessMemory(process_handle, shellcode_address, shellcode, len(shellcode), None) thread_h = start_thread(process_handle, shellcode_address) time.sleep(0.5) pymem.memory.free_memory(process_handle, wxNull_address) pymem.memory.free_memory(process_handle, buffer_address) pymem.memory.free_memory(process_handle, wxid_struct_address) pymem.memory.free_memory(process_handle, wxid_address) pymem.memory.free_memory(process_handle, msg_struct_address) pymem.memory.free_memory(process_handle, msg_address) pymem.memory.free_memory(process_handle, call_p_address) pymem.memory.free_memory(process_handle, shellcode_address) pymem.process.close_handle(process_handle) if __name__ == "__main__": wxpid = 16892 wxid = "filehelper" msg = "python test" main(wxpid, wxid, msg)
第三次優(yōu)化
直接在Python里寫(xiě)匯編,然后自動(dòng)轉(zhuǎn)機(jī)器碼寫(xiě)入內(nèi)存。使用的是Python的keystone庫(kù)
# -*- coding: utf-8 -*- import os import pymem import ctypes import time from keystone import Ks, KS_ARCH_X86, KS_MODE_32 def asm2code(asm_code, syntax=0): ks = Ks(KS_ARCH_X86, KS_MODE_32) bytes_code, _ = ks.asm(asm_code, as_bytes=True) return bytes_code def WxBaseStruct(process_handle, content): struct_address = pymem.memory.allocate_memory(process_handle, 20) bcontent = content.encode('utf-16le') content_address = pymem.memory.allocate_memory(process_handle, len(bcontent)+16) pymem.ressources.kernel32.WriteProcessMemory(process_handle, content_address, bcontent, len(bcontent), None) pymem.memory.write_int(process_handle, struct_address, content_address) pymem.memory.write_int(process_handle, struct_address+0x4, len(content)) pymem.memory.write_int(process_handle, struct_address+0x8, len(content)*2) pymem.memory.write_int(process_handle, struct_address+0xC, 0) pymem.memory.write_int(process_handle, struct_address+0x10, 0) return struct_address, content_address def start_thread(process_handle, address, params=None): params = params or 0 NULL_SECURITY_ATTRIBUTES = ctypes.cast(0, pymem.ressources.structure.LPSECURITY_ATTRIBUTES) thread_h = pymem.ressources.kernel32.CreateRemoteThread( process_handle, NULL_SECURITY_ATTRIBUTES, 0, address, params, 0, ctypes.byref(ctypes.c_ulong(0)) ) last_error = ctypes.windll.kernel32.GetLastError() if last_error: pymem.logger.warning('Got an error in start thread, code: %s' % last_error) pymem.ressources.kernel32.WaitForSingleObject(thread_h, -1) return thread_h def main(wxpid, wxid, msg): process_handle = pymem.process.open(wxpid) wxNull_address = pymem.memory.allocate_memory(process_handle, 0x100) buffer_address = pymem.memory.allocate_memory(process_handle, 0x3B0) wxid_struct_address, wxid_address = WxBaseStruct(process_handle, wxid) msg_struct_address, msg_address = WxBaseStruct(process_handle, msg) process_WeChatWin_handle = pymem.process.module_from_name(process_handle, "WeChatWin.dll") call_address = process_WeChatWin_handle.lpBaseOfDll + 0x521D30 call_p_address = pymem.memory.allocate_memory(process_handle, 4) pymem.memory.write_int(process_handle, call_p_address, call_address) format_asm_code = ''' push edi; lea eax,dword ptr ds:[{wxNull:#02x}]; push 0x1; push eax; lea edi,dword ptr ds:[{wxTextMsg:#02x}]; push edi; lea edx,dword ptr ds:[{wxWxid:#02x}]; lea ecx,dword ptr ds:[{buffer:#02x}]; call dword ptr ds:[{callAddress:#02x}]; add esp, 0xC; pop edi; ret; ''' asm_code = format_asm_code.format(wxNull=wxNull_address, wxTextMsg=msg_struct_address, wxWxid=wxid_struct_address, buffer=buffer_address, callAddress=call_p_address) shellcode = asm2code(asm_code.encode()) shellcode_address = pymem.memory.allocate_memory(process_handle, len(shellcode)+5) pymem.ressources.kernel32.WriteProcessMemory(process_handle, shellcode_address, shellcode, len(shellcode), None) thread_h = start_thread(process_handle, shellcode_address) time.sleep(0.5) pymem.memory.free_memory(process_handle, wxNull_address) pymem.memory.free_memory(process_handle, buffer_address) pymem.memory.free_memory(process_handle, wxid_struct_address) pymem.memory.free_memory(process_handle, wxid_address) pymem.memory.free_memory(process_handle, msg_struct_address) pymem.memory.free_memory(process_handle, msg_address) pymem.memory.free_memory(process_handle, call_p_address) pymem.memory.free_memory(process_handle, shellcode_address) pymem.process.close_handle(process_handle) if __name__ == "__main__": wxpid = 18604 wxid = "filehelper" msg = "python test msg" main(wxpid, wxid, msg)
到此這篇關(guān)于Python實(shí)現(xiàn)向好友發(fā)送微信消息優(yōu)化篇的文章就介紹到這了,更多相關(guān)Python微信消息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python實(shí)現(xiàn)aes加密及pycryptodome庫(kù)使用
AES算法是高級(jí)加密標(biāo)準(zhǔn),它是一種對(duì)稱(chēng)加密算法,AES只有一個(gè)密鑰,這個(gè)密鑰既用來(lái)加密,也用于解密,這篇文章主要給大家介紹了關(guān)于python實(shí)現(xiàn)aes加密及pycryptodome庫(kù)使用的相關(guān)資料,需要的朋友可以參考下2023-10-10Python實(shí)現(xiàn)PS圖像調(diào)整黑白效果示例
這篇文章主要介紹了Python實(shí)現(xiàn)PS圖像調(diào)整黑白效果,結(jié)合實(shí)例形式分析了Python實(shí)現(xiàn)PS圖像的黑白效果原理與相關(guān)操作技巧,需要的朋友可以參考下2018-01-01基于Python 函數(shù)和方法的區(qū)別說(shuō)明
這篇文章主要介紹了基于Python 函數(shù)和方法的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03對(duì)Python 簡(jiǎn)單串口收發(fā)GUI界面的實(shí)例詳解
今天小編就為大家分享一篇對(duì)Python 簡(jiǎn)單串口收發(fā)GUI界面的實(shí)例詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06詳解Python相關(guān)文件常見(jiàn)的后綴名
常見(jiàn)的 Python 文件后綴有:py、pyc 、pyo、 pyi、pyw、 pyd、 pyx 等。本文給大家介紹Python相關(guān)文件常見(jiàn)的后綴名,感興趣的朋友跟隨小編一起看看吧2021-05-05完美解決Python 2.7不能正常使用pip install的問(wèn)題
今天小編就為大家分享一篇完美解決Python 2.7不能正常使用pip install的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06PyTorch之torch.randn()如何創(chuàng)建正態(tài)分布隨機(jī)數(shù)
這篇文章主要介紹了PyTorch之torch.randn()如何創(chuàng)建正態(tài)分布隨機(jī)數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02Django創(chuàng)建一個(gè)后臺(tái)的基本步驟記錄
這篇文章主要給大家介紹了關(guān)于Django創(chuàng)建一個(gè)后臺(tái)的基本步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10