无LoadLibrary获取指定模块基址

实际上,这块可以写成汇编,然后做远程注入用

方法

1、通过fs:[30h]获取当前进程的_PEB结构

2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构

3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构

4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构,注意:这里的Flink指向的是_LDR_DATA_TABLE_ENTRY结构中的InMemoryOrderLinks成员,因此需要计算真正的_LDR_DATA_TABLE_ENTRY起始地址,我们可以用CONTAINING_RECORD来计算。

5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息。

 1 #include <windows.h>  
 2 
 3 #define CONTAINING_RECORD(address, type, field) ((type *)( (PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))  
 4 
 5 typedef struct _UNICODE_STRING {  
 6     USHORT  Length;  
 7     USHORT  MaximumLength;  
 8     PWSTR  Buffer;  
 9 } UNICODE_STRING, *PUNICODE_STRING;  
10 
11 typedef struct _PEB_LDR_DATA  
12 {  
13     DWORD Length;  
14     UCHAR Initialized;  
15     PVOID SsHandle;  
16     LIST_ENTRY InLoadOrderModuleList;  
17     LIST_ENTRY InMemoryOrderModuleList;  
18     LIST_ENTRY InInitializationOrderModuleList;  
19     PVOID EntryInProgress;  
20 }PEB_LDR_DATA,*PPEB_LDR_DATA;  
21 
22 typedef struct _LDR_DATA_TABLE_ENTRY  
23 {  
24     LIST_ENTRY InLoadOrderLinks;  
25     LIST_ENTRY InMemoryOrderLinks;  
26     LIST_ENTRY InInitializationOrderLinks;  
27     PVOID DllBase;  
28     PVOID EntryPoint;  
29     DWORD SizeOfImage;  
30     UNICODE_STRING FullDllName;  
31     UNICODE_STRING BaseDllName;  
32     DWORD Flags;  
33     WORD LoadCount;  
34     WORD TlsIndex;  
35     LIST_ENTRY HashLinks;  
36     PVOID SectionPointer;  
37     DWORD CheckSum;  
38     DWORD TimeDateStamp;  
39     PVOID LoadedImports;  
40     PVOID EntryPointActivationContext;  
41     PVOID PatchInformation;  
42 }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;  
43 
44 typedef struct _PEB  
45 {  
46     UCHAR InheritedAddressSpace;  
47     UCHAR ReadImageFileExecOptions;  
48     UCHAR BeingDebugged;  
49     UCHAR SpareBool;  
50     PVOID Mutant;  
51     PVOID ImageBaseAddress;  
52     PPEB_LDR_DATA Ldr;  
53 }PEB,*PPEB;  
54 
55 int main(void)  
56 {  
57     PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;  
58     PLIST_ENTRY pListEntryStart = NULL,pListEntryEnd = NULL;  
59     PPEB_LDR_DATA pPebLdrData = NULL;  
60     PPEB pPeb = NULL;  
61 
62     __asm  
63     {  
64         //1、通过fs:[30h]获取当前进程的_PEB结构  
65         mov eax,dword ptr fs:[30h];  
66         mov pPeb,eax  
67     }  
68 
69     //2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构  
70     pPebLdrData = pPeb->Ldr;  
71 
72     //3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构  
73     pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;  
74 
75     //查找所有已载入到内存中的模块  
76     do  
77     {  
78         //4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构  
79         pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks);  
80 
81         //5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息  
82         printf("%S
",pLdrDataEntry->BaseDllName.Buffer);  
83 
84         pListEntryStart = pListEntryStart->Flink;  
85 
86     }while(pListEntryStart != pListEntryEnd);  
87 
88 
89     return 0;
90 }  

