精华内容
下载资源
问答
  • 监控windows下的某一进程是否关闭 java调用bat:如果要和Runtime创建的进程交互,必须自己写交互的代码,例如通过socket,两个java进程互相通信。 Java代码 import java.io.IOException;   ...

    java调用bat&监控windows下的某一进程是否关闭


    java调用bat:如果要和Runtime创建的进程交互,必须自己写交互的代码,例如通过socket,两个java进程互相通信。

    Java代码 复制代码
    1. import java.io.IOException;   
    2.   
    3. public class Main {   
    4.   
    5. public static void main(String[] args){   
    6. try {   
    7. Runtime rt = Runtime.getRuntime();   
    8. rt.exec("cmd.exe /c start c:\\1.bat");   
    9. catch (IOException e) {   
    10. e.printStackTrace();   
    11. }   
    12. }   
    13. /* 1.bat的内容  
    14. * @echo off  
    15. * echo lsd>>c:\lsd.txt  
    16. *  
    17. * */  
    18. }  
    import java.io.IOException;
    
    public class Main {
    
    public static void main(String[] args){
    try {
    Runtime rt = Runtime.getRuntime();
    rt.exec("cmd.exe /c start c:\\1.bat");
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    /* 1.bat的内容
    * @echo off
    * echo lsd>>c:\lsd.txt
    *
    * */
    }
     



    java监控windows下的某一进程是否关闭:应为这里直接调用的操作系统带的命令,所以可以直接用getInputStream()来获得操作系统的反馈信息。如果调用命令启动另一个java应用,两个java应用互相交互,则getInputStream()就没用了。

    Java代码 复制代码
    1. ProcessBuilder pb = new ProcessBuilder("tasklist");   
    2. try {   
    3. Process p = pb.start();   
    4. BufferedReader rb = new BufferedReader(new InputStreamReader(p.getInputStream()));   
    5. String line;   
    6. String storeLine="";   
    7. while((line=rb.readLine())!=null){   
    8. if(line.indexOf("eclipse.exe")!=-1)//过滤进程eclipse.exe的信息   
    9. storeLine = line;   
    10. System.out.println(line);   
    11. }   
    12. //获取进程的pid号   
    13. if(storeLine!=""){   
    14. int beginIndex = storeLine.indexOf("exe");   
    15. int endIndex = storeLine.indexOf("Console");   
    16. String pid = storeLine.substring(beginIndex+3, endIndex).trim();   
    17. System.out.println("this process id is "+pid);   
    18. }else{   
    19. System.out.println("this process is not exist");   
    20. }   
    展开全文
  • 一、问题提出 在Windows操作系统中,dll属性查看的版本信息是在R3层获取的,如下图所示,在项目中经常要保证监控获取的透明性,能否...由于项目的某些需求,需要透明地监控Windows进程的列表,进程调用的dll库和版...

    一、问题提出

    在Windows操作系统中,dll属性查看的版本信息是在R3层获取的,如下图所示,在项目中经常要保证监控获取的透明性,能否在R0层直接获取这些信息?

    二、libvmi简介

    libvmi是Google的一个开源项目,利用Memory introspection技术在Dom0中监视DomU的情况。由于项目的某些需求,需要透明地监控Windows进程的列表,进程调用的dll库和版本。对于特定的操作系统版本,libvmi给的默认配置文件libvmi-example.conf中详细的配置参数,例如Windows 7的32位系统默认是

    libvmi中个重要的函数:给定进程的虚拟地址空间,直接读取对应位数的数据。

    vmi_read_32_vavmi_instance_t vmi addr_t vaddrvmi_pid_t pid, uint64_t *value

    [in]vmilibvmi实例

    [in]vaddr: 读取的虚拟地址基地址

    [in]pid:进程的pid

    [out]value:读取的值

    三、获取进程调用的dll基地址

    首先使用libvmi自带的例子process-list.c得到进程的列表,以及每个进程的基地址,该例子基本思路是使用vmi_read_addr_ksym这个函数获取PsActiveProcessHead,然后再得到系统中的进程双向链表,获得每个进程的EPROCESS结构体基地址和进程PID。后绪的就是利用上面libvmi函数直接去读内存,遍历进程地址空间(代码没整理好,有点乱,整理好再补充上去,这里使用windbg遍历一次,知道思路写代码就容易了)。

    首先找到要监控的具体的进程基地址,然后开始下列步骤找到模块链表:

    1. 通过进程的EPROCESS获取对应的_PEB结构
    2. 通过_PEB找到_PEB_LDR_DATA
    3. 在_PEB_LDR_DATA内部有3个LIST_ENTRY,这也就是进程加载的模块信息的链表头,_PEB_LDR_DATA内部的3个链表就是进程调用的所有dll库,而这三个链表的区别就是dll的排列顺序不同,里面的内容是一致的。
    4. 知道了链表头,只需要知道链表的结点就行了,需要遍历的结点是_LDR_DATA_TABLE_ENTRY结构,在这个结构中有一个FullDllName,也就是模块的路径,就是我们要找的。

    下面以notepad为例,使用windbg查看遍历,步骤如下:

    • 命令!process 0 0 notepad.exe

    • Peb的地址是小于0x80000000,属于用户地址空间,是不能直接访问的,直接访问的话看到的都是问号,所以切换到这个应用程序后才能访问地址空间,使用下面的命令切换到notepad.exe这个进程,.process /p /r 0x93c85470
    • 已经切换到notepad.exe,命令dt _EPROCESS 93c85470查看EPROCESS,可以看到Peb的地址7ffdf000,使用命令dt _PEB 0x7ffdf000查看PEB的信息,如图所示,在0x00c处找到了_PEB_LDR_DATA

     

    • 继续跟进_PEB_LDR_DATA,使用命令dt _PEB_LDR_DATA 0x77827880,进程的三个链表也就是这个了。

    • 我们已经找到了链表的头部,以InLoadOrderModuleList为例,dt _LDR_DATA_TABLE_ENTRY 0x2219f0,第一个模块是notepad.exe

    • 继续找下一个模块dt _LDR_DATA_TABLE_ENTRY 0x221a78

    遍历到ntdll.dll,继续按照这种方法可以遍历该进程所有的模块。这里以ntdll为例探索,如图,它的基地址是0x77750000。PE文件的格式如下图所示:

    四、找资源字节段

    下面开始遍历dll文件:

    • 首先是DOS头,使用命令dt _IMAGE_DOS_HEADER 0x77750000

     

    • 里面最重要的一个字段,e_lfanew:是32位可执行文件的扩展域,用来表示DOS头之后的NT头相对文件起始地址的偏移。
    • 使用命令dt /r1 ntdll!_IMAGE_NT_HEADERS notepad+e0查看PE的NT头结构

    可以看到在_IMAGE_NT_HEADERS里面的0x018偏移OptionalHeader的偏移0x060处有一个DataDiretory数组,数组的下标和对应的类型如下图所示,下标为2的代表资源段(.rsrc):

    • 跟进这个结构体_IMAGE_DATA_DIRECTORY继续看,dt _IMAGE_DATA_DIRECTORY 0x77750000+0n208+0x018+0x060+0x008+0x008(0n208+0x018+0x060代表DataDirectory第一个元素的基地址,每个成员大小是0x008)。

    可以看到VirtualAddress的值是0xe0000,这个值代表.rsrc字节段相对于dll基地址的偏移量。它的大小是0x560d8

    五、获取dll文件版本

    找到这个偏移量后,就可以对它进行遍历了,首先看看resource table的结构:

     

    resource table的整体结构组成成员

    1.IMAGE_RESOURCE_DIRECTORY结构(简称Directory)

    2.IMAGE_RESOURCE_DIRECTORY_ENTRY结构(简称Entry)

    3.IMAGE_RESOURCE_DIRECTORY_STRING结构(或者IMAGE_RESOURCE_DIR_STRING_U)

    4.IMAGE_RESOURCE_DATA_ENTRY结构

    整个resource结构是个树型结构,只有一个root根节点,然后长出许多的树枝,最后是叶子。根部和每个树枝是一个节点,该节点由IMAGE_RESOURCE_DIRECTORY结构和IMAGE_RESOURCE_DIRECTORY_ENTRY结构组成,并且他们是紧密排列的,而IMAGE_RESOURCE_DIRECTORY_STRING和IMAGE_RESOURCE_DATA_ENTRY都是整个资源树的叶子。

    资源树的节点由IMAGE_RESOURCE_DIRECTORY与IMAGE_RESOURCE_DIRECTORY_ENTRY构成,他们的关系是:

    1.由Directory指出有多少个Entry

    2.然后由每个Entry延伸出一个Directory或者最终的Data数据。

    下面来看具体的_IMAGE_RESOURCE_DIRECTORY的具体结构

    这个结构里的Characteristics,MajorVersion以及MinorVersion一直为0不使用。NumberOfNamedEntries代表一个数量,以Name作为子树的个数。NameOfIdEntries代表一个数量,以ID作为子树的个数。而Directory引出的Entry数量是NumberOfNamedEntries和NumberOfIdEntries之和。并且Entry是排列紧密的。这里注意到Directory的大小是0x010。

    Entry表组成

    在WinNT.h文件中,Entry结构定义为

    这个结构看上去很复杂,实际上他成员只有两个DEWORD,供8个字节,如下:

    DWORD Name;

    DWORD OffsetToData;

    他想表达的策略是:

    1. 当Name的最高位(Bit31)是1时:Name[30:0]是一个offset指向IMAGE_RESOURCE_DIR_STRING的结构,Bit31位为0时,Name表示一个ID
    2. 当OffsetToData的最高位Bit31为1时,OffsetToData[30:0]是一个Offset指向下一个Directory结构,Bit31位为0时,OffsetToData仍然是一个Offset值,它指向一个IMAGE_RESOURCE_DATA_ENTRY结构。
    3. 总的来说,Entry的职责是给出下一个Directory或Data,从资源树的角度来看,Entry要么给出下一个节点,要么给出叶子。Entry中当Name表示ID值的时候,它的类型如下:也就是说,dll版本信息的ID值是16,对应的16进制是0x10

    由于只有3个Entry(Entry大小是0x008),我们遍历完,如下图所示:可以看到在第三个Entry是dll版本相关的信息(Name为0x10)。

     

    根据偏移量找到下一个Directory的位置,偏移量0x58,如上图所示,它只有1个节点。按照上面的方式继续跟进:

    终于找到了叶子节点,它的偏移量是0xd8。这里找到dll版本信息的Raw data区域,偏移量是 0xe00f0,大小是0x380。

    使用命令:db 0x77750000+0xe00f0 L380可以dump出该便宜量的0x380大小的所有字节数据。

    获得了版本数据,还没有结束,还需要解析这一段数据,抽取里面的内容。

    六、解析版本信息数据

    位于版本信息数据起始位置的是一个VS_VERSIONINFO类型的结构,其定义:

    typedef struct tag_VS_VERSIONINFO

    {

        WORD             wLength;        // 00 length of entire version resource

        WORD             wValueLength;   // 02 length of fixed file info, if any

        WORD             wType;          // 04 type of resource (1 = text, 0 = binary)

        WCHAR            szKey[16];      // 06 key -- VS_VERSION_INFO

        WORD             Padding1;       // 26 padding byte 1

        VS_FIXEDFILEINFO Value;          // 28 fixed information about this file (13 dwords)

    } VS_VERSIONINFO, *PVS_VERSIONINFO;   // 5C

    wLength:是一个WORD类型的数,表示整个版本信息资源数据块的字节数;

    wValueLength指示成员VS_FIXEDFILEINFO Value的字节数;如果当前版本信息结构体未指定Value成员,则该值为0

    wType:表示资源类型,值为1表示文本,值为2表示二进制数据;

    szKey:是一个char类型的元素个数为16的字符数组,其值始终为L”VS_VERSION_INFO”,并且最后一个元素为0值;

    value:是一个VS_FIXEDFILEINFO类型的结构,存储当前版本信息结构指定的任意数据,其值目前可以无需过多关注,除了其中的DWOR dwSignature成员,其值恒为0xFEEF04BD。根据结构体对齐原则,在szKeyValue之间有2字节的间隔;

    Padding1:占位的作用。

    在此之后是VS_VERSIONINFO结构的子节点,它的子节点是由StringFileInfo结构体和VarFileInfo结构体组成的数组,而且他们扔收结构地对齐的约束,这两个数组都有可能为0,并且其先后顺序没有固定,我们需要获得的是StringFileInfo结构体。因此这里提供一个结构体对齐的函数:

    // offset: 当前成员对于文件缓冲区基地址的偏移

    // base: 当前结构体起始地址对于文件缓冲区基地址的偏移

    #define DWORD_ALIGN(offset, base)  (((offset + base + 3) & 0xfffffffcL) - (base & 0xfffffffcL))

    首先需要判断是不是VarFileInfo结构体,该结构体定义如下:

    typedef struct {

        WORD   wLength;

        WORD   wValueLength;

        WORD   wType;

        WCHAR  szKey[12]; // WCHAR L"VarFileInfo"

        // WORD Padding;

        Var    Children[1];

    } VarFileInfo;

    这里有两个关键字段:

    szKey:恒为L”VarFileInfo”字符串的WCHAR字符数组,所以只需要判断数组的内容是否为L”VarFileInfo”字符串,若是,直接根据wLength的长度跳过。

    wLength:该结构体的大小

    StringFileInfo结构体和VarFileInfo结构体类似,区别在于,它的szKey是一个大小为15的字符数组,值恒为L”StringFileInfo”,最后一个成员由Var Children的数组变成StringTable类型的变长Children数组,长度至少为1,具体的版本信息就包含在StringTable成员中。

    typedef struct {

        WORD   wLength;

        WORD   wValueLength;

        WORD   wType;

        WCHAR  szKey[9]; // WCHAR L"88888888"

        // WORD Padding;

        String Children[1];

    } StringTable;

    数组中每个不同的 StringTable 元素表示各个不同语言的版本信息,StringTable 结构的 szKey 成员表示该 StringTable 数据块中展示文本的语言编码和代码页。现在按通常情况定位到数组的第 0 个元素。如果有解析多语言版本 PE 文件的特殊需求,可针对不同语言的版本信息,对数组中每个 StringTable 元素单独解析。

    定位到当前 StringTable 结构的 Children[] 成员。该成员是一个 String 类型的变长数组。需要注意的是,这里的 String 类型并非 C++ 中定义的 std::string 数据类型,而只是 PE 文件结构定义中的一种结构体类型。

    typedef struct {

        WORD   wLength;

        WORD   wValueLength;

        WORD   wType;

        WCHAR  szKey[1]; // WCHAR L"String"

        // WORD Padding;

        // WCHAR Value[1];

    } String;

    与前面的各个结构体定义不同的是,String 结构中的 szKey 是个不定长的 WCHAR 字符数组,其内容表示当前版本信息类型的名称。其可取的内容如下:

    L"Comments"          // 为诊断信息展示的附加信息

    L"CompanyName"       // 公司名称

    L"FileDescription"   // 文件描述

    L"FileVersion"       // 文件版本

    L"InternalName"      // 内部名称

    L"LegalCopyright"    // 版权信息

    L"LegalTrademarks"   // 应用于该文件的商标或注册商标

    L"OriginalFilename"  // 原始文件名

    L"PrivateBuild"      // PrivateBuild *

    L"ProductName"       // 产品名称

    L"ProductVersion"    // 产品版本

    L"SpecialBuild"      // SpecialBuild *

    获取版本信息类型名称后,绕过该字符数组长度的内存地址,定位到 String 结构的 WORD Value 成员位置。成员 Value 由于它前面的 szKey 成员导致是一个不固定位置的成员。所以只能根据 szKey 的长度来辅助定位。注意字节对齐。

    Value 成员是一个以 0 结尾的 WCHAR 字符数组。其内容则是当前版本信息类型的值,长度通过 wValueLength 成员指示。

    下一个 String 元素紧随当前 Value 成员的结尾之后,通过宏 DWORD_ALIGN 获取其地址偏移之后,计算其实际内存地址,并根据与前面同样的获取方法,获取下一个版本信息类型的内容。可根据当前 StringTable 结构的 wLength 域作为限定范围遍历完。

     

     

     

    展开全文
  • java 监控 windows进程

    2009-07-09 23:04:34
    现在需要用java写个进程监控和网络监控,Snmp4j能实现网络的监控 Snmp4j能否监控制定的...我要监控的是windows进程 好像可以先用c#写个dll文件 在用jni调用 不过这样感觉很费事 ,不知到有没有什么更好的方法。
  • 通过Hook API调用打造进程监控程序

    千次阅读 2010-04-13 11:30:00
    *(收藏)http://hi.baidu.com/linuxetc/blog/item/1b91c813b017e4035baf53a7.htmlHook(钩子)是Windows消息处理过程中的一个监视点,应用程序可以通过Hook拦截Windows消息,这样就可以捕捉到目标进程的消息,并做...
    *(收藏)http://hi.baidu.com/linuxetc/blog/item/1b91c813b017e4035baf53a7.html
    Hook(钩子)是Windows消息处理过程中的一个监视点,应用程序可以通过Hook拦截Windows消息,这样就可以捕捉到目标进程的消息,并做相应的处理,从而达到修改系统默认行为的目的,另外,在相对封闭的Windows世界里,Hook技术也为我们了解系统内部机制提供了更好的机会。Hook技术在“黑”与“反黑”的对抗中,也扮演着重要的角色,很多木马,后门,都是通过键盘钩子,在后台记录密码,聊天信息。。。通过Hook系统的;可以通过Hook文件操作函数实现对文件的隐藏,躲避查杀;Hook注册表操作函数,实现对注册表中某些键值的隐藏。 另外,杀毒软件,防火墙也可以通过Hook系统的关键函数,实现对系统行为的监控,防止恶意程序在用户不知情的情况下,恶意破坏系统。
    下面,我们就通过利用Hook Explorer 进程的CreateProcess函数打造一个小小的进程监控程序,来给大家讲讲如何利用PE文件的导入表实现Hook API的吧。该程序Hook Explore进程的CreateProcess函数后,在windows资源管理器在要运行其它程序时,会弹出这样一个提示框:

     

    点击“是”,则程序运行,点击“否”则,程序被阻止运行。(注意:本例只Hook了Explore进程的CreateProcess,因此,该程序不能监控到系统范围内的程序运行情况,如果要这样,可以通过Hook Windows系统调用来实现,希望以后以机会和大家一起讨论这方面的话题。本例作为一个例子对于说明Hook API 调用的原理已足够)。
    我们可以通过SetWindowsHookEx函数安装一个Windows标准钩子,根据你安装的钩子类型,钩子可以是远程的,也可以是局部的。可是,Windows所提供的标准钩子中,并没有直接钩挂API调用的。那么如果我们要钩挂某个API,以达到某些目的,该怎么做呢?
    先来复习一下PE文件的导入表的相关知识吧。各种文件都有一定的格试,在windows下,EXE,DLL文件用的就是PE文件格式。如果我们现在要调用的是某个DLL中的一个函数,在代码编译期,使用隐式链接方式时,并不需要有指定的DLL,只要需要有DLL 对应的Lib文件就可以了,很明显,在编译的时候,对应的函数的地址是无法确定下来的。那么,在运行的时候又怎么能够正确调用这个API呢?原因是:PE文件在导入表中记录了它所用到的每一个DLL的名字,以及从相应的DLL导入的函数的名字。(在使用显式链接,通过LoadLibrary/GetProcAddress调用函数时,所需要DLL名,和函数名并不会出现在导入表中)。这样,当运行这个程序的时候,Windows可执行文件装载器,就会搜索并载入出现在该程序的导入表的所有DLL,(如果装载器,找不到导入表中的DLL,就会弹出提示框)然后,根据导入表中的导入的函数名字,在DLL的导出表中找到匹配的函数,取得它的地址,再把这个地址填入可执行文件对应的地方。(如果找到所需要的DLL,但是在该DLL的导出表中找不到可执行文件所导入的函数,就会弹出提示框)这就是动态链接的概念。

    /
    通过PE文件的头的数据目录中的第二个IMAGE_DATA_DIRECTORY项,我们就可以定位到导入表项。也可以直接用ImageDirectoryEntryToData这个API直接定位的导入表项。而导入表由IMAGE_IMPORT_DESCRIPTOR结构组成。
    Typedef struct _IMAGE_IMPORT_DESCRIPTOR{
    union{
    DWORD Characteristics;
    DWORD OriginalFirstThunk;
    };
    DWORD TimeDateStamp;
    DWORD ForwarderChain;
    DWORD Name;
    DWORD FirstThunk;
    }IMAGE_IMPORT_DESCRIPTOR;
    其中Name是一个相对虚拟地址(RVA),它指向所导入的DLL名字的一个字符串。如果一个可执行文件导入了多个DLL,则它的导入表中有多个这样的结构,最后有一个全0的IMAGE_IMPORT_DESCRIPTOR结束。OriginalFirstThunk和FirstThunk都是RVA,它们分别指向两个相同的IMAGE_THUNK_DATA。
    typedef struct _IMAGE_THUNK_DATA32{
    union{
    DWORD ForwarderSting;
    DWORD Function;
    DWORD Ordinal;
    DWORD AddressOfData;
    }u1;
    }IMAGE_THUNK_DATA32;
    Typedef IMAGE_THUNK_DATA32 IMAGE_THUNK_DATA;
    由此可见,实际上这个联合结构就是一个DWORD,根据规定,当这个DWORD最高位为1时,表示这个导入函数是通过序号形式导入的,否则函数是通过名称导入的,当通过名称导入时,这个DWORD是一个RVA,它指向了一个IMAGE_IMPORT_BY_NAME的结构。
    typedef struct _IMAGE_IMPORT_BY_NAME{
    WORD Hint;
    BYTE Name[?];
    }IMAGE_IMPORT_BY_NAME;
    这里面的Name是一个变长数组,它存着所导入的函数名。呵呵,如果没有耐心的话,估计你早就头晕了。现在我们来理一理这些结构的关系吧/。
    /
    现在,OriginalFirstThunk和FirstThunk都指向两个一样的IMAGE_THUNK_DATA,而这两个IMAGE_THUNK_DATA又都指向了包含了函数名的IMAGE_IMPORT_BY_NAME结构。当Windows装入一个可执行文件的时候,它会找到并载入Name指定的DLL,然后,在该DLL的导出表中找到
    IMAGE_IMPORT_BY_NAME所指定的函数名称的地址并填入FirstThunk所指的IMAGE_IMPORT_BY_NAME中。所以当载入完成后.

    这样的话,当调用CreateProcess,就会到FirstThunk中找到对应的CreateProcess的入口地址。现在,如果在装载后,把CreateProcess的入口地址改成我们指定的某个地址,那么对CreateProcess的调用会不会转到调用我们的代码上来呢?答案是肯定的。但是在Windows中各个进程都有各自独立的虚拟地址空间,如果我们要Hook一个远程进程,就一定得保证把代码映射到目标进程的地址空间中去。这个,可以使用VirtualAllocEx为目标进程分配空间,然后用WriteProcessMemory把代码写入到目标进程的地址空间中去,再把FirstThunk中的CreateProcess的入口地址改成写入代码的首地址。该方法要自己解决地址重定位的问题。另一种方法,就是把代码放到一个DLL中,然后,让目标进程加载这个DLL,这样就把地址重定位的事情交给Windows来做了。再把FirstThunk中的CreateProcess的入口地址改写成这个DLL中的某段代码的地址。但是,又怎么才能让目标进程加载这个DLL呢?这个我们可以通过为目标进程安装一个远程的钩子(SetWindowsHookEx),这样,就可以把一个DLL映射到目标进程的地址空间中去,然后,修改目标进程相关函数的入口地址就可以了。好了,说到这里,相关的基础知识,相信你也清楚了。我们就来看看程序的实现过程吧。程序分为两部分,一部分是主程序,一部分是一个DLL。启动Hook的过程如下:
    // 找到Explorer的窗口句柄
    hWnd = FindWindow("Progman", "Program Manager");
    DWORD dwProcessId; //获取Explorer进程及窗口线程的ID。
    DWORD dwThreadId = GetWindowThreadProcessId(hWnd, &dwProcessId);
    if (!dwThreadId){
    MessageBox(GetActiveWindow(), "Explorer 没有启动", "Explorer 没有启动", MB_OK);
    return;
    }
    HMODULE hModule = LoadLibrary("HookApi.dll"); // HookApi.dll是要注入的DLL
    HOOKPROC GetMsgProc = (HOOKPROC)GetProcAddress(hModule, "MsgHook");
    hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, hModule, dwThreadId);
    PostMessage(hWnd, WM_HOOK, 0, 0);
    FreeLibrary(hModule);
    上面的代码关键处是用SetWindowsHookEx为Explorer的窗口线程安装了一个WH_GETMESSAGE类型的钩子,这样,每当Explorer的窗口线程从它的消息队列中取到消息的时候,就会先调用HookApi.dll中的GetMsgProc回调函数。注意这里,不能用SendMessage,因为SendMessage并不把消息放入目标窗口的消息队列中,而是直接调用目标窗口的消息回调函数。
    接下来,我们看看HookApi.dll中的GetMsgProc回调函数,
    __declspec(dllexport) LRESULT CALLBACK MsgHook(int nCode, WPARAM wParam, LPARAM lParam){
    PMSG pmsg = (PMSG)lParam;
    switch(pmsg->message){
    case WM_HOOK:
    GetDebugPrivilege(); // 提高进程权限,为写导入表做准备
    // 用于同步,我将在后面详细解释为什么。
    hEvent = CreateEvent(NULL, TRUE, FALSE, "MyApiHookEvent");
    Hook("Kernel32.dll", "CreateProcessA", (PROC)NewCreateProcessA);
    Hook("Kernel32.dll", "CreateProcessW", (PROC)NewCreateProcessW);
    break;
    case WM_UNHOOK:
    UnHook();
    SetEvent(hEvent);
    CloseHandle(hEvent);
    break;
    default:
    CallNextHookEx(NULL, nCode, wParam, lParam);
    break;
    }
    return 0;
    }
    每当Explorer从它的窗口消息队列中,取到消息的时候,就会先调用MsgHook回调函数,我们在这个函数中,先判断消息是不是我们自己定义的消息WM_HOOK或WM_UNHOOK,如果是,则处理,如果不是,则不是我们关心的消息,调用CallNextHookEx把消息往下传。
    void Hook(LPCTSTR lpModule, LPCTSTR lpFunction, PROC pfnNewFunc){
    HMODULE hThisModule = GetThisModule(); // 获取本DLL的模块句柄
    // 这里取得Explorer进程中的所有模块。
    HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
    MODULEENTRY32 me = {sizeof(me)};
    for (BOOL fFlag = Module32First(hSnapShot, &me); fFlag; fFlag = Module32Next(hSnapShot, &me)){
    if (me.hModule != hThisModule){
    try{
    ReplaceFunc(me.hModule, pfnNewFunc, lpModule, lpFunction);
    }catch(...){
    continue;
    }
    }
    }
    CloseHandle(hSnapShot);
    }
    代码首先获取Explorer进程中的每一个模块,然后调用ReplaceFunc尝试修改每个模块的导入表。
    void ReplaceFunc(HMODULE hModule, PROC pfnNew, LPCTSTR lpModule, LPCTSTR lpFunction){
    ULONG ulSize;
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
    // 获取导入表的地址。
    pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData
    (hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
    if (pImportDesc == NULL)
    return;
    // 由于导入表中,可能导入了很多DLL,我们先找到,要Hook的DLL,此例中,为kernel32.dll
    while (pImportDesc->Name){
    PSTR pszName = (PSTR) ((PBYTE) hModule + pImportDesc->Name);
    if (lstrcmpi(pszName, lpModule) == 0)
    break; // 找到目标DLL
    else
    pImportDesc++;
    }
    if (pImportDesc == 0 || pImportDesc->Name == 0)
    return;
    // 定位FirstThunk和OriginalThunk,前面说过,在内存中,FirstThunk间接指向导入表中,真实的函数
    //地址的结构,而OriginalThunk间接指向真实的函数名。
    PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDesc->FirstThunk);
    PIMAGE_THUNK_DATA pOriginalThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDesc->OriginalFirstThunk);
    // 确保函数不是以序号导入的。
    if ((pOriginalThunk->u1.ForwarderString & IMAGE_ORDINAL_FLAG32) != 0)
    return;
    while (pOriginalThunk->u1.Function){ // 找到函数名。
    PIMAGE_IMPORT_BY_NAME pImageByName = (PIMAGE_IMPORT_BY_NAME)((PBYTE) hModule + pOriginalThunk->u1.ForwarderString);
    // 比较该项的函数名是不是我们要Hook的函数,如果是,则修改对应的导入地址。
    if (lstrcmpi(((LPCSTR)&(pImageByName->Name)), lpFunction) == 0){
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, GetCurrentProcessId());
    // 将修改的信息保存起来,以简化UnHook的工作。
    PHooker p;
    p = new Hooker;
    p->pNext = Head;
    p->lpFunction = lpFunction;
    p->lpModule = lpModule;
    p->pfnNew = pfnNew;
    p->pfnOld = (PROC)pFirstThunk->u1.Function;
    p->lpAddr = &(pFirstThunk->u1.Function);
    Head = p;
    WriteProcessMemory(hProcess, (LPVOID)(&(pFirstThunk->u1.Function)), (LPVOID)(&pfnNew), sizeof(pfnNew), NULL);
    }
    pFirstThunk++;
    pOriginalThunk++;
    }
    }
    主程序,能过下列方式通知HookApi.dll进行UnHook动作。
    PostMessage(hWnd, WM_UNHOOK, 0, 0);
    HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "MyApiHookEvent");
    WaitForSingleObject(hEvent, INFINITE);
    CloseHandle(hEvent);
    UnhookWindowsHookEx(hHook);

    HookApi.dll中的MsgHook回调函数对WM_UNHOOK消息的处理:
    case WM_UNHOOK:
    UnHook();
    SetEvent(hEvent);
    CloseHandle(hEvent);
    UnHook过程就非常简单了,前面每修改了一项导入表中的函数地址,就把它的相关信息保存在一个链表中,现在,只要根据这个链表,把每一个函数地址恢复,就完成了UnHook过程。这里我要说的是,当调用PostMessage把消息丢入Explorer的消息队列中,但不能保证Explorer什么时候来处理这条消息,而我们是通过SetWindowsHookEx把HookApi.dll映射到Explorer的进程地址空间中去的,当调用UnhookWindowsHookEx的时候,HookApi.dll会从Explorer进程中卸载。现在,考虑这样一种情况,当用PostMessage发送消息后,由于Explorer因为某种原因没来得及处理这条消息,而主程序调用了UnhookWindowsHookEx,这时候,HookApi.dll在Explorer进程地址空间中的映射被解除,后来,Explorer从它的消息队列中取出WM_UNHOOK,由于消息钩子也已经被解除,所以WM_UNHOOK消息不会再有机会被处理,因而也没有机会把导入表中的函数地址恢复回样,如果在个时候,再调用之前被HOOK了的API,那个地址还是指向HookApi.dll中的某个函数中的地址,但是,这个DLL已经被解除,很明显,由于一个对无效地址的CALL,将直接导致Explorer进程的崩溃。所以,本例中,在WM_HOOK中,建立了一个未通知状态的事件对象,然后,主程序UnHook时,用PostMessage发送消息后,用WaitForSingleObject无限期等待这个事件对象,只有当Explorer的消息钩子处理了WM_UNHOOK消息时,才用SetEvent把这个事件对象设为通知状态,这样,主程序中的UnhookWindowsHookEx才有机会被执行,从而保证了同步。
    后记:本文结合消息钩子以及对PE文件导入表的操作,实现了对API调用的拦截,由于篇幅的原因,本文只对关键代码进行了分析,详细的代码请参阅附带的源代码。注意本文的代码,只做说明之用,略去了一些错误处理,用VS 2003编译通过,可执行程序,在作者的Windows XP SP2以及Windows 2K中测试通过,对于其它机器上作者不能保证其正确运行,对此引起的任何问题,作者不承担任何责任。对本文的纰漏之处,望诸位大侠斧正。

    展开全文
  • TipokHostManager是在Windows平台下针对Windows service实现分布式管理监控的服务 它的实现原理不复杂,是基于调用系统WMI服务,然后通过WCF实现远程调用管理windows 服务及控制台程序的分布式部署管理服务  该...

    TipokHostManager是在Windows平台下针对Windows service实现分布式管理监控的服务

     它的实现原理不复杂,是基于调用系统WMI服务,然后通过WCF实现远程调用管理windows 服务及控制台程序的分布式部署管理服务

     该服务基于WMI实现了对系统服务,进程的监听守护,通过定制,可以基于该服务进行短信,邮件通知等功能。

    简尔言之,通过该服务,实现了对WINDOWS 服务实现分布式部署,升级,安装,卸载,监控的功能。

    先发张类图

     类的关系说明

    Program 管理服务的启动类,负责服务的启动,在main方法中,初始化HostService 的实例。

    当服务启动的时候,调用HostService的Start方法

    停止的时候调用对应的Stop方法。

     

    HostService Start 中主要做2件事:

    1.启动监视本地服务的类,MonitorLocalService,实现对本机的Win服务监控及系统进程(控制台,窗体这类程序)的监控。

    2.调用InitilazerWCFService 的静态方法,启动WCF服务对外接口,提供服务控制的远程调用接口

     

    项目地址:https://tipokhostmanager.codeplex.com/

    转载于:https://www.cnblogs.com/wyxy2005/archive/2013/04/01/2992993.html

    展开全文
  • 文章目录9.linux的简单运维9.1 linux的进程管理9.2 什么是进程9.2.1 进程的定义9.2.2 进程与程序9.2.3 进程分类9.2.4 调用过程(为方便满足多用户操作需求)9.3 进程管理9.3.1 查看进程:ps1)列出目前所有的正在内存...
  • 服务老是莫名的死翘翘,客户不停的电话给我,搞的我心情很差,于是在一个下午,静下心来,用python写了个简单的监控进程的脚本,当发现进程消失的时候,立即调用服务,开启服务。。。脚本的工作原理是这样的:脚本...
  • Process Monitor(以下简称 Procmon)是一种进程监控工具,为开发者提供了简便有效的方式来跟踪系统调用(syscall)活动。该工具能够帮助诊断程序崩溃、资源占用率过高,甚至是潜在的恶意感染等问题。 Sysinternals...
  • 微软最近为 Windows ...Windows 上的 ProcmonProcess Monitor(以下简称 Procmon)是一种进程监控工具,为开发者提供了简便有效的方式来跟踪系统调用(syscall)活动。该工具能够帮助诊断程序崩溃、资源占用率过高,...
  • newlisp 监控Linux进程

    千次阅读 2013-11-16 16:09:38
    本节尝试将监控进程的方式交给调用者。主要有两个原因:1. 调用者传递判定代码,这样可以根据不同的平台进行变化,比如windows肯定没有ps -def 命令。这样可以适应更多的情况2. ps -def | grep ***的方式,在newlisp...
  • windows ddk驱动开发,编写一个文件监控程序.zip 用vc++开发的windows驱动程序,用来实现监视文件操作 在sys的IRP_MJ_CREATE和IRP_MJ_CLOSE中调用exe,给exe传递两个参数:1)进程名,2)文件PATH,传递完后: 传递进程名和...
  • Windows NT Kernel是单人多任务的OS,OS Kernel的功能无外乎是“承上启下”即驱动硬件、为上层应用程序提供系统调用、内存管理、FS管理、进程管理等,所以Linux的进程、线程机制和Windows有一些区别,我说的是原理。...
  • 进程欺骗实践

    2020-12-26 16:42:12
    项目介绍 ...Windows API调用"CreateProcess"允许用户传入一个用于分配父PID的参数,这意味着当恶意进程从实际执行的父进程创建时,它可以使用不同的父进程。 项目地址 https://github.com/Al1ex/Select
  • 进程遍历创建进程快照遍历首次进程遍历下个进程API调用链 恶意代码的包括计算机病毒、蠕虫、木马、后门、流氓软件、Exploit等等。 恶意代码常见功能技术如下:进程遍历,文件遍历,按键记录,后门,桌面截屏,文件...
  • 运维监控程序中经常需要根据一个进程号pid去监控实时的cpu和内存占用,以下整理了一个C++实现的简单例子,并封装为方便跨平台调用的函数 代码 #include <iostream> #include <thread> #include <...
  • 运维监控程序中经常需要根据一个进程号pid去监控实时的cpu和内存占用,以下整理了一个C++实现的简单例子,并封装为方便跨平台调用的函数代码#include <iostream> #include <thread> #include <chrono...
  • ProcessMonitor是Windows系统下的高级监视工具,提供一种方式来监控注册表、文件系统、网络、进程和线程行为。 通过Filter-Filter打开过滤菜单,过滤文件行为 查找PID、针对某些特定的函数过滤,比如CreateFile、...
  • 课题设计就是模拟Windows任务管理器,开发的一个Windows进程管理软件。主要设计的是一个基于窗体的C#程序,在主对话框上面放置了一个标签控件,并创建了应用程序、进程和性能三个页面,标签控件用于选择并显示页面。...
  • 恶意软件检测:通过监控主机中正在运行进程的行为来区分是否为恶意软件。 传统恶意软件检测方法:使用从windows API调用中提供的信息。数据挖掘,分类模型:Naive Bayes, SVM, Decision Tree 。 相关研究方法 1....
  • 调试windows消息

    千次阅读 2013-08-16 02:07:18
    spy->message->windows->windows finder tool,拖动焦距图标到想监视的指定窗口,定好消息格式,重定向到日志文件,最小化到后台运行。一系列操作完成基本的监控功能。 需要注意的是,spy++的消息顺序可能被程序中的...
  • 搭建Cacti监控

    2013-10-22 11:34:32
    Cacti是一款使用PHP语言开打的性能与流量监测工具,监测的对象可以是linux或windows服务器,也可以是路由器,交换机等网络设备,主要基于SNMP(简单网络管理协议)搜集CPU占用,内存占用,运行进程数,磁盘空间,网卡...
  • Procmon监控软件使用教程

    万次阅读 2018-10-10 16:46:56
    Procmon是微软出品用于监视Windows系统里程序的运行情况,监视内容包括该程序对注册表的读写、对文件的读写、网络的连接、进程和线程的调用情况,procmon 是一款超强的系统监视软件。 下载完成之后,直接启动...
  • Procmon是微软出品用于监视Windows系统里程序的运行情况,监视内容包括该程序对注册表的读写、对文件的读写、网络的连接、进程和线程的调用情况,procmon 是一款超强的系统监视软件。 官网直达: ...
  • 目前windows下注入dll的技术大体上就是两种 1:...这里提供一个巧妙的方法能够利用目标进程(确切地说是线程) 自己主动调用LoadLibrary装载dll. <br />我们想一想,windows下vc调试器可以调试正
  • Cacti是一款用PHP开发的性能与流量监测工具,监测对象可以使Linux或Windows服务器,也可以是路由器、交换机等网络设备,主要基于SNMP来搜集CPU占用、内存使用、运行进程数、磁盘空间、网卡流量等各种数据。...
  • 常规计数器 收集操作系统服务器的服务器性能信息,包括Processor、磁盘、网络、内存 Processor 处理器 1.1 % Processor Time指处理器用来执行非闲置线程时间的...当调用 Windows 系统服务时,此服务经常在特权模...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 146
精华内容 58
关键字:

windows进程调用监控