免杀基础-IAT隐藏
导入表包含了导入的DLL和使用的函数 其中如Kernel32.dll
下的CreateRemoteThread VirtualAllocEx
等函数被杀软认为是高度可疑的
我们可以通过导入表隐藏来减小被判断为恶意软件的几率
动态调用
使用Loadlibrary
GetProcAddress
来动态加载函数
pVirtualAllocEx myVirtualAllocEx = (pVirtualAllocEx)GetProcAddress(GetModuleHandleA("KERNEL32.DLL"), "VirtualAllocEx");
这个解决方案存在两个问题
第一个是VirtualAllocEx
字符串会存在
第二个是导入了新的敏感函数GetProcAddress
GetModuleHandleA
第一个问题可以通过 对字符串加密 或者使用局部变量数组来解决
char str1[] = {'V','i','r','t','u','a','l','A','l','l','o','c','E','x','\0'};
pVirtualAllocEx myVirtualAllocEx = (pVirtualAllocEx)GetProcAddress(GetModuleHandleA("KERNEL32.DLL"), str1);
注意是局部变量 全局变量无效
第二个问题的解决方案是自实现GetProcAddress
GetModuleHandle
自实现GetProcAddress
GetProcAddress
接收两个参数 一个是指定dll基址 一个是导出函数名
dll是pe文件 我们可以自己来遍历导出表对比name 来拿到RVA
获取导出表
void getExportTable(HMODULE module,PIMAGE_EXPORT_DIRECTORY* exportTable) {
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)module;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD64)module + pDosHeader->e_lfanew);
IMAGE_DATA_DIRECTORY dataDir = (IMAGE_DATA_DIRECTORY)pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
*exportTable = (PIMAGE_EXPORT_DIRECTORY)((DWORD64)module + dataDir.VirtualAddress);
}
遍历导出表拿地址
FARPROC myGetProcAddr(HMODULE module,PIMAGE_EXPORT_DIRECTORY exportTable,LPCSTR funcName) {
PDWORD NameArray = (PDWORD)((DWORD64)module + exportTable->AddressOfNames);
PDWORD AddressArray = (PDWORD)((DWORD64)module + exportTable->AddressOfFunctions);
PWORD OrdinalArray = (PWORD)((DWORD64)module + exportTable->AddressOfNameOrdinals);
for (SIZE_T i = 0; i < exportTable->NumberOfNames; i++) {
LPCSTR currentName = (LPCSTR)((DWORD64)module + NameArray[i]);
if (strcmp(funcName, currentName) == 0) {
return (FARPROC)((DWORD64)module + AddressArray[OrdinalArray[i]]);
}
}
}
自实现GetModuleHandle
现在解决了GetProcAddress
的问题 再来解决HMODLUE
的获取 直接读文件当然也行
PEB中有三个链表 描述的是同一组模块 但是顺序不同 其中存储着加载到进程的模块
通过遍历链表拿到指定的模块即可 相关结构定义可以在如下网站找到
https://github.com/winsiderss/systeminformer
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
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 _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 _PEB_LDR_DATA {
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
typedef struct _PEB {
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PVOID FastPebLockRoutine;
PVOID FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PVOID FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID* ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} PEB, * PPEB;
typedef BOOLEAN(NTAPI* PLDR_INIT_ROUTINE)(
_In_ PVOID DllHandle,
_In_ ULONG Reason,
_In_opt_ PVOID Context
);
typedef struct _ACTIVATION_CONTEXT* PACTIVATION_CONTEXT;
typedef struct _LDR_SERVICE_TAG_RECORD
{
struct _LDR_SERVICE_TAG_RECORD* Next;
ULONG ServiceTag;
} LDR_SERVICE_TAG_RECORD, * PLDR_SERVICE_TAG_RECORD;
typedef struct _LDRP_CSLIST
{
PSINGLE_LIST_ENTRY Tail;
} LDRP_CSLIST, * PLDRP_CSLIST;
typedef enum _LDR_DDAG_STATE
{
LdrModulesMerged = -5,
LdrModulesInitError = -4,
LdrModulesSnapError = -3,
LdrModulesUnloaded = -2,
LdrModulesUnloading = -1,
LdrModulesPlaceHolder = 0,
LdrModulesMapping = 1,
LdrModulesMapped = 2,
LdrModulesWaitingForDependencies = 3,
LdrModulesSnapping = 4,
LdrModulesSnapped = 5,
LdrModulesCondensed = 6,
LdrModulesReadyToInit = 7,
LdrModulesInitializing = 8,
LdrModulesReadyToRun = 9
} LDR_DDAG_STATE;
typedef struct _LDR_DDAG_NODE
{
LIST_ENTRY Modules;
PLDR_SERVICE_TAG_RECORD ServiceTagList;
ULONG LoadCount;
ULONG LoadWhileUnloadingCount;
ULONG LowestLink;
union
{
LDRP_CSLIST Dependencies;
SINGLE_LIST_ENTRY RemovalLink;
};
LDRP_CSLIST IncomingDependencies;
LDR_DDAG_STATE State;
SINGLE_LIST_ENTRY CondenseLink;
ULONG PreorderNumber;
} LDR_DDAG_NODE, * PLDR_DDAG_NODE;
typedef enum _LDR_DLL_LOAD_REASON
{
LoadReasonStaticDependency,
LoadReasonStaticForwarderDependency,
LoadReasonDynamicForwarderDependency,
LoadReasonDelayloadDependency,
LoadReasonDynamicLoad,
LoadReasonAsImageLoad,
LoadReasonAsDataLoad,
LoadReasonEnclavePrimary, // since REDSTONE3
LoadReasonEnclaveDependency,
LoadReasonPatchImage, // since WIN11
LoadReasonUnknown = -1
} LDR_DLL_LOAD_REASON, * PLDR_DLL_LOAD_REASON;
typedef struct _LDRP_LOAD_CONTEXT* PLDRP_LOAD_CONTEXT;
typedef struct _RTL_BALANCED_NODE
{
union
{
struct _RTL_BALANCED_NODE* Children[2];
struct
{
struct _RTL_BALANCED_NODE* Left;
struct _RTL_BALANCED_NODE* Right;
};
};
union
{
UCHAR Red : 1;
UCHAR Balance : 2;
ULONG_PTR ParentValue;
};
} RTL_BALANCED_NODE, * PRTL_BALANCED_NODE;
typedef enum _LDR_HOT_PATCH_STATE
{
LdrHotPatchBaseImage,
LdrHotPatchNotApplied,
LdrHotPatchAppliedReverse,
LdrHotPatchAppliedForward,
LdrHotPatchFailedToPatch,
LdrHotPatchStateMax,
} LDR_HOT_PATCH_STATE, * PLDR_HOT_PATCH_STATE;
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PLDR_INIT_ROUTINE EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
union
{
UCHAR FlagGroup[4];
ULONG Flags;
struct
{
ULONG PackagedBinary : 1;
ULONG MarkedForRemoval : 1;
ULONG ImageDll : 1;
ULONG LoadNotificationsSent : 1;
ULONG TelemetryEntryProcessed : 1;
ULONG ProcessStaticImport : 1;
ULONG InLegacyLists : 1;
ULONG InIndexes : 1;
ULONG ShimDll : 1;
ULONG InExceptionTable : 1;
ULONG ReservedFlags1 : 2;
ULONG LoadInProgress : 1;
ULONG LoadConfigProcessed : 1;
ULONG EntryProcessed : 1;
ULONG ProtectDelayLoad : 1;
ULONG ReservedFlags3 : 2;
ULONG DontCallForThreads : 1;
ULONG ProcessAttachCalled : 1;
ULONG ProcessAttachFailed : 1;
ULONG CorDeferredValidate : 1;
ULONG CorImage : 1;
ULONG DontRelocate : 1;
ULONG CorILOnly : 1;
ULONG ChpeImage : 1;
ULONG ChpeEmulatorImage : 1;
ULONG ReservedFlags5 : 1;
ULONG Redirected : 1;
ULONG ReservedFlags6 : 2;
ULONG CompatDatabaseProcessed : 1;
};
};
USHORT ObsoleteLoadCount;
USHORT TlsIndex;
LIST_ENTRY HashLinks;
ULONG TimeDateStamp;
PACTIVATION_CONTEXT EntryPointActivationContext;
PVOID Lock; // RtlAcquireSRWLockExclusive
PLDR_DDAG_NODE DdagNode;
LIST_ENTRY NodeModuleLink;
PLDRP_LOAD_CONTEXT LoadContext;
PVOID ParentDllBase;
PVOID SwitchBackContext;
RTL_BALANCED_NODE BaseAddressIndexNode;
RTL_BALANCED_NODE MappingInfoIndexNode;
ULONG_PTR OriginalBase;
LARGE_INTEGER LoadTime;
ULONG BaseNameHashValue;
LDR_DLL_LOAD_REASON LoadReason; // since WIN8
ULONG ImplicitPathOptions;
ULONG ReferenceCount; // since WIN10
ULONG DependentLoadFlags;
UCHAR SigningLevel; // since REDSTONE2
ULONG CheckSum; // since 22H1
PVOID ActivePatchImageBase;
LDR_HOT_PATCH_STATE HotPatchState;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
获取PEB
#ifdef _WIN64
PPEB peb = (PPEB)__readgsqword(0x60);
#endif
#ifdef _X86_
PPEB peb = (PPEB)__readfsdword(0x30);
#endif
遍历链表 通过匹配dll名称来找到指定的dll
PPEB_LDR_DATA ldrData = peb->LoaderData;
PLIST_ENTRY moduleList = &ldrData->InLoadOrderModuleList;
PLIST_ENTRY current = moduleList->Flink;
while (current != moduleList) {
PLDR_DATA_TABLE_ENTRY entry = (PLDR_DATA_TABLE_ENTRY)current;
if (_wcsnicmp(entry->BaseDllName.Buffer, target, wcslen(target)) == 0) {
return (HMODULE)entry->DllBase;
}
current = current->Flink;
}
这里使用_wcsnicmp
来忽略大小写
通过PEB获取HMODULE
实际上是不全的 因为只能获取到进程加载的那些dll中的 可以考虑反射dll注入来获取别的dll