目标:在扫雷中注入一个messagebox弹窗;

方法:打开一个进程(扫雷的进程),申请内存,写入messagebox;

另外启动一个线程,让整个代码跑起来

项目创建

注入代码

.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
    g_szWinmine db "扫雷", 0
    g_szKernel db "Kernel32", 0
    g_szLoadLibrary db "LoadLibraryA", 0
    g_szGetProcAddress db "GetProcAddress", 0
    g_hKer   dd 0
    g_dwPid   dd 0
    g_hProc   dd 0
    g_pAddr   dd 0
    g_dwBytesWrited dd 0
    g_dwOldProc dd 0 
    g_szMsg   db "你被注入了", 0
    g_szTitle db "不要担心,重启就行", 0
    
    
.code

MSGBOX:
int 3
invoke MessageBox,NULL,offset g_szMsg,offset g_szTitle, MB_OK

    

start:
    ;打开进程
    invoke FindWindow,NULL,offset g_szWinmine           ;窗口句柄
    invoke GetWindowThreadProcessId,eax,offset g_dwPid  ; 进程id
    invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,g_dwPid ;打开进程
	mov g_hProc,eax
	
	;申请内存
    invoke VirtualAllocEx,g_hProc,NULL,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
    mov g_pAddr,eax
    
    
    ;生成机器码写入到申请的内存,跨进程写内存
    invoke WriteProcessMemory, g_hProc, g_pAddr, offset MSGBOX, offset start - offset MSGBOX, offset g_dwBytesWrited
	
	; 创建线程,执行代码
	invoke CreateRemoteThread,g_hProc,NULL,0,g_pAddr,NULL,NULL,NULL
	
	invoke ExitProcess,eax
	end start

扫雷的可执行文件放进去,先执行了扫雷,在执行程序,导致直接扫雷崩溃,,,,,,,,

调试分析过程记录

在chongdingwei.exe中内存申请成功,在02770000处;

在winmine.exe中找到这个位置查看,4个push和1个call;

在chongdingwei.exe再查看

查看chongdingwei.exe,找到二进制数据,4个push(00结尾)和1个call;

在winmine.exe的02770000处下断点,当chongdingwei.exe启动线程时,在这个位置断下来

这里重新开始跑了,申请的地址变了,不过不影响分析,继续进行,新申请的地址 02b60000

当chongdingwei.exe启动线程

在winmine.exe的02770000处这个位置断下来;

继续单步走一下就崩溃了; 这里是怎么看出来崩掉的 ?????????

查看日志: 查看 - 记录

这里日志没有报错信息

用x64dbg打开调一下,这里的日志信息比较详细;

winmine.exe用x64dbg打开,先让进程跑起来;

在radasm生成代码的前面加个int 3,当断点用,到int3的时候调试器就会停下来的,就能知道下断点的位置;

radasm中 构建-运行,主线程调用,winmine.exe在x64dbg断下来

f8单步,直接崩溃;

下个断点,(将断点int 3,改为Nop, 继续走)

走到call的位置就挂掉了

4个push,中间两个是两个字符串: 右键-内存窗口中转到-这个地址 ;发现并不是传入的字符串

字符串没有拷贝过来,而且地址不对,地址在原进程中写成固定值了;

这个字符串地址是原进程中的地址,并没有拷贝到winmine.exe中

打开chongdingwei.exe,看一下字符串的位置

查看字符串: 右键 - 数据窗口跟随 - 立即数

分析完成,开始处理问题;

问题处理

字符串问题处理: 先把字符串带到winmine.exe线程:

修改用这种方式

先让winmine.exe用x64dbg打开,程序跑起来;

双击chongdingwei.exe

程序断下来

下断点,查看字符串是否带进来了

字符串从02ac0003开始的

可以看到字符串代进来了;

但是push的地址不对,push的地址应该是在jmp的位置;

因为这个地址是写的注入代码时内存的地址,拷贝到主线程后,机器码没有变化,这个地址还是 原来的地址。

地址需要动态算出来

