const WCHAR SourceString[]=L"\\SystemRoot\\system32\\ntdll.dll";
char aNtCreateProcess[]="NtCreateProcess";
void op_ntdll()
{
NTSTATUS status=STATUS_SUCCESS;
IMAGE_NT_HEADERS32 nt_headers; //var_1e4
char name[0x32];
IMAGE_SECTION_HEADER section_header; //var_b8
IMAGE_EXPORT_DIRECTORY image_export; //var_90
UNICODE_STRING DestinationString;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG AddressOfName;
ULONG file_AddressOfFunctions;
ULONG file_AddressOfNameOrdinals;
ULONG file_AddressOfNames;
IO_STATUS_BLOCK IoStatusBlock;
ULONG Buffer=0;//initialize before use
HANDLE FileHandle;
LARGE_INTEGER ByteOffset;
ULONG i;
RtlInitUnicodeString(&DestinationString,SourceString);
ObjectAttributes.ObjectName=&DestinationString;
ObjectAttributes.Length=0x18;
ObjectAttributes.RootDirectory=NULL;
ObjectAttributes.Attributes=0x240;
ObjectAttributes.SecurityDescriptor=NULL;
ObjectAttributes.SecurityQualityOfService=NULL;
status=ZwOpenFile(&FileHandle,GENERIC_READ,&ObjectAttributes,&IoStatusBlock,FILE_SHARE_READ,0x20);
if(status==STATUS_SUCCESS)
{
KdPrint(("open file %wZ successfully!e\n",&DestinationString));
ByteOffset.LowPart=0x3c;
ByteOffset.HighPart=0;
ZwReadFile(FileHandle,NULL,NULL,NULL,&IoStatusBlock,&Buffer,2,&ByteOffset,0);
KdPrint(("file_3c is 0x%08x\n",Buffer));
ByteOffset.LowPart=Buffer;
ZwReadFile(FileHandle,NULL,NULL,NULL,&IoStatusBlock,&nt_headers,0xf8,&ByteOffset,0);
KdPrint(("PE mark--->0x%08x\n",nt_headers.Signature));
if(nt_headers.Signature==IMAGE_NT_SIGNATURE)
{
Buffer+=0xf8;
if(nt_headers.FileHeader.NumberOfSections)
{
KdPrint(("ntdll.dll has 0x%x sections.\n",nt_headers.FileHeader.NumberOfSections));
do
{
ByteOffset.LowPart=Buffer;
ByteOffset.HighPart=0;
ZwReadFile(FileHandle,NULL,NULL,NULL,&IoStatusBlock,§ion_header,IMAGE_SIZEOF_SECTION_HEADER,&ByteOffset,0);
KdPrint(("VirtualAddress of image export is 0x%08x\n",nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
if(nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress>=section_header.VirtualAddress)
{
if(nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress<section_header.VirtualAddress+section_header.Misc.VirtualSize)
{
KdPrint(("the export table is located in %s.\n",section_header.Name));
ByteOffset.LowPart=nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress-section_header.VirtualAddress+section_header.PointerToRawData;
ZwReadFile(FileHandle,NULL,NULL,NULL,&IoStatusBlock,&image_export,IMAGE_EXPORT_DIRECTORY_SIZE,&ByteOffset,0);
KdPrint(("image_export.NumberOfFunctions is 0x%x\n",image_export.NumberOfFunctions));
file_AddressOfNames=image_export.AddressOfNames-section_header.VirtualAddress+section_header.PointerToRawData;
file_AddressOfFunctions=image_export.AddressOfFunctions-section_header.VirtualAddress+section_header.PointerToRawData;
file_AddressOfNameOrdinals=image_export.AddressOfNameOrdinals-section_header.VirtualAddress+section_header.PointerToRawData;
if(image_export.NumberOfNames)
{
i=image_export.NumberOfNames;
do
{
ByteOffset.LowPart=file_AddressOfNames;
ZwReadFile(FileHandle,NULL,NULL,NULL,&IoStatusBlock,&AddressOfName,4,&ByteOffset,0);
AddressOfName=AddressOfName-section_header.VirtualAddress+section_header.PointerToRawData;
ByteOffset.LowPart=AddressOfName;
ZwReadFile(FileHandle,NULL,NULL,NULL,&IoStatusBlock,name,0x32,&ByteOffset,0);
// KdPrint(("func name is %s\n",name));
if(0==ansi_string_compare(aNtCreateProcess,name,ansi_string_length(aNtCreateProcess)))
KdPrint(("NtCreateProcess is found!\n"));
file_AddressOfNames+=0x4;
}while(--i);
}
break;
}
}
else
{
Buffer+=IMAGE_SIZEOF_SECTION_HEADER;
}
}while(--nt_headers.FileHeader.NumberOfSections);
}
}
ZwClose(FileHandle);
}
else
{
KdPrint(("error:0x%08x\n",status));
}
}
ULONG ansi_string_compare(char *stra,char *strb,ULONG Length)
{
if(strb!=NULL&&Length)
{
if(Length==ansi_string_length(strb))
{
do
{
if(*stra!=*strb)
break;
stra++;
strb++;
Length--;
}while(Length);
}
}
return Length;
}
ULONG ansi_string_length(char *str)
{
int length=0;
if(str!=NULL)
{
while(*str&&length<0x100)
{
length++;
str++;
}
}
return length;
}
pe练习本
//从文件解析导入表,支持32/64pe
void op_ntdll()
{
NTSTATUS status = STATUS_SUCCESS;
IMAGE_NT_HEADERS64 NtHeaders64; //var_1e4
IMAGE_NT_HEADERS32 NtHeaders32;
DWORD Signature = 0;//image_nt_headers Signature
IMAGE_FILE_HEADER FileHeader = { 0 };
DWORD NtHeadersSize = 0;
DWORD ExportDirVA = 0;
char name[0x32];
IMAGE_SECTION_HEADER section_header; //var_b8
IMAGE_EXPORT_DIRECTORY image_export; //var_90
UNICODE_STRING DestinationString;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG AddressOfName;
ULONG file_AddressOfFunctions;
ULONG file_AddressOfNameOrdinals;
ULONG file_AddressOfNames;
IO_STATUS_BLOCK IoStatusBlock;
ULONG AddressOfNewExe = 0;//initialize before use
HANDLE FileHandle;
LARGE_INTEGER ByteOffset;
ULONG i;
RtlInitUnicodeString(&DestinationString, SourceString);
ObjectAttributes.ObjectName = &DestinationString;
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.Attributes = 0x240;
ObjectAttributes.SecurityDescriptor = NULL;
ObjectAttributes.SecurityQualityOfService = NULL;
FileHandle=CreateFileW(SourceString, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (FileHandle)
{
printf("open file %wZ successfully!e\n", &DestinationString);
ByteOffset.LowPart = 0x3c;//get e_lfanew
ByteOffset.HighPart = 0;
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, &AddressOfNewExe, 2, &ByteOffset, 0);
printf("file_3c is 0x%08x\n", AddressOfNewExe);
ByteOffset.LowPart = AddressOfNewExe;
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, &Signature, 0x4, &ByteOffset, 0);
printf("PE mark--->0x%08x\n", Signature);
if (Signature != IMAGE_NT_SIGNATURE)
return;
ByteOffset.LowPart = AddressOfNewExe+4;
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, &FileHeader, sizeof(IMAGE_FILE_HEADER), &ByteOffset, 0);
if (FileHeader.NumberOfSections)
{
printf("ntdll.dll has 0x%x sections.\n", FileHeader.NumberOfSections);
}
else
{
return;
}
//the difference between pe32 and pe64 is the optional header
//
//under pe32,address length is 4
//
//under pe64,address length is 8
//
if (FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
{
printf("FileHeader.Machine:0x%x,it is a pe32.\n",FileHeader.Machine);
NtHeadersSize = sizeof(IMAGE_NT_HEADERS32);
ByteOffset.LowPart = AddressOfNewExe;
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, &NtHeaders32, NtHeadersSize, &ByteOffset, 0);
ExportDirVA = NtHeaders32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
}
else if (FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
{
printf("FileHeader.Machine:0x%x,it is a pe64.\n", FileHeader.Machine);
NtHeadersSize = sizeof(IMAGE_NT_HEADERS64);
ByteOffset.LowPart = AddressOfNewExe;
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock,&NtHeaders64, NtHeadersSize, &ByteOffset, 0);
ExportDirVA = NtHeaders64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
}
else
{
printf("unknown file format!\n");
return;
}
printf("VirtualAddress of image export is 0x%08x\n", ExportDirVA);
do
{
ByteOffset.LowPart = AddressOfNewExe+NtHeadersSize;
ByteOffset.HighPart = 0;
//read section header
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, §ion_header, IMAGE_SIZEOF_SECTION_HEADER, &ByteOffset, 0);
printf("section name:%s\n", section_header.Name);
if (ExportDirVA >= section_header.VirtualAddress)
{
if (ExportDirVA < section_header.VirtualAddress + section_header.Misc.VirtualSize)
{
printf("the export table is located in %s.\n", section_header.Name);
ByteOffset.LowPart = ExportDirVA - section_header.VirtualAddress + section_header.PointerToRawData;
//read export dir
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, &image_export, sizeof(IMAGE_EXPORT_DIRECTORY), &ByteOffset, 0);
printf("image_export.NumberOfFunctions is 0x%x\n", image_export.NumberOfFunctions);
//here it reads the raw data from the file not in the memory
//
//first get the names's offset in the raw data
//
//second read the raw data from file
//
//
file_AddressOfNames = image_export.AddressOfNames - section_header.VirtualAddress + section_header.PointerToRawData;
file_AddressOfFunctions = image_export.AddressOfFunctions - section_header.VirtualAddress + section_header.PointerToRawData;
file_AddressOfNameOrdinals = image_export.AddressOfNameOrdinals - section_header.VirtualAddress + section_header.PointerToRawData;
if (image_export.NumberOfNames)
{
i = image_export.NumberOfNames;
do
{
ByteOffset.LowPart = file_AddressOfNames;
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, &AddressOfName, 4, &ByteOffset, 0);
AddressOfName = AddressOfName - section_header.VirtualAddress + section_header.PointerToRawData;
ByteOffset.LowPart = AddressOfName;
NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, name, 0x32, &ByteOffset, 0);
//printf("func name is %s\n",name);
if (0 == ansi_string_compare(aNtCreateProcess, name, ansi_string_length(aNtCreateProcess)))
printf("%s is found!\n",name);
if (0x3B1B637B == loop_right_move((byte*)name, 0xd))
{
printf("name:%s\n", name);
}
file_AddressOfNames += 0x4;
} while (--i);
}
break;
}
}
AddressOfNewExe += IMAGE_SIZEOF_SECTION_HEADER;
} while (--FileHeader.NumberOfSections);
NtClose(FileHandle);
}
else
{
printf("CreateFileW fails,error:0x%08x\n", GetLastError());
}
}