远程线程注入汇编代码

20,853次阅读
没有评论

共计 4395 个字符,预计需要花费 11 分钟才能阅读完成。

远程线程注入汇编代码

重定位问题

编译器在处理调用的 API 时,由于 API 地址不确定,他就会定义一个全局变量,然后在运行时由系统去填充全局变量(放入 API 的实现位置)

远程线程注入汇编代码
远程线程注入汇编代码
远程线程注入汇编代码
注入代码,而实际上调用这个 call MessageBox,实际上 CALL 的是一个偏移地址,

injectCode proc
    int   3
    push  0
    push  0
    push  0
    push  0
    call  MessageBox
    retn  4                ; 这里是一个线程回调函数,有一个参数 DWORD WINAPI ThreadProc(LPVOID lpParameter);
injectCode endp

注入程序中,在注入程序中 MessageBox 这个偏移位置是正确的 API 位置
远程线程注入汇编代码
被注入程序,而在被注入程序这个偏移是一个错误的位置(无效地址)
远程线程注入汇编代码

模拟系统这个功能,首先申请一个全局变量,然后在模拟操作系统把 API 地址填入全局变量

    ; 获取自己模块基质
    invoke GetModuleHandle,offset USER32_NAME
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @hUser32,eax

    ; 获取 API 地址
    invoke GetProcAddress,@hUser32,offset MSGBOX_NAME
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @hMsgBoxAddr,eax
    mov dword ptr [MessageBoxAddr],eax

    ; 正常情况(MessageBoxAddr - @hUser32)+ 对方 User32 模块基质

需要注意的是,写入的位置是一个代码区没有权限写入,要不然就写入数据区,要不然就修改内存属性

injectCode proc
    int     3
    push  0
    push  0
    push  0
    push  0
    call    dword ptr [MessageBoxAddr]
    retn   4                             ; 这里是一个线程回调函数,有一个参数 DWORD WINAPI ThreadProc(LPVOID lpParameter);

MessageBoxAddr  dd  ?
injectCode endp

call dword ptr [MessageBoxAddr],但是这样会变成 Call 一个绝对地址取内容,而绝对地址是由注入方生成的

注入方
远程线程注入汇编代码
被注入方
远程线程注入汇编代码

所以要解决这个问题,我们就要使用相互地址,而不是绝对地址,这个就叫代码重定位问题

方法一

一个巧妙的方法,通过 CALL 标号 把当前 EIP 当前地址入栈,然后我们直接 POP ebx 出栈把当前地址给 ebx,在用 edx + 偏移这样就可以获取到正确的地址,缺陷就是每次都需要计算

injectCode proc
    int     3
    push  0
    push  0
    push  0
    push  0

    call NEXT
NEXT:
    pop   ebx
    call    dword ptr[ebx + 7]
    retn   4                             ; 这里是一个线程回调函数,有一个参数 DWORD WINAPI ThreadProc(LPVOID lpParameter);

MessageBoxAddr  dd  ?
injectCode endp

远程线程注入汇编代码

方法二

首先通过被注入程序地址 – 注入程序地址 得到程序的偏移,然后注入程序的地址里面的数据地址 + 程序偏移就是被注入程序的实际位置

远程线程注入汇编代码

injectCode proc
    int     3
    call NEXT
NEXT:
    pop     ebx
    sub     ebx,NEXT 

    push    MB_OK
    lea eax,[ebx+Title1]
    push    eax
    lea eax,[ebx+Msg1]
    push    eax
    push    NULL

    call    dword ptr[ebx + MessageBoxAddr]
    retn   4                             ; 这里是一个线程回调函数,有一个参数 DWORD WINAPI ThreadProc(LPVOID lpParameter);

MessageBoxAddr  dd  ?
Msg1                    db "Hello World",0
Title1                    db  "51ASM",0
injectCode endp

远程线程注入汇编代码

获取 API 的偏移地址

拿自己的模块基质 减掉 API 地址,得到一个 API 偏移,然后在被注入程序中 加上这个偏移 就是一个正确的 API 地址
(MessageBoxAddr – @hUser32)+ 对方 User32 模块基质

    ; 获取自己模块基质
    invoke GetModuleHandle,offset USER32_NAME
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @hUser32,eax

    ; 获取 API 地址
    invoke GetProcAddress,@hUser32,offset MSGBOX_NAME
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @hMsgBoxAddr,eax
    mov dword ptr [MessageBoxAddr],eax

    ; 正常情况(MessageBoxAddr - @hUser32)+ 对方 User32 模块基质

