请选择 进入手机版 | 继续访问电脑版

C++编程

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2072|回复: 1

不调用api实现枚举自身加载的模块(拓展一下可以偷偷调用api)

[复制链接]

4

主题

9

帖子

65

积分

码农

Rank: 2

积分
65
发表于 2015-11-18 15:05:04 | 显示全部楼层 |阅读模式
我这里是针对 win7 32位的。所以有些数据结构可能和大家的不一样。但是基本原理是一样的。
首先我们获取peb,x86下很方便的有个fs寄存器可以获取到peb,用内联汇编的方式即可。(之后的论诉不会再采用内联汇编)
__asm{
  mov eax,fs:[30h]
  //add eax,30h
  //mov eax,[eax]
  mov DWORD PTR addr_peb,eax
}
如此就获取到了peb的地址。在我的机器当中用windbg查看peb结构,如下所示
lkd> dt nt!_peb
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar      
   +0x002 BeingDebugged    : UChar            //是否被调试
   +0x003 BitField         : UChar
   +0x003 ImageUsesLargePages : Pos 0, 1 Bit
   +0x003 IsProtectedProcess : Pos 1, 1 Bit
   +0x003 IsLegacyProcess  : Pos 2, 1 Bit
   +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit
   +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit
   +0x003 SpareBits        : Pos 5, 3 Bits
   +0x004 Mutant           : Ptr32 Void
   +0x008 ImageBaseAddress : Ptr32 Void
   +0x00c Ldr              : Ptr32 _PEB_LDR_DATA   //这里是我们需要的
   +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : Ptr32 Void
   +0x018 ProcessHeap      : Ptr32 Void
   +0x01c FastPebLock      : Ptr32 _RTL_CRITICAL_SECTION
   +0x020 AtlThunkSListPtr : Ptr32 Void
   +0x024 IFEOKey          : Ptr32 Void
   +0x028 CrossProcessFlags : Uint4B
   +0x028 ProcessInJob     : Pos 0, 1 Bit
   +0x028 ProcessInitializing : Pos 1, 1 Bit
   +0x028 ProcessUsingVEH  : Pos 2, 1 Bit
   +0x028 ProcessUsingVCH  : Pos 3, 1 Bit
   +0x028 ProcessUsingFTH  : Pos 4, 1 Bit
   +0x028 ReservedBits0    : Pos 5, 27 Bits
   +0x02c KernelCallbackTable : Ptr32 Void
   +0x02c UserSharedInfoPtr : Ptr32 Void
   +0x030 SystemReserved   : [1] Uint4B
   +0x034 AtlThunkSListPtr32 : Uint4B
   +0x038 ApiSetMap        : Ptr32 Void
   +0x03c TlsExpansionCounter : Uint4B
   +0x040 TlsBitmap        : Ptr32 Void
   +0x044 TlsBitmapBits    : [2] Uint4B
   +0x04c ReadOnlySharedMemoryBase : Ptr32 Void
   +0x050 HotpatchInformation : Ptr32 Void
   +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
   +0x058 AnsiCodePageData : Ptr32 Void
   +0x05c OemCodePageData  : Ptr32 Void
   +0x060 UnicodeCaseTableData : Ptr32 Void
   +0x064 NumberOfProcessors : Uint4B
   +0x068 NtGlobalFlag     : Uint4B
   +0x070 CriticalSectionTimeout : _LARGE_INTEGER
   +0x078 HeapSegmentReserve : Uint4B
   +0x07c HeapSegmentCommit : Uint4B
   +0x080 HeapDeCommitTotalFreeThreshold : Uint4B
   +0x084 HeapDeCommitFreeBlockThreshold : Uint4B
   +0x088 NumberOfHeaps    : Uint4B
   +0x08c MaximumNumberOfHeaps : Uint4B
   +0x090 ProcessHeaps     : Ptr32 Ptr32 Void
   +0x094 GdiSharedHandleTable : Ptr32 Void
   +0x098 ProcessStarterHelper : Ptr32 Void
   +0x09c GdiDCAttributeList : Uint4B
   +0x0a0 LoaderLock       : Ptr32 _RTL_CRITICAL_SECTION
   +0x0a4 OSMajorVersion   : Uint4B
   +0x0a8 OSMinorVersion   : Uint4B
   +0x0ac OSBuildNumber    : Uint2B
   +0x0ae OSCSDVersion     : Uint2B
   +0x0b0 OSPlatformId     : Uint4B
   +0x0b4 ImageSubsystem   : Uint4B
   +0x0b8 ImageSubsystemMajorVersion : Uint4B
   +0x0bc ImageSubsystemMinorVersion : Uint4B
   +0x0c0 ActiveProcessAffinityMask : Uint4B
   +0x0c4 GdiHandleBuffer  : [34] Uint4B
   +0x14c PostProcessInitRoutine : Ptr32     void
   +0x150 TlsExpansionBitmap : Ptr32 Void
   +0x154 TlsExpansionBitmapBits : [32] Uint4B
   +0x1d4 SessionId        : Uint4B
   +0x1d8 AppCompatFlags   : _ULARGE_INTEGER
   +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
   +0x1e8 pShimData        : Ptr32 Void
   +0x1ec AppCompatInfo    : Ptr32 Void
   +0x1f0 CSDVersion       : _UNICODE_STRING
   +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA
   +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP
   +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA
   +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP
   +0x208 MinimumStackCommit : Uint4B
   +0x20c FlsCallback      : Ptr32 _FLS_CALLBACK_INFO
   +0x210 FlsListHead      : _LIST_ENTRY
   +0x218 FlsBitmap        : Ptr32 Void
   +0x21c FlsBitmapBits    : [4] Uint4B
   +0x22c FlsHighIndex     : Uint4B
   +0x230 WerRegistrationData : Ptr32 Void
   +0x234 WerShipAssertPtr : Ptr32 Void
   +0x238 pContextData     : Ptr32 Void
   +0x23c pImageHeaderHash : Ptr32 Void
   +0x240 TracingFlags     : Uint4B
   +0x240 HeapTracingEnabled : Pos 0, 1 Bit
   +0x240 CritSecTracingEnabled : Pos 1, 1 Bit
   +0x240 SpareTracingBits : Pos 2, 30 Bits
