Win32汇编学习笔记04.重定位与汇编引擎

news/2025/1/6 15:55:08/文章来源:https://www.cnblogs.com/weiyuanzhang/p/18652649

Win32汇编学习笔记04.重定位与汇编引擎-C/C++基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net

重定位

**重定位:**也称为代码自重定位,代码自己去计算自己使用的各种资源再新进程中的地址,相应代码被称为被重新定位过后的代码。

示例

  • 目标:向指定进程 扫雷 注入一段机器码,机器码的作用是弹出MessageBox。
与远程注入dll的区别:原是加载dll,本目标是注入一段机器码。

注机器码就是 把机器码写到对应进程里面去,写的地方不能覆盖它原本代码,否则会影响它原本的功能 ,可以去找一些空隙,但是这种方法不是很通用.最好的办法是 申请一块内存,把代码写进去,在调用线程去跑这个段代码

.asm

.586
.model flat,stdcall
option casemap:noneinclude windows.incinclude user32.incinclude kernel32.incincludelib user32.libincludelib kernel32.libWinMain proto .datag_szCap    db "扫雷",0          ;窗口标题,用来获取窗口句柄g_szTitle  db "温情提示",0      ;弹窗窗口标题g_szText   db "你被注入了!!!",0 ;弹窗内容  
.codeCODE_BEGIN:
invoke MessageBox,NULL,offset  g_szText,offset g_szTitle,MB_OK; ---------------------------------------------------------------------------
WinMain proc LOCAL @hWndWinMine :HWND    ;窗口句柄LOCAL @dwPid :HWND          ;进程idLOCAL @hProc :HINSTANCE     ;进程句柄LOCAL @pAddr :LPVOID        ;申请的内存地址LOCAL @dwBytesWirites :DWORD    ;写入的字节数invoke FindWindow,NULL ,offset g_szCap  ;通过窗口标题获取窗口句柄mov    @hWndWinMine,eaxinvoke GetWindowThreadProcessId,@hWndWinMine,addr @dwPid  ;获取进程id  invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,@dwPid   ;获取进程句柄mov   @hProc,eaxinvoke VirtualAllocEx,@hProc, NULL,1,MEM_COMMIT,PAGE_EXECUTE_READWRITE    ;自动申请内存空间mov   @pAddr,eax;在内存中写入代码invoke WriteProcessMemory,@hProc,@pAddr,\      ;\是换行offset CODE_BEGIN, offset WinMain -   offset CODE_BEGIN,\addr @dwBytesWiritesinvoke CreateRemoteThread,@hProc ,NULL,0,@pAddr,NULL,0,NULL  ;创建线程mov     eax,0ret
WinMain endpstart:invoke WinMaininvoke ExitProcess,eaxend start

没重定向之前运行程序,发现我么的文件和扫雷都崩了,单独调试我们自己的代码是没问题,所以需要同时调试2个进程

image.png

写入代码的地址是 05790000

image.png

image.png

可以看出,我们字符串的内存地址获取失败了,因为我们的字符串写在了我们的自己程序中,并不在扫雷程序中

把字符串移进来,调试发现地址还是我们自己的地址,字符串地址需要调整,最好让他自己算.我们只要原来代码所在的地址,与新地址所在的差值,就可以推算出新字符串所在的地址

image.png

