Code Analysis for connecting processes and ports under Win2K

Source: Internet
Author: User

Associating processes and ports is a very useful function. You can clearly know which programs are using which ports are helpful for trojan detection and removal. However, although we can use the task manager to browse the process list and use Netstat to view the port usage, no command can be directly associated with the process and port WinXP to add the new NetStat function, allows you to directly view the port Process status). If you go out to a famous software Fport, it can display all the current ports and their processes. However, this software does not disclose source code, I have developed a similar tool based on the reverse engineering of this software. I will discuss its principles here.
When I got Fport, I performed API analysis on it and found that in addition to some basic APIs, it also called NTDLL. several undisclosed dll APIs, such as NtQuerySystemInfomation and NtQueryInfomationProcess, intuitively tell me that the key should be in these two functions, especially the former. To understand the running mechanism of Fport, we should first review what SOCKET. SOCKET is? Its Chinese name is called a set interface. However, the so-called SOCKET data structure is actually a 32-bit unsigned integer that is 16 bits in UNIX ), in Windows, it is actually a file handle. Is SOCKET a file? Strange? When the operating system is implemented at the underlying layer, the file concept is often used to complete some basic functions). In this case, the problem becomes clear. If we can enumerate all the handles of the system, if the property is SOCKET, can the Fport function be completed? Now you should think about why Fport needs to call the NtQuerySystemInfomation API. In fact, the NtQuerySystemInfomation function provides a simple way to get all the HANDLE of the system. Let's first look at the prototype of this function:
DWORD NtQuerySystemInformation DWORD dwRecordType,
PDWORD pdwHandleList,
DWORD dwNumBytes,
PDWORD pdwNumBytesRet );
The NtQuerySystemInformation function has four parameters. The first parameter is dwRecordType. This parameter specifies the system information type we are querying. to query the HANDLE list, we define a constant # define NT_HANDLE_LIST 16, which is obtained by data query. If anyone has more detailed information, please share it with me). The second parameter is a pointer, this pointer is used to return the system handle list. before calling the NtQuerySystemInformation function, you must allocate enough memory for this pointer; otherwise, the function call will fail; the third parameter specifies the size of the memory space allocated for HandleList, in bytes. The fourth parameter is the size of HandleList returned by NtQuerySystemInformation. If the NtQuerySystemInformation function is called successfully, the return value is 0, otherwise, you can use GetLastError to obtain detailed error codes. .
Once the NtQuerySystemInformation function is called successfully, all the handles in the system will be stored in the first 32-digit number pointed by pdwHandleList to the memory space, it is the number of handles contained in the buf, followed by the sequential handle pointer pHandleInfo, pointing to the HANDLEINFO structure:
Typedef struct _ HandleInfo
{
USHORT dwPid;
USHORT CreatorBackTraceIndex;
BYTEObjType;
BYTEHandleAttributes;
USHORT HndlOffset;
DWORD dwKeObject;
ULONG GrantedAccess;
} HANDLEINFO, * PHANDLEINFO;
We can see this structure in our hearts. The handle information includes the PID of the process to which the handle belongs, so that we can associate the process with the SOCKET. However, there are various handles in NT: Process Handle, Token handle, file handle, window handle ...... How can we determine whether a handle is SOCKET? This depends on the ObjType attribute in the HANDLEINFO structure. After analysis, we find that the SOCKET handle type value is 0x1A. Therefore, we can retrieve all the handles with the SOCKET handle type 0x1A, perform the getsockname operation to obtain the corresponding list of processes/ports. Otherwise, you must know that all the handles we get belong to other processes. In NT, according to the process protection principle, A process cannot directly obtain information about other processes, especially the handle. The value of the same handle in different processes is the same, we must also perform a conversion to convert the handles of other processes to the handles of this process. This conversion can be completed by simply calling the DuplicateHandle function:
DuplicateHandlehSourceProc,
HANDLE) pHandleInfo-> HndlOffset,
HCurrentProc,
& HMyHandle,
STANDARD_RIGHTS_REQUIRED,
True,
0 );
Then we can use functions such as getsockname and getsockopt to obtain various SOCKET attributes. What puzzles me is that Fport does not call getsockname, there should be a simpler way to get the various attributes of the SOCKET handle. It seems that I have a superficial understanding of the SOCKET handle)
Sockaddr_in name = {0 };
Name. sin_family = AF_INET;
Int namelen = sizeofsockaddr_in );
SOCKET s = SOCKET) hMyHandle;
Char szSockType [6] [6] = {"NUL", "TCP", "UDP", "RAW", "RDM", "SEQ "};
IRet = getsockname s, sockaddr *) & name, & namelen );
If iRet! = SOCKET_ERROR)
{
Int sockType = 0;
Int optlen = 4;
IRet = getsockopts, SOL_SOCKET, SO_TYPE, char *) & sockType, & optlen );
Printf "PID = % 4d PORT = % 5d % s \ n", pHandleInfo-> dwPid,
Ntohs name. sin_port), szSockType [sockType]);
}
So far, the process and Port Association work has been basically completed, but there are still some shortcomings, first of all, this software is not as capable of viewing the system process as the famous 8 # process like Fport) SOCKET, error code is 5 access denied), a simple solution is to make your own service, so that you have access to the Local System process, however, it seems that Fport does not do this. This is a question. Secondly, due to my superficial understanding of the HANDLE attribute, sometimes there will be false positives or false negatives, even if there is no false positives, the efficiency of getsockname for all the handles whose attributes are 0x1A is also slightly lower. There should be a better solution, which is suspect 2. Finally, fport does not call the socket function to obtain the socket attribute. This indicates that there is a simpler and more direct way to obtain port and protocol information from the SOCKET handle. Unfortunately, I don't know, this is suspect 3. However, the Gport I wrote can be run under a non-administrator user of Win2K. At this time, only the ports of all processes of the user can be obtained, this is probably not a function provided by Fport.

