zoukankan      html  css  js  c++  java
  • Sysinternals工具—pipelist分析

    这段时间用到了SysinternalsSuite中的pipelist工具来查看使用的NamedPipe是什么,用过之后就想自己了解下它是怎样工作,于是就反汇编一下,没想到却意外的简单。

    下面是反汇编出的伪代码

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      int result; // eax@2
      HMODULE v4; // eax@3
      HMODULE v5; // eax@6
      HANDLE hHandle; // ebp@9
      DWORD v7; // eax@10
      FILE_DIRECTORY_INFORMATION *FileInformation; // edi@11
      int v9; // eax@12
      FILE_DIRECTORY_INFORMATION *i; // esi@13
      int v11; // [sp+34h] [bp-94Ch]@12
      int IoStatusBlock; // [sp+38h] [bp-948h]@12
      char v13; // [sp+40h] [bp-940h]@14
      char v14; // [sp+E0h] [bp-8A0h]@14
      __int16 v15[1024]; // [sp+180h] [bp-800h]@14
    
      LOBYTE(v11) = 1;
      printf("\nPipeList v1.01\n");
      printf("by Mark Russinovich\n");
      printf("http://www.sysinternals.com\n\n");
      if ( EulaAccept((LPARAM)"PipeList") )
      {
        v4 = GetModuleHandleA("ntdll.dll");
        pfnNtQueryDirectoryFile = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))GetProcAddress(v4, "NtQueryDirectoryFile");
        if ( !pfnNtQueryDirectoryFile )
        {
          printf("\nCould not find NtQueryDirectoryFile entry point in NTDLL.DLL\n");
          exit(1);
        }
        v5 = GetModuleHandleA("ntdll.dll");
        pfnRtlNtStatusToDosError = (int)GetProcAddress(v5, "RtlNtStatusToDosError");
        if ( !pfnRtlNtStatusToDosError )
        {
          printf("\nCould not find RtlNtStatusToDosError entry point in NTDLL.DLL\n");
          exit(1);
        }
        hHandle = CreateFileA("\\\\.\\Pipe\\", 0x80000000u, 7u, 0, 3u, 0, 0);
        if ( hHandle == (HANDLE)-1 )
        {
          v7 = GetLastError();
          sub_401050((int)"Pipe error", v7);
          result = 0;
        }
        else
        {
          printf("%-40s%14s%20s\n", "Pipe Name", "Instances", "Max Instances");
          printf("%-40s%14s%20s\n", "---------", "---------", "-------------");
          FileInformation = (FILE_DIRECTORY_INFORMATION *)malloc(0x1000u);
          while ( 1 )
          {
            v9 = pfnNtQueryDirectoryFile(hHandle, 0, 0, 0, &IoStatusBlock, FileInformation, 4096, 1, 0, 0, v11);
            if ( v9 < 0 )
              break;
            for ( i = FileInformation; ; i = (FILE_DIRECTORY_INFORMATION *)((char *)i + i->NextEntryOffset) )
            {
              swprintf((wchar_t *)&v14, (size_t)L"%d   ", (const wchar_t *)i->EndOfFile.LowPart);
              swprintf((wchar_t *)&v13, (size_t)L"%d      ", (const wchar_t *)i->AllocationSize.LowPart);
              wcsncpy((wchar_t *)v15, i->FileName, i->FileNameLength >> 1);
              v15[i->FileNameLength >> 1] = 0;
              wprintf(L"%-40s%14s%20s\n", v15, &v14, &v13);
              if ( !i->NextEntryOffset )
                break;
            }
            LOBYTE(v11) = 0;
          }
          if ( v9 != -2147483642 )
            sub_401000((int)"Error querying pipe directory:", v9);
          free(FileInformation);
          CloseHandle(hHandle);
          result = 0;
        }
      }
      else
      {
        result = 1;
      }
      return result;
    }
    

    Named Pipes是一种简单的进程间通信(IPC)机制。可在同一台计算机的不同进程之间,或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信。命名管道是围绕Windows文件系统设计的一种机制,采用“命名管道文件系统”(Named Pipe File System,NPFS)接口,客户机和服务器应用可利用标准的Win32文件系统相关API函数。

    命名管道的标识采用UNC格式的进行命名的:

    \\server\pipe\[path]name

    从上面反汇编出代码可以看出,它是使用NtQueryDirectoryFile来查询\\.\pipe\下的File Information。查看NtQueryDirectoryFile的声明(在Window NT 2000 Native API这文档中可以找到,叫做ZwQueryDirectoryFile)

    ZwQueryDirectoryFile retrieves information about the contents of a directory.
    NTSYSAPI
    NTSTATUS
    NTAPI
    ZwQueryDirectoryFile(
    	IN HANDLE FileHandle,
    	IN HANDLE Event OPTIONAL,
    	IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
    	IN PVOID ApcContext OPTIONAL,
    	OUT PIO_STATUS_BLOCK IoStatusBlock,
    	OUT PVOID FileInformation,
    	IN ULONG FileInformationLength,
    	IN FILE_INFORMATION_CLASS FileInformationClass,
    	IN BOOLEAN ReturnSingleEntry,
    	IN PUNICODE_STRING FileName OPTIONAL,
    	IN BOOLEAN RestartScan
    );

    这个功能的关键在于:

    1、CreateFileA("\\\\.\\Pipe\\", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0);

    2、NtQueryDirectoryFile(hHandle, 0, 0, 0, &IoStatusBlock, FileInformation, 4096, FileDirectoryInformation /*=1*/, 0, 0, v11);

    当然除了枚举本地计算机的Named Pipes,也可以枚举其他机器的,只要把对应的服务器名加到路径中,如\ \ m y s e r v e r \ pipe \ ,这样可枚举出服务器\ \ m y s e r v e r 的Named Pipes,当然要有权限才行。

  • 相关阅读:
    使用JdbcTemplate访问数据库
    解决为什么每次打开Eclipse新的workspace需要更新nexus-maven-repository-index问题
    java内存设置
    Eclipse如何解决启动慢
    eclipse的包的加减号展开方式
    maven总结5
    maven总结4
    maven总结3
    maven总结2
    maven总结1
  • 原文地址:https://www.cnblogs.com/Quincy/p/1746816.html
Copyright © 2011-2022 走看看