截获API函数

  • 主题发起人 主题发起人 import
  • 开始时间 开始时间
I

import

Unregistered / Unconfirmed
GUEST, unregistred user!
装载一篇文章,也许有用,但我在MSDN上没有查到IMAGE_IMPORT_DESCRIPTOR的结构,Kingron:你把它转成Delphi代码后记得给我发一份哦
====================================
下面是GoodHope的翻译:
// 我只是照着翻译了一下,可以编译通过。代码本身不全,所以没有进行任何的调试。
// 如果在格式对齐上有问题,请把Tab设为2。
unit x;
// 如何截获API函数(转)
// 该程序是基于HOOK原理,主要是将自己的函数放到目标PROCESS的地址空间,这里是使用HOOK实现.
// 首先建立一个MOUSE的HOOK程序,然后在全局鼠标HOOK的DLL中做截获动作,
// 可以在PROCESS_ATTACH时做,也可以在鼠标的HOOK链函数中做.
// 建立全局HOOK就不说了,可以在网上很多地方看到.主要是截获动作.
// 通过PE格式(使用IMAGE)改变API函数在调用时的地址.DLL部分参考如下代码:
interface
const
IMAGE_ORDINAL_FLAG64 = $8000000000000000;
IMAGE_ORDINAL_FLAG32 = $80000000;
{$IFDEF _WIN64}
IMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG64;
{$ELSE}
IMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG32;
{$ENDIF}
 
