// just test on win7sp1x64
#include <windows.h>
#include <stdlib.h>
typedef enum _MEMORY_INFORMATION_CLASS {
MemoryBasicInformation,
MemoryWorkingSetList,
MemorySectionName,
MemoryBasicVlmInformation
} MEMORY_INFORMATION_CLASS;
LONG (WINAPI
*pfn_NtQueryVirtualMemory)(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
OUT PVOID MemoryInformation,
IN SIZE_T MemoryInformationLength,
OUT PSIZE_T ReturnLength
);
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
WCHAR gModuleName[] = L"C:\\windows\\system32\\kernelbase.dll";
WCHAR gNtdllPath[] = L"\\Device\\HarddiskVolume1\\Windows\\System32\\ntdll.dll";
PVOID __fastcall GetFuncAddress64(PVOID ImageBase, PUCHAR ApiName )
{
PVOID FuncAddress = NULL;
PIMAGE_DOS_HEADER DosHdr ;
PIMAGE_NT_HEADERS32 NtHdrs ;
PIMAGE_NT_HEADERS64 NtHdrs2;
PIMAGE_DATA_DIRECTORY DatDir ;
PIMAGE_EXPORT_DIRECTORY ExpDir ;
PULONG AddressOfNames ;
PULONG AddressOfFunctions ;
PUSHORT AddressOfNameOrdinals ;
BOOL bAMD64 = FALSE;
LONG Idx;
LONG ret;
LONG low;
LONG mid;
LONG high;
PCHAR pName;
do
{
(PVOID)DosHdr = ImageBase;
if( !DosHdr || DosHdr->e_magic != IMAGE_DOS_SIGNATURE )
{
break;
}
(PUCHAR)NtHdrs = (PUCHAR)ImageBase + DosHdr->e_lfanew;
if( (PUCHAR)NtHdrs <(PUCHAR)DosHdr || NtHdrs->Signature != IMAGE_NT_SIGNATURE )
{
break;
}
(PUCHAR)NtHdrs2 = (PUCHAR)NtHdrs;
if( NtHdrs->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && NtHdrs2->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC )
{
break;
}
bAMD64 = NtHdrs2->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
if( bAMD64 )
{
DatDir = &NtHdrs2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
}
else
{
DatDir = &NtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
}
if( DatDir->Size == 0 || DatDir->VirtualAddress == 0 )
{
break;
}
(PUCHAR)ExpDir = (PUCHAR)ImageBase + DatDir->VirtualAddress;
if ( (PUCHAR)ExpDir < (PUCHAR)NtHdrs )
{
break;
}
AddressOfNames = (PULONG)( (ULONG)ImageBase + ExpDir->AddressOfNames );
AddressOfFunctions = (PULONG)( (ULONG)ImageBase + ExpDir->AddressOfFunctions );
AddressOfNameOrdinals = (PUSHORT)( (ULONG)ImageBase + ExpDir->AddressOfNameOrdinals );
high = ExpDir->NumberOfNames-1;
low = 0;
while(low <= high)//二分查找,快速定位
{
mid = (high+low)>>1;
pName = (PCHAR)ImageBase+AddressOfNames[mid] ;
Idx = 0;
while( pName[Idx] && pName[Idx] == ApiName[Idx] )
{
++Idx;
}
ret = pName[Idx] - ApiName[Idx];
if ( ret==0 )
{
(PUCHAR)FuncAddress=(PUCHAR)ImageBase + AddressOfFunctions[ AddressOfNameOrdinals[ mid ] ];
break;
}
else if( ret > 0 )
{
high=mid-1;
}
else
{
low=mid+1;
}
}
}while( FALSE );
return FuncAddress;
}
PVOID WINAPI GetNativeNtdll( )
{
PVOID hNtdll = NULL;
PUCHAR ptr = (PUCHAR)GetModuleHandleA( NULL ) + 0x100000;
MEMORY_BASIC_INFORMATION MemInfo;
SIZE_T RetLen;
LONG Status;
WCHAR NameBuf[MAX_PATH+16];
HANDLE hProcess = GetCurrentProcess();
PUNICODE_STRING Filename = (PUNICODE_STRING)NameBuf;
if( !pfn_NtQueryVirtualMemory )
{
(FARPROC)pfn_NtQueryVirtualMemory = GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtQueryVirtualMemory" );
}
if( !pfn_NtQueryVirtualMemory )
{
return hNtdll;
}
while( ptr < (PUCHAR)0x80000000 )
{
Status = pfn_NtQueryVirtualMemory( hProcess, ptr, MemoryBasicInformation, &MemInfo, sizeof(MemInfo), &RetLen);
if( Status < 0 )
{
ptr += 0x10000;
continue;
}
if( MemInfo.State == MEM_COMMIT && MEM_IMAGE == MemInfo.Type )
{
Status = pfn_NtQueryVirtualMemory( hProcess, ptr, MemorySectionName, Filename, sizeof(NameBuf), &RetLen );
if( Status == 0 )
{
if( !_wcsnicmp(gNtdllPath, Filename->Buffer, Filename->Length) )
{
hNtdll = (PVOID)ptr;
break;
}
}
}
ptr += MemInfo.RegionSize;
}
return hNtdll;
}
PVOID WINAPI MapDllToMem( PCWSTR FileName )
{
PVOID DllBase = NULL;
HANDLE hFile;
CHAR DllData[512];
DWORD dwRetLen;
BOOL bRet;
ULONG SizeOfImage;
ULONG SizeOfHeaders;
ULONG NumOfSections;
ULONG Index;
PIMAGE_DOS_HEADER DosHdr ;
PIMAGE_NT_HEADERS NtHdrs ;
PIMAGE_SECTION_HEADER SecHdr;
BOOL bAMD64 = FALSE;
do
{
hFile = CreateFileW( FileName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE ) break;
bRet = ReadFile( hFile, DllData, sizeof(DllData), &dwRetLen, NULL );
if( !bRet ) break;
DosHdr = (PIMAGE_DOS_HEADER)DllData;
if( !DosHdr || DosHdr->e_magic != IMAGE_DOS_SIGNATURE )
{
break;
}
(PUCHAR)NtHdrs = (PUCHAR)DllData + DosHdr->e_lfanew;
if( (PUCHAR)NtHdrs <(PUCHAR)DosHdr || NtHdrs->Signature != IMAGE_NT_SIGNATURE )
{
break;
}
NumOfSections = NtHdrs->FileHeader.NumberOfSections;
SizeOfHeaders = NtHdrs->OptionalHeader.SizeOfHeaders;
SizeOfImage = NtHdrs->OptionalHeader.SizeOfImage;
DllBase = VirtualAlloc( NULL, SizeOfImage, MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
if( !DllBase )break;
RtlZeroMemory( DllBase, SizeOfImage );
SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
ReadFile( hFile, DllBase, SizeOfHeaders, &dwRetLen, NULL );
(PUCHAR)SecHdr = (PUCHAR)DllBase + ((PUCHAR)&NtHdrs->OptionalHeader - DllData) + NtHdrs->FileHeader.SizeOfOptionalHeader ;
for( Index=0; Index<NumOfSections; Index++ )
{
SetFilePointer( hFile, SecHdr->PointerToRawData, NULL, FILE_BEGIN );
ReadFile( hFile, (PUCHAR)DllBase + SecHdr->VirtualAddress, SecHdr->SizeOfRawData, &dwRetLen, NULL );
SecHdr++;
}
}while( FALSE );
return DllBase;
}
VOID WINAPI UnMapDllFromMem( PVOID DllBase )
{
VirtualFree( DllBase, 0, MEM_RELEASE );
}
BOOL WINAPI Wow64Check()
{
BOOL bWow64 = FALSE;
return IsWow64Process(GetCurrentProcess(), &bWow64) && bWow64;
}
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
HMODULE hNtdll32 = GetModuleHandleA("ntdll.dll");
HMODULE hNtdll = (HMODULE)GetNativeNtdll( );
if( hNtdll32 && hNtdll && Wow64Check() )
{
PVOID OldValue;
PVOID MemNtdllx64;
BOOL bProtectChanged;
ULONG OldProtect;
PUCHAR Buf = VirtualAlloc( NULL, 4096, MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
if( Buf )
{
LONG (WINAPI* pfn_NtDeleteKey)( HANDLE );
PUCHAR pData = Buf+256;
PUCHAR pInst = Buf+256+256;
RtlFillMemory( Buf, 256, 0 );
RtlFillMemory( pData, 256, 0 );
RtlFillMemory( pInst, 256, 0xCC );
*(PULONG)(Buf+0) = 0x00460044;
*(PULONG)(Buf+8) = (ULONG)Buf + 0x10;
RtlMoveMemory( Buf + 16 , gModuleName, 34*sizeof(WCHAR) );
*(PULONG)(pInst+ 0) = 0x40EC8148; //sub rsp, 40;
*(PULONG)(pInst+ 4) = 0x90000000;
*(PULONG)(pInst+ 8) = 0x90C93348; //xor rcx,rcx
*(PULONG)(pInst+12) = 0x90D23348; //xor rdx,rdx
*(PULONG)(pInst+16) = 0xF9000068; //push, dllpath
*(PULONG)(pInst+20) = 0x9058417E; //pop r8
*(PULONG)(pInst+17) = (ULONG)Buf;
*(PULONG)(pInst+24) = 0xF9000068; //push, pData
*(PULONG)(pInst+28) = 0x9059417E; //pop r9
*(PULONG)(pInst+25) = (ULONG)pData;
*(PULONG)(pInst+32) = 0x017AC068; //push offset ntdll!LdrLoadDll
*(PULONG)(pInst+36) = 0xD0FF5877; //pop rax; call rax
/* 00000000`7ef90228 680001f97e push 7EF90100h
00000000`7ef9022d 5e pop rsi
00000000`7ef9022e 8b06 mov eax,dword ptr [rsi]
00000000`7ef90230 014610 add dword ptr [rsi+10h],eax
00000000`7ef90233 014618 add dword ptr [rsi+18h],eax
00000000`7ef90236 014620 add dword ptr [rsi+20h],eax
00000000`7ef90239 4833c9 xor rcx,rcx
00000000`7ef9023c 681000f97e push 7EF90010h
00000000`7ef90241 5a pop rdx
00000000`7ef90242 ff5620 call qword ptr [rsi+20h]
00000000`7ef90245 83c440 add esp,40h
00000000`7ef90248 c3 ret */
*(PULONG)(pInst+40) = 0xf9010068;
*(PULONG)(pInst+44) = 0x068b5e7e;
*(PULONG)(pInst+48) = 0x01104601;
*(PULONG)(pInst+52) = 0x46011846;
*(PULONG)(pInst+56) = 0xc9334820;
*(PULONG)(pInst+60) = 0xf9001068;
*(PULONG)(pInst+64) = 0x56ff5a7e;
*(PULONG)(pInst+68) = 0x40c48320;
*(PSHORT)(pInst+72) = 0xCCC3;
*(PULONG)(pInst+41) = (ULONG)pData;
*(PULONG)(pInst+61) = (ULONG)Buf+16;
*(PVOID*)(pInst+33) = GetFuncAddress64( (PVOID)hNtdll, "LdrLoadDll" );
(PVOID)pfn_NtDeleteKey = GetFuncAddress64( (PVOID)hNtdll, "NtDeleteKey" );
Wow64DisableWow64FsRedirection(&OldValue);
MemNtdllx64 = MapDllToMem( gModuleName );
Wow64RevertWow64FsRedirection(OldValue);
if( MemNtdllx64 )
{
*(PULONG)(pData + 0x10) = (ULONG)GetFuncAddress64( (PVOID)MemNtdllx64, "GetProcAddress" ) - (ULONG)MemNtdllx64;
*(PULONG)(pData + 0x18) = (ULONG)GetFuncAddress64( (PVOID)MemNtdllx64, "OpenProcess" ) - (ULONG)MemNtdllx64;
*(PULONG)(pData + 0x20) = (ULONG)GetFuncAddress64( (PVOID)MemNtdllx64, "FatalAppExitW" ) - (ULONG)MemNtdllx64;
UnMapDllFromMem( MemNtdllx64 );
}
bProtectChanged = VirtualProtect( (PVOID)pfn_NtDeleteKey, 0x20, PAGE_EXECUTE_READWRITE, &OldProtect );
if( bProtectChanged )
{
*(PUSHORT)pfn_NtDeleteKey = 0xB848;
*(PULONG)((PUCHAR)pfn_NtDeleteKey + 2) = (ULONG)pInst;
*(PULONG)((PUCHAR)pfn_NtDeleteKey + 6) = 0x00;
*(PULONG)((PUCHAR)pfn_NtDeleteKey + 10)= 0xCCCCE0FF;
VirtualProtect( (PVOID)pfn_NtDeleteKey, 0x20, OldProtect, &OldProtect );
(PVOID)pfn_NtDeleteKey = GetFuncAddress64( (PVOID)hNtdll32, "NtDeleteKey" );
pfn_NtDeleteKey( (HANDLE)pInst );
}
VirtualFree( Buf, 0, MEM_RELEASE );
}
}
return 0;
}