• 重写WriteProcessMemory


    分析WriteProcessMemory调用过程

    首先咱们先查看kernel32.dll这个库,并找到WriteProcessMemory

    .text:7C802213 WriteProcessMemory proc near            ; DATA XREF: .text:off_7C802654↓o
    .text:7C802213
    .text:7C802213 BaseAddress     = dword ptr -8
    .text:7C802213 NumberOfBytesToProtect= dword ptr -4
    .text:7C802213 ProcessHandle   = dword ptr  8
    .text:7C802213 lpBaseAddress   = dword ptr  0Ch
    .text:7C802213 Buffer          = dword ptr  10h
    .text:7C802213 OldAccessProtection= dword ptr  14h
    .text:7C802213 lpNumberOfBytesWritten= dword ptr  18h
    .text:7C802213
    .text:7C802213                 mov     edi, edi
    .text:7C802215                 push    ebp
    .text:7C802216                 mov     ebp, esp
    .text:7C802218                 push    ecx
    .text:7C802219                 push    ecx
    .text:7C80221A                 mov     eax, [ebp+lpBaseAddress]
    .text:7C80221D                 push    ebx
    .text:7C80221E                 mov     ebx, [ebp+OldAccessProtection]
    .text:7C802221                 push    esi
    .text:7C802222                 mov     esi, ds:NtProtectVirtualMemory
    .text:7C802228                 push    edi
    .text:7C802229                 mov     edi, [ebp+ProcessHandle]
    .text:7C80222C                 mov     [ebp+BaseAddress], eax
    .text:7C80222F                 lea     eax, [ebp+OldAccessProtection]
    .text:7C802232                 push    eax             ; OldAccessProtection
    .text:7C802233                 push    40h             ; NewAccessProtection
    .text:7C802235                 lea     eax, [ebp+NumberOfBytesToProtect]
    .text:7C802238                 push    eax             ; NumberOfBytesToProtect
    .text:7C802239                 lea     eax, [ebp+BaseAddress]
    .text:7C80223C                 push    eax             ; BaseAddress
    .text:7C80223D                 push    edi             ; ProcessHandle
    .text:7C80223E                 mov     [ebp+NumberOfBytesToProtect], ebx
    .text:7C802241                 call    esi ; NtProtectVirtualMemory
    .text:7C802243                 cmp     eax, 0C000004Eh
    .text:7C802248                 jz      short loc_7C8022A6
    .text:7C80224A
    .text:7C80224A loc_7C80224A:                           ; CODE XREF: WriteProcessMemory+A4↓j
    .text:7C80224A                 test    eax, eax
    .text:7C80224C                 jl      short loc_7C80229B
    .text:7C80224E                 mov     eax, [ebp+OldAccessProtection]
    .text:7C802251                 test    al, 0CCh
    .text:7C802253                 jz      short loc_7C8022B9
    .text:7C802255                 lea     ecx, [ebp+OldAccessProtection]
    .text:7C802258                 push    ecx             ; OldAccessProtection
    .text:7C802259                 push    eax             ; NewAccessProtection
    .text:7C80225A                 lea     eax, [ebp+NumberOfBytesToProtect]
    .text:7C80225D                 push    eax             ; NumberOfBytesToProtect
    .text:7C80225E                 lea     eax, [ebp+BaseAddress]
    .text:7C802261                 push    eax             ; BaseAddress
    .text:7C802262                 push    edi             ; ProcessHandle
    .text:7C802263                 call    esi ; NtProtectVirtualMemory
    .text:7C802265                 lea     eax, [ebp+ProcessHandle]
    .text:7C802268                 push    eax             ; NumberOfBytesWritten
    .text:7C802269                 push    ebx             ; NumberOfBytesToWrite
    .text:7C80226A                 push    [ebp+Buffer]    ; Buffer
    .text:7C80226D                 push    [ebp+lpBaseAddress] ; BaseAddress
    .text:7C802270                 push    edi             ; ProcessHandle
    .text:7C802271                 call    ds:NtWriteVirtualMemory
    .text:7C802277                 mov     ecx, [ebp+lpNumberOfBytesWritten]
    .text:7C80227A                 test    ecx, ecx
    .text:7C80227C                 jnz     loc_7C802320
    .text:7C802282
    .text:7C802282 loc_7C802282:                           ; CODE XREF: WriteProcessMemory+112↓j
    .text:7C802282                 test    eax, eax
    .text:7C802284                 jl      short loc_7C80229B
    .text:7C802286
    .text:7C802286 loc_7C802286:                           ; CODE XREF: WriteProcessMemory+E1↓j
    .text:7C802286                 push    ebx             ; NumberOfBytesToFlush
    .text:7C802287                 push    [ebp+lpBaseAddress] ; BaseAddress
    .text:7C80228A                 push    edi             ; ProcessHandle
    .text:7C80228B                 call    ds:NtFlushInstructionCache
    .text:7C802291                 xor     eax, eax
    .text:7C802293                 inc     eax
    .text:7C802294
    .text:7C802294 loc_7C802294:                           ; CODE XREF: WriteProcessMemory+108↓j
    .text:7C802294                                         ; WriteProcessMemory+119↓j
    .text:7C802294                 pop     edi
    .text:7C802295                 pop     esi
    .text:7C802296                 pop     ebx
    .text:7C802297                 leave
    .text:7C802298                 retn    14h
    .text:7C80229B ; ---------------------------------------------------------------------------
    .text:7C80229B
    .text:7C80229B loc_7C80229B:                           ; CODE XREF: WriteProcessMemory+39↑j
    .text:7C80229B                                         ; WriteProcessMemory+71↑j
    .text:7C80229B                 push    eax             ; Status
    .text:7C80229C                 call    sub_7C8093FD
    .text:7C8022A1                 jmp     loc_7C80232A
    .text:7C8022A6 ; ---------------------------------------------------------------------------
    .text:7C8022A6
    .text:7C8022A6 loc_7C8022A6:                           ; CODE XREF: WriteProcessMemory+35↑j
    .text:7C8022A6                 lea     eax, [ebp+OldAccessProtection]
    .text:7C8022A9                 push    eax             ; OldAccessProtection
    .text:7C8022AA                 push    4               ; NewAccessProtection
    .text:7C8022AC                 lea     eax, [ebp+NumberOfBytesToProtect]
    .text:7C8022AF                 push    eax             ; NumberOfBytesToProtect
    .text:7C8022B0                 lea     eax, [ebp+BaseAddress]
    .text:7C8022B3                 push    eax             ; BaseAddress
    .text:7C8022B4                 push    edi             ; ProcessHandle
    .text:7C8022B5                 call    esi ; NtProtectVirtualMemory
    .text:7C8022B7                 jmp     short loc_7C80224A
    .text:7C8022B9 ; ---------------------------------------------------------------------------
    .text:7C8022B9
    .text:7C8022B9 loc_7C8022B9:                           ; CODE XREF: WriteProcessMemory+40↑j
    .text:7C8022B9                 test    al, 3
    .text:7C8022BB                 jnz     short loc_7C8022FD
    .text:7C8022BD                 lea     eax, [ebp+ProcessHandle]
    .text:7C8022C0                 push    eax             ; NumberOfBytesWritten
    .text:7C8022C1                 push    ebx             ; NumberOfBytesToWrite
    .text:7C8022C2                 push    [ebp+Buffer]    ; Buffer
    .text:7C8022C5                 push    [ebp+lpBaseAddress] ; BaseAddress
    .text:7C8022C8                 push    edi             ; ProcessHandle
    .text:7C8022C9                 call    ds:NtWriteVirtualMemory
    .text:7C8022CF                 mov     [ebp+Buffer], eax
    .text:7C8022D2                 mov     eax, [ebp+lpNumberOfBytesWritten]
    .text:7C8022D5                 test    eax, eax
    .text:7C8022D7                 jz      short loc_7C8022DE
    .text:7C8022D9                 mov     ecx, [ebp+ProcessHandle]
    .text:7C8022DC                 mov     [eax], ecx
    .text:7C8022DE
    .text:7C8022DE loc_7C8022DE:                           ; CODE XREF: WriteProcessMemory+C4↑j
    .text:7C8022DE                 lea     eax, [ebp+OldAccessProtection]
    .text:7C8022E1                 push    eax             ; OldAccessProtection
    .text:7C8022E2                 push    [ebp+OldAccessProtection] ; NewAccessProtection
    .text:7C8022E5                 lea     eax, [ebp+NumberOfBytesToProtect]
    .text:7C8022E8                 push    eax             ; NumberOfBytesToProtect
    .text:7C8022E9                 lea     eax, [ebp+BaseAddress]
    .text:7C8022EC                 push    eax             ; BaseAddress
    .text:7C8022ED                 push    edi             ; ProcessHandle
    .text:7C8022EE                 call    esi ; NtProtectVirtualMemory
    .text:7C8022F0                 cmp     [ebp+Buffer], 0
    .text:7C8022F4                 jge     short loc_7C802286
    .text:7C8022F6                 mov     esi, 0C0000005h
    .text:7C8022FB                 jmp     short loc_7C80230F
    .text:7C8022FD ; ---------------------------------------------------------------------------
    .text:7C8022FD
    .text:7C8022FD loc_7C8022FD:                           ; CODE XREF: WriteProcessMemory+A8↑j
    .text:7C8022FD                 lea     ecx, [ebp+OldAccessProtection]
    .text:7C802300                 push    ecx             ; OldAccessProtection
    .text:7C802301                 push    eax             ; NewAccessProtection
    .text:7C802302                 lea     eax, [ebp+NumberOfBytesToProtect]
    .text:7C802305                 push    eax             ; NumberOfBytesToProtect
    .text:7C802306                 lea     eax, [ebp+BaseAddress]
    .text:7C802309                 push    eax             ; BaseAddress
    .text:7C80230A                 push    edi             ; ProcessHandle
    .text:7C80230B                 call    esi ; NtProtectVirtualMemory
    .text:7C80230D                 xor     esi, esi
    .text:7C80230F
    .text:7C80230F loc_7C80230F:                           ; CODE XREF: WriteProcessMemory+E8↑j
    .text:7C80230F                 push    0C0000005h      ; Status
    .text:7C802314                 call    sub_7C8093FD
    .text:7C802319                 mov     eax, esi
    .text:7C80231B                 jmp     loc_7C802294
    .text:7C802320 ; ---------------------------------------------------------------------------
    .text:7C802320
    .text:7C802320 loc_7C802320:                           ; CODE XREF: WriteProcessMemory+69↑j
    .text:7C802320                 mov     edx, [ebp+ProcessHandle]
    .text:7C802323                 mov     [ecx], edx
    .text:7C802325                 jmp     loc_7C802282
    .text:7C80232A ; ---------------------------------------------------------------------------
    .text:7C80232A
    .text:7C80232A loc_7C80232A:                           ; CODE XREF: WriteProcessMemory+8E↑j
    .text:7C80232A                 xor     eax, eax
    .text:7C80232C                 jmp     loc_7C802294
    .text:7C80232C WriteProcessMemory endp

    发现该函数调用过程会先检查该虚拟地址的状态,然后在调用NTWriteProcessMemory这个函数,当我们在查看导入表的时候,会发现这个函数在ntdll.dll里面,所以我们查看ntdll.dll里NTWriteProcessMemory这个函数

    ZwWriteVirtualMemory proc near
    mov     eax, 115h       ; NtWriteVirtualMemory
    mov     edx, 7FFE0300h
    call    dword ptr [edx]
    retn    14h
    ZwWriteVirtualMemory endp

    发现他调用了7ffe0300这个位置的函数,这里其实是一个结构体_KUSER_SHARED_DATA

    _KUSER_SHARED_DATA

    先来看看成员

    0: kd> dt _KUSER_SHARED_DATA 
    ntdll!_KUSER_SHARED_DATA
       +0x000 TickCountLow     : Uint4B
       +0x004 TickCountMultiplier : Uint4B
       +0x008 InterruptTime    : _KSYSTEM_TIME
       +0x014 SystemTime       : _KSYSTEM_TIME
       +0x020 TimeZoneBias     : _KSYSTEM_TIME
       +0x02c ImageNumberLow   : Uint2B
       +0x02e ImageNumberHigh  : Uint2B
       +0x030 NtSystemRoot     : [260] Uint2B
       +0x238 MaxStackTraceDepth : Uint4B
       +0x23c CryptoExponent   : Uint4B
       +0x240 TimeZoneId       : Uint4B
       +0x244 Reserved2        : [8] Uint4B
       +0x264 NtProductType    : _NT_PRODUCT_TYPE
       +0x268 ProductTypeIsValid : UChar
       +0x26c NtMajorVersion   : Uint4B
       +0x270 NtMinorVersion   : Uint4B
       +0x274 ProcessorFeatures : [64] UChar
       +0x2b4 Reserved1        : Uint4B
       +0x2b8 Reserved3        : Uint4B
       +0x2bc TimeSlip         : Uint4B
       +0x2c0 AlternativeArchitecture : _ALTERNATIVE_ARCHITECTURE_TYPE
       +0x2c8 SystemExpirationDate : _LARGE_INTEGER
       +0x2d0 SuiteMask        : Uint4B
       +0x2d4 KdDebuggerEnabled : UChar
       +0x2d5 NXSupportPolicy  : UChar
       +0x2d8 ActiveConsoleId  : Uint4B
       +0x2dc DismountCount    : Uint4B
       +0x2e0 ComPlusPackage   : Uint4B
       +0x2e4 LastSystemRITEventTickCount : Uint4B
       +0x2e8 NumberOfPhysicalPages : Uint4B
       +0x2ec SafeBootMode     : UChar
       +0x2f0 TraceLogging     : Uint4B
       +0x2f8 TestRetInstruction : Uint8B
       +0x300 SystemCall       : Uint4B
       +0x304 SystemCallReturn : Uint4B
       +0x308 SystemCallPad    : [3] Uint8B
       +0x320 TickCount        : _KSYSTEM_TIME
       +0x320 TickCountQuad    : Uint8B
       +0x330 Cookie           : Uint4B

    在偏移0x300处有syscall这个成员,通过windbg查看一下,发现了ntdll!KiFastSystemCall函数

     通过调用了sysenter指令,从而进入了0环

     这里还有个小细节,是否支持快调用

    快调用

    快调用是什么呢?在CPU中还有一个寄存器叫做MSR寄存器,这个寄存器里面存储了在提权时需要改变寄存器的值,查看msr寄存器 rdmsr xx(偏移)

     既然有快调用,肯定会有比他慢的调用,之前我们学习中断门的时候,都是通过中断进入0环的,那么我们也可以通过中断进入

    中断调用

    当机器不知道快调用的时候,则会使用ntdll.dll!KiIntSystemCall()函数进入0环,来看看他的内容

     通过调用中断2e来中断,我们来看看中断会运行去哪里

    804dee00`0008eff0

     众所周知,中断提权填入各个段寄存器的是用TSS任务门的值填入的,而快调用则是用MSR调用的,一个是寄存器一个是内存,寄存器肯定是比内存块的

    接下来,我们来试试自己写一个简单的WriteProcessMemory函数,这里参考了hambaga师傅的博客,因为我一开始写的真的很垃圾,看完他的后,才发现自己的完全错误了

    分析WriteProcessMemory

    #include<stdio.h>
    #include<Windows.h>
    BOOL OverWriteProcessMemory_Fast(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesWritten)
    {
        LONG NtStatus;
        __asm
        {
            push lpNumberOfBytesWritten//压参数
            push nSize
            push lpBuffer
            push lpBaseAddress
            push hProcess
    
            sub esp,4                    //提升栈
            mov eax,0x115                
            mov edx,0x7ffe0300
    
            push NtWriteProcessMemoryRet
            mov edx,esp
            _emit 0x0f
            _emit 0x34
            mov NtStatus,eax
    NtWriteProcessMemoryRet:
            add esp,0x18
        }
    
        if(lpNumberOfBytesWritten!=NULL)
        {
            *lpNumberOfBytesWritten=nSize;
        }
    
        if(NtStatus<0)
        {
            return FALSE;
        }
        return TRUE;
    }
    
    BOOL OverWriteProcessMemory_Int(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesWritten)
    {
        LONG NtStatus;
        __asm
        {
            push lpNumberOfBytesWritten//压参数
            push nSize
            push lpBuffer
            push lpBaseAddress
            push hProcess
    
            sub esp,4                    //提升栈
            mov eax,0x115                
            mov edx,0x7ffe0300
    
            push NtWriteProcessMemoryRet
    
            lea edx,[esp+8]
            int 0x2E
    
            NtWriteProcessMemoryRet:
            add esp,0x18
            mov NtStatus,eax
        }
        if(lpNumberOfBytesWritten!=NULL)
        {
            *lpNumberOfBytesWritten=nSize;
        }
    
        if(NtStatus<0)
        {
            return FALSE;
        }
        return TRUE;
    }
    
    BOOL WINAPI ReadProcessMemory_FAST(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead)
    {
        LONG NtStatus;
        __asm
        {
            // 模拟 ReadProcessMemory
            lea eax,nSize;
            push eax;
            push nSize;
            push lpBuffer;
            push lpBaseAddress;
            push hProcess;
            sub esp, 0x04; // 模拟 ReadProcessMemory 里的 CALL NtReadVirtualMemory
            // 模拟 NtReadVirtualMemory
            mov eax, 0xBA;
            push NtReadVirtualMemoryReturn; // 模拟 NtReadVirtualMemory 函数里的 CALL [0x7FFE0300]
            // 模拟 KiFastSystemCall
            mov edx, esp;
            _emit 0x0F; // sysenter 
            _emit 0x34;
    NtReadVirtualMemoryReturn:        
            add esp, 0x18; // 模拟 NtReadVirtualMemory 返回到 ReadProcessMemory 时的 RETN 0x14
            mov NtStatus, eax;
        }
        if (lpNumberOfBytesRead != NULL)
        {
            *lpNumberOfBytesRead = nSize;        
        }
        // 错误检查
        if (NtStatus < 0)
        {
            return FALSE;
        }
        return TRUE;
    }
    
    BOOL EnableDebugPrivilege()
    {
        HANDLE hToken;
        BOOL fOk=FALSE;
        if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
        {
            TOKEN_PRIVILEGES tp;
            tp.PrivilegeCount=1;
            LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid);
    
            tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
            AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);
    
            fOk=(GetLastError()==ERROR_SUCCESS);
            CloseHandle(hToken);
        }
        return fOk;
    }
    
    int main()
    {
        EnableDebugPrivilege();
    
        DWORD pid,addr,dwRead,dwWrite;
        PVOID buffer[256];
        scanf("%x%x",&pid,&addr);
    
        getchar();
        printf("start:");
        ReadProcessMemory_FAST(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid),(LPCVOID)addr,buffer,4,&dwRead);
    
        printf("
    Writeing
    ");
        OverWriteProcessMemory_Fast(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid),(LPVOID)addr,"ppp",4,&dwWrite);
    
        printf("end:");
        ReadProcessMemory_FAST(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid),(LPCVOID)addr,buffer,4,&dwRead);
        printf("%s",(char*)buffer);
        getchar();
    }
  • 相关阅读:
    初学Python语言者必须理解的下划线
    Python初学者必须了解的星号(*)90%的人都不懂
    90%人不知道的Python炫技操作:合并字典的七种方法
    用Python爬取了妹子网100G的套图,值得收藏
    这种python反爬虫手段有点意思,看我怎么破解
    函数极限(上)
    数学分析--实数和数列极限--数轴
    B1046. 划拳
    B1026. 程序运行时间
    2019考研英语一 Text2分析
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/13977126.html
Copyright © 2020-2023  润新知