字段很多,但是我们不需要都理解。当然大家可以自己写一个typedef struct _My_PEB,以后用指针的形式访问。但是我偷懒一下,直接用地址+偏移的方式访问Ptr32 _PEB_LDR_DATA  。
DWORD addr_Ldr=*(DWORD*)(addr_peb+0x0c); //取得_PEB_LDR_DATA的地址,我们用windbg查看一下他的结构
lkd> dt _PEB_LDR_DATA
nt!_PEB_LDR_DATA
   +0x000 Length           : Uint4B
   +0x004 Initialized      : UChar
   +0x008 SsHandle         : Ptr32 Void
   +0x00c InLoadOrderModuleList : _LIST_ENTRY      //一个链表,占用8字节,根据这个名字推测可能是模块的加载顺序的一个链表
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY
   +0x024 EntryInProgress  : Ptr32 Void
   +0x028 ShutdownInProgress : UChar
   +0x02c ShutdownThreadId : Ptr32 Void
我们获取一下这个InLoadOrderModuleList 的地址(大家喜欢的话可以typedef struct _My__PEB_LDR_DATA获取。但是我就直接根据偏移获取)
DWORD addr_InLoadOrderModuleList=(addr_Ldr+0x0c);//取得 InLoadOrderModuleList的地址
我们用windbg查看一下这个_LIST_ENTRY是什么样子
lkd> dt _LIST_ENTRY
nt!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY
   +0x004 Blink            : Ptr32 _LIST_ENTRY
看来是两个指针。而且根据名字,一个f一个b,可能是代表前驱和后继,多半是个链表的结构,那么这个链表保存着什么呢?我们可以试试在wrk当中寻找答案,但是经过测试。如果直接搜索Flink,搜索出来的结果会很多,多到无法筛选(可能windows当中很多的数据结构都用到了这个东西吧),那我我们换个思路,搜索他的父亲,InLoadOrderModuleList,看看,一共找到5个结果,找到这么几句代码
PLDR_DATA_TABLE_ENTRY32 LdrEntry;
PLIST_ENTRY LdrHead, LdrNext;
LdrHead = &Ldr->InLoadOrderModuleList;
LdrNext = LdrHead->Flink;
LdrEntry = CONTAINING_RECORD (LdrNext, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
CONTAINING_RECORD 是一个宏,它的主要作用是:根据结构体中的某成员的地址来推算出该结构体整体的地址,说明这个 LDR_DATA_TABLE_ENTRY也有一个_LIST_ENTRY的指针,不妨用windbg查看一下他的定义
lkd> dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY                //也有相似的_LIST_ENTRY
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
   +0x018 DllBase          : Ptr32 Void
   +0x01c EntryPoint       : Ptr32 Void
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING              //dll的全路径名称
   +0x02c BaseDllName      : _UNICODE_STRING            //dll自身的名称
   +0x034 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x03c SectionPointer   : Ptr32 Void
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32 Void
   +0x048 EntryPointActivationContext : Ptr32 _ACTIVATION_CONTEXT
   +0x04c PatchInformation : Ptr32 Void
   +0x050 ForwarderLinks   : _LIST_ENTRY
   +0x058 ServiceTagLinks  : _LIST_ENTRY
   +0x060 StaticLinks      : _LIST_ENTRY
   +0x068 ContextInformation : Ptr32 Void
   +0x06c OriginalBase     : Uint4B
   +0x070 LoadTime         : _LARGE_INTEGER
到这里有些似懂非懂了。整理一下我们的思路。首先我们找到了peb结构。然后在peb结构当中找到了一个名叫Ldr的_PEB_LDR_DATA结构。在这个_PEB_LDR_DATA结构当中找到了一个_LIST_ENTRY 结构,这个结构目测是一个链表。我们开始对这个链表里面存放的东西产生不理解。后来在wrk当中又找到了一个_LDR_DATA_TABLE_ENTRY结构,并且经过一个CONTAINING_RECORD宏,翻译过来就是这样:
把 _PEB_LDR_DATA当中的_InLoadOrderModuleList的Flink 当成_LDR_DATA_TABLE_ENTRY的 InLoadOrderLinks 的Flink,并且把 _PEB_LDR_DATA当中的_InLoadOrderModuleList的Flink 指向的结构,当成一个_LDR_DATA_TABLE_ENTRY结构,其最终效果是形成了一个链表。这样我们就可以根据这个_PEB_LDR_DATA的_InLoadOrderModuleList的Flink,找到一个_LDR_DATA_TABLE_ENTRY,根据这个_LDR_DATA_TABLE_ENTRY的FullDllName找到一个模块名字,然后继续根据这个_LDR_DATA_TABLE_ENTRY的InLoadOrderLinks的Flink找到下一个模块。

代码在附件里面,很短。很多注释是多余的,但是为了保留思路所以留了下来。期待大家一起交流

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

8

主题

31

帖子

323

积分

版主

Rank: 7Rank: 7Rank: 7

积分
323
QQ
发表于 2015-11-18 20:24:15 | 显示全部楼层
代码建议不要直接贴,要选 添加代码文字 的功能,这样方便大家看代码。

VC纵横、磐实编程网
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|C++编程  

GMT+8, 2019-8-19 07:41 , Processed in 0.093750 second(s), 27 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表