.586
.model flat,stdcall
option casemap:noneinclude windows.incinclude user32.incinclude kernel32.incincludelib user32.libincludelib kernel32.libWinMain proto .datag_szCap    db "扫雷",0          ;窗口标题,用来获取窗口句柄.codeCODE_BEGIN:jmp MSGBOXg_szTitle  db "温情提示",0      ;弹窗窗口标题g_szText   db "你被注入了!!!",0 ;弹窗内容  MSGBOX:call LTEST  ;会把  LIST 的地址入站   LTEST:pop ebx                ;获取 LTEST 在新进程的地址sub ebx ,offset LTEST  ;可以得到LTEST 在 新进程地址和我们自己进程的地址差值push MB_OKmov eax, offset  g_szTitle  ;获取字符串在原进程中的地址add eax, ebx     ;获取字符串在新进程中的地址push eax         ;入栈mov eax, offset  g_szTextadd eax, ebxpush eaxpush NULLcall  MessageBox;invoke MessageBox,NULL,offset  g_szText,offset g_szTitle,MB_OK
ret; ---------------------------------------------------------------------------
WinMain proc LOCAL @hWndWinMine :HWND    ;窗口句柄LOCAL @dwPid :HWND    ;进程idLOCAL @hProc :HINSTANCE    ;线程句柄LOCAL @pAddr :LPVOID    ;申请的内存地址LOCAL @dwBytesWirites :DWORD    ;写入的字节数invoke FindWindow,NULL ,offset g_szCap  ;通过窗口标题获取窗口句柄mov    @hWndWinMine,eaxinvoke GetWindowThreadProcessId,@hWndWinMine,addr @dwPid  ;获取进程id  invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,@dwPid   ;创建新线程mov   @hProc,eaxinvoke VirtualAllocEx,@hProc, NULL,1,MEM_COMMIT,PAGE_EXECUTE_READWRITE    ;自动申请内存空间mov   @pAddr,eax;在内存中写入代码invoke WriteProcessMemory,@hProc,@pAddr,\      ;\是换行offset CODE_BEGIN, offset WinMain -   offset CODE_BEGIN,\addr @dwBytesWiritesinvoke CreateRemoteThread,@hProc ,NULL,0,@pAddr,NULL,0,NULL  mov     eax,0ret
WinMain endpstart:invoke WinMaininvoke ExitProcess,eaxend start

再继续调试,发现此数地址已经变了

img

有时候 CTRL + G 找地址会提示无效地址, 可以先到内存窗口,右键,在cpu数据窗口中查看,找到自己跳转的地址,在回到 代码页面 用 CTRL + G 跟随就可以了

img

user32 在 同一台电脑上的 不同进程的地址是一样的,因此可以利用这一点,还要注意,我们写的代码位于代码段,必须修改才能写入

重定位后的代码

.586
.model flat,stdcall
option casemap:noneinclude windows.incinclude user32.incinclude kernel32.incincludelib user32.libincludelib kernel32.libWinMain proto .datag_szCap    db "扫雷",0          ;窗口标题,用来获取窗口句柄g_szUser32 db "user32", 0g_szMessageBox db "MessageBoxA", 0.codeCODE_BEGIN:jmp MSGBOXg_szTitle  db "温情提示",0      ;弹窗窗口标题g_szText   db "你被注入了!!!",0 ;弹窗内容 g_dwMessageBox   dd 0           ;MessageBox的地址  MSGBOX:;下面四条就是重定位的核心代码call NEXT  ;会把  LIST 的地址入站   
NEXT:pop ebx                ;获取 NEXT 在新进程的地址sub ebx ,offset NEXT  ;可以得到NEXT 在 新进程地址和我们自己进程的地址差值push MB_OKmov eax, offset  g_szTitle  ;获取字符串在原进程中的地址add eax, ebx     ;获取字符串在新进程中的地址push eax         ;入栈mov eax, offset  g_szTextadd eax, ebxpush eaxpush NULLmov eax, offset g_dwMessageBoxadd eax, ebxmov eax, [eax]call eax;call  MessageBox;invoke MessageBox,NULL,offset  g_szText,offset g_szTitle,MB_OK
ret; ---------------------------------------------------------------------------
WinMain proc LOCAL @hWndWinMine :HWND    ;窗口句柄LOCAL @dwPid :HWND    ;进程idLOCAL @hProc :HINSTANCE    ;线程句柄LOCAL @pAddr :LPVOID    ;申请的内存地址LOCAL @dwBytesWirites :DWORD    ;写入的字节数LOCAL @dwOldProc:DWORD    ;之前的内存属性invoke FindWindow,NULL ,offset g_szCap  ;通过窗口标题获取窗口句柄mov    @hWndWinMine,eaxinvoke GetWindowThreadProcessId,@hWndWinMine,addr @dwPid  ;获取进程id  invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,@dwPid   ;创建新线程mov   @hProc,eaxinvoke VirtualAllocEx,@hProc, NULL,1,MEM_COMMIT,PAGE_EXECUTE_READWRITE    ;自动申请内存空间mov   @pAddr,eax;修改代码区内存属性invoke VirtualProtect, offset CODE_BEGIN, 1, PAGE_EXECUTE_READWRITE, addr @dwOldProcinvoke GetModuleHandle, offset g_szUser32invoke GetProcAddress, eax, offset g_szMessageBoxmov g_dwMessageBox, eax;还原内存属性invoke VirtualProtect, offset CODE_BEGIN, 1, @dwOldProc, addr @dwOldProc;在内存中写入代码invoke WriteProcessMemory,@hProc,@pAddr,\      ;\是换行offset CODE_BEGIN, offset WinMain -   offset CODE_BEGIN,\addr @dwBytesWiritesinvoke CreateRemoteThread,@hProc ,NULL,0,@pAddr,NULL,0,NULL  mov     eax,0ret
WinMain endpstart:invoke WinMaininvoke ExitProcess,eaxend start

