• 无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 了

  • 相关阅读:
    HTML技巧: 语义化你的代码
    css sprite
    Redis主从复制原理
    idea修改快捷键
    Ubuntu14.20 安装docker,创建centos6.7容器,并访问centos容器
    [转]SQL 中 with as 的用法
    ftp与sftp及sftp和scp的区别
    Linux top 命令
    Linux free 命令
    ubuntu 源方式 安装jdk
  • 原文地址:https://www.cnblogs.com/suanguade/p/5869023.html
Copyright © 2020-2023  润新知