地址问题处理:发现主线程地址与注入代码地址差是一样的(偏移值相同)。 动态算出来地址

当代码跑起来的时候,需要算出来在哪个地址;

用相同指令位置的值来相减就可以;

偏移值: 获取当前的EIP ,减去之前的offset地址值

获取当前指令在新的内存中地址:

call 会把下一条指令的地址压栈,标号正好在pop指令上,所以就把pop ebx指令地址压栈,然后再执行pop ebx,此时ebx就是这条指令的地址(eip的值);

获取偏移:

新地址 - 原先的地址

invoke不能用了,否则地址仍然是固定的,但地址要实时取,所以用push四个参数。

先让winmine.exe用x64dbg打开,程序跑起来;

双击chongdingwei.exe

程序断下来,可以看到各个差值是正确的

但是这个call的地址值为空,这里无法调用messagebox

messagebox地址也不能写死,否则不能做到通用;

看一下chongdingwei.exe的call怎么调用messagebox的

call 跑到jmp的位置,jmp跳到messagebox函数地址的,是一个偏移

同一台电脑上,不同进程中的dll地址相同,包括kernal32,user32,那么LoadLib,GetProcAddr,地址也是一样的; 模块地址一样,那么导出函数地址一样

假设不同进程中地址不一样,获取到LoadLibary,GetProcAddress地址,就获取任何api的地址

未使用宏的时候,代码保存一下

.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

spush macro x
    mov eax, offset x
    add eax,ebx
    push eax
endm

scall macro x
    mov eax, offset x
    add eax,ebx
    call dword ptr[eax]
endm

smov macro x,reg
    mov eax, offset x
    add eax,ebx
    mov dword ptr [eax],reg
endm



.data
    g_szWinmine db "扫雷", 0
    g_szKernel db "Kernel32", 0
    g_szLoadLibrary db "LoadLibraryA", 0
    g_szGetProcAddress db "GetProcAddress", 0
    g_hKer   dd 0
    g_dwPid   dd 0
    g_hProc   dd 0
    g_pAddr   dd 0
    g_dwBytesWrited dd 0
    g_dwOldProc dd 0 


.code

MSGBOX:
int 3

jmp COMEONBABY
g_szMsg   db "你被注入了", 0
g_szTitle db "不要担心,重启就行", 0
g_szUser32 db "user32",0  ;拿到user32基址
g_szMsgBox db "MessageBoxA",0

g_pfnLoadLib   dd 0
g_pfnGetProcAddr dd 0
g_pfnMessageBox dd 0
g_hUser32    dd 0

COMEONBABY:
call NEXT
NEXT:
pop ebx    ; 获取新内存地址
sub ebx, offset NEXT ;获取偏移

mov edx, offset g_pfnLoadLib
add edx,ebx ;LoadLibary地址

mov eax, offset g_szUser32
add eax, ebx
push eax

call dword ptr [edx]; 调用LoadLibary,加载User32模块

mov edx, offset g_hUser32
add edx,ebx
mov dword ptr [edx],eax

mov edx, offset g_pfnGetProcAddr
add edx,ebx ;GetProcAddress地址

mov eax, offset g_szMsgBox
add eax,ebx
push eax 

call dword ptr[eax] ;调用GetProcAddress,获取MessageBox地址

mov edx, offset g_pfnMessageBox
add edx, ebx
mov dword ptr [edx], eax

push MB_OK

mov eax, offset g_szTitle
add eax,ebx  ;当前地址+偏移地址
push eax

mov eax, offset g_szMsg
add eax,ebx 
push eax

push NULL


mov edx, offset g_pfnMessageBox
add edx, ebx
call dword ptr [edx] ; 调用MessageBox

ret 4 ; 执行之后从线程函数中返回,线程函数一个参数,参数平栈

;invoke MessageBox,NULL,offset g_szMsg,offset g_szTitle, MB_OK

    