type
// 我定义了一个结构
tag_HOOKAPI = record
szFunc: LPCSTR;//待HOOK的API函数名
pNewProc: FARPROC;//新的函数指针
pOldProc: FARPROC;//老的函数指针
end;
HOOKAPI = tag_HOOKAPI;
LPHOOKAPI = ^HOOKAPI;
THookAPI = tag_HOOKAPI;
LONG = Longint;
ULONGLONG = Int64;
PSTR = LPSTR;
PVOID = Pointer;
// WinNT.h Begin;
{$ALIGN OFF}
{$IFDEF _WIN64}
ULONG_PTR = ULONGLONG;
PULONG_PTR = ^ULONG_PTR;
{$ELSE}
ULONG_PTR = LONG;
PULONG_PTR = ^ULONG_PTR;
{$ENDIF}
SIZE_T = ULONG_PTR;
PSIZE_T = ^SIZE_T;
tag_IMAGE_IMPORT_DESCRIPTOR = record
case Boolean of
False: (Characteristics: DWORD); // 0 for terminating null import descriptor
True: (OriginalFirstThunk: DWORD; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
TimeDateStamp: DWORD; // 0 if not bound,
// -1 if bound, and real datestamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
ForwarderChain: DWORD; // -1 if no forwarders
Name: DWORD;
FirstThunk: DWORD; // RVA to IAT (if bound this IAT has actual addresses)
);
end;
IMAGE_IMPORT_DESCRIPTOR = tag_IMAGE_IMPORT_DESCRIPTOR;
PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
tag_IMAGE_DOS_HEADER = record // DOS .EXE header
e_magic: WORD; // Magic number
e_cblp: WORD; // Bytes on last page of file
e_cp: WORD; // Pages in file
e_crlc: WORD; // Relocations
e_cparhdr: WORD; // Size of header in paragraphs
e_minalloc: WORD; // Minimum extra paragraphs needed
e_maxalloc: WORD; // Maximum extra paragraphs needed
e_ss: WORD; // Initial (relative) SS value
e_sp: WORD; // Initial SP value
e_csum: WORD; // Checksum
e_ip: WORD; // Initial IP value
e_cs: WORD; // Initial (relative) CS value
e_lfarlc: WORD; // File address of relocation table
e_ovno: WORD; // Overlay number
e_res:array[0..4-1]of
WORD; // Reserved words
e_oemid: WORD; // OEM identifier (for e_oeminfo)
e_oeminfo: WORD; // OEM information; e_oemid specific
e_res2:array[0..10-1]of
WORD; // Reserved words
e_lfanew: LONG; // File address of new exe header
end;
IMAGE_DOS_HEADER = tag_IMAGE_DOS_HEADER;
PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
tag_IMAGE_FILE_HEADER = record
Machine: WORD;
NumberOfSections: WORD;
TimeDateStamp: DWORD;
PointerToSymbolTable: DWORD;
NumberOfSymbols: DWORD;
SizeOfOptionalHeader: WORD;
Characteristics: WORD;
end;
IMAGE_FILE_HEADER = tag_IMAGE_FILE_HEADER;
PIMAGE_FILE_HEADER = ^IMAGE_FILE_HEADER;
tag_IMAGE_DATA_DIRECTORY = record
VirtualAddress: DWORD;
Size: DWORD;
end;
IMAGE_DATA_DIRECTORY = tag_IMAGE_DATA_DIRECTORY;
PIMAGE_DATA_DIRECTORY = ^IMAGE_DATA_DIRECTORY;
tag_IMAGE_OPTIONAL_HEADER64 = record
Magic: WORD;
MajorLinkerVersion: BYTE;
MinorLinkerVersion: BYTE;
SizeOfCode: DWORD;
SizeOfInitializedData: DWORD;
SizeOfUninitializedData: DWORD;
AddressOfEntryPoint: DWORD;
BaseOfCode: DWORD;
ImageBase: ULONGLONG;
SectionAlignment: DWORD;
FileAlignment: DWORD;
MajorOperatingSystemVersion: WORD;
MinorOperatingSystemVersion: WORD;
MajorImageVersion: WORD;
MinorImageVersion: WORD;
MajorSubsystemVersion: WORD;
MinorSubsystemVersion: WORD;
Win32VersionValue: DWORD;
SizeOfImage: DWORD;
SizeOfHeaders: DWORD;
CheckSum: DWORD;
Subsystem: WORD;
DllCharacteristics: WORD;
SizeOfStackReserve: ULONGLONG;
SizeOfStackCommit: ULONGLONG;
SizeOfHeapReserve: ULONGLONG;
SizeOfHeapCommit: ULONGLONG;
LoaderFlags: DWORD;
NumberOfRvaAndSizes: DWORD;
DataDirectory:
array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1]of IMAGE_DATA_DIRECTORY;
end;
IMAGE_OPTIONAL_HEADER64 = tag_IMAGE_OPTIONAL_HEADER64;
PIMAGE_OPTIONAL_HEADER64 = ^IMAGE_OPTIONAL_HEADER64;
tag_IMAGE_OPTIONAL_HEADER = record
//
// Standard fields.
//
Magic: WORD;
MajorLinkerVersion: BYTE;
MinorLinkerVersion: BYTE;
SizeOfCode: DWORD;
SizeOfInitializedData: DWORD;
SizeOfUninitializedData: DWORD;
AddressOfEntryPoint: DWORD;
BaseOfCode: DWORD;
BaseOfData: DWORD;
//
// NT additional fields.
//
ImageBase: DWORD;
SectionAlignment: DWORD;
FileAlignment: DWORD;
MajorOperatingSystemVersion: WORD;
MinorOperatingSystemVersion: WORD;
MajorImageVersion: WORD;
MinorImageVersion: WORD;
MajorSubsystemVersion: WORD;
MinorSubsystemVersion: WORD;
Win32VersionValue: DWORD;
SizeOfImage: DWORD;
SizeOfHeaders: DWORD;
CheckSum: DWORD;
Subsystem: WORD;
DllCharacteristics: WORD;
SizeOfStackReserve: DWORD;
SizeOfStackCommit: DWORD;
SizeOfHeapReserve: DWORD;
SizeOfHeapCommit: DWORD;
LoaderFlags: DWORD;
NumberOfRvaAndSizes: DWORD;
DataDirectory:array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1]of
IMAGE_DATA_DIRECTORY;
end;
IMAGE_OPTIONAL_HEADER32 = tag_IMAGE_OPTIONAL_HEADER;
PIMAGE_OPTIONAL_HEADER32 = ^IMAGE_OPTIONAL_HEADER32;
tag_IMAGE_NT_HEADERS64 = record
Signature: DWORD;
FileHeader: IMAGE_FILE_HEADER;
OptionalHeader: IMAGE_OPTIONAL_HEADER64;
end;
IMAGE_NT_HEADERS64 = tag_IMAGE_NT_HEADERS64;
PIMAGE_NT_HEADERS64 = IMAGE_NT_HEADERS64;
tag_IMAGE_NT_HEADERS = record
Signature: DWORD;
FileHeader: IMAGE_FILE_HEADER;
OptionalHeader: IMAGE_OPTIONAL_HEADER32;
end;
IMAGE_NT_HEADERS32 = tag_IMAGE_NT_HEADERS;
PIMAGE_NT_HEADERS32 = ^IMAGE_NT_HEADERS32;
 
