;made by correy
;Email:leguanyuan@126.com
;QQ:112426112
;rc me.rc
;ml /coff test.asm /link /subsystem:windows me.res
.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
include comdlg32.inc
includelib user32.lib
includelib kernel32.lib
includelib comdlg32.lib
.data
correy db "made by correy",0
wrong db "error,will over!",0
FilterString db "dll File",0,"*.dll",0,0
h db "%8x",0
edata db "导出节或导出目录表的首地址",0
correy2 db "导出名称指针表",0
dllnameaddr db "dll name address:",0
dllname db "dll name :",0
ordinalbase db "ordinal base:",0
ordinalbaseaddr db "ordinal base address:",0
eat db "export address table rva:",0
np db "name pointer rva:",0
ot db "ordinal table rva:",0
ate db "address table entries",0
nnp db "number of name pointers",0
apiname db "api name is:",0
apiaddr db "api address is:",0
.data?
ofn OPENFILENAME <>
buffer db 256 DUP (?)
mz dd ?
pe dd ?
OptionalHeader dd ?
header dd ?
magic word ?
sizeOfOptionalHeader dd ?
sections dd ?
v dd ?
nnps dd ?
e dd ?
.code
rvatooffset proc sectionsn,head,rva
push esi
push edi
push ecx
mov edi,rva
mov esi,head
mov ecx,sectionsn
again:cmp ecx,0
jna show
cmp edi,[esi+12]
jb add40
mov eax,[esi+12]
add eax,[esi+16]
cmp edi,eax
jnb add40
mov eax,[esi+12]
sub edi,eax
mov eax,[esi+20]
add eax,edi
jmp show
add40:add esi,40
dec ecx
jmp again
show:pop ecx
pop edi
pop esi
ret
rvatooffset endp
start:
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
invoke CreateFile, addr buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
invoke CreateFileMapping,eax, NULL, PAGE_READONLY,0,0,0
invoke MapViewOfFile,eax,FILE_MAP_READ,0,0,0
mov mz,eax
mov esi,mz
add esi,3ch
mov esi,[esi]
mov eax,mz
add esi,eax
mov pe,esi
mov esi,pe
add esi,6
mov dx,word ptr [esi]
movsx edx,dx
mov sections,edx
mov esi,pe
add esi,24
mov OptionalHeader,esi ;保存可选头的地址。
mov esi,pe
add esi,20
mov dx,word ptr [esi]
movsx edx,dx
mov sizeOfOptionalHeader,edx
mov esi,OptionalHeader
add esi,sizeOfOptionalHeader
mov header,esi ;保存节头的地址。
mov esi,OptionalHeader
add esi,96
mov esi,[esi]
;导出节或导出目录表的首地址
invoke rvatooffset,sections,header,esi
mov edi,eax
mov esi,eax
;add edi,mz
invoke wsprintf,addr buffer,addr h,edi
;invoke MessageBox,0,addr buffer,addr edata,0
add edi,mz
mov e,edi;;导出节或导出目录表的首地址
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;dll name rva
push edi
add edi,12
mov edi,[edi]
invoke rvatooffset,sections,header,edi
push eax
invoke wsprintf,addr buffer,addr h,eax
;invoke MessageBox,0,addr buffer,addr dllnameaddr,0
pop eax
add eax,mz
;invoke MessageBox,0,eax,addr dllname,0
pop edi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push edi
add edi,16
mov edi,[edi]
invoke wsprintf,addr buffer,addr h,edi
;invoke MessageBox,0,addr buffer,addr ordinalbase,0
pop edi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push edi
add edi,20
mov edi,[edi]
invoke wsprintf,addr buffer,addr h,edi
;invoke MessageBox,0,addr buffer,addr ate,0
pop edi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push edi
add edi,24
mov edi,[edi]
mov nnps,edi
invoke wsprintf,addr buffer,addr h,edi
;invoke MessageBox,0,addr buffer,addr nnp,0
pop edi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push edi
add edi,28
mov edi,[edi]
invoke rvatooffset,sections,header,edi
push eax
invoke wsprintf,addr buffer,addr h,eax
invoke MessageBox,0,addr buffer,addr eat,0
pop eax
mov ecx,nnps
add eax,mz ;导出地址表的首地址
showapiaddr:
push eax
mov eax,[eax]
invoke rvatooffset,sections,header,eax
;add eax,mz
invoke wsprintf,addr buffer,addr h,eax
invoke MessageBox,0,addr buffer,addr apiaddr,0
pop eax
add eax,4
dec ecx
cmp ecx,0
jne showapiaddr
pop edi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push edi
add edi,32
mov edi,[edi]
invoke rvatooffset,sections,header,edi
mov ecx,nnps
add eax,mz
showapi:
push eax
mov eax,[eax]
invoke rvatooffset,sections,header,eax
add eax,mz
;invoke MessageBox,0,eax,addr apiname,0
pop eax
add eax,4
dec ecx
cmp ecx,0
jne showapi
push eax
invoke wsprintf,addr buffer,addr h,eax
;invoke MessageBox,0,addr buffer,addr np,0
pop eax
add eax,mz
pop edi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push edi
add edi,36
mov edi,[edi]
invoke rvatooffset,sections,header,edi
push eax
invoke wsprintf,addr buffer,addr h,eax
invoke MessageBox,0,addr buffer,addr ot,0
pop eax
mov ecx,nnps
add eax,mz
showo:
push eax
mov ax,word ptr [eax]
movzx eax,ax
invoke wsprintf,addr buffer,addr h,eax
invoke MessageBox,0,addr buffer,addr apiname,0
pop eax
add eax,2
dec ecx
cmp ecx,0
jne showo
add eax,mz
pop edi
invoke ExitProcess,NULL
end start
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <Windows.h>
#include <stdio.h> // for printf
/*
写作目的:遍历一个PE文件导出的DLL及其函数的信息。
made by correy
made at 2015.06.23
*/
unsigned int RVATOOFFSET(IN PVOID lpFileBase,IN unsigned int rva)
/*
返回0表示失败,其他的是在文件中的偏移。
*/
{
unsigned int offset = 0;//返回值。
IMAGE_DOS_HEADER * p_image_dos_header = (IMAGE_DOS_HEADER * )lpFileBase;
ULONG ntSignature = (ULONG)p_image_dos_header + p_image_dos_header->e_lfanew;
ntSignature = * (ULONG *)ntSignature;
DWORD CoffHeaderOffset = (ULONG)p_image_dos_header + p_image_dos_header->e_lfanew + sizeof(ULONG);
IMAGE_FILE_HEADER * p_image_file_header = (IMAGE_FILE_HEADER *)CoffHeaderOffset;
//注意这里用的永远是:IMAGE_OPTIONAL_HEADER32.
//要分析IMAGE_OPTIONAL_HEADER64的一个办法是:强制定义一个,载赋值转换.
//其实这个结构的大小是固定的,只不过32位的和64位的不一样.但还是用规范建议的.IMAGE_FILE_HEADER的成员访问好.
IMAGE_OPTIONAL_HEADER * p_image_optional_header = (IMAGE_OPTIONAL_HEADER *)((ULONG)p_image_file_header + sizeof(IMAGE_FILE_HEADER));
IMAGE_SECTION_HEADER * p_image_section_header = (IMAGE_SECTION_HEADER *)((ULONG)p_image_optional_header + p_image_file_header->SizeOfOptionalHeader);//必须加(ULONG),不然出错.
for (int i = 0;i < p_image_file_header->NumberOfSections;i++) //规范规定是从1开始的.
{
if (rva >= p_image_section_header[i].VirtualAddress && rva <= (p_image_section_header[i].VirtualAddress + p_image_section_header[i].Misc.VirtualSize))
{
offset = rva - p_image_section_header[i].VirtualAddress + p_image_section_header[i].PointerToRawData;
break;
}
}
return offset;
}
void DumpFile(LPCWSTR filename)
/*
摘自:Peering Inside the PE: A Tour of the Win32 Portable Executable File Format.有改动。
*/
{
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if ( hFile == INVALID_HANDLE_VALUE )
{
printf("Couldn't open file with CreateFile()\n");
return;
}
HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if ( hFileMapping == 0 )
{
CloseHandle(hFile);
printf("Couldn't open file mapping with CreateFileMapping()\n");
return;
}
LPVOID lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
if ( lpFileBase == 0 )
{
CloseHandle(hFileMapping);
CloseHandle(hFile);
printf("Couldn't map view of file with MapViewOfFile()\n");
return;
}
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
if ( dosHeader->e_magic != IMAGE_DOS_SIGNATURE )
{
printf("dosHeader->e_magic != IMAGE_DOS_SIGNATURE\n");
UnmapViewOfFile(lpFileBase);
CloseHandle(hFileMapping);
CloseHandle(hFile);
return;
}
LONG e_lfanew = dosHeader->e_lfanew;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((PCHAR)dosHeader + e_lfanew);
if (ntHeader->Signature != IMAGE_NT_SIGNATURE)
{
printf("ntHeader->Signature != IMAGE_NT_SIGNATURE\n");
UnmapViewOfFile(lpFileBase);
CloseHandle(hFileMapping);
CloseHandle(hFile);
return;
}
//if (FlagOn(ntHeader->FileHeader.Characteristics, IMAGE_FILE_DLL) || FlagOn(ntHeader->FileHeader.Characteristics, IMAGE_FILE_SYSTEM))
//{
// return;
//}
PIMAGE_EXPORT_DIRECTORY ExportDescriptor = (PIMAGE_EXPORT_DIRECTORY)(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (SIZE_T)lpFileBase);
ULONG ExportSize = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
//IMPORT_DESCRIPTOR = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData ((SIZE_T)lpFileBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &InportSize);//经测试二者相等。这一行等于上面的两行。
if (ExportDescriptor == NULL)
{
//没有导出表。
//__debugbreak();
printf("InportDescriptor == NULL\n");
UnmapViewOfFile(lpFileBase);
CloseHandle(hFileMapping);
CloseHandle(hFile);
return;
}
ExportDescriptor = (PIMAGE_EXPORT_DIRECTORY)(RVATOOFFSET(lpFileBase, (SIZE_T)ExportDescriptor - (SIZE_T)lpFileBase) + (SIZE_T)lpFileBase);
char * dll_name = (char *)(RVATOOFFSET(lpFileBase, ExportDescriptor->Name) + (SIZE_T)lpFileBase);
printf("dll_name;%s\n", dll_name);
DWORD AddressOfFunctions = (DWORD)RVATOOFFSET(lpFileBase, (ExportDescriptor->AddressOfFunctions)) + (SIZE_T)lpFileBase;
DWORD AddressOfNames = RVATOOFFSET(lpFileBase, (ExportDescriptor->AddressOfNames)) + (SIZE_T)lpFileBase;
DWORD AddressOfNameOrdinals = RVATOOFFSET(lpFileBase, (ExportDescriptor->AddressOfNameOrdinals)) + (SIZE_T)lpFileBase;
PDWORD PAddressOfFunctions = (PDWORD)AddressOfFunctions;
//只遍历有名字的函数。
DWORD NumberOfNames = 0;
for ( ;NumberOfNames < ExportDescriptor->NumberOfNames ;NumberOfNames++ )
{
DWORD hint = *(WORD *)AddressOfNameOrdinals;
DWORD api_Ordinals = hint + ExportDescriptor->Base;//必须从序数值中减去 Ordinal Base 域的值得到的才是导出地址表真正的索引.
//ExportDescriptor->Base == 0x000005dc。C:\Windows\SysWOW64\user32.dll.
DWORD t = *(DWORD *)AddressOfNames;
char * api_name = (char *)(RVATOOFFSET(lpFileBase, t) + (SIZE_T)lpFileBase);
printf("Ordinal:%d, api_name;%s, Address:0x%x\n", api_Ordinals, api_name, PAddressOfFunctions[hint] + ntHeader->OptionalHeader.ImageBase);
AddressOfNames = AddressOfNames + sizeof(DWORD);
AddressOfNameOrdinals = AddressOfNameOrdinals + sizeof(WORD);
}
UnmapViewOfFile(lpFileBase);
CloseHandle(hFileMapping);
CloseHandle(hFile);
}
int wmain(int argc, wchar_t *argv[])
{
if ( argc != 2 )
{
return 1;
}
DumpFile(argv[1]);
return 0;
}
没有评论:
发表评论