LONG_PTR SetWindowLongPtr( HWND hWnd, int nIndex, LONG_PTR dwNewLong);
对窗口才有用,不过很多地方都用了,可以做很多事情,hWnd是你要改的窗口的句柄,nIndex说明你要改的东西,dwNewLong是你要替换的东西(其实是个长整型);
if(nIndex==GWLP_WNDPROC)
dwNewLong写你自己写的窗口消息处理函数地址,这样所有消息都你自己处理了,爽吧~
else if(nIndex==GWL_STYLE||GWL_EXSTYLE)
dwNewLong写你要加的风格,可以改变窗口的外观
else if(其他值)
大部分应用用这两个就很足够了,其他的有:
还不懂,自己去看msdn
二:
象LoadLibrary,LoadLibraryEx,,FreeLibrary不说了,简单,这里说下FreeLibraryAndExitThread
它的参数和实现是
VOID FreeLibraryAndExitThread(HINSTANCE hinstDll, DWORD dwExitCode)
{
FreeLibrary(hinstDll);
ExitThread(dwExitCode);
}
可能大家看了有点奇怪,为什么MS写了个这么SB的函数,自己实现不就行了....
如果这样想的话,再去看看dll的内部原理....没听说过....老大,你可以回火星去了..
还是得从dll的调用和销毁说起:
假定你要编写一个D L L,当它被初次映射到进程的地址空间中时,该D L L就创建一个线程。当该线程完成它的操作时,它通过调用F r e e L i b r a r y函数,从进程的地址空间中卸载该D L L,并且终止运行,然后立即调用E x i t T h r e a d。但是,如果线程分开调用F r e e L i b r a r y和E x i t T h r e a d,就会出现一个严重的问题。这个问题是调用F r e e L i b r a r y会立即从进程的地址空间中卸载D L L。当调用的F r e e L i b r a r y返回时,包含对E x i t T h r e a d调用的代码就不再可以使用,因此线程将无法执行任何代码。这将导致访问违规,同时整个进程终止运行。 但是,如果线程调用F r e e L i b r a r y A n d E x i t T h r e a d,该函数调用F r e e L i b r a r y,使D L L立即被卸载。下一个执行的指令是在K e r n e l 3 2 . d l l中,而不是在刚刚被卸载的D L L中。这意味着该线程能够继续执行,并且可以调用E x i t T h r e a d。E x i t T h r e a d使该线程终止运行并且不返回。
不过这个函数不是很常用,了解它得前提是你对dll有很深得理解,如果你只是停留在怎么按规矩写dll,永远不会有提高的...
三:
HINSTANCE GetModuleHandle(PCTSTR pszModuleName);
这个函数在很多apihook里面可以看到,得到已经加载的dll的一个句柄,可以判断程序是否加载你指定的dll,
四:
FARPROC GetProcAddress( HINSTANCE hinstDll, PCSTR pszSymbolName);
这个函数用来获得dll中你要调用的函数的地址,在使用前要声明下调用的函数的参数,返回值,类型;多用就觉得熟了.
五:
PVOID ImageDirectoryEntryToData( PVOID Base, BOOLEAN Base, BOOLEAN Base, BOOLEAN MappedAsImage, USHORT MappedAsImage, USHORT DirectoryEntry, PULONG DirectoryEntry, PULONG Size);
这个函数很牛..可以做很多事情..大家可能对Base这个参数不是很熟悉,觉得有点郁闷,怎么是个PVOID?这是什么东西?
那知道HMODULE,HINSTANCE,HANDLE不,很熟悉吧,从宏定义里面追溯,他们的祖先都是PVOID,而PVOID是一个void* 类型指针,
通俗点说就是一个通用类型的指针,可以转换成其他的指针,为什么上课的时候这个东西从来没讲过......郁闷Size);
这个函数很牛..可以做很多事情..大家可能对Base这个参数不是很熟悉,觉得有点郁闷,怎么是个PVOID?这是什么东西?
那知道HMODULE,HINSTANCE,HANDLE不,很熟悉吧,从宏定义里面追溯,他们的祖先都是PVOID,而PVOID是一个void* 类型指针,
通俗点说就是一个通用类型的指针,可以转换成其他的指针,为什么上课的时候这个东西从来没讲过......郁闷..
知道了Base的用法,其他的就简单了,举个例子,如果你要看dll里面的导出函数,导入函数,或者其他什么东西,以导出函数为例,可以这样写:
ULONG ulSize;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(HMODULE_OF_DLL_OR_EXE, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT,&ulSize);
所以象网上的函数查看器写得简单得就是用了个这个函数(这里看的是分析的dll文件名),如果复杂的就直接分析dll的PE结构吧..那样写出来才是高手,就像我一样,查找文件的功能,做了半天还是用了api,如果分析了NTFS的文件系统结构的话,效率肯定有很大的提高.api考虑了很多不同的地方,肯定性能有损失....不扯远了,用了函数后,可以这样看:
for (; pImportDesc ->Name; pImportDesc ++)
{
PSTR pszModName = (PSTR)((PBYTE)HMODULE_OF_DLL_OR_EXE+ pImportDesc ->Name);
prinft("%s\n",pszModName);
}
差不多了..具体其他用法可以看msdn........
这里的IMAGE_IMPORT_DESCRIPTOR结构,在msdn里面可是找不到的哦,在定义里面看的
ypedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
};
DWORD TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
这是结构的解释:
DWORD Characteristics
DWORD TimeDateStamp
DWORD ForwarderChain
DWORD Name
PIMAGE_THUNK_DATA FirstThunk
可以看一下,这里要说明的是Name,是dll的名字,而FirstThunk则是一个PIMAGE_THUNK_DATA结构,在winnt.h是这样定义的
typedef PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA;
typedef struct _IMAGE_THUNK_DATA32 {
union {
DWORD ForwarderString; // PBYTE
DWORD Function; // PDWORD
DWORD Ordinal;
DWORD AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;
这里u1的枚举里面的Function就指示了你的函数的地址,藏的很深吧...
如果看导入函数的话,给个不完全的示例:
..........唉,还是算了,以后再写~~~~~~
上面看的是导入函数,如果要看导出函数,把IMAGE_DIRECTORY_ENTRY_IMPORT改成IMAGE_DIRECTORY_ENTRY_EXPORT
再传给下面这个结构就可以了,MS太不人道了,什么东西都藏起来....害我找了好久
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions; // RVA from base of image
DWORD AddressOfNames; // RVA from base of image
DWORD AddressOfNameOrdinals; // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
不过对于apihook而言,导出表没什么用...
六:
DWORD GetModuleFileName(
HMODULE hModule,
LPTSTR lpFilename,
DWORD nSize
);
取得hModule的路径,如果为NULL.就是当前执行这个函数的程序的路径..作用也不小...
呼,写得好累,整整花了我2个小时啊,终于知道rn得精华帖是怎么来得了..........如果上面得几个函数都明白了的话,基本上apihook就完成了一大半了,剩下的只要替换你自己的函数就ok拉.什么外挂,木马,基本都是这个原理...
不过只是完成了基本功能,在程序的健壮性方面还要反复改进...通过写这个心得,自己对pe文件格式,dll的机制理解又深了一层,高兴....,又进步拉,...在这里放出我刚刚找到的关于pe文件的一篇文章,很通俗...相信看了后大家对系统底层也会有了解和体会....
ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.WIN32COM.v10.en/dndebug/html/msdn_peeringpe.htm,在msdn2005里面打开,其他的地方我就不知道..
又到了一点半了...现在每次都是这样,一边研究一边写,不知不觉就到了半夜.........不过就是不困,知道了这里的原理,又来了新的问题,感觉真的很好,看样子找到了自己的兴趣所在,不象上课的时候,除了mis还是mis,我自己的感觉,可能中国很多程序员就这样把青春与时间花在了写一个个重复的mis上面,心里突然觉得有点感伤..人大了,确实对人生,还有社会的认识深了很多,虽然以前不想,可这是不可避免的,重要的是自己能够保持自己的目标,永远保持对未知的探索的激情,不要抱怨生活(虽然我会..)这样你自然就会得到你所付出的,这是我在心里所坚信的.........这个学期数学一定要过~~~~~~~~~!!!!!!!!!!!
感觉博客园的.text在线编辑系统功能很cool,不过对系统资源要求高了点,有时间好好研究下...........也为博客园的发展出一份力~~
不说了,睡觉了~~~~希望自己的D.Lemon Connector能够早点出世,这个名字是我老婆起的,很幼稚吧,哈哈,Good Night World!