{$IFDEF _WIN64}
IMAGE_NT_HEADERS = IMAGE_NT_HEADERS64;
PIMAGE_NT_HEADERS = PIMAGE_NT_HEADERS64;
// IMAGE_FIRST_SECTION64(ntheader) IMAGE_FIRST_SECTION(ntheader)
{$ELSE}
IMAGE_NT_HEADERS = IMAGE_NT_HEADERS32;
PIMAGE_NT_HEADERS = PIMAGE_NT_HEADERS32;
//IMAGE_FIRST_SECTION32(ntheader) = IMAGE_FIRST_SECTION(ntheader);
{$ENDIF}
 
 
tag_IMAGE_IMPORT_BY_NAME = record
Hint: WORD;
Name: array[0..0]of BYTE;
end;
IMAGE_IMPORT_BY_NAME = tag_IMAGE_IMPORT_BY_NAME;
PIMAGE_IMPORT_BY_NAME = ^IMAGE_IMPORT_BY_NAME;
tag_U1_64 = record
case BYTE of
1: (ForwarderString: PBYTE;);
2: (Function_: PDWORD;);
3: (Ordinal: ULONGLONG;);
4: (AddressOfData: PIMAGE_IMPORT_BY_NAME;);
end;
tag_IMAGE_THUNK_DATA64 = record
u1: tag_U1_64;
end;
IMAGE_THUNK_DATA64 = tag_IMAGE_THUNK_DATA64;
PIMAGE_THUNK_DATA64 = ^IMAGE_THUNK_DATA64;
tag_U1_32 = record
case BYTE of
1: (ForwarderString: PBYTE; );
2: (Function_: PDWORD);
3: (Ordinal: DWORD);
4: (AddressOfData: PIMAGE_IMPORT_BY_NAME);
end;
tag_IMAGE_THUNK_DATA32 = record
u1: tag_U1_32;
end;
IMAGE_THUNK_DATA32 = tag_IMAGE_THUNK_DATA32;
PIMAGE_THUNK_DATA32 = ^IMAGE_THUNK_DATA32;
 