汇编引擎

使用 XDE

库: 如果装了x32DEBUG ,那么就有需要的库

image.png用C来实现 汇编引擎

创建一个控制台程序

把头文件,dll,lib 拷贝到项目

image.png

成员:

1 32位还是64位,true 64位 flase 32位

2 汇编的地址 (跳转类指令必须)

3返回参数,汇编出来的机器码有几个字节

4回调,用不上,空就行

5传出的机器吗

6我们写进去的源码

7错误信息

// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>#include "XEDParse.h"
#pragma comment (lib, "XEDParse_x86.lib")int main()
{XEDPARSE xde = {};xde.x64 = false;xde.cip = 0x00401000;strcpy_s(xde.instr, sizeof(xde.instr), "mov eax, eax");XEDPARSE_STATUS stus = XEDParseAssemble(&xde);std::cout << "Hello World!\n";
}

汇编实现汇编引擎

.586
.model flat,stdcall
option casemap:noneinclude windows.incinclude user32.incinclude kernel32.incinclude msvcrt.incinclude AsmXde.incincludelib user32.libincludelib kernel32.libincludelib msvcrt.libincludelib XEDParse_x86.libWinMain proto :DWORD,:DWORD,:DWORD,:DWORD.dataxdep XEDPARSE <FALSE, 00401000h>   g_szInstr db "mov ebp, esp", 0.code
start:invoke crt_strcpy, offset xdep._instr, offset g_szInstrinvoke XEDParseAssemble, offset xdepend start

.inc

ifndef XDE_INC 
XDE_INC  equ 1XEDPARSE_ERROR equ 0
XEDPARSE_OK equ 1XEDPARSE_MAXBUFSIZE equ 256
XEDPARSE_MAXASMSIZE equ 16;定义结构体  
XEDPARSE strucx64 db 0ALIGN 8   ;设置对齐值cip dd 0  ;只用低32位dd 0dest_size dd 0cbUnknown dd 0dest db XEDPARSE_MAXASMSIZE dup(0)_instr db XEDPARSE_MAXBUFSIZE dup(0)error db XEDPARSE_MAXBUFSIZE dup(0)
XEDPARSE endsXEDParseAssemble proto c :ptr XEDPARSE   ;函数声明endif

img

img

img

比较强悍的工具是:Asmjit 但只能c使用

作业

周作业

1. 代码注入器

有bug, eip 每次要加它的长度

头文件xde.inc

ifndef XDE_INC
XDE_INC equ 1 ;防止重复包含;这是原先出错或成功的枚举,换成equXEDPARSE_ERROR equ 0XEDPARSE_OK equ 1;原先的宏XEDPARSE_MAXBUFSIZE  equ 256XEDPARSE_MAXASMSIZE equ 16;定义结构体 还需要设置对齐值,它的对齐值是8XEDPARSE strucx64       db 0 ;x64 ALIGN     8 ;设置对齐值,只影响它下一条cip       dd 0 ;它是__int64类型的,但是我们只用低32位,所以就dd ,高32位就不用了dd 0 ;它的高32位dest_size dd 0;传出参数,机器码有几个字节cbUnknown dd 0;回调dest      db XEDPARSE_MAXASMSIZE dup(0) ;机器码_instr     db XEDPARSE_MAXBUFSIZE dup(0);汇编指令error     db XEDPARSE_MAXBUFSIZE dup(0)XEDPARSE ends;函数声明,C调用约定 ,参数为结构体指针XEDParseAssemble proto C :ptr XEDPARSE endif

code.inc

