Solved

Enumerate modules in Win9* by reading process memory.

Posted on 2004-04-16
14
281 Views
Last Modified: 2010-05-18
How can i find list of loaded modules of current process by reading process memory in Win9*.
I don't want use CreateToolhelp32Snapshot, Module32Next. I try use "Process Database Block".
Who know, how from TP9xModule get filename of module? Maybe Madshi know?
 
< http:Q_20956766.html copyrighted code removed -- Lunchy>
0
Comment
Question by:Dook2
  • 6
  • 5
14 Comments
 
LVL 20

Expert Comment

by:Madshi
ID: 10844114
Do *NOT* post my code publically. You're violating my license agreement!!!!!!!!
0
 

Author Comment

by:Dook2
ID: 10845125
This from your post
http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_20684816.html
You're self violating your license agreement :)
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10845942
Oh well, sorry then...   :-)   I didn't remember that old question.

I've commented on your question on my newsgroup. Where do you want to discuss this? Here or there?
0
 

Author Comment

by:Dook2
ID: 10848344
> You can enumerate modules by parsing through the system structures, but
> that's a bit on the dangerous side, because thanks to multitasking the
> linked lists can be broken while you're reading them.
>
> I'd suggest using a VirtualQuery loop. That works just fine for
> enumerating modules - without any danger...

Where i can find info about this structure?
I need analog this NT structure but for win9*

PTLDR_MODULE=^TLDR_MODULE;
LIST_LDR_MODULE=record
   Flink: PTLDR_MODULE;
   Blink: PTLDR_MODULE;
end;
TLDR_MODULE=packed record
  InLoadOrderModuleList:LIST_LDR_MODULE;
  InMemoryOrderModuleList:LIST_ENTRY;
  InInitOrderModuleList:LIST_ENTRY;
  BaseAddress:pointer;
  EntryPoint:pointer;
  SizeOfImage:ULONG;
  FullDllName:UNICODE_STRING;
  BaseDllName:UNICODE_STRING;
  Flags:ulong;
  LoadCount:SHORT;
  TlsIndex:SHORT;
  HashTableEntry:LIST_ENTRY;
  TimeDateStamp:ULONG ;
 end;
 TPEB_LDR_DATA=packed record
{ +0x000}  Length:ULONG;
{ +0x004}  Initialized:dword;
{ +0x008}  SsHandle:dword;
{ +0x00C}  InLoadOrderModuleList:LIST_LDR_MODULE;
{ +0x014}  InMemoryOrderModuleList:LIST_ENTRY;
{ +0x01C}  InInitOrderModuleList:LIST_ENTRY;
 end;
TPEB=packed record
{ +0x000}    InheritedAddressSpace :boolean;
{ +0x001}    ReadImageFileExecOptions : boolean;
{ +0x002}    BeingDebugged :boolean;
{ +0x003}    SpareBool:boolean;
{ +0x004}    Mutant:pointer;
{ +0x008}    ImageBaseAddress :pointer;
{ +0x00c}    Ldr:^TPEB_LDR_DATA;
   end;

I try loop through this

  TP9xModule=^T9xModule;
  T9xModule=record
    next: TP9xModule;
    prev: TP9xModule;
    d2: DWORD;
    d3: DWORD;
    gmlIndex: DWORD;
    d4: DWORD;
    d5: DWORD;
    ownerProcess: TPPDB;
    d6: pchar;
    d7: pchar;
    d8: pchar;
end;

but there is have not module name.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10848391
Please tell me: Why do you want to use the system structures? Why not using a VirtualQuery loop as I suggested? I see not a single advantage in browsing through the system structures when enumerating modules.
0
 

Author Comment

by:Dook2
ID: 10848479
I know what you mean:

function GetModuleList: TModuleList;
var
  Module, Base: pointer;
  ModuleCount: integer;
  lpModuleName: array [0..MAX_PATH] of char;
  MemoryBasicInformation: TMemoryBasicInformation;
begin
  SetLength(Result, 10);
  ModuleCount := 0;
  Module := nil;
  Base := nil;
  while VirtualQueryEx(GetCurrentProcess, Module, MemoryBasicInformation, SizeOf(MemoryBasicInformation)) = SizeOf(MemoryBasicInformation) do
  begin
    if (MemoryBasicInformation.State = MEM_COMMIT) and(MemoryBasicInformation.AllocationBase <> Base) and (MemoryBasicInformation.AllocationBase = MemoryBasicInformation.BaseAddress) and (GetModuleFileName(dword(MemoryBasicInformation.AllocationBase), lpModuleName, MAX_PATH) > 0) then
    begin
      if ModuleCount = Length(Result) then SetLength(Result, ModuleCount * 2);
      Result[ModuleCount] := dword(MemoryBasicInformation.AllocationBase);
      Inc(ModuleCount);
    end;
    Base := MemoryBasicInformation.AllocationBase;
    dword(Module) := dword(Module) + MemoryBasicInformation.RegionSize;
  end;
  SetLength(result, ModuleCount);
end;

Its?
But i already make in my program for NT through this structure,
so i need and win9* through analog structure.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 20

Expert Comment

by:Madshi
ID: 10848537
Yeah, this is what I mean. Was this code written by  me? Almost looks like that...   :-)   Anyway, why not using that code? It works in both OS familes (win9x and winNT). And it's completely safe.

> But i already make in my program for NT through this structure,
> so i need and win9* through analog structure.

Why not using the VirtualQueryEx code instead? It's short, it works for all OSs and it's safe.
0
 

Author Comment

by:Dook2
ID: 10848689
This code from Aphex afxCodeHook .
In this case module name get from GetmodulenameEx, but if another hooked this API ?
Because name is not clear. This is not for me.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10848721
>> This code from Aphex afxCodeHook

That's my code. He seems to have copied it from here:

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20660084.html

>> In this case module name get from GetmodulenameEx, but if another hooked this API ?

Ok, I see.

The problem with win9x is that there is a global module list and a process specific module list. The process specific module list is what you by using TP9xModule. In that record you find the element "gmlIndex". That stands for "(g)lobal(m)odule(l)istIndex". The module name can be found in the global list only. The big problem is how to get a pointer to the global module list. To be honest, currently I don't know how to.

You should try to find a copy of Matt Pietreks book about Windows 95 programming secrets. It's by far the best book about 9x system internals. A lot of my 9x code is based on this book. It contains information about the global module list. It also sais how to get a point to the list. But if I remember right, it was difficult and a bit on the unreliable side.

Unfortunately that book is out of print. You could try to find a copy on ebay. Probably you could also find the book in pdf format on the net. But of course you must not download it, because it would be illegal...   :-)
0
 

Author Comment

by:Dook2
ID: 10849514
Thanks for suggestion.
I found source Matt Pietreks from this book:

void InitModuleTableBase(void)
{
    // Yes, this is really disgusting!
    GDIReallyCares( GetModuleHandle(0) );
    __asm   mov     [PModuleTable], ecx
}

But this trick now not work (time go), GDIReallyCares remove from kernel32.dll (in Win95 12.11.96  this function not founded).
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10849547
Yeah, seems I remembered right. Sorry, I don't know how to get a pointer to the global module list. Perhaps disassembling GetModuleFileName or GetModuleFileHandle would help?
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 13284908
PAQed with points refunded (130)

modulo
Community Support Moderator
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now