重写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("\nWriteing\n");
    OverWriteProcessMemory_Fast(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid),(LPVOID)addr,"ppp\0",4,&dwWrite);

    printf("end:");
    ReadProcessMemory_FAST(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid),(LPCVOID)addr,buffer,4,&dwRead);
    printf("%s",(char*)buffer);
    getchar();
}

 

posted @ 2020-11-15 16:17  PYozo_free  阅读(981)  评论(0编辑  收藏  举报