include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
include msvcrt.inc
include Xde.incincludelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
includelib msvcrt.lib
includelib XEDParse_x86.libDlgProc			PROTO	:HWND,:UINT,:WPARAM,:LPARAM.constIDD_DIALOG1			equ 101
BTN_SELECT          equ 1001
BTN_INJECTION       equ 1002
EDT_PROCESSID       equ 1003
EDT_CODE            equ 1004DLG_PROCESS         equ 1000
LST_PROCESS         equ 1005;#########################################################################.data?hInstance			dd ?;#########################################################################

code.asm

.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitiveinclude CodeIn.inc.datag_szHintProcessID db "进程ID" , 0 ;提示的中文g_szHintProcessName db "进程名" , 0 ;提示的中文g_szFmt db "%d",0 ;格式化字符串g_szProcess db 255 dup(0) ; 进程ID字符串g_hWnd dd 0 ;主窗口句柄g_szCode db 255 dup(0)
.code;获取进程信息
GetProcess proc hWin:HWND LOCAL lvcol:LVCOLUMN ;lst的列结构体LOCAL item:LVITEM  ;项的结构体local hlistLOCAL pe32:PROCESSENTRY32 ;pe32LOCAL hProcessSnap:HANDLELOCAL bRet:BOOL ; bool类型的返回值LOCAL nRowCount:dword  ;列数LOCAL szTh32ProcessID[255]:byteLOCAL oldStyle :dword;先初始化list控件invoke GetDlgItem,hWin,LST_PROCESS  ;获取控件句柄mov hlist,eax;向样式结构体里填数据mov lvcol.imask,LVCF_FMT or LVCF_WIDTH or  LVCF_TEXT or LVCF_SUBITEMmov lvcol.fmt,LVCFMT_CENTERmov lvcol.lx,275mov lvcol.pszText,offset g_szHintProcessID;发消息,增加一列;invoke SendMessage,hlist,LVM_INSERTCOLUMN,0,addr lvcolinvoke SendDlgItemMessage,hWin,LST_PROCESS,LVM_INSERTCOLUMN,0,addr lvcol;第二列mov lvcol.pszText,offset g_szHintProcessName;invoke SendMessage,hlist,LVM_INSERTCOLUMN,1,addr lvcolinvoke SendDlgItemMessage,hWin,LST_PROCESS,LVM_INSERTCOLUMN,1,addr lvcol;开始获取进程;hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);invoke CreateToolhelp32Snapshot,TH32CS_SNAPALL,0mov hProcessSnap,eax;Process32First(hProcessSnap, &pe32)mov pe32.dwSize,size PROCESSENTRY32invoke Process32First,hProcessSnap,addr pe32mov bRet,eax;First成功后循环.if bRet != 0;列数先置为0 mov nRowCount ,0;开始循环.REPEAT;插入第一列mov eax,nRowCountmov item.iItem , eax; ;行号 从0开始mov item.iSubItem,0 ;列号mov item.imask,LVCF_FMT or LVCF_WIDTH or LVCF_TEXTmov eax,pe32.th32ProcessID;格式化字符串进程IDinvoke wsprintf,addr szTh32ProcessID,offset g_szFmt, pe32.th32ProcessIDlea eax,szTh32ProcessIDmov item.pszText,eaxinvoke SendDlgItemMessage,hWin,LST_PROCESS,LVM_INSERTITEM,0,addr item;清除内存invoke crt_memset,addr item,0,size item;插入第二列mov eax,nRowCountmov item.iItem , eax; ;行号mov item.iSubItem,1;列号mov item.imask , LVCF_FMT or LVCF_WIDTH or LVCF_TEXT;lea eax,pe32.szExeFile ;进程名称mov item.pszText,eax;插入其他列invoke SendDlgItemMessage,hWin,LST_PROCESS,LVM_SETITEMTEXT,nRowCount,addr item;行号++mov eax,nRowCountinc eaxmov nRowCount,eax;清除内存lea eax, pe32invoke crt_memset,eax,0,128;重新赋值大小mov pe32.dwSize,size PROCESSENTRY32;Next获取下一个invoke Process32Next,hProcessSnap,addr pe32mov bRet,eax.UNTIL bRet == 0.endif ;获取旧样式invoke SendDlgItemMessage,hWin,LST_PROCESS,LVM_GETEXTENDEDLISTVIEWSTYLE,0,0;拼接新样式or eax,LVS_EX_FULLROWSELECTor eax,LVS_EX_GRIDLINES;设置选中高亮一行和网格线样式invoke SendDlgItemMessage,hWin,LST_PROCESS,LVM_SETEXTENDEDLISTVIEWSTYLE,0,eax retGetProcess endpOnProc proc hWin:HWND,wParam:WPARAM,lParam :LPARAMLOCAL item:LVITEM  ;项的结构体LOCAL dwSel:dword ;判断控件IDmov eax,wParam.if eax == LST_PROCESSmov esi,lParamassume esi:ptr NMHDRmov ebx,[esi].codeassume esi:nothing.if ebx == NM_DBLCLK ;invoke MessageBox,hWin,offset g_szHintProcessID,offset g_szHintProcessID,MB_OK;获取选中的IDinvoke SendDlgItemMessage ,hWin,LST_PROCESS,LVM_GETSELECTIONMARK,0,0;选中ID赋值mov dwSel,eax;开始获取选中的文本mov item.iItem , eax; ;行号mov item.iSubItem,0;列号mov item.imask , LVCF_FMT or LVCF_WIDTH or LVCF_TEXT;lea eax,g_szProcessmov item.pszText,eaxmov item.cchTextMax,size g_szProcessinvoke SendDlgItemMessage,hWin,LST_PROCESS,LVM_GETITEMTEXT,dwSel,addr item;给外面的进程文本框赋值invoke	SetDlgItemText,g_hWnd,EDT_PROCESSID,offset g_szProcess;关闭窗口invoke EndDialog,hWin,0.endif.endif retOnProc endp
;进程对话框过程函数
DlgProcessProc proc hWin:HWND,uMsg:UINT,  wParam  :WPARAM,lParam:LPARAMmov		eax,uMsg.if eax==WM_INITDIALOG ;初始化invoke GetProcess,hWin.elseif eax==WM_CLOSEinvoke EndDialog,hWin,0.elseif eax == WM_NOTIFYinvoke OnProc,hWin,wParam,lParam .elsemov		eax,FALSEret.endifmov		eax,TRUEretDlgProcessProc endpInject procLOCAL @hProc:HINSTANCE ; 进程句柄LOCAL @pAddr :LPVOID ;申请的内存地址LOCAL @dwBytesWrited:dword ;写入的字节数,它是返回值LOCAL @dwOldProc:dword ;旧的内存属性LOCAL @xdep:XEDPARSELOCAL @machineCode[255]:byte ;字符串LOCAL @StrLen :dword LOCAL @idx:dword;把进程ID字符串转成数字invoke crt_atoi,offset g_szProcess; 打开进程invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,eax;把进程句柄存储一下mov @hProc,eax ;申请内存invoke VirtualAllocEx,@hProc,NULL,1,MEM_COMMIT,PAGE_EXECUTE_READWRITE;把申请的内存地址存一下 mov @pAddr,eax ;解析指令;代码注入;获取指令长度invoke crt_strlen,offset g_szCodemov @StrLen,eax;一个字节一个字节读取lea esi,g_szCodelea edi,@machineCode.WHILE @StrLen > 0mov eax,@idx.if byte ptr[esi] == 0dhinc esi.continue.endif .if byte ptr[esi] == 0ahinc esi;开始注入代码mov @xdep.x64,FALSE ;64位mov eax,@pAddrmov @xdep.cip,eax   ;内存地址;拷贝指令invoke crt_strcpy ,addr @xdep._instr,addr @machineCodeinvoke XEDParseAssemble,addr @xdep;要加上机器码的长度,也就是写入的字节数,确保下次正确写入mov eax,@pAddradd eax,@dwBytesWritedmov @pAddr,eax;写入机器码invoke WriteProcessMemory,@hProc,@pAddr,addr @xdep.dest,@xdep.dest_size,addr @dwBytesWrited;edi恢复lea edi,@machineCodeinvoke crt_memset,addr @machineCode,0,255;invoke crt_memset, @xdep, 0,255invoke crt_memset,addr @xdep._instr,0,255invoke crt_memset,addr @xdep.dest,0,16.continue.endif;读取一个字节movsb;长度--sub @StrLen,1.ENDW;创建远程线程 它的地址就是申请的内存地址,那块内存已经写入了自己的代码了invoke CreateRemoteThread,@hProc,NULL,0,@pAddr,NULL,0,NULLretInject endp
start:invoke GetModuleHandle,NULLmov		hInstance,eaxinvoke InitCommonControlsinvoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULLinvoke ExitProcess,0;########################################################################; 主对话框过程函数
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAMmov eax,hWinmov g_hWnd,eaxmov		eax,uMsg.if eax==WM_INITDIALOG ;初始化.elseif eax==WM_COMMANDmov eax,wParam.if ax == BTN_SELECT     ;打开对话框选择进程invoke CreateDialogParam,hInstance,DLG_PROCESS,NULL,addr DlgProcessProc,NULL.elseif ax == BTN_INJECTION  ;代码注入;获取输入的代码invoke GetDlgItemText,hWin,EDT_CODE,offset g_szCode,255invoke Inject;解析输入的代码.endif.elseif eax==WM_CLOSEinvoke EndDialog,hWin,0.elsemov		eax,FALSEret.endifmov		eax,TRUE

