汇编学习实战修改win32扫雷
Posted 不会写代码的丝丽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编学习实战修改win32扫雷相关的知识,希望对你有一定的参考价值。
概述
概述下面的游戏我们都玩过
这个扫雷的程序点击右上角的关闭按钮会直接退出整个程序。我们利用od实现如下效果:
点击右上角弹出一个dialog
,让用户确认是否是否关闭。
思路概念
win
程序有消息机制,关闭的时候会触发WM_CLOSE
消息.因此我们首先断点这个消息看看大致逻辑。
OD
窗口点击查看->窗口(无数据请右键刷新)
选中对应的窗口选中消息断点。
接着点击扫雷关闭按钮触发关闭消息
这里利用断点分析后续流程
我首先记录下结论:
01001c23
如果是close消息会跳转到010021a2
010021a2
会将消息分发到系统默认处理。010021bb
将会返回过程函数
于是我们利用如下思想完成需求:
01001c23
跳转我们的额外我们内部插入新的代码。
内部代码如果是close消息那么弹出dialog,如果不是跳转回010021a2
.
如果用户点击dialog确认关闭按钮,那么跳转回010021a2
如果用用户点击dialog取消按钮,那么跳转到010021bb
从而跳过关闭事件
于是我们在某处写入如下代码:
疑问点你怎么知道MessageBoxA函数位置?
od如何保存修改的代码到新的exe?
注入与重定位
假设我们需要单独写一个程序,对扫雷进行注入弹出一个dialog
.其需要考虑重定位问题.
执行上面的按钮会执行注入一段代码到扫雷程序.
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
include dlgdemo.inc
.data
g_szWinimeName db "扫雷",0
g_szUser32 db "user32",0
g_szMessageBoxA db "MessageBoxA",0
.code
;被注入的代码
INJECT_CODE:
;这里主要让其把字符串也拷贝过去
jmp INJECT_MESGBOX
g_szHello db "helloworld",0
;存储messagbox函数的相对位置
;messagbox是dll库地址,因此每个程序相对dll的位置是固定的
g_pfnMessageBox dd 0
INJECT_MESGBOX:
;重定向代码正确位置,因为注入后offset是原始程序的地址,而不是目标程序的地址
call NEXT
NEXT:
;call后会存储当前返回地址到栈。此处弹出返回地址计算相对偏移
pop ebx
;减去之后得到两个程序之间的偏移差
sub ebx,offset NEXT
;得到字符串的地址
lea eax,[offset g_szHello+ebx]
;得到messagebox的相对位置
lea ecx,[offset g_pfnMessageBox+ebx]
push MB_OK
push NULL
push eax
push NULL
call dword ptr [ecx]
ret
INJECT_END:
g_dwCodeSize dd $ - offset INJECT_CODE
;InitInject 主要用于让其代码段可读可写
;g_pfnMessageBox存储在代码段但是我们需要让其存储MessageBoxA函数地址
InitInject proc
LOCAL @hUser32:HANDLE
LOCAL @dwOldProc:DWORD
invoke VirtualProtect,offset INJECT_CODE,g_dwCodeSize,PAGE_EXECUTE_READWRITE,addr @dwOldProc
invoke GetModuleHandle,offset g_szUser32
;存储模块句柄
mov @hUser32,eax
invoke GetProcAddress,@hUser32,offset g_szMessageBoxA
mov g_pfnMessageBox,eax
invoke VirtualProtect,offset INJECT_CODE,g_dwCodeSize,@dwOldProc,addr @dwOldProc
ret
InitInject endp
Inject proc
LOCAL @hWnd:HWND
LOCAL @dwPid:DWORD
LOCAL @hProc:HWND
LOCAL @lpAddr:LPVOID
LOCAL @dwBytesWrited:DWORD
LOCAL @hUser32:HANDLE
int 3
;得到窗口句柄
invoke FindWindow,NULL,offset g_szWinimeName
mov @hWnd,eax
;得到进程的id
invoke GetWindowThreadProcessId,@hWnd,addr @dwPid
;得到进程句柄并获取所有权限
invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,@dwPid
;保存进程句柄
mov @hProc,eax
;申请内存
invoke VirtualAllocEx,@hProc,NULL,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
;保存内存引用
mov @lpAddr,eax
;int 3
;内存写入
invoke WriteProcessMemory,@hProc,@lpAddr,offset INJECT_CODE,offset INJECT_END - offset INJECT_CODE,addr @dwBytesWrited
;创建线程
invoke CreateRemoteThread,@hProc,NULL,0,@lpAddr,NULL,0,NULL
ret
Inject endp
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke InitCommonControls
invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
invoke ExitProcess,0
;########################################################################
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_INITDIALOG
.elseif eax==WM_COMMAND
mov edx,wParam
.if dx==btn_xxx
invoke InitInject
;invoke MessageBox,hWin,offset g_szHello,NULL,MB_OK
invoke Inject
.endif
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
end start
以上是关于汇编学习实战修改win32扫雷的主要内容,如果未能解决你的问题,请参考以下文章