You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
889 lines
23 KiB
889 lines
23 KiB
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <errno.h>
|
|
#include <malloc.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "pperf.h"
|
|
#include "..\pstat.h"
|
|
|
|
|
|
extern HANDLE DriverHandle;
|
|
extern UCHAR Buffer[];
|
|
#define BufferSize 60000
|
|
|
|
typedef struct NameList {
|
|
struct NameList *Next;
|
|
ULONG Parm;
|
|
struct NameList *ChildList;
|
|
PUCHAR Name;
|
|
} NAME_LIST, *PNAME_LIST;
|
|
|
|
PNAME_LIST DriverList;
|
|
PNAME_LIST ActiveThunks;
|
|
|
|
PNAME_LIST SourceModule, ImportModule;
|
|
|
|
#define COMBOCMD(a,b) ((a << 16) | b)
|
|
|
|
|
|
NTSTATUS
|
|
openfile (
|
|
IN PHANDLE filehandle,
|
|
IN PUCHAR BasePath,
|
|
IN PUCHAR Name
|
|
);
|
|
|
|
VOID
|
|
readfile (
|
|
HANDLE handle,
|
|
ULONG offset,
|
|
ULONG len,
|
|
PVOID buffer
|
|
);
|
|
|
|
ULONG
|
|
ConvertImportAddress (
|
|
IN ULONG ImageRelativeAddress,
|
|
IN ULONG PoolAddress,
|
|
IN PIMAGE_SECTION_HEADER SectionHeader
|
|
);
|
|
|
|
VOID ThunkCreateDriverList (VOID);
|
|
#define IMPADDRESS(a) ConvertImportAddress((ULONG)a, (ULONG)Buffer, &SectionHeader)
|
|
|
|
ULONG HookThunk (PNAME_LIST, PNAME_LIST, PNAME_LIST);
|
|
VOID SnapPrivateInfo (PDISPLAY_ITEM);
|
|
VOID NameList2ComboBox (HWND hDlg, ULONG id, PNAME_LIST List);
|
|
PNAME_LIST AddNameEntry (PNAME_LIST *head, PUCHAR name, ULONG Parm);
|
|
VOID FreeNameList (PNAME_LIST List);
|
|
PNAME_LIST GetComboSelection (HWND h, ULONG id);
|
|
VOID NameList2ListBox (HWND hDlg, ULONG id, PNAME_LIST List);
|
|
VOID loadimagedir (PUCHAR, ULONG, PIMAGE_SECTION_HEADER);
|
|
VOID RemoveHook (HWND hDlg);
|
|
VOID ClearAllHooks (HWND hDlg);
|
|
VOID AddThunk (HWND hDlg);
|
|
VOID loadexports (PNAME_LIST Driver, PNAME_LIST Item);
|
|
|
|
|
|
|
|
//#define IDM_THUNK_LIST 301
|
|
//#define IDM_THUNK_SOURCE 302
|
|
//#define IDM_THUNK_IMPORT 303
|
|
//#define IDM_THUNK_FUNCTION 304
|
|
//#define IDM_THUNK_ADD 305
|
|
//#define IDM_THUNK_REMOVE 306
|
|
|
|
INT_PTR
|
|
CALLBACK ThunkDlgProc(
|
|
HWND hDlg,
|
|
unsigned int message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PNAME_LIST Item;
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
SourceModule = NULL;
|
|
ImportModule = NULL;
|
|
ThunkCreateDriverList ();
|
|
NameList2ComboBox (hDlg, IDM_THUNK_SOURCE, DriverList);
|
|
NameList2ListBox (hDlg, IDM_THUNK_LIST, ActiveThunks);
|
|
return (TRUE);
|
|
|
|
case WM_COMMAND:
|
|
switch(wParam) {
|
|
|
|
//
|
|
// end function
|
|
//
|
|
|
|
case COMBOCMD (CBN_SELCHANGE, IDM_THUNK_SOURCE):
|
|
case COMBOCMD (CBN_SELCHANGE, IDM_THUNK_IMPORT):
|
|
Item = GetComboSelection (hDlg, IDM_THUNK_SOURCE);
|
|
if (Item && Item != SourceModule) {
|
|
SourceModule = Item;
|
|
NameList2ComboBox (hDlg, IDM_THUNK_IMPORT, Item->ChildList);
|
|
}
|
|
|
|
Item = GetComboSelection (hDlg, IDM_THUNK_IMPORT);
|
|
if (Item && Item != ImportModule) {
|
|
ImportModule = Item;
|
|
NameList2ComboBox (hDlg, IDM_THUNK_FUNCTION, Item->ChildList);
|
|
}
|
|
|
|
break;
|
|
|
|
case IDM_THUNK_REMOVE:
|
|
RemoveHook (hDlg);
|
|
break;
|
|
|
|
case IDM_THUNK_CLEAR_ALL:
|
|
ClearAllHooks (hDlg);
|
|
break;
|
|
|
|
case IDM_THUNK_ADD:
|
|
AddThunk (hDlg);
|
|
break;
|
|
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
//DlgThunkData (hDlg);
|
|
FreeNameList (DriverList);
|
|
DriverList = NULL;
|
|
EndDialog(hDlg, DIALOG_SUCCESS);
|
|
return (TRUE);
|
|
}
|
|
|
|
}
|
|
return (FALSE);
|
|
}
|
|
|
|
VOID AddThunk (HWND hDlg)
|
|
{
|
|
PDISPLAY_ITEM pPerf;
|
|
PNAME_LIST Item;
|
|
ULONG id, i;
|
|
PUCHAR p;
|
|
HWND thunklist;
|
|
int result;
|
|
|
|
id = 0;
|
|
Item = GetComboSelection (hDlg, IDM_THUNK_FUNCTION);
|
|
if (Item && SourceModule && ImportModule) {
|
|
id = HookThunk (SourceModule, ImportModule, Item);
|
|
}
|
|
|
|
if (!id) {
|
|
MessageBox(hDlg,"Thunk was not hooked","Hook error",MB_OK);
|
|
return;
|
|
}
|
|
|
|
pPerf = AllocateDisplayItem();
|
|
|
|
//
|
|
// build name (the hard way?)
|
|
//
|
|
|
|
pPerf->PerfName[sizeof(pPerf->PerfName) - 1] = 0;
|
|
//
|
|
// BogdanA 02/20/2002: this is ugly,
|
|
// but I'll try to do the best as quickly as I can
|
|
// since I do not own the code and do not intend to own it...
|
|
//
|
|
result = _snprintf(pPerf->PerfName,
|
|
sizeof(pPerf->PerfName) - 1,
|
|
"%s(%s",
|
|
Item->Name, SourceModule->Name);
|
|
if (result > 0 && sizeof(pPerf->PerfName) > result + strlen(ImportModule->Name) + 2) {
|
|
//
|
|
// We still have space in the buffer.
|
|
// Check how much and do the pokey below
|
|
//
|
|
for (p=pPerf->PerfName; *p; p++) {
|
|
if (*p == '.')
|
|
*p = 0;
|
|
}
|
|
strcat (pPerf->PerfName, ">");
|
|
strcat (pPerf->PerfName, ImportModule->Name);
|
|
for (p=pPerf->PerfName; *p; p++) {
|
|
if (*p == '.')
|
|
*p = 0;
|
|
}
|
|
strcat (pPerf->PerfName, ")");
|
|
|
|
}
|
|
//
|
|
// Add to thunk list
|
|
//
|
|
|
|
Item = malloc (sizeof (NAME_LIST));
|
|
if (Item == NULL) {
|
|
printf("Memory allocation failed.\n");
|
|
exit(1);
|
|
}
|
|
|
|
Item->Name = _strdup (pPerf->PerfName);
|
|
Item->Parm = (ULONG) pPerf;
|
|
Item->ChildList = NULL;
|
|
Item->Next = ActiveThunks;
|
|
ActiveThunks = Item;
|
|
pPerf->SnapParam2 = id;
|
|
|
|
// bugbug
|
|
NameList2ListBox (hDlg, IDM_THUNK_LIST, ActiveThunks);
|
|
|
|
//
|
|
// Add graph to windows
|
|
//
|
|
|
|
pPerf->SnapData = SnapPrivateInfo; // generic snap
|
|
pPerf->SnapParam1 = OFFSET(PSTATS, ThunkCounters[id-1]);
|
|
|
|
SetDisplayToTrue (pPerf, 99);
|
|
RefitWindows(NULL, NULL);
|
|
UpdateInternalStats ();
|
|
pPerf->SnapData (pPerf);
|
|
UpdateInternalStats ();
|
|
pPerf->SnapData (pPerf);
|
|
}
|
|
|
|
VOID ClearAllHooks (HWND hDlg)
|
|
{
|
|
PDISPLAY_ITEM pPerf;
|
|
IO_STATUS_BLOCK IOSB;
|
|
ULONG id;
|
|
PNAME_LIST Item;
|
|
|
|
while (ActiveThunks) {
|
|
pPerf = (PDISPLAY_ITEM) ActiveThunks->Parm;
|
|
Item = ActiveThunks;
|
|
ActiveThunks = ActiveThunks->Next;
|
|
|
|
free (Item->Name);
|
|
free (Item);
|
|
|
|
id = pPerf->SnapParam2;
|
|
|
|
SetDisplayToFalse (pPerf); // remove window
|
|
FreeDisplayItem (pPerf);
|
|
|
|
// notify driver
|
|
if (DriverHandle) {
|
|
NtDeviceIoControlFile(
|
|
DriverHandle,
|
|
(HANDLE) NULL, // event
|
|
(PIO_APC_ROUTINE) NULL,
|
|
(PVOID) NULL,
|
|
&IOSB,
|
|
PSTAT_REMOVE_HOOK,
|
|
&id, // input buffer
|
|
sizeof (ULONG),
|
|
NULL, // output buffer
|
|
0
|
|
);
|
|
}
|
|
}
|
|
|
|
NameList2ListBox (hDlg, IDM_THUNK_LIST, ActiveThunks);
|
|
RefitWindows (NULL, NULL);
|
|
}
|
|
|
|
VOID RemoveHook (HWND hDlg)
|
|
{
|
|
ULONG i, id;
|
|
HWND ListBox;
|
|
PNAME_LIST Item, *pp;
|
|
PDISPLAY_ITEM pPerf;
|
|
IO_STATUS_BLOCK IOSB;
|
|
|
|
ListBox = GetDlgItem(hDlg, IDM_THUNK_LIST);
|
|
i = SendMessage(ListBox, LB_GETCURSEL, 0, 0);
|
|
if (i == -1) {
|
|
return;
|
|
}
|
|
|
|
pPerf = (PDISPLAY_ITEM) SendMessage(ListBox, LB_GETITEMDATA, i, 0);
|
|
|
|
Item = NULL;
|
|
for (pp = &ActiveThunks; *pp; pp = &(*pp)->Next) {
|
|
if ((*pp)->Parm == (ULONG)pPerf) {
|
|
Item = *pp;
|
|
*pp = (*pp)->Next; // remove from list
|
|
break ;
|
|
}
|
|
}
|
|
|
|
if (!Item) {
|
|
return ;
|
|
}
|
|
|
|
free (Item->Name);
|
|
free (Item);
|
|
|
|
id = pPerf->SnapParam2;
|
|
SetDisplayToFalse (pPerf); // remove window
|
|
FreeDisplayItem (pPerf);
|
|
|
|
// notify driver
|
|
if (DriverHandle) {
|
|
NtDeviceIoControlFile(
|
|
DriverHandle,
|
|
(HANDLE) NULL, // event
|
|
(PIO_APC_ROUTINE) NULL,
|
|
(PVOID) NULL,
|
|
&IOSB,
|
|
PSTAT_REMOVE_HOOK,
|
|
&id, // input buffer
|
|
sizeof (ULONG),
|
|
NULL, // output buffer
|
|
0
|
|
);
|
|
}
|
|
|
|
NameList2ListBox (hDlg, IDM_THUNK_LIST, ActiveThunks);
|
|
RefitWindows (NULL, NULL);
|
|
}
|
|
|
|
VOID
|
|
NameList2ListBox (HWND hDlg, ULONG id, PNAME_LIST List)
|
|
{
|
|
HWND ListBox;
|
|
ULONG nIndex;
|
|
|
|
ListBox = GetDlgItem(hDlg, id);
|
|
SendMessage(ListBox, LB_RESETCONTENT, 0, 0);
|
|
SendMessage(ListBox, LB_SETITEMDATA, 0L, 0L);
|
|
|
|
while (List) {
|
|
nIndex = SendMessage(ListBox, LB_ADDSTRING, 0, (LPARAM)List->Name);
|
|
SendMessage(ListBox, LB_SETITEMDATA, nIndex, List->Parm);
|
|
List = List->Next;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NameList2ComboBox (HWND hDlg, ULONG id, PNAME_LIST List)
|
|
{
|
|
HWND ComboList;
|
|
ULONG nIndex;
|
|
|
|
ComboList = GetDlgItem(hDlg, id);
|
|
SendMessage(ComboList, CB_RESETCONTENT, 0, 0);
|
|
SendMessage(ComboList, CB_SETITEMDATA, 0L, 0L);
|
|
|
|
while (List) {
|
|
nIndex = SendMessage(ComboList, CB_ADDSTRING, 0, (LPARAM)List->Name);
|
|
SendMessage(ComboList, CB_SETITEMDATA, nIndex, (ULONG) List);
|
|
List = List->Next;
|
|
}
|
|
|
|
SendMessage(ComboList, CB_SETCURSEL, 0, 0L);
|
|
}
|
|
|
|
PNAME_LIST
|
|
GetComboSelection (HWND hDlg, ULONG id)
|
|
{
|
|
ULONG i;
|
|
HWND ComboList;
|
|
|
|
ComboList = GetDlgItem(hDlg, id);
|
|
i = SendMessage(ComboList, CB_GETCURSEL, 0, 0);
|
|
if (i == -1) {
|
|
return NULL;
|
|
}
|
|
return (PNAME_LIST) SendMessage(ComboList, CB_GETITEMDATA, i, 0);
|
|
}
|
|
|
|
VOID
|
|
FreeNameList (PNAME_LIST List)
|
|
{
|
|
PNAME_LIST p1;
|
|
|
|
while (List) {
|
|
if (List->ChildList)
|
|
FreeNameList (List->ChildList);
|
|
|
|
p1 = List->Next;
|
|
free (List->Name);
|
|
free (List);
|
|
List = p1;
|
|
}
|
|
}
|
|
|
|
|
|
ULONG
|
|
HookThunk (PNAME_LIST HookSource, PNAME_LIST TargetModule, PNAME_LIST Function)
|
|
{
|
|
PNAME_LIST sourceModule;
|
|
IO_STATUS_BLOCK IOSB;
|
|
HOOKTHUNK HookData;
|
|
ULONG TracerId;
|
|
NTSTATUS status;
|
|
|
|
if (! DriverHandle) {
|
|
return 0;
|
|
}
|
|
|
|
TracerId = 0;
|
|
for (sourceModule=DriverList; sourceModule; sourceModule = sourceModule->Next) {
|
|
if (sourceModule->Parm == -1) {
|
|
continue;
|
|
}
|
|
if (sourceModule->Parm != HookSource->Parm &&
|
|
HookSource->Parm != -1) {
|
|
continue;
|
|
}
|
|
|
|
HookData.SourceModule = sourceModule->Name;
|
|
HookData.ImageBase = sourceModule->Parm;
|
|
HookData.TargetModule = TargetModule->Name;
|
|
HookData.Function = Function->Name;
|
|
HookData.TracerId = TracerId;
|
|
|
|
//
|
|
// Ask driver to hook this thunk
|
|
//
|
|
|
|
status = NtDeviceIoControlFile(
|
|
DriverHandle,
|
|
(HANDLE) NULL, // event
|
|
(PIO_APC_ROUTINE) NULL,
|
|
(PVOID) NULL,
|
|
&IOSB,
|
|
PSTAT_HOOK_THUNK,
|
|
&HookData, // input buffer
|
|
sizeof (HookData),
|
|
NULL, // output buffer
|
|
0
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
TracerId = HookData.TracerId;
|
|
}
|
|
}
|
|
|
|
return TracerId;
|
|
}
|
|
|
|
VOID
|
|
ThunkCreateDriverList ()
|
|
{
|
|
ULONG i;
|
|
PRTL_PROCESS_MODULES Modules;
|
|
PRTL_PROCESS_MODULE_INFORMATION Module;
|
|
NTSTATUS status;
|
|
PNAME_LIST Driver, Import, Item, AbortState;
|
|
PIMAGE_IMPORT_DESCRIPTOR ImpDescriptor;
|
|
IMAGE_SECTION_HEADER SectionHeader;
|
|
ULONG ThunkAddr, ThunkData;
|
|
|
|
//
|
|
// Query driver list
|
|
//
|
|
|
|
status = NtQuerySystemInformation (
|
|
SystemModuleInformation,
|
|
Buffer,
|
|
BufferSize,
|
|
&i);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Add drivers
|
|
//
|
|
|
|
Modules = (PRTL_PROCESS_MODULES) Buffer;
|
|
Module = &Modules->Modules[ 0 ];
|
|
for (i = 0; i < Modules->NumberOfModules; i++) {
|
|
Driver = AddNameEntry (
|
|
&DriverList,
|
|
Module->FullPathName + Module->OffsetToFileName,
|
|
(ULONG) Module->ImageBase
|
|
);
|
|
Module++;
|
|
}
|
|
|
|
//
|
|
// Add imports for each driver
|
|
//
|
|
|
|
for (Driver = DriverList; Driver; Driver = Driver->Next) {
|
|
try {
|
|
|
|
//
|
|
// Read in source image's headers
|
|
//
|
|
AbortState = Driver;
|
|
loadimagedir (Driver->Name, IMAGE_DIRECTORY_ENTRY_IMPORT, &SectionHeader);
|
|
|
|
//
|
|
// Go through each import module
|
|
//
|
|
|
|
ImpDescriptor = (PIMAGE_IMPORT_DESCRIPTOR) Buffer;
|
|
while (ImpDescriptor->Characteristics) {
|
|
|
|
AbortState = Driver;
|
|
|
|
//
|
|
// Add this import to driver's list
|
|
//
|
|
|
|
Import = AddNameEntry (
|
|
&Driver->ChildList,
|
|
(PUCHAR) IMPADDRESS(ImpDescriptor->Name),
|
|
1
|
|
);
|
|
|
|
AbortState = Import;
|
|
|
|
//
|
|
// Go through each function for the import module
|
|
//
|
|
|
|
ThunkAddr = IMPADDRESS (ImpDescriptor->OriginalFirstThunk);
|
|
for (; ;) {
|
|
ThunkData = (ULONG)((PIMAGE_THUNK_DATA) ThunkAddr)->u1.AddressOfData;
|
|
if (ThunkData == 0) {
|
|
// end of table
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Add this function to import list
|
|
//
|
|
|
|
AddNameEntry (
|
|
&Import->ChildList,
|
|
((PIMAGE_IMPORT_BY_NAME) IMPADDRESS(ThunkData))->Name,
|
|
0
|
|
);
|
|
|
|
// next thunk
|
|
ThunkAddr += sizeof (IMAGE_THUNK_DATA);
|
|
}
|
|
|
|
// next import table
|
|
ImpDescriptor++;
|
|
}
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
AddNameEntry(&AbortState->ChildList, "* ERROR *", 1);
|
|
}
|
|
// next driver
|
|
}
|
|
|
|
//
|
|
// Add "Any driver" selection
|
|
//
|
|
|
|
Driver = AddNameEntry(&DriverList, "*Any", (ULONG)-1);
|
|
|
|
//
|
|
// For child module list use complete driver list, which is
|
|
// now on the next pointer of Driver.
|
|
//
|
|
|
|
for (Item = Driver->Next; Item; Item = Item->Next) {
|
|
|
|
// bogus compiler - need to make a subfunction here to keep
|
|
// the compiler happy
|
|
|
|
loadexports (Driver, Item);
|
|
}
|
|
}
|
|
|
|
VOID loadexports (PNAME_LIST Driver, PNAME_LIST Item)
|
|
{
|
|
IMAGE_SECTION_HEADER SectionHeader;
|
|
PIMAGE_EXPORT_DIRECTORY ExpDirectory;
|
|
PULONG ExpNameAddr;
|
|
PNAME_LIST Import;
|
|
ULONG i;
|
|
|
|
|
|
try {
|
|
loadimagedir (
|
|
Item->Name,
|
|
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
|
&SectionHeader
|
|
);
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
return ;
|
|
}
|
|
|
|
Import = AddNameEntry (&Driver->ChildList, Item->Name, Item->Parm);
|
|
|
|
try {
|
|
ExpDirectory = (PIMAGE_EXPORT_DIRECTORY) Buffer;
|
|
ExpNameAddr = (PULONG)IMPADDRESS (ExpDirectory->AddressOfNames);
|
|
for (i=0; i < ExpDirectory->NumberOfNames; i++) {
|
|
AddNameEntry (
|
|
&Import->ChildList,
|
|
(PUCHAR) IMPADDRESS(*ExpNameAddr),
|
|
0
|
|
);
|
|
ExpNameAddr++;
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
AddNameEntry(&Import->ChildList, "* ERROR *", 1);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
loadimagedir (
|
|
IN PUCHAR filename,
|
|
IN ULONG dirno,
|
|
OUT PIMAGE_SECTION_HEADER SectionHeader
|
|
)
|
|
{
|
|
HANDLE filehandle;
|
|
ULONG i, j, Dir;
|
|
NTSTATUS status;
|
|
IMAGE_DOS_HEADER DosImageHeader;
|
|
IMAGE_NT_HEADERS NtImageHeader;
|
|
PIMAGE_SECTION_HEADER pSectionHeader;
|
|
|
|
status = openfile (&filehandle, "\\SystemRoot\\", filename);
|
|
if (!NT_SUCCESS(status)) {
|
|
status = openfile (&filehandle, "\\SystemRoot\\System32\\", filename);
|
|
}
|
|
if (!NT_SUCCESS(status)) {
|
|
status = openfile (&filehandle, "\\SystemRoot\\System32\\Drivers\\", filename);
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
RtlRaiseStatus (1);
|
|
}
|
|
|
|
try {
|
|
readfile (
|
|
filehandle,
|
|
0,
|
|
sizeof (DosImageHeader),
|
|
(PVOID) &DosImageHeader
|
|
);
|
|
|
|
if (DosImageHeader.e_magic != IMAGE_DOS_SIGNATURE) {
|
|
RtlRaiseStatus (1);
|
|
}
|
|
|
|
readfile (
|
|
filehandle,
|
|
DosImageHeader.e_lfanew,
|
|
sizeof (NtImageHeader),
|
|
(PVOID) &NtImageHeader
|
|
);
|
|
|
|
if (NtImageHeader.Signature != IMAGE_NT_SIGNATURE) {
|
|
RtlRaiseStatus (1);
|
|
}
|
|
|
|
//
|
|
// read in complete sections headers from image
|
|
//
|
|
|
|
i = NtImageHeader.FileHeader.NumberOfSections
|
|
* sizeof (IMAGE_SECTION_HEADER);
|
|
|
|
j = ((ULONG) IMAGE_FIRST_SECTION (&NtImageHeader)) -
|
|
((ULONG) &NtImageHeader) +
|
|
DosImageHeader.e_lfanew;
|
|
|
|
if (i > BufferSize) {
|
|
RtlRaiseStatus (1);
|
|
}
|
|
|
|
readfile (
|
|
filehandle,
|
|
j, // file offset
|
|
i, // length
|
|
Buffer
|
|
);
|
|
|
|
//
|
|
// Find section with import directory
|
|
//
|
|
|
|
Dir = NtImageHeader.OptionalHeader.DataDirectory[dirno].VirtualAddress;
|
|
i = 0;
|
|
pSectionHeader = (PIMAGE_SECTION_HEADER)Buffer;
|
|
for (; ;) {
|
|
if (i >= NtImageHeader.FileHeader.NumberOfSections) {
|
|
RtlRaiseStatus (1);
|
|
}
|
|
if (pSectionHeader->VirtualAddress <= Dir &&
|
|
pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData > Dir) {
|
|
break;
|
|
}
|
|
i += 1;
|
|
pSectionHeader += 1;
|
|
}
|
|
|
|
Dir -= pSectionHeader->VirtualAddress;
|
|
pSectionHeader->VirtualAddress += Dir;
|
|
pSectionHeader->PointerToRawData += Dir;
|
|
pSectionHeader->SizeOfRawData -= Dir;
|
|
|
|
*SectionHeader = *pSectionHeader;
|
|
|
|
//
|
|
// read in complete export section from image
|
|
//
|
|
|
|
if (SectionHeader->SizeOfRawData > BufferSize) {
|
|
RtlRaiseStatus (1);
|
|
}
|
|
|
|
readfile (
|
|
filehandle,
|
|
SectionHeader->PointerToRawData,
|
|
SectionHeader->SizeOfRawData,
|
|
Buffer
|
|
);
|
|
} finally {
|
|
|
|
//
|
|
// Clean up
|
|
//
|
|
|
|
NtClose (filehandle);
|
|
}
|
|
}
|
|
|
|
PNAME_LIST
|
|
AddNameEntry (PNAME_LIST *head, PUCHAR name, ULONG Parm)
|
|
{
|
|
PNAME_LIST Entry;
|
|
|
|
Entry = malloc (sizeof (NAME_LIST));
|
|
if (Entry == NULL) {
|
|
printf("Memory allocation failed.\n");
|
|
exit(1);
|
|
}
|
|
|
|
Entry->Name = _strdup (name);
|
|
if (Entry->Name == NULL) {
|
|
printf("Memory allocation failed.\n");
|
|
exit(1);
|
|
}
|
|
|
|
Entry->Parm = Parm;
|
|
Entry->ChildList = NULL;
|
|
|
|
if (Parm) {
|
|
_strlwr (Entry->Name);
|
|
}
|
|
|
|
Entry->Next = *head;
|
|
*head = Entry;
|
|
|
|
return Entry;
|
|
}
|
|
|
|
NTSTATUS
|
|
openfile (
|
|
IN PHANDLE filehandle,
|
|
IN PUCHAR BasePath,
|
|
IN PUCHAR Name
|
|
)
|
|
{
|
|
ANSI_STRING AscBasePath, AscName;
|
|
UNICODE_STRING UniPathName, UniName;
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES ObjA;
|
|
IO_STATUS_BLOCK IOSB;
|
|
UCHAR StringBuf[500];
|
|
|
|
//
|
|
// Build name
|
|
//
|
|
|
|
UniPathName.Buffer = (PWCHAR)StringBuf;
|
|
UniPathName.Length = 0;
|
|
UniPathName.MaximumLength = sizeof( StringBuf );
|
|
|
|
RtlInitString(&AscBasePath, BasePath);
|
|
status = RtlAnsiStringToUnicodeString( &UniPathName, &AscBasePath, FALSE );
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
RtlInitString(&AscName, Name);
|
|
status = RtlAnsiStringToUnicodeString( &UniName, &AscName, TRUE );
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
status = RtlAppendUnicodeStringToString (&UniPathName, &UniName);
|
|
if (!NT_SUCCESS(status)) {
|
|
RtlFreeUnicodeString (&UniName);
|
|
return status;
|
|
}
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjA,
|
|
&UniPathName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
0,
|
|
0 );
|
|
|
|
//
|
|
// open file
|
|
//
|
|
|
|
status = NtOpenFile (
|
|
filehandle, // return handle
|
|
SYNCHRONIZE | FILE_READ_DATA, // desired access
|
|
&ObjA, // Object
|
|
&IOSB, // io status block
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
|
|
FILE_SYNCHRONOUS_IO_ALERT // open options
|
|
);
|
|
|
|
RtlFreeUnicodeString (&UniName);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
readfile (
|
|
HANDLE handle,
|
|
ULONG offset,
|
|
ULONG len,
|
|
PVOID buffer
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
IO_STATUS_BLOCK iosb;
|
|
LARGE_INTEGER foffset;
|
|
|
|
foffset = RtlConvertUlongToLargeInteger(offset);
|
|
|
|
status = NtReadFile (
|
|
handle,
|
|
NULL, // event
|
|
NULL, // apc routine
|
|
NULL, // apc context
|
|
&iosb,
|
|
buffer,
|
|
len,
|
|
&foffset,
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
RtlRaiseStatus (1);
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
ConvertImportAddress (
|
|
IN ULONG ImageRelativeAddress,
|
|
IN ULONG PoolAddress,
|
|
IN PIMAGE_SECTION_HEADER SectionHeader
|
|
)
|
|
{
|
|
ULONG EffectiveAddress;
|
|
|
|
EffectiveAddress = PoolAddress + ImageRelativeAddress -
|
|
SectionHeader->VirtualAddress;
|
|
|
|
if (EffectiveAddress < PoolAddress ||
|
|
EffectiveAddress > PoolAddress + SectionHeader->SizeOfRawData) {
|
|
|
|
RtlRaiseStatus (1);
|
|
}
|
|
|
|
return EffectiveAddress;
|
|
}
|