资源界面

img

img

2. 扫雷辅助

C++版

#include <Windows.h>
#include <Windowsx.h>#define ARY_0 0x1005340
#define MINE 0x8FHWND g_hWnd = 0;
WNDPROC g_OldProc = 0;LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{switch (Msg){case WM_MOUSEMOVE:{int x = LOWORD(lParam);int y = HIWORD(lParam);int ary_x = (x + 4) >> 4;int ary_y = ((y - 0x27) >> 4) << 5;if (*(PBYTE)((DWORD)ARY_0 + ary_x + ary_y) == MINE){SetWindowText(hWnd, "扫雪");}else{SetWindowText(hWnd, "扫雷");}}default:break;}return CallWindowProc(g_OldProc, hWnd, Msg, wParam, lParam);
}void Init()
{g_hWnd = ::FindWindow(NULL, "扫雷");g_OldProc = (WNDPROC)SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG)WindowProc);
}BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:{Init();break;}}return TRUE;
}

win32asm版

.386
.model flat, stdcall
option casemap :noneinclude WinMineDLL.Inc.datag_szBuffSnow db "扫雪", 0g_szBuffMine db "扫雷", 0g_szBuffError db "SetWindowLong success", 0g_szBuffX db "X", 0 g_szBuffY db "Y", 0g_OldProc dd 0g_ddMine dd 0g_hMine dd 0.codeMYWindowProc proc uses ecx esi edi, hwnd:HWND, uMsg:UINT , wParam:WPARAM, lParam:LPARAM.if uMsg == WM_MOUSEMOVE; coordinate -> arymov eax, dword ptr [lParam]shr eax, 010hsub eax, 027hsar eax, 04hmov edi, eaxshl edi, 5 ; edi - Ymovzx eax, word ptr [lParam]add eax, 4hsar eax, 4hmov esi, eax ; esi - X; ary[0] = 01005340hxor eax, eaxmov ebx, 01005340hadd ebx, esiadd ebx, edimov al, byte ptr [ebx]; is minemov g_ddMine, eax.if g_ddMine == 08Fhinvoke SetWindowText, hwnd, offset g_szBuffSnow.elseifinvoke SetWindowText, hwnd, offset g_szBuffMine.endif.endifinvoke CallWindowProc, g_OldProc, hwnd, uMsg, wParam, lParamret
MYWindowProc endpInitDLL procinvoke FindWindow, NULL, offset g_szBuffMinemov g_hMine, eaxinvoke SetWindowLongW, g_hMine, GWL_WNDPROC, offset MYWindowProcmov g_OldProc, eax.if g_OldProc != NULLinvoke MessageBox, NULL, offset g_szBuffError, NULL, MB_OK.endifInitDLL endpDllMain proc hinstDLL:HINSTANCE, fdwReason:DWORD, lpvReserved:LPVOID.if fdwReason == DLL_PROCESS_ATTACHinvoke InitDLL.endifmov eax, TRUEret
DllMain endpend DllMain
 
