zxWraith的窝
dotnet,Warcraft and life!
一:
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(其他值)
        大部分应用用这两个就很足够了,其他的有:
    GWLP_HINSTANCE
Sets a new application instance handle.
    GWLP_ID
Sets a new identifier of the window.
    GWLP_USERDATA
Sets the user data associated with the window. This data is intended for use by the application that created the window. Itsvalue is initially zero.

还不懂,自己去看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
At one time, this may have been a set of flags. However, Microsoft changed its meaning and never bothered to update WINNT.H. This field is really an offset (an RVA) to an array of pointers. Each of these pointers points to an IMAGE_IMPORT_BY_NAME structure.
DWORD TimeDateStamp
The time/date stamp indicating when the file was built.
DWORD ForwarderChain
This field relates to forwarding. Forwarding involves one DLL sending on references to one of its functions to another DLL. For example, in Windows NT, NTDLL.DLL appears to forward some of its exported functions to KERNEL32.DLL. An application may think it's calling a function in NTDLL.DLL, but it actually ends up calling into KERNEL32.DLL. This field contains an index into FirstThunk array (described momentarily). The function indexed by this field will be forwarded to another DLL. Unfortunately, the format of how a function is forwarded isn't documented, and examples of forwarded functions are hard to find.
DWORD Name
This is an RVA to a NULL-terminated ASCII string containing the imported DLL's name. Common examples are "KERNEL32.DLL" and "USER32.DLL".
PIMAGE_THUNK_DATA FirstThunk
This field is an offset (an RVA) to an IMAGE_THUNK_DATA union. In almost every case, the union is interpreted as a pointer to an IMAGE_IMPORT_BY_NAME structure. If the field isn't one of these pointers, then it's supposedly treated as an export ordinal value for the DLL that's being imported. It's not clear from the documentation if you really can import a function by ordinal rather than by name.

可以看一下,这里要说明的是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!



posted on 2006-04-06 01:34  zxWraith  阅读(1421)  评论(0编辑  收藏  举报