- 浏览: 258775 次
- 性别:
- 来自: 深圳
最新评论
-
whizkid:
[img] private void enableNdefEx ...
android通过NFC读写数据 -
zhangminglife:
您好!不错,最近正在弄这个东西,能否把demo发给我一份谢谢了 ...
SSL双向认证java实现(转) -
water卡:
android如何调用显示和隐藏系统默认的输入法 -
water卡:
android如何调用显示和隐藏系统默认的输入法 -
sjp524617477:
good
生成android使用的BKS证书
本人对几种穿透防火墙技术
以下是本人对几种穿透技术学习笔记和一点自己的想法:
防火墙是基本网络安全策略之一,它可以阻止不信任的外部网络用户对内部网络用户的访问,如果外网用户同内网用户之间的通信由外网用户发起,通信通常会被防火墙阻断,尤其是对TCP连接敏感,因此我们如果才能保证正常的数据传输呢,特别是非主动连接情况下,怎么保证连接和数据通信的安全稳定性呢?
人们使用穿透防火墙技术(常用):
1.反向连接------>由内网用户发起的连接请求,在防火墙规则下,是允许安全的
2.HTTP隧道技术------>就是吧所有要传送的数据全部封装到Http协议里进行传送
3.端口复用技术------>也称端口劫持技术,。其原理主要是通过修改套接字属性来实现端口重绑定,这种技术在接受外来数据包的时候通常是由主机进行转化,然后用户接受的
4.共享DNS套接字句柄技术------>这主要是使用了dns服务是所有防火墙免疫的功能来实现的,同时DNS套接字句柄技术最大的特点还是才用UDP通信的(后面将通过引用ZwelL的一些代码来说明)
今天我们主要介绍几种组合的穿透防火墙技术
1.反向连接与HTTP隧道技术
反向连接是由内部网络用户主动发起的连接请求,在防火墙规则下是合法的,假设现在有程序S,C
S---->代理------>C 服务端程序s由内部网络发起对C连接请求,通过代理服务器获取相应的IP和端口
<-----(ip,port) 建立socket套接字,设置端口号:80 80 ------------- ============ ===========当C/S建立连接后,进行数据传送的时候,这个时候我们使用HTTP隧道技术,将所有要传输的数据头经过HTTP协议封装,加个HTTP请求头:"Get/HTTP/1.0\r\nUse-Agent:Molliza/1.22\r\nAccept:*/*\r\n\r\n",同时在数据后面加上$$标记,用户在接受到数据的时程序根据预先设定的标记找到数据段,去除HTTP请求头,再把数据交由程序进行处理 采用反向连接+HTTP隧道技术也存在很多局限性 1.采用的端口号为80 2.利用HTTP隧道传输数据需要对数据进行HTTP封装,在混乱的HTTP隧道不能完全保证数据的完整性和安全性,对数据的解封也是一些需要考虑的问题 3.采用数据采集工具和像IS那样的工具可以检测出来 4.防火墙不是傻子,所以规则由时候是不能由我们去改变的 如何可以的吗,我们希望是让S程序为我们自动做个第三方端口映射,而此时第三的稳定性成为了我们的.......... 2.共享DNS套接字句柄技术 这个技术大家在05的时候就应该有所闻了,那是ZwelL发表在安焦上的一篇“一种新的穿透防火墙技术”里面采用的就是利用了dns服务是UDP通信同时又是所有防火墙所不能拒绝的....... 该技术使用了win终端服务库所提供的API函数 大概的流程:
利用wstapi中提供的函数列举所有系统进程----->查找目标进程或目标服务进程----->记录保存目标进程的PID------>利用获取的PID得到套接字句柄---->创建套接字进行通信
============具体实现代码:以下引用ZwelL关于一种.....代码==================
/*++
Made By ZwelL
zwell@sohu.com
2005.4.12
--*/
#include <winsock2.h>
#include <stdio.h>
#include <wtsapi32.h>
#pragma comment(lib, "ws2_32")
#pragma comment(lib, "wtsapi32")
#define NT_SUCCESS(status) ((NTSTATUS)(status)>=0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
typedef LONG NTSTATUS;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef ULONG (WINAPI *ZWQUERYSYSTEMINFORMATION)(ULONG, PVOID, ULONG, PULONG);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
BOOL LocateNtdllEntry ( void )
{
BOOL ret = FALSE;
char NTDLL_DLL[] = "ntdll.dll";
HMODULE ntdll_dll = NULL;
if ( ( ntdll_dll = GetModuleHandle( NTDLL_DLL ) ) == NULL )
{
printf( "GetModuleHandle() failed");
return( FALSE );
}
if ( !( ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( ntdll_dll, "ZwQuerySystemInformation" ) ) )
{
goto LocateNtdllEntry_exit;
}
ret = TRUE;
LocateNtdllEntry_exit:
if ( FALSE == ret )
{
printf( "GetProcAddress() failed");
}
ntdll_dll = NULL;
return( ret );
}
/*++
This routine is used to get a process's username from it's SID
--*/
BOOL GetUserNameFromSid(PSID pUserSid, char *szUserName)
{
// sanity checks and default value
if (pUserSid == NULL)
return false;
strcpy(szUserName, "?");
SID_NAME_USE snu;
TCHAR szUser[_MAX_PATH];
DWORD chUser = _MAX_PATH;
PDWORD pcchUser = &chUser;
TCHAR szDomain[_MAX_PATH];
DWORD chDomain = _MAX_PATH;
PDWORD pcchDomain = &chDomain;
// Retrieve user name and domain name based on user's SID.
if (
::LookupAccountSid(
NULL,
pUserSid,
szUser,
pcchUser,
szDomain,
pcchDomain,
&snu
)
)
{
wsprintf(szUserName, "%s", szUser);
}
else
{
return false;
}
return true;
}
/*++
This routine is used to get the DNS process's Id
Here, I use WTSEnumerateProcesses to get process user Sid,
and then get the process user name. Beacause as it's a "NETWORK SERVICE",
we cann't use OpenProcessToken to catch the DNS process's token information,
even if we has the privilege in catching the SYSTEM's.
--*/
DWORD GetDNSProcessId()
{
PWTS_PROCESS_INFO pProcessInfo = NULL;
DWORD ProcessCount = 0;
char szUserName[255];
DWORD Id = -1;
if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pProcessInfo, &ProcessCount))
{
// dump each process description
for (DWORD CurrentProcess = 0; CurrentProcess < ProcessCount; CurrentProcess++)
{
if( strcmp(pProcessInfo[CurrentProcess].pProcessName, "svchost.exe") == 0 )
{
GetUserNameFromSid(pProcessInfo[CurrentProcess].pUserSid, szUserName);
if( strcmp(szUserName, "NETWORK SERVICE") == 0)
{
Id = pProcessInfo[CurrentProcess].ProcessId;
break;
}
}
}
WTSFreeMemory(pProcessInfo);
}
return Id;
}
/*++
This doesn't work as we know, sign...
but you can use the routine for other useing...
--*/
/*
BOOL GetProcessUserFromId(char *szAccountName, DWORD PID)
{
HANDLE hProcess = NULL,
hAccessToken = NULL;
TCHAR InfoBuffer[1000], szDomainName[200];
PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
DWORD dwInfoBufferSize,dwAccountSize = 200, dwDomainSize = 200;
SID_NAME_USE snu;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PID);
if(hProcess == NULL)
{
printf("OpenProcess wrong");
CloseHandle(hProcess);
return false;
}
if(0 == OpenProcessToken(hProcess,TOKEN_QUERY,&hAccessToken))
{
printf("OpenProcessToken wrong:%08x", GetLastError());
return false;
}
GetTokenInformation(hAccessToken,TokenUser,InfoBuffer,
1000, &dwInfoBufferSize);
LookupAccountSid(NULL, pTokenUser->User.Sid, szAccountName,
&dwAccountSize,szDomainName, &dwDomainSize, &snu);
if(hProcess)
CloseHandle(hProcess);
if(hAccessToken)
CloseHandle(hAccessToken);
return true;
}*/
/*++
Now, it is the most important stuff... ^_^
--*/
SOCKET GetSocketFromId (DWORD PID)
{
NTSTATUS status;
PVOID buf = NULL;
ULONG size = 1;
ULONG NumOfHandle = 0;
ULONG i;
PSYSTEM_HANDLE_INFORMATION h_info = NULL;
HANDLE sock = NULL;
DWORD n;
buf=malloc(0x1000);
if(buf == NULL)
{
printf("malloc wrong\n");
return NULL;
}
status = ZwQuerySystemInformation( 0x10, buf, 0x1000, &n );
if(STATUS_INFO_LENGTH_MISMATCH == status)
{
free(buf);
buf=malloc(n);
if(buf == NULL)
{
printf("malloc wrong\n");
return NULL;
}
status = ZwQuerySystemInformation( 0x10, buf, n, NULL);
}
else
{
printf("ZwQuerySystemInformation wrong\n");
return NULL;
}
NumOfHandle = *(ULONG*)buf;
h_info = ( PSYSTEM_HANDLE_INFORMATION )((ULONG)buf+4);
for(i = 0; i<NumOfHandle ;i++)
{
try
{
if( ( h_info[i].ProcessId == PID ) && ( h_info[i].ObjectTypeNumber == 0x1c )
&& (h_info[i].Handle!=0x2c) // I don't know why if the Handle equal to 0x2c, in my test, it stops at getsockname()
// So I jump over this situation...
// May be it's different in your system,
) //wind2000 is 0x1a
{
//printf("Handle:0x%x Type:%08x\n",h_info[i].Handle, h_info[i].ObjectTypeNumber);
if( 0 == DuplicateHandle(
OpenProcess(PROCESS_ALL_ACCESS, TRUE, PID),
(HANDLE)h_info[i].Handle,
GetCurrentProcess(),
&sock,
STANDARD_RIGHTS_REQUIRED,
true,
DUPLICATE_SAME_ACCESS)
)
{
printf("DuplicateHandle wrong:%8x", GetLastError());
continue;
}
//printf("DuplicateHandle ok\n");
sockaddr_in name = {0};
name.sin_family = AF_INET;
int namelen = sizeof(sockaddr_in);
getsockname( (SOCKET)sock, (sockaddr*)&name, &namelen );
//printf("PORT=%5d\n", ntohs( name.sin_port ));
if(ntohs(name.sin_port)>0) // if port > 0, then we can use it
break;
}
}
catch(...)
{
continue;
}
}
if ( buf != NULL )
{
free( buf );
}
return (SOCKET)sock;
}
/*++
This is not required...
--*/
BOOL EnablePrivilege (PCSTR name)
{
HANDLE hToken;
BOOL rv;
TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
LookupPrivilegeValue (
0,
name,
&priv.Privileges[0].Luid
);
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
OpenProcessToken(
GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
&hToken
);
AdjustTokenPrivileges (
hToken,
FALSE,
&priv,
sizeof priv,
0,
0
);
rv = GetLastError () == ERROR_SUCCESS;
CloseHandle (hToken);
return rv;
}
void main()
{
WSADATA wsaData;
char testbuf[255];
SOCKET sock;
sockaddr_in RecvAddr;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");
if(!LocateNtdllEntry())
return;
if(!EnablePrivilege (SE_DEBUG_NAME))
{
printf("EnablePrivilege wrong\n");
return;
}
sock = GetSocketFromId(GetDNSProcessId());
if( sock==NULL)
{
printf("GetSocketFromId wrong\n");
return;
}
//Change there value...
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(5555);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(SOCKET_ERROR == sendto(sock,
"test",
5,
0,
(SOCKADDR *) &RecvAddr,
sizeof(RecvAddr)))
{
printf("sendto wrong:%d\n", WSAGetLastError());
}
else
{
printf("send ok... Have fun, right? ^_^\n");
}
getchar();
//WSACleanup();
return;
}
很早以前我就有这个想法了,只是一直没有去实现.在上面的代码中,
因为要找出DNS进程句柄,而svchost.exe又有多个,所以以用户名来进行判断,本来是用OpenProcessToken,
但是怎么也不行,所以换个方法.用到了wtsapi32库函数.
再用下面的代码测试:
/*++
UdpReceiver
--*/
#include <stdio.h>
#include "winsock2.h"
#pragma comment(lib, "ws2_32")
void main()
{
WSADATA wsaData;
SOCKET RecvSocket;
sockaddr_in RecvAddr;
int Port = 5555;
char RecvBuf[1024];
int BufLen = 1024;
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
//-----------------------------------------------
// Initialize Winsock
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr));
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
printf("Receiving datagrams...\n");
while(1)
{
recvfrom(RecvSocket,
RecvBuf,
BufLen,
0,
(SOCKADDR *)&SenderAddr,
&SenderAddrSize);
printf("%s\n", RecvBuf);
}
//-----------------------------------------------
// Close the socket when finished receiving datagrams
printf("Finished receiving. Closing socket.\n");
closesocket(RecvSocket);
//-----------------------------------------------
// Clean up and exit.
printf("Exiting.\n");
WSACleanup();
return;
}
===========================================================
测试步骤:
1. 在一台机器上执行UdpReceiver,
2. 在安装防火墙的机器上执行第一个程序.
以上就是我的学习笔记了,希望对你有帮助,目前正在组合一些大牛们的想法,正在思考一种新的穿透防火墙的数据传输技术
以下是本人对几种穿透技术学习笔记和一点自己的想法:
防火墙是基本网络安全策略之一,它可以阻止不信任的外部网络用户对内部网络用户的访问,如果外网用户同内网用户之间的通信由外网用户发起,通信通常会被防火墙阻断,尤其是对TCP连接敏感,因此我们如果才能保证正常的数据传输呢,特别是非主动连接情况下,怎么保证连接和数据通信的安全稳定性呢?
人们使用穿透防火墙技术(常用):
1.反向连接------>由内网用户发起的连接请求,在防火墙规则下,是允许安全的
2.HTTP隧道技术------>就是吧所有要传送的数据全部封装到Http协议里进行传送
3.端口复用技术------>也称端口劫持技术,。其原理主要是通过修改套接字属性来实现端口重绑定,这种技术在接受外来数据包的时候通常是由主机进行转化,然后用户接受的
4.共享DNS套接字句柄技术------>这主要是使用了dns服务是所有防火墙免疫的功能来实现的,同时DNS套接字句柄技术最大的特点还是才用UDP通信的(后面将通过引用ZwelL的一些代码来说明)
今天我们主要介绍几种组合的穿透防火墙技术
1.反向连接与HTTP隧道技术
反向连接是由内部网络用户主动发起的连接请求,在防火墙规则下是合法的,假设现在有程序S,C
S---->代理------>C 服务端程序s由内部网络发起对C连接请求,通过代理服务器获取相应的IP和端口
<-----(ip,port) 建立socket套接字,设置端口号:80 80 ------------- ============ ===========当C/S建立连接后,进行数据传送的时候,这个时候我们使用HTTP隧道技术,将所有要传输的数据头经过HTTP协议封装,加个HTTP请求头:"Get/HTTP/1.0\r\nUse-Agent:Molliza/1.22\r\nAccept:*/*\r\n\r\n",同时在数据后面加上$$标记,用户在接受到数据的时程序根据预先设定的标记找到数据段,去除HTTP请求头,再把数据交由程序进行处理 采用反向连接+HTTP隧道技术也存在很多局限性 1.采用的端口号为80 2.利用HTTP隧道传输数据需要对数据进行HTTP封装,在混乱的HTTP隧道不能完全保证数据的完整性和安全性,对数据的解封也是一些需要考虑的问题 3.采用数据采集工具和像IS那样的工具可以检测出来 4.防火墙不是傻子,所以规则由时候是不能由我们去改变的 如何可以的吗,我们希望是让S程序为我们自动做个第三方端口映射,而此时第三的稳定性成为了我们的.......... 2.共享DNS套接字句柄技术 这个技术大家在05的时候就应该有所闻了,那是ZwelL发表在安焦上的一篇“一种新的穿透防火墙技术”里面采用的就是利用了dns服务是UDP通信同时又是所有防火墙所不能拒绝的....... 该技术使用了win终端服务库所提供的API函数 大概的流程:
利用wstapi中提供的函数列举所有系统进程----->查找目标进程或目标服务进程----->记录保存目标进程的PID------>利用获取的PID得到套接字句柄---->创建套接字进行通信
============具体实现代码:以下引用ZwelL关于一种.....代码==================
/*++
Made By ZwelL
zwell@sohu.com
2005.4.12
--*/
#include <winsock2.h>
#include <stdio.h>
#include <wtsapi32.h>
#pragma comment(lib, "ws2_32")
#pragma comment(lib, "wtsapi32")
#define NT_SUCCESS(status) ((NTSTATUS)(status)>=0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
typedef LONG NTSTATUS;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef ULONG (WINAPI *ZWQUERYSYSTEMINFORMATION)(ULONG, PVOID, ULONG, PULONG);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
BOOL LocateNtdllEntry ( void )
{
BOOL ret = FALSE;
char NTDLL_DLL[] = "ntdll.dll";
HMODULE ntdll_dll = NULL;
if ( ( ntdll_dll = GetModuleHandle( NTDLL_DLL ) ) == NULL )
{
printf( "GetModuleHandle() failed");
return( FALSE );
}
if ( !( ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( ntdll_dll, "ZwQuerySystemInformation" ) ) )
{
goto LocateNtdllEntry_exit;
}
ret = TRUE;
LocateNtdllEntry_exit:
if ( FALSE == ret )
{
printf( "GetProcAddress() failed");
}
ntdll_dll = NULL;
return( ret );
}
/*++
This routine is used to get a process's username from it's SID
--*/
BOOL GetUserNameFromSid(PSID pUserSid, char *szUserName)
{
// sanity checks and default value
if (pUserSid == NULL)
return false;
strcpy(szUserName, "?");
SID_NAME_USE snu;
TCHAR szUser[_MAX_PATH];
DWORD chUser = _MAX_PATH;
PDWORD pcchUser = &chUser;
TCHAR szDomain[_MAX_PATH];
DWORD chDomain = _MAX_PATH;
PDWORD pcchDomain = &chDomain;
// Retrieve user name and domain name based on user's SID.
if (
::LookupAccountSid(
NULL,
pUserSid,
szUser,
pcchUser,
szDomain,
pcchDomain,
&snu
)
)
{
wsprintf(szUserName, "%s", szUser);
}
else
{
return false;
}
return true;
}
/*++
This routine is used to get the DNS process's Id
Here, I use WTSEnumerateProcesses to get process user Sid,
and then get the process user name. Beacause as it's a "NETWORK SERVICE",
we cann't use OpenProcessToken to catch the DNS process's token information,
even if we has the privilege in catching the SYSTEM's.
--*/
DWORD GetDNSProcessId()
{
PWTS_PROCESS_INFO pProcessInfo = NULL;
DWORD ProcessCount = 0;
char szUserName[255];
DWORD Id = -1;
if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pProcessInfo, &ProcessCount))
{
// dump each process description
for (DWORD CurrentProcess = 0; CurrentProcess < ProcessCount; CurrentProcess++)
{
if( strcmp(pProcessInfo[CurrentProcess].pProcessName, "svchost.exe") == 0 )
{
GetUserNameFromSid(pProcessInfo[CurrentProcess].pUserSid, szUserName);
if( strcmp(szUserName, "NETWORK SERVICE") == 0)
{
Id = pProcessInfo[CurrentProcess].ProcessId;
break;
}
}
}
WTSFreeMemory(pProcessInfo);
}
return Id;
}
/*++
This doesn't work as we know, sign...
but you can use the routine for other useing...
--*/
/*
BOOL GetProcessUserFromId(char *szAccountName, DWORD PID)
{
HANDLE hProcess = NULL,
hAccessToken = NULL;
TCHAR InfoBuffer[1000], szDomainName[200];
PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
DWORD dwInfoBufferSize,dwAccountSize = 200, dwDomainSize = 200;
SID_NAME_USE snu;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PID);
if(hProcess == NULL)
{
printf("OpenProcess wrong");
CloseHandle(hProcess);
return false;
}
if(0 == OpenProcessToken(hProcess,TOKEN_QUERY,&hAccessToken))
{
printf("OpenProcessToken wrong:%08x", GetLastError());
return false;
}
GetTokenInformation(hAccessToken,TokenUser,InfoBuffer,
1000, &dwInfoBufferSize);
LookupAccountSid(NULL, pTokenUser->User.Sid, szAccountName,
&dwAccountSize,szDomainName, &dwDomainSize, &snu);
if(hProcess)
CloseHandle(hProcess);
if(hAccessToken)
CloseHandle(hAccessToken);
return true;
}*/
/*++
Now, it is the most important stuff... ^_^
--*/
SOCKET GetSocketFromId (DWORD PID)
{
NTSTATUS status;
PVOID buf = NULL;
ULONG size = 1;
ULONG NumOfHandle = 0;
ULONG i;
PSYSTEM_HANDLE_INFORMATION h_info = NULL;
HANDLE sock = NULL;
DWORD n;
buf=malloc(0x1000);
if(buf == NULL)
{
printf("malloc wrong\n");
return NULL;
}
status = ZwQuerySystemInformation( 0x10, buf, 0x1000, &n );
if(STATUS_INFO_LENGTH_MISMATCH == status)
{
free(buf);
buf=malloc(n);
if(buf == NULL)
{
printf("malloc wrong\n");
return NULL;
}
status = ZwQuerySystemInformation( 0x10, buf, n, NULL);
}
else
{
printf("ZwQuerySystemInformation wrong\n");
return NULL;
}
NumOfHandle = *(ULONG*)buf;
h_info = ( PSYSTEM_HANDLE_INFORMATION )((ULONG)buf+4);
for(i = 0; i<NumOfHandle ;i++)
{
try
{
if( ( h_info[i].ProcessId == PID ) && ( h_info[i].ObjectTypeNumber == 0x1c )
&& (h_info[i].Handle!=0x2c) // I don't know why if the Handle equal to 0x2c, in my test, it stops at getsockname()
// So I jump over this situation...
// May be it's different in your system,
) //wind2000 is 0x1a
{
//printf("Handle:0x%x Type:%08x\n",h_info[i].Handle, h_info[i].ObjectTypeNumber);
if( 0 == DuplicateHandle(
OpenProcess(PROCESS_ALL_ACCESS, TRUE, PID),
(HANDLE)h_info[i].Handle,
GetCurrentProcess(),
&sock,
STANDARD_RIGHTS_REQUIRED,
true,
DUPLICATE_SAME_ACCESS)
)
{
printf("DuplicateHandle wrong:%8x", GetLastError());
continue;
}
//printf("DuplicateHandle ok\n");
sockaddr_in name = {0};
name.sin_family = AF_INET;
int namelen = sizeof(sockaddr_in);
getsockname( (SOCKET)sock, (sockaddr*)&name, &namelen );
//printf("PORT=%5d\n", ntohs( name.sin_port ));
if(ntohs(name.sin_port)>0) // if port > 0, then we can use it
break;
}
}
catch(...)
{
continue;
}
}
if ( buf != NULL )
{
free( buf );
}
return (SOCKET)sock;
}
/*++
This is not required...
--*/
BOOL EnablePrivilege (PCSTR name)
{
HANDLE hToken;
BOOL rv;
TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
LookupPrivilegeValue (
0,
name,
&priv.Privileges[0].Luid
);
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
OpenProcessToken(
GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
&hToken
);
AdjustTokenPrivileges (
hToken,
FALSE,
&priv,
sizeof priv,
0,
0
);
rv = GetLastError () == ERROR_SUCCESS;
CloseHandle (hToken);
return rv;
}
void main()
{
WSADATA wsaData;
char testbuf[255];
SOCKET sock;
sockaddr_in RecvAddr;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");
if(!LocateNtdllEntry())
return;
if(!EnablePrivilege (SE_DEBUG_NAME))
{
printf("EnablePrivilege wrong\n");
return;
}
sock = GetSocketFromId(GetDNSProcessId());
if( sock==NULL)
{
printf("GetSocketFromId wrong\n");
return;
}
//Change there value...
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(5555);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(SOCKET_ERROR == sendto(sock,
"test",
5,
0,
(SOCKADDR *) &RecvAddr,
sizeof(RecvAddr)))
{
printf("sendto wrong:%d\n", WSAGetLastError());
}
else
{
printf("send ok... Have fun, right? ^_^\n");
}
getchar();
//WSACleanup();
return;
}
很早以前我就有这个想法了,只是一直没有去实现.在上面的代码中,
因为要找出DNS进程句柄,而svchost.exe又有多个,所以以用户名来进行判断,本来是用OpenProcessToken,
但是怎么也不行,所以换个方法.用到了wtsapi32库函数.
再用下面的代码测试:
/*++
UdpReceiver
--*/
#include <stdio.h>
#include "winsock2.h"
#pragma comment(lib, "ws2_32")
void main()
{
WSADATA wsaData;
SOCKET RecvSocket;
sockaddr_in RecvAddr;
int Port = 5555;
char RecvBuf[1024];
int BufLen = 1024;
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
//-----------------------------------------------
// Initialize Winsock
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr));
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
printf("Receiving datagrams...\n");
while(1)
{
recvfrom(RecvSocket,
RecvBuf,
BufLen,
0,
(SOCKADDR *)&SenderAddr,
&SenderAddrSize);
printf("%s\n", RecvBuf);
}
//-----------------------------------------------
// Close the socket when finished receiving datagrams
printf("Finished receiving. Closing socket.\n");
closesocket(RecvSocket);
//-----------------------------------------------
// Clean up and exit.
printf("Exiting.\n");
WSACleanup();
return;
}
===========================================================
测试步骤:
1. 在一台机器上执行UdpReceiver,
2. 在安装防火墙的机器上执行第一个程序.
以上就是我的学习笔记了,希望对你有帮助,目前正在组合一些大牛们的想法,正在思考一种新的穿透防火墙的数据传输技术
发表评论
-
PBOC规范研究之六、变长记录文件
2014-08-14 20:11 947PBOC规范研究之六、变长记录文件 此博文包含图片 (20 ... -
Windows桌面共享中一些常见的抓屏技术
2014-06-06 15:01 10821. BitBlt 我想做Windows开 ... -
error C2440 “static_cast” 无法从“void (__thiscall )(void)”转换为“LRESULT
2013-11-18 13:51 1571error C2440 “static_cast” 无法从 ... -
WOSA/XFS结构、背景等介绍
2013-11-14 13:28 1237前言: 写给 ... -
查看oracle用户数据库连接数
2013-10-30 12:31 686查看oracle用户数据库连接数 1、查询oracle的连接 ... -
C# Socket编程笔记
2013-06-16 08:58 0看到这个题目,是不是 ... -
金融行业密钥详解
2013-05-15 16:48 946金融行业因为对数据比较敏感,所以对数据的加密也相应的比较重视。 ... -
rdp delphi实现远程桌面
2012-11-11 00:17 76581. 首先确保你的机器上存在mstscax.dll,如果没有这 ... -
xml通配符
2012-11-09 09:33 2460解析xml字符串 < -> < &g ... -
cobol中常用的数据类型
2012-08-22 15:13 1284COBOL上的基本类型大致分为:常量、变量、直接数和结构体。下 ... -
(转)学习maven的使用,看到一篇很实用的入门教程(菜鸟级入门)
2012-07-12 15:19 866一、前言 早 ... -
NFC相关研究
2012-05-15 14:07 1166NFC概述 NFC是短距离的无线通信,通常距 ... -
Android 面试题
2012-05-15 14:05 992Android 面试题 经典 1、 Android dvm的进 ... -
使用Java实现CA
2012-04-11 14:31 939一. 准备 1. JDK 1.6 2. 安 ... -
Eclipse快捷键汇总
2012-03-20 10:39 824自动补齐类名 Alt+. 作用 ... -
SSL的工作流程简介(转)
2012-03-01 16:47 9631:客户端的浏览器向服务器传送客户端 SSL 协议的版本号,加 ... -
Http之Get/Post请求区别
2011-09-06 15:24 8991.HTTP请求格式: <request line> ... -
keystore提取私钥和证书
2011-07-19 10:46 2731keytool -genkey -alias test -ke ... -
Keytool命令行参数说明
2011-07-11 15:47 1167Keytool命令行参数说明 2010-03-19 17:05 ... -
如何用jdk的keytool制作ssl证书
2011-07-11 10:19 1725C=CN,OU=IT,O=YIXIUWANG,ST=BEIJI ...
相关推荐
NAT打洞技术分为几种类型,常见的有TCP打洞、UDP打洞和STUN/TURN/ICE等协议。TCP打洞是利用TCP连接的三次握手过程,尝试在两个NAT设备之间建立通道;UDP打洞则更为复杂,通常需要借助外部服务器进行辅助。STUN...
在P2P NAT穿透技术实例中,主要涉及以下几点关键知识点: 1. **ICE(Interactive Connectivity Establishment)**:这是一种综合穿越NAT的协议,它允许两个处于不同NAT后的对等体通过中继或直接通信。ICE结合了STUN...
在C#中,实现UPNP的TCP穿透,通常需要以下几个步骤: 1. **UPNP设备搜索**:程序首先需要查找网络上的UPNP设备。这通常通过发送M-SEARCH消息到多播地址239.255.255.250:1900来进行。C#可以使用`System.Net.Sockets....
UDP穿透主要有以下几种方法: 1. **UDP Hole Punching**:这种方法依赖于NAT设备的一致性,即设备在短时间内向同一目标发送多个数据包时,NAT会保留一个“洞”(即端口映射)。两个内网设备首先各自向公网服务器...
内网穿透技术是一种解决局域网(LAN)内的设备与公网(WAN)通信问题的方法。在日常生活中,我们有时会遇到这样的情况:一台设备在内网环境下,无法被公网直接访问,例如本地开发服务器、家庭NAS存储等。此时,就...
UDP穿透NAT的常见方法有以下几种: 1. **UDP hole punching**:这是一种利用NAT设备自身的规则来创建通信通道的方法。当两个内部分设备同时向对方的公网IP和端口发送数据时,NAT设备会记录这些通信尝试,并在一段...
UDP NAT穿透通常采用以下几种方法: 1. **UDP Hole Punching**:这种方法利用了NAT设备的一致性。当一个设备向另一个设备发送数据后,NAT设备会记住这个通信通道,并在一段时间内保持开放。设备A先向设备B的公网IP...
内网穿透,也称为端口转发,是解决局域网内设备与公网通信的一种技术。其原理是通过一个公网服务器作为中继,将公网的请求转发到内网的特定服务上,同时将内网服务的响应回传给公网。这样,即使内网服务没有直接对外...
Ajax技术主要依赖于以下几种关键技术: 1. **XMLHttpRequest对象**:用于发送异步请求到服务器,并接收响应。 2. **JavaScript**:用来处理客户端逻辑,控制请求发送及响应数据的处理。 3. **DOM(Document Object ...
WebSocket协议基于TCP,设计时考虑了HTTP/1.1的兼容性,因此可以通过常见的80和443端口进行通信,减少了穿透防火墙的障碍。在建立连接时,WebSocket使用HTTP的Upgrade头进行握手,一旦握手成功,连接就保持打开状态...
为了实现服务器推送,通常采用以下几种方式: 1. **传统轮询**:利用HTML的meta刷新或者Ajax定时请求来模拟服务器推送。这种方式简单但效率低下,频繁的请求不仅增加服务器压力,还浪费带宽。用户体验也不理想,...
UDP打洞P2P技术是互联网通信中一种用于穿透网络地址转换(NAT)的技术,它使得两个位于不同NAT后的设备能够直接通信,而无需通过中心服务器作为中介。这一技术在实现点对点(P2P)应用,如文件共享、实时通信和在线...
此外,SSH还支持端口转发,可以将本地端口上的流量转发到远程服务器,或者将远程服务器的端口转发到本地,这在穿透防火墙时非常有用。 6. **X11转发**:SSH还可以提供X11转发功能,允许用户在安全的SSH连接下远程...
有几种穿透NAT的方法,如STUN(Simple Traversal of UDP through NATs)、TURN(Traversal Using Relays around NATs)和ICE(Interactive Connectivity Establishment)。 2. **STUN服务器**:它是一个公开可访问...
研究了IETF关于NGN网络中会话业务穿透NAT技术的各种草案,结合网络的实际情况,对目前SIP业务开展可以使用的几种NAT穿越技术和方案进行了比较,提出了一种结合SIP协议扩展和MIDCOM协议构架的方法,解决了由于传统NAT...
- **NAT分类**:根据处理规则的不同,NAT设备可以分为几种类型,如对称NAT、受限锥形NAT、端口受限锥形NAT和全锥形NAT等。不同类型NAT的处理方式会影响打孔技术的成功率。 - **安全性考量**:虽然打孔技术在某些...
文章部分内容提到了几种常见的分布式数据同步方法,如数据库厂商提供的同步功能和基于Web服务的同步方法。前者易于实现但可能局限于特定类型的数据库,后者能够跨平台通信但需要额外设计数据一致性机制。然后,文章...
6. **防火墙穿透**:能够穿透防火墙,使得远程连接成为可能,尤其在企业环境中。 7. **安全加密**:使用SSL/TLS等安全协议,确保数据传输过程中的隐私和安全。 在选择远程控制软件时,用户应该考虑以下几个关键因素...
- **防火墙穿透**:TeamViewer有能力绕过大多数防火墙限制,实现远程连接。 总结来说,"不同网段远程控制"是通过远程控制软件如TeamViewer,结合网络通信和穿越障碍的技术,实现跨越网络分段的设备控制。这种技术在...