.386 .model flat, stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib .data g_hwnd HWND 0 g_windowtitle db "扫雷", 0 g_dProcessId dd 0 g_dThreadId dd 0 g_hHook HHOOK 0 g_sz db "钩子", 0 .code GetMessageProc proc nCode:dword, wParam:WPARAM, lParam:LPARAM .if nCode < 0 invoke CallNextHookEx, g_hHook, nCode, wParam, lParam ret .endif mov eax, lParam assume eax:ptr MSG .if [eax].message == WM_COMMAND invoke MessageBox, NULL, offset g_sz, offset g_sz, MB_OK .endif invoke CallNextHookEx, g_hHook, nCode, wParam, lParam ret GetMessageProc endp DllMain proc hinstDLL:HINSTANCE, fdwReason:DWORD, lpvReserved:LPVOID ;给扫雷安装消息钩子

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/864074.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【哈希算法】实战应用

一、使用哈希进行函数调用 使用哈希隐藏API调用 代码 #include <windows.h> #include <stdio.h>int main() {MessageBoxA(NULL, "Meow-meow!","=^..^=", MB_OK);return 0; }编译 i686-w64-mingw32-g++ meow.c -o meow.exe -mconsole -I/usr/sh…

恶意软件常用加密算法

前面主要是加密字符串信息,加密算法还可以加密shellcode、通信数据包、配置信息等 一、常用加密算法概述 加密配置信息、加密通信信道、加密窃取数据、混淆代码放置静态分析 总体来说就是加密shellcode、代码模块、配置信息、通信等 二、加密配置信息 设置一个场景,恶意dll文…