start:
    ;打开进程
    invoke FindWindow,NULL,offset g_szWinmine           ;窗口句柄
    invoke GetWindowThreadProcessId,eax,offset g_dwPid  ; 进程id
    invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,g_dwPid ;打开进程
	mov g_hProc,eax
	
	;申请内存
    invoke VirtualAllocEx,g_hProc,NULL,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
    mov g_pAddr,eax
    
    
    ;生成机器码写入到申请的内存,跨进程写内存
    invoke WriteProcessMemory, g_hProc, g_pAddr, offset MSGBOX, offset start - offset MSGBOX, offset g_dwBytesWrited
	
	; 创建线程,执行代码
	invoke CreateRemoteThread,g_hProc,NULL,0,g_pAddr,NULL,NULL,NULL
	
	invoke ExitProcess,eax

end start

使用宏代码记录

.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

spush macro x
    mov eax, offset x
    add eax,ebx
    push eax
endm

scall macro x
    mov eax, offset x
    add eax,ebx
    call dword ptr[eax]
endm

smov macro x,reg
    mov eax, offset x
    add eax,ebx
    mov dword ptr [eax],reg
endm



.data
    g_szWinmine db "扫雷", 0
    g_szKernel db "Kernel32", 0
    g_szLoadLibrary db "LoadLibraryA", 0
    g_szGetProcAddress db "GetProcAddress", 0
    g_hKer   dd 0
    g_dwPid   dd 0
    g_hProc   dd 0
    g_pAddr   dd 0
    g_dwBytesWrited dd 0
    g_dwOldProc dd 0 


.code

MSGBOX:
int 3

jmp COMEONBABY
g_szMsg   db "你被注入了", 0
g_szTitle db "不要担心,重启就行", 0
g_szUser32 db "user32",0  ;拿到user32基址
g_szMsgBox db "MessageBoxA",0


g_pfnLoadLib   dd 0
g_pfnGetProcAddr dd 0
g_pfnMessageBox dd 0
g_hUser32    dd 0

COMEONBABY:
call NEXT
NEXT:
pop ebx    ; 获取新内存地址
sub ebx, offset NEXT ;获取偏移


;加载user32.dll
spush offset g_szUser32
scall g_pfnLoadLib

mov edx,eax
smov g_hUser32,edx


;获取MessageBox地址
spush offset g_szMsgBox
scall g_pfnGetProcAddr

mov edx,eax
smov g_pfnMessageBox,edx


;调用MessageBox
push MB_OK
spush offset g_szTitle
spush offset g_szMsg
push NULL
scall offset g_pfnMessageBox

ret 4 ; 执行之后从线程函数中返回,线程函数一个参数,参数平栈

;invoke MessageBox,NULL,offset g_szMsg,offset g_szTitle, MB_OK

    

start:
    ;打开进程
    invoke FindWindow,NULL,offset g_szWinmine           ;窗口句柄
    invoke GetWindowThreadProcessId,eax,offset g_dwPid  ; 进程id
    invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,g_dwPid ;打开进程
	mov g_hProc,eax
	
	;写入loadLibrary和GetProcAddress地址
	invoke GetModuleHandle,offset g_szKernel
	mov g_hKer,eax
	
	invoke GetProcAddress,g_hKer,offset g_szLoadLibrary
	mov g_pfnLoadLib,eax
	
	invoke GetProcAddress,g_hKer,offset g_szGetProcAddress
	mov g_pfnGetProcAddr,eax
	
	
	
	
	
	;申请内存
    invoke VirtualAllocEx,g_hProc,NULL,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
    mov g_pAddr,eax
    
    
    ;生成机器码写入到申请的内存,跨进程写内存
    invoke WriteProcessMemory, g_hProc, g_pAddr, offset MSGBOX, offset start - offset MSGBOX, offset g_dwBytesWrited
	
	; 创建线程,执行代码
	invoke CreateRemoteThread,g_hProc,NULL,0,g_pAddr,NULL,NULL,NULL
	
	invoke ExitProcess,eax

end start

地址写数据的时候报C00005,401034代码区,地址写到代码区就完蛋

代码需要改一下属性

主进程也报错异常了;