调试技巧

INT 3 断点,当被调试进程执行 INT3 指令导致一个异常时,调试器就会捕捉这个异常从而停在断点处

所以在注入的汇编代码写入 INT 3,调试被注入程序时代码注入后会自动停止在 INT 3 的位置
远程线程注入汇编代码

注入代码

.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include Project1.inc

.code

start:
    invoke  GetModuleHandle,NULL
    mov     hInstance,eax

       invoke  InitCommonControls
    invoke  DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
    invoke  ExitProcess,0

injectCode proc
    int     3
    call NEXT
NEXT:
    pop     ebx
    sub     ebx,NEXT 

    push    MB_OK
    lea eax,[ebx+Title1]
    push    eax
    lea eax,[ebx+Msg1]
    push    eax
    push    NULL

    call    dword ptr[ebx + MessageBoxAddr]
    retn   4                             ; 这里是一个线程回调函数,有一个参数 DWORD WINAPI ThreadProc(LPVOID lpParameter);

MessageBoxAddr  dd  ?
Msg1                    db "Hello World",0
Title1                    db  "51ASM",0
injectCode endp

Inject proc
    LOCAL   @hWnd:HWND
    LOCAL   @dwPid:DWORD
    LOCAL   @hProcess:HANDLE
    LOCAL   @lpBuffer:PVOID
    LOCAL   @dwBytes:PVOID
    LOCAL   @hThread:HANDLE
    LOCAL   @hUser32:HANDLE
    LOCAL   @hMsgBoxAddr:PVOID
    LOCAL   @dwOld:dword

    mov @hWnd,NULL
    mov @dwPid,0
    mov @hProcess,NULL
    mov @lpBuffer,NULL
    mov @dwBytes,0
    mov @hThread,NULL
    mov @hUser32,NULL
    mov @hMsgBoxAddr,NULL
    mov @dwOld,0

    ; 获取窗口句柄
    invoke FindWindow,NULL,offset WND_NAME
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @hWnd,eax

    ; 获取进程 ID
    invoke GetWindowThreadProcessId,@hWnd,addr @dwPid
    .if eax==NULL
        jmp Inject_End
    .endif

    ; 打开进程
    invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,@dwPid
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @hProcess,eax

    ; 申请内存
    invoke VirtualAllocEx,@hProcess,NULL,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @lpBuffer,eax

    ; 获取自己模块基质
    invoke GetModuleHandle,offset USER32_NAME
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @hUser32,eax

    ; 获取 API 地址
    invoke GetProcAddress,@hUser32,offset MSGBOX_NAME
    .if eax==NULL
        jmp Inject_End
    .endif
    mov @hMsgBoxAddr,eax

    invoke VirtualProtect,offset MessageBoxAddr,Inject-MessageBoxAddr,PAGE_EXECUTE_READWRITE,addr @dwOld
    .if eax==NULL
        jmp Inject_End
    .endif
    mov eax,@hMsgBoxAddr
    mov  [MessageBoxAddr],eax

    ; 正常情况(MessageBoxAddr - @hUser32)+ 对方 User32 模块基质

    ; 写入汇编代码
    invoke WriteProcessMemory,@hProcess,@lpBuffer,offset injectCode,Inject-injectCode,addr @dwBytes
    .if eax==0
        jmp Inject_End
    .endif

    ; 创建远程线程
    invoke CreateRemoteThread,@hProcess,NULL,0,@lpBuffer,NULL,0,NULL
    .if eax==0
        jmp Inject_End
    .endif

    ; 等待线程结束

    ; 删除注入代码

Inject_End:

    .if @hWnd != NULL
        invoke CloseHandle,@hWnd
    .endif

    .if @hProcess!= NULL
        invoke CloseHandle,@hProcess
    .endif

     .if @hThread!= NULL
        invoke CloseHandle,@hThread
    .endif

     .if @hUser32!= NULL
        invoke CloseHandle,@hUser32
    .endif

    ret
Inject endp

DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    mov eax,uMsg
    .if eax==WM_INITDIALOG

    .elseif eax==WM_COMMAND
        mov eax,wParam
        .if ax == IDC_BTN1
            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

正文完
 0
s2ad0w
版权声明:本站原创文章,由 s2ad0w 于2023-10-10发表,共计4395字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)