Bash 定义变量

定义数组 在 Bash 中,declare -a 用于显式地声明一个变量为数组类型。虽然在许多情况下,即使不使用 declare -a,Bash 也能自动将变量识别为数组,但使用 declare -a 可以明确地说明该变量是一个数组,并且在某些情况下可以提高代码的可读性和可维护性。 区别与作用:declare…

内网渗透

内网渗透 内网基础知识 前言 本文主要介绍内网方面的一些概念,作为内网学习的一个开端。在本文中,所有内容仅供参考,哪有不对,还请指出,谢谢各位师傅。 单域和多域 内网概念 内网也指局域网,是指在某个区域由多台计算机互联而成的计算机组,内网渗透就是在内网中获取计算…

Ubuntu 22.04 手动安装MySQL 5.7.41时依赖包libtinfo5失败

在Ubuntu 22.04安装MySQL5.7.41低版本时,需要安装依赖包libtinfo5,但偶尔会出现安装失败,可使用以下步骤解决此问题。 1、sudo apt install software-properties-common2、sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ jammy main universe"…

Python图注意力神经网络GAT与蛋白质相互作用数据模型构建、可视化及熵直方图分析

全文链接:https://tecdat.cn/?p=38617 原文出处:拓端数据部落公众号 摘要: 本文聚焦于图注意力网络GAT在蛋白质 - 蛋白质相互作用数据集中的应用。首先介绍了研究背景与目的,阐述了相关概念如归纳设置与转导设置的差异。接着详细描述了数据加载与可视化的过程,包括代码实…

AtCoder Beginner Contest 387 赛后复盘

abc。省流:A,B,C,D,FA - B 模拟即可。 C 数位 dp。 首先我们先将问题转换为 \([1,R]\) 中蛇数的个数减去 \([1,L-1]\) 中蛇数的个数。 设 \(num_i\) 为数字的第 \(i\) 位(从左往右数)。 我们设 \(f_{dep,mx,lim,ze}\) 表示当前第 \(dep\) 位,首位为 \(mx\),有没有达到…

厨师服穿戴智能监测摄像机

厨师服穿戴智能监测摄像机的应用可以提高厨师在工作中的效率和规范性。通过摄像头的实时监测功能,主厨或者厨房管理人员可以远程观察厨师的工作情况,及时发现问题并进行指导和纠正。此外,设备还能够实现对厨房工作流程的记录和分析,为厨师提供数据支持,帮助其更好地管理工…

骑车不戴头盔监测摄像机

骑车不戴头盔监测摄像机的作用是对骑行者是否戴头盔进行监测和识别,当监测到有骑行者未戴头盔时,摄像机会发出警报,并提示骑行者戴上头盔。这种智能设备可以有效地规范骑行行为,提高骑行安全系数,减少交通事故的发生率。此外,通过监测和识别,还可以对骑行者未戴头盔的行…

电瓶车进电梯识别报警摄像机

电瓶车进电梯识别报警摄像机的作用是对电动车进入电梯过程中的安全情况进行监测和预警,及时发现潜在的安全隐患,提醒用户和管理人员采取相应措施避免事故发生。这种智能设备可以通过监测电动车进入电梯的行为、车辆状态等信息,进行实时分析和判断,发现电动车可能存在的安全…

已读乱回

我将safetensors格式的TableGPT2-7B通过llama.cpp转换成gguf