{$IFDEF _WIN64}
// IMAGE_ORDINAL64(Ordinal) = IMAGE_ORDINAL(Ordinal)
IMAGE_THUNK_DATA = IMAGE_THUNK_DATA64;
PIMAGE_THUNK_DATA = PIMAGE_THUNK_DATA64;
// IMAGE_SNAP_BY_ORDINAL64(Ordinal)IMAGE_SNAP_BY_ORDINAL(Ordinal)
//IMAGE_TLS_DIRECTORY = IMAGE_TLS_DIRECTORY64;
//PIMAGE_TLS_DIRECTORY = PIMAGE_TLS_DIRECTORY64
{$ELSE}
// IMAGE_ORDINAL32(Ordinal) =IMAGE_ORDINAL(Ordinal)
IMAGE_THUNK_DATA = IMAGE_THUNK_DATA32;
PIMAGE_THUNK_DATA = PIMAGE_THUNK_DATA32;
// IMAGE_SNAP_BY_ORDINAL32(Ordinal) = IMAGE_SNAP_BY_ORDINAL(Ordinal)
//IMAGE_TLS_DIRECTORY = IMAGE_TLS_DIRECTORY32
//PIMAGE_TLS_DIRECTORY = PIMAGE_TLS_DIRECTORY32
{$ENDIF}
{$ALIGN ON}
function GetNamedImportDescriptor(
hModule: HMODULE;
szImportMod: LPCSTR): PIMAGE_IMPORT_DESCRIPTOR; stdcall;
function HookAPIByName(
hModule: HMODULE; // 被HOOK的目标进程MODULE
szImportMod: LPCSTR; // 如GDI32.DLL
pHookApi: LPHOOKAPI // 指定函数名,如'MessageBoxW'
): Boolean; stdcall
implementation
//自己的MessageBoxW函数
function MyMessageBoxW(hWnd: HWND;
lpText: LPCWSTR; lpCaption: LPCWSTR; uType: UINT): Integer; stdcall;
begin
Result := MessageBox(hWnd, 'TNT'{lpText}, 'TNT'{lpCaption}, uType);
end;
function GetNamedImportDescriptor(
hModule: HMODULE;
szImportMod: LPCSTR): PIMAGE_IMPORT_DESCRIPTOR;
var
pDOSHeader: PIMAGE_DOS_HEADER;
pNTHeader: PIMAGE_NT_HEADERS;
pImageDataDirectory: PIMAGE_DATA_DIRECTORY;
pImportDesc: PIMAGE_IMPORT_DESCRIPTOR;
szCurrMod: PSTR;
begin
Result := nil;
//首先是DOS头
pDOSHeader := PIMAGE_DOS_HEADER(hModule);
if pDOSHeader.e_magic <> IMAGE_DOS_SIGNATURE then Exit;
pNTHeader :=
PIMAGE_NT_HEADERS(DWORD(pDOSHeader) + DWORD(pDOSHeader.e_lfanew));
if pNTHeader.Signature <> IMAGE_NT_SIGNATURE then Exit;
//如果没有Import部分,返回失败
pImageDataDirectory :=
@pNTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if (pImageDataDirectory.VirtualAddress = 0) then Exit;
//取Import部分
pImportDesc := PIMAGE_IMPORT_DESCRIPTOR
(DWORD(pDOSHeader) + DWORD(pImageDataDirectory.VirtualAddress));
//寻找与szImportMod相配部分
while pImportDesc.Name <> 0 do
begin
szCurrMod := PSTR(DWORD(pDOSHeader) + DWORD(pImportDesc.Name));
if (CompareText(szCurrMod, szImportMod) = 0) then
Break; //找到
Inc(pImportDesc);
end;
if pImportDesc.Name <> 0 then
Result := pImportDesc;
end;
function HookAPIByName(
hModule: HMODULE;
szImportMod: LPCSTR;
pHookApi: LPHOOKAPI
): Boolean;
var
pImportDesc: PIMAGE_IMPORT_DESCRIPTOR;
pOrigThunk: PIMAGE_THUNK_DATA;
pRealThunk: PIMAGE_THUNK_DATA;
pByName: PIMAGE_IMPORT_BY_NAME;
mbi_thunk: TMemoryBasicInformation;
dwOldProtect: DWORD;
begin
Result := False;
pImportDesc :=
GetNamedImportDescriptor(hModule, szImportMod);
//需要改换的API不能取到正确描
pOrigThunk :=
PIMAGE_THUNK_DATA(DWORD(hModule) + DWORD(pImportDesc.OriginalFirstThunk));
if pImportDesc = nil then Exit;
pRealThunk :=
PIMAGE_THUNK_DATA(DWORD(hModule) + DWORD(pImportDesc.FirstThunk));
while pOrigThunk.u1.Function_ <> nil do
begin
if(pOrigThunk.u1.Ordinal and IMAGE_ORDINAL_FLAG) <> IMAGE_ORDINAL_FLAG then
begin
pByName :=
PIMAGE_IMPORT_BY_NAME(DWORD(hModule) + DWORD(pOrigThunk.u1.AddressOfData));
if pByName.Name[0] = 0 then Exit; //失败
if CompareText(pHookApi.szFunc, PChar(@pByName.Name[0])) = 0 then
begin
//改变thunk保护属性
VirtualQuery (
pRealThunk,
mbi_thunk,
SizeOf(MEMORY_BASIC_INFORMATION));
VirtualProtect(
mbi_thunk.BaseAddress,
mbi_thunk.RegionSize,
PAGE_READWRITE,
@mbi_thunk.Protect);
//保存原来的API函数指针
if pHookApi.pOldProc = nil then
pHookApi.pOldProc := FARPROC(pRealThunk.u1.Function_);
//改变API函数指针
pRealThunk.u1.Function_ := PDWORD(pHookApi.pNewProc);
//将thunk保护属性改回来
VirtualProtect(
mbi_thunk.BaseAddress,
mbi_thunk.RegionSize,
mbi_thunk.Protect,
@dwOldProtect);
end;
end;
Inc(pOrigThunk);
Inc(pRealThunk);
end;
SetLastError(ERROR_SUCCESS);
Result := True;
end;
====================================
如何截获API函数(转)
该程序是基于HOOK原理,主要是将自己的函数放到目标PROCESS的地址空间,这里是使用HOOK实现.首先建立一个MOUSE的HOOK程序,然后在全局鼠标HOOK的DLL中做截获动作,可以在PROCESS_ATTACH时做,也可以在鼠标的HOOK链函数中做.
建立全局HOOK就不说了,可以在网上很多地方看到.主要是截获动作.通过PE格式(使用IMAGE)改变API函数在调用时的地址.DLL部分参考如下代码:
static int WINAPI MyMessageBoxW(HWND hWnd , LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)//自己的MessageBoxW函数
{return MessageBox(hWnd, "TNT"/*lpText*/, "TNT"/*lpCaption*/, uType);
}
我定义了一个结构
typedef struct tag_HOOKAPI
{
LPCSTR szFunc;//待HOOK的API函数名
PROC pNewProc;//新的函数指针
PROC pOldProc;//老的函数指针
}HOOKAPI, *LPHOOKAPI;
extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportMod)
{//首先是DOS头
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule;
if(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL;
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader + (DWORD)(pDOSHeader->e_lfanew));
if(pNTHeader->Signature != IMAGE_NT_SIGNATURE) return NULL;
//如果没有Import部分,返回失败
if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return NULL;
//取Import部分
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
((DWORD)pDOSHeader + (DWORD)(pNTHeader->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
//寻找与szImportMod相配部分
while (pImportDesc->Name)
{
PSTR szCurrMod = (PSTR)((DWORD)pDOSHeader + (DWORD)(pImportDesc->Name));
if (stricmp(szCurrMod, szImportMod) == 0)
break; //找到
pImportDesc++;
}
if(pImportDesc->Name == NULL) return NULL;
return pImportDesc;
}
extern "C" __declspec(dllexport) HookAPIByName(HMODULE hModule/*被HOOK的目标进程MODULE*/, LPCSTR szImportMod/*如GDI32.DLL*/,LPHOOKAPI pHookApi/*指定函数名,如"MessageBoxW"*/)
{
PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
GetNamedImportDescriptor(hModule, szImportMod);
if (pImportDesc == NULL)
return FALSE; //需要改换的API不能取到正确描PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->OriginalFirstThunk));
PIMAGE_THUNK_DATA pRealThunk =
(PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->FirstThunk));
while(pOrigThunk->u1.Function)
{
if((pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
PIMAGE_IMPORT_BY_NAME pByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + (DWORD)(pOrigThunk->u1.AddressOfData));
if(pByName->Name[0] == '0')
return FALSE; //失败
if(strcmpi(pHookApi->szFunc, (char*)pByName->Name) == 0)
{
//改变thunk保护属性
MEMORY_BASIC_INFORMATION mbi_thunk;
VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect);
//保存原来的API函数指针
if(pHookApi->pOldProc == NULL)
pHookApi->pOldProc = (PROC)pRealThunk->u1.Function;
//改变API函数指针
pRealThunk->u1.Function = (PDWORD)pHookApi->pNewProc;
//将thunk保护属性改回来
DWORD dwOldProtect;
VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
mbi_thunk.Protect, &dwOldProtect);
}
}
pOrigThunk++;
pRealThunk++;
}
SetLastError(ERROR_SUCCESS);
return TRUE;
}
 

Similar threads

I
回复
0
查看
771
import
I
I
回复
0
查看
609
import
I
I
回复
0
查看
536
import
I
I
回复
0
查看
1K
import
I
后退
顶部