注入相关的代码在这里

  1 #include <Windows.h>
  2 
  3 #include <stdio.h>
  4 
  5 typedef struct _UNICODE_STRING {
  6     USHORT Length;
  7     USHORT MaximumLength;
  8     PWCH   Buffer;
  9 } UNICODE_STRING;
 10 
 11 typedef struct _LDR_DATA_TABLE_ENTRY
 12 {
 13     LIST_ENTRY InLoadOrderLinks;
 14     LIST_ENTRY InMemoryOrderLinks;
 15     LIST_ENTRY InInitializationOrderLinks;
 16     PVOID DllBase;
 17     PVOID EntryPoint;
 18     ULONG SizeOfImage;
 19     UNICODE_STRING FullDllName;
 20     UNICODE_STRING BaseDllName;
 21     ULONG Flags;
 22     WORD LoadCount;
 23     WORD TlsIndex;
 24     union
 25     {
 26         LIST_ENTRY HashLinks;
 27         struct
 28         {
 29             PVOID SectionPointer;
 30             ULONG CheckSum;
 31         };
 32     };
 33     union
 34     {
 35         ULONG TimeDateStamp;
 36         PVOID LoadedImports;
 37     };
 38     void * EntryPointActivationContext;
 39     PVOID PatchInformation;
 40     LIST_ENTRY ForwarderLinks;
 41     LIST_ENTRY ServiceTagLinks;
 42     LIST_ENTRY StaticLinks;
 43 } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
 44 
 45 //    把一个字符串做成一个 hash 值
 46 __declspec(naked) DWORD __stdcall HashString( WCHAR *name )
 47 {
 48     __asm
 49     {
 50         push esi;
 51         push edi;
 52         mov esi , [esp + 0x0C];
 53         xor edi , edi;
 54         cld;
 55 __iter:
 56         xor eax , eax;
 57         lodsw ;
 58         cmp al , ah;
 59         je __done;
 60         ror edi , 0x0D;
 61         add edi ,eax ;
 62         jmp __iter;
 63 __done:
 64         mov eax , edi;
 65         pop edi;
 66         pop esi;
 67         retn 4;
 68     }
 69 }
 70 
 71 //    遍历 LDR 表,找到要找的 DLL 基址
 72 PVOID __stdcall GetDllBase( LIST_ENTRY *head  , DWORD hash )
 73 {
 74     PLDR_DATA_TABLE_ENTRY t;
 75     LIST_ENTRY *p = head->Flink;
 76     for ( ; p != head ; p = p->Flink )
 77     {
 78         t = (PLDR_DATA_TABLE_ENTRY)((char*)p - 0x10);
 79         if ( hash == HashString( t->BaseDllName.Buffer ) )
 80         {
 81             return t->DllBase;
 82         }
 83     }
 84     return 0;
 85 }
 86 
 87 //    从 fs 段找到 TEB ,从 TEB 找到 PEB ,从 PEB 找到 LDR 表
 88 //    返回值为 LDR 表链的头节点
 89 __declspec(naked) LIST_ENTRY * __stdcall FindLDRTable()
 90 {
 91     __asm
 92     {
 93         push esi;
 94         xor eax , eax;
 95         mov eax , fs:[0x30];
 96         test eax , eax;
 97         js __k9x;
 98         mov eax , [eax + 0x0C];
 99         lea esi , [eax + 0x1C];
100         mov eax , esi;
101         jmp near __finish;
102 __k9x:
103         xor eax , eax;
104 __finish:
105         pop esi;
106         ret;
107     }
108 }
109 
110 //    获取一个已经加载了的模块地址
111 //    name 只是名字,不可以是路径带名字
112 PVOID LoadLibraryIn( WCHAR *name )
113 {
114     return GetDllBase( FindLDRTable() , HashString( name ) );
115 }
116 
117 int main()
118 {
119     //printf("0x%p
" , HashString(L"kernel32.dll"));
120     //printf("0x%p
" , HashString(L"User32.dll"));
121 
122     printf( "0x%p 
" , LoadLibraryIn( L"kernel32.dll" ) );
123     printf( "0x%p 
" , LoadLibraryA( "kernel32.dll" ) );
124     printf( "0x%p 
" , LoadLibraryA( "ntdll.dll" ) );
125 
126     return 0;
127 }
View Code

用汇编来做3个关键函数,然后shellcode获取模块基址,计算PE,得到导出表,根据名称表找到对应的名字,地址表直接就能找到对应的函数地址了,

比较类似,自重定位,然后LoadLibrary GetProcAddress 了

原文地址:https://www.cnblogs.com/suanguade/p/5869023.html