等雁归来

Just do it.

导航

windows sdk 学习笔记(7)

  1. 代理函数:在windows下,应用程序都有自己的地址空间,它们只能调用自己地址空间的函数,所以在挂钩api之前,必须将一个可以代替api执行的函数的执行代码,注入到目标进程,然后设法让目标进程对api的调用,改为对注入到目标进程中的自定义的函数的调用,此函数,即是“代理函数”(此代理函数和目标函数的签名,应完全相同)
  2. 通过把注入代码写到dll中,然后让目标进程加载这个dll,这即是所谓的dll注入。
  3. 可以趁dll在目标进程的初始化其实创建新线程,此线程运行在目标进程中,它对目标进程有着完全的访问权限,可以设置之为守护线程,或者,通过此种方式隐藏自己,创建没有“进程”的线程。
  4. 在windows中,使用钩子注入到特定dll到其他进程时,一般是安装:WM_GETMESSAGE类型的钩子,因为有些程序不需要处理键盘,而消息是必须的。
  5. 安装WH_GETMESSAGE钩子的目的是让其他进程加载钩子函数所在的dll,所以只是顺着调用 CallNextHookEx,而不做有用的工作(?)
  6. 模块的导出函数的实现及其他都驻留在导出他的dll中,而在目标进程中,相关的导入函数名,dll名这些信息被放置在一个由 IMAGE_IMPORT_DESCRIPTIOS 结构体变量构成的数组中(被称为:导入表,每个模块对应数组中的一项), 在这个结构中,成员:name标识了dll库名字,OriginalFirstChunk,此成员标识了,导出函数的名称、函数序号及其他相关信息,所在数组(hint/name表),相对于模块基地址的偏移量(模块中导出函数数量,对应了此数组的大小,对应了导入表中的另一成员:FirstChunk所指示的地址表的大小)。
  7. 在应用程序启动时,loader根据每个模块的pe文件的导入表中记录的其导入的每个模块的表名,加载相应的dll,再根据originalFirstChunk所标识的数组中记录的函数名/序号取得函数地址(估计是调用了:GetProcAddress),然后将相应的地址,copy到 FirstChunk,所指示的地址表中的,相应项,而后当应用程序在使用时,先从导入表中,找到此函数的地址,再转而调用此函数。
  8. 通过修改导入地址表中目标函数所在地址为,自定义的api的地址的这种hook api的方法是最稳定的。
  9. PE文件中保留 16个数据目录:前面提到的导出表,算是其中的一个,可以通过以下两种方式,取得相应数据目录的地址(如下:)

a)        IMAGE_IMPORT_DESCRIPTOR*pImportDesc = ( IMAGE_IMPORT_DESCRIPTOR*)( (BYTE*)hMod + pOptHeader->DataDirector[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

b)        … ImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &uiSize )

  1. WriteProcessMemory 此函数用以在指定进程中改写内存,但是整个区域必须是可访问的。
  2. VirtualQuery函数,提供特定进程的指定虚拟内存页面区间的信息。
  3. VritualProtect: 此函数用以改写调用进程的虚拟地址空间中,已经被提交的面面象蹋恒区域的访问保护。
  4. IMAGE_THUNK_DATA32 ??
  5. PE文件是每模块一个。
  6. 由于一个模块导入的模块可能有多个,所以先取得首个导入表,搜索目标导入表,在目标导入表中,搜索目标导入函数,找到后改变虚拟内存页属性,然后用自定义函数地址,修改目标函数地址。
  7. 所谓地址就是一dword整形数。
  8. 通过快照,可以取得本进程中的所有模块的信息,进而hook
  9. 由于dll的链接方式有:加载期间动态链接和运行期动态链接两种,对于前一种情况,相应的DLL及其所导出的函数的信息,已经在:导入表中有了记录,所以只需要在目标导入表中的目标导入地址表中找到相应地址修改即可,有多少需要被hook的函数,就查找修改多次。而对于后者,运行期动态链接时,通过 loadLibaray函数,可以加载感兴趣的dll,而此dll相关信息并没有放在“Import Table”中,这时,我们就需要做的是,在成功加载了某个dll的同时,hook掉其内导出某些感兴趣的函数。由于loadLibary函数,有四种变体,所以需要我们对四种变化都编写“代理函数”,而在代理函数中,完成导入,检测,并钩掉目标函数(s),在前一种方式中,由于已经在iat上做了手脚,所以在调用函数时,是默认调用我们的代理函数,而在后一种方式中,由于调用哪个函数,只有在getProcAddress时,才知道,所以同样我们需要用自己的getProcAddress,替换之前的函数,由于其余的函数是通过 loadLibaray/getProcAddress这个函数对来操作的,所以他们必须通过改写地址表的方式,来达到让hook自己。
  10. If you want to transform datafrom one process to another, you must fill a structure: COPYDATASTATRUCT, andsend a message “WM_COPYDATA”, and use this variable as the lParam.

posted on 2010-04-21 22:00  等雁归来  阅读(315)  评论(0编辑  收藏  举报