BOOL WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten );
首先分析一下kernel32中的WriteProcessMemory,这里不管检查部分
push eax ; NumberOfBytesWritten push ebx ; NumberOfBytesToWrite push [ebp+Buffer] ; Buffer push [ebp+lpBaseAddress] ; BaseAddress push edi ; ProcessHandle call ds:NtWriteVirtualMemory
分析ntdll中的NtWriteVirtualMemory
ZwWriteVirtualMemory proc near mov eax, 115h ; NtWriteVirtualMemory mov edx, 7FFE0300h call dword ptr [edx] retn 14h
这里用到了_KUSER_SHARED_DATA结构
kd> dt _KUSER_SHARED_DATA nt!_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
+300处为系统调用,有两种方式
KiFastSystemCall KiIntSystemCall
KiIntSystemCall proc near arg_4= byte ptr 8 lea edx, [esp+arg_4] int 2Eh retn
KiFastSystemCall proc near mov edx, esp sysenter
到这栈为
分析结束,重写WriteProcessMemory的三环部分
#include "stdafx.h" #include <windows.h> void __declspec(naked) MyIntWriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten){ __asm{ mov eax,0x115 lea edx,[esp+4] int 0x2e ret } } void __declspec(naked) MyFastWriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten){ __asm{ push retaddr mov eax,0x115 mov edx,esp _emit 0x0f _emit 0x34 retaddr: ret } } int main(int argc, char* argv[]) { DWORD X=0xabcd; DWORD addr=0; DWORD dwProcessId = 0; DWORD check=0; printf("input Pid:"); scanf("%x",&dwProcessId); printf("input addr:"); scanf("%x",&addr); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId); //MyIntWriteProcessMemory(hProcess,(char*)addr,(char*)&X,(SIZE_T)4,(SIZE_T*)NULL); MyFastWriteProcessMemory(hProcess,(char*)addr,(char*)&X,(SIZE_T)4,(SIZE_T*)NULL); return 0; }
测试代码
#include "stdafx.h" #include <windows.h> int main(int argc, char* argv[]) { DWORD X=0x1234; DWORD PID=GetCurrentProcessId(); printf("PID = %x\n",PID); printf("X = %x\n",X); printf("Xaddr = %x\n",&X); getchar(); printf("X = %x\n",X); getchar(); return 0; }
有两点要注意
1,在fast时要注意栈的结构
2,vc6脑瘫编译器把push retaddr编译成了push [retaddr]