Attached Gport code, Gport beta and code files can be downloaded on my homepage at: http://shotgun.patching.net/Gport.zip
Appendix: Gport. cpp
# Include
# Include
# Include
# Include
# Pragma comment lib, "ws2_32.lib ")
// NtQuerySystemInformation record type 16
# Define NT_HANDLE_LIST 16
# Define OBJECT_TYPE_SOCKET 0x1A
# Define MAX_HANDLE_LIST_BUF 0x200000
// Define the HanleInfo Data Structure
Typedef struct _ HandleInfo
{
USHORT dwPid;
USHORT CreatorBackTraceIndex;
BYTE ObjType;
BYTE HandleAttributes;
USHORT HndlOffset;
DWORD dwKeObject;
ULONG GrantedAccess;
} HANDLEINFO, * PHANDLEINFO;
// Declare NtQuerySystemInformation) Function
Typedef dword callback * NTQUERYSYSTEMINformATION) DWORD, PDWORD, DWORD, PVOID );
NTQUERYSYSTEMINformATION NtQuerySystemInformation;
// Determine the SOCKET type array
Char szSockType [6] [6] = {"NUL", "TCP", "UDP", "RAW", "RDM", "SEQ "};
//
// RaisePrivleges) function is used to raise the privilege of this process.
//
Bool RaisePrivleges HANDLE hToken, char * pPriv)
{
TOKEN_PRIVILEGES tkp;
If! LookupPrivilegevalue NULL, pPriv, & tkp. Privileges [0]. Luid ))
{
Printf "LookupPrivilegevalue Error: % d \ n", GetLastError ));
Return false;
}
Tkp. PrivilegeCount = 1;
Tkp. Privileges [0]. Attributes | = SE_PRIVILEGE_ENABLED;
Int iRet = AdjustTokenPrivileges hToken,
False,
& Tkp,
0,
PTOKEN_PRIVILEGES) NULL,
0 );
If iRet = NULL) // The AdjustTokenPrivileges function fails to be called.
{
Printf "AdjustTokenPrivileges Error: % d \ n", GetLastError ));
Return false;
}
Else // AdjustTokenPrivileges call successful
{// Use GetLastError) to obtain the returned value
IRet = GetLastError );
Switch iRet)
{
Case ERROR_NOT_ALL_ASSIGNED: // no privileges are assigned.
Printf "AdjustTokenPrivileges ERROR_NOT_ALL_ASSIGNED \ n ");
Return false;
Case ERROR_SUCCESS: // All privileges are successfully assigned.
Return true;
Default: // unknown error
Printf "AdjustTokenPrivileges Unknow Error: % d \ n", iRet );
Return false;
}
}
} // End of RaisePrivleges
//
// AdjustDacl is used to adjust the DACL of the target process.
//
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 SetEntriesInAcl1, & ea, 0, & pdacl )! = ERROR_SUCCESS)
Printf "SetEntriesInAcl Error: % d", GetLastError ));
If SetSecurityInfohProcess,
SE_KERNEL_OBJECT,
DACL_SECURITY_INformATION,
0, 0, pdacl, 0 )! = ERROR_SUCCESS)
Printf "SetSecurityInfo Error: % d", GetLastError ));
LocalFreepdacl );
} // End of AdjustDacl
Int main)
{
Printf "\ t = * = GPort Beta1 Shotgun@xici.net) = * = \ n ");
Int iRet;
WSADATA wsaData;
IRet = WSAStartup MAKEWORD1, 1), & wsaData );
If iRet)
Printf "WSAStartup Error: % d \ n", GetLastError ));
HANDLE hCurrentProc = GetCurrentProcess );
HANDLE hToken;
If! OpenProcessToken hcur1_proc,
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
& HToken ))
Printf "OpenProcessToken Error: % d \ n", GetLastError ));
Else
{
If! RaisePrivleges hToken, SE_DEBUG_NAME ))
Printf "SetPrivleges SE_DEBUG_NAME Error: % d \ n", GetLastError ));
}
If hToken)
CloseHandle hToken );
HMODULE hNtdll = NULL;
HNtdll = LoadLibrary "ntdll. dll ");
If! HNtdll)
{
Printf "LoadLibrary NTDLL. DLL) Error: % d \ n", GetLastError ));
Return false;
}
NtQuerySystemInformation = NTQUERYSYSTEMINformATION)
GetProcAddress hNtdll, "NtQuerySystemInformation ");
If! NtQuerySystemInformation)
{
Printf "GetProcess NtQuerySystemInformation) Error: % d \ n", GetLastError ));
Return false;
}
DWORD dwNumBytes = MAX_HANDLE_LIST_BUF;
PDWORD pdwHandleList = PDWORD) malloc dwNumBytes );
If! PdwHandleList)
{
Printf "Malloc for Handle List Error: % d \ n", GetLastError ));
Return false;
}
DWORD dwNumBytesRet = 0;
IRet = * NtQuerySystemInformation) NT_HANDLE_LIST,
PdwHandleList,
DwNumBytes,
& DwNumBytesRet );
DWORD dwNumEntries;
PHANDLEINFO pHandleInfo;
If iRet)
{
Printf "NtQuerySystemInformation return % d, Error: % d \ n ",
DwNumBytesRet,
GetLastError ));
}
Else
{
HANDLE hProc;
DwNumEntries = pdwHandleList [0];
PHandleInfo = PHANDLEINFO) pdwHandleList + 1 );
For DWORD I = 0; I <dwNumEntries; I ++)
{
If pHandleInfo-> ObjType = OBJECT_TYPE_SOCKET)
& PHandleInfo-> dwPid ))
{
HProc = OpenProcessWRITE_DAC,
False,
PHandleInfo-> dwPid );
If hProc)
{
AdjustDacl hProc );
CloseHandle hProc );
}
Else
Printf "OpenProcessWRITE_DAC) % d Error: % d \ n ",
PHandleInfo-> dwPid,
GetLastError ));
HANDLE hMyHandle = NULL;
HProc = OpenProcessPROCESS_DUP_HANDLE,
True,
PHandleInfo-> dwPid );
If hProc)
{
DuplicateHandlehProc,
HANDLE) pHandleInfo-> HndlOffset,
HCurrentProc,
& HMyHandle,
STANDARD_RIGHTS_REQUIRED,
True,
0 );
CloseHandle hProc );
}
Else
Printf "OpenProcess % d Error: % d \ n ",
PHandleInfo-> dwPid,
GetLastError ));
If! HMyHandle)
{
Sleep 0 );
// Printf "DuplicateHandle PID = % 4d HANDLE: % 4d Error: % d \ n ",
// PHandleInfo-> dwPid, pHandleInfo-> HndlOffset, GetLastError ));
}
Else
{
Sockaddr_in name = {0 };
Name. sin_family = AF_INET;
Int namelen = sizeofsockaddr_in );
SOCKET s = SOCKET) hMyHandle;
IRet = getsockname s,
Sockaddr *) & name,
& Namelen );
If iRet! = SOCKET_ERROR)
{
Int sockType = 0;
Int optlen = 4;
IRet = getsockopts,
SOL_SOCKET,
SO_TYPE,
Char *) & sockType,
& Optlen );
Printf "PID = % 4d PORT = % 5d % s \ n ",
PHandleInfo-> dwPid,
Ntohs name. sin_port ),
SzSockType [sockType]);
}
}
}
PHandleInfo ++;
}
}
If pdwHandleList)
Free pdwHandleList );
If hCurrentProc)
CloseHandle hCurrentProc );
Return 0;
}


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.