发现

参数不够的表现

代码修改,messageBox增加参数

spush offset g_szMsgBox

spushval g_hUser32

scall g_pfnGetProcAddr

注入成功

完整代码记录

.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib
   
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
spush macro x
    mov eax, offset x
    add eax, ebx
    push eax
endm

spushval macro x
    mov eax, offset x
    add eax, ebx
    push dword ptr[eax]
endm

scall macro x
    mov eax, offset x
    add eax, ebx
    call dword ptr[eax]
endm

smov macro x, reg
    mov eax, offset x
    add eax, ebx
    mov dword ptr [eax], reg
endm

.data

g_szWinmine db "扫雷", 0
g_szKernel db "Kernel32", 0
g_szLoadLibrary db "LoadLibraryA", 0
g_szGetProcAddress db "GetProcAddress", 0
g_hKer   dd 0
g_dwPid   dd 0
g_hProc   dd 0
g_pAddr   dd 0
g_dwBytesWrited dd 0
g_dwOldProc dd 0 

.code
MSGBOX:

jmp EXECODE
g_szMsg   db "你被注入了", 0
g_szTitle db "不要担心,重启就行", 0

g_szUser32 db "user32", 0
g_szMsgBox db "MessageBoxA", 0

g_pfnLoadLib        dd 0 ;三个函数地址,在主函数赋值了。
g_pfnGetProcAddr    dd 0
g_pfnMessageBox     dd 0

g_hUser32           dd 0 ;句柄


EXECODE:

call NEXT
NEXT:
pop ebx
sub ebx,offset NEXT  ;获取偏移

;----------------------------------------messagebox函数在user32.dll里-------------------
;加载user32.dll
spush offset g_szUser32
scall g_pfnLoadLib

mov edx, eax
smov g_hUser32, edx

;获取MessageBox地址
spush   offset g_szMsgBox
spushval g_hUser32
scall g_pfnGetProcAddr

mov edx, eax
smov g_pfnMessageBox, edx

;----------------------------------------调用messagebox函数-------------------
push MB_OK
spush offset g_szMsg
spush offset g_szTitle
push NULL
scall offset g_pfnMessageBox
ret 4                 ;线程过程函数有一个参数
;invoke MessageBox, NULL, offset g_szMsg, offset g_szTitle, MB_OK
;---------------------------------------------------------------------------------


start:
	
    invoke FindWindow,NULL,offset g_szWinmine  ;窗口句柄,返回到了eax
    invoke GetWindowThreadProcessId,eax,offset g_dwPid ;进程id
    invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,g_dwPid ;打开进程
    mov g_hProc,eax                                    ;进程句柄
    
    ;改代码段属性
    invoke VirtualProtect, offset MSGBOX, offset start - offset MSGBOX, PAGE_EXECUTE_READWRITE, offset g_dwOldProc
    
    
    ;写入LoadLibaray和GetProcAddress地址;LoadLibaray加载user32.dll,GetProcAddress得到messagebox地址。
    invoke GetModuleHandle, offset g_szKernel
    mov g_hKer, eax
    
    invoke GetProcAddress,g_hKer,offset g_szLoadLibrary
    mov g_pfnLoadLib, eax
    
    invoke GetProcAddress, g_hKer, offset g_szGetProcAddress
    mov g_pfnGetProcAddr, eax
    
    ;申请内存
    invoke VirtualAllocEx,g_hProc,NULL,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
    mov g_pAddr,eax
    
    invoke VirtualProtect, offset MSGBOX, offset start - offset MSGBOX, g_dwOldProc, offset g_dwOldProc
    
    ;写入机器码
    invoke WriteProcessMemory,g_hProc,g_pAddr,offset MSGBOX, offset start - offset MSGBOX, offset g_dwBytesWrited
    
    ;创建线程,执行代码
    invoke CreateRemoteThread, g_hProc, NULL,0, g_pAddr, NULL, NULL, NULL
    
	invoke ExitProcess,eax


end start

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/awmking/p/17029334.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!