0x00 Preface

---

Windows Communication Foundation (WCF) is a framework for building service-oriented applications in the .NET Framework. This article will introduce the relevant content of WCF development, paving the way for subsequent topics.

0x01 Introduction

---

This article will cover the following:

  • Implementing WCF using basicHttpBinding
  • Implementing WCF using NetTcpBinding
  • Implementing WCF via command line
  • Implementing WCF via IIS
  • Implementing WCF via services

0x02 Basics

---

References:

https://docs.microsoft.com/en-us/dotnet/framework/wcf/whats-wcf

Common transport protocols:

  • HTTP, http://localhost:8080/
  • TCP, net.tcp://localhost:8080/
  • IPC, net.pipe://localhost/

Common Bindings:

  • BasicHttpBinding
  • WSHttpBinding
  • NetTcpBinding
  • NetNamedPipeBinding

Metadata exchange, abbreviated as MEX

WCF disables MEX by default to prevent data leakage.

Following the principle of gradual progression, this series of articles first introduces the usage of enabling MEX to improve client development efficiency. The usage of disabling MEX will be covered in the next article.

0x03 Implementing WCF using basicHttpBinding

---

This section uses the command-line implementation of WCF as an example

Development tool: Visual Studio 2015

1. Server-side development

(1) Create a new project

Select Visual C#->Console Application, name it basicHttpBindingWCFServer

(2) Create a new WCF service

Select Add->New Item..., choose WCF Service, name it Service1.cs

(3) Modify service1.cs

Add implementation code for DoWork, code example:

using System;
namespace basicHttpBindingWCFServer
{
public class Service1 : IService1
{
public void DoWork()
{
Console.Write("Run Server.DoWork()");
}
}
}

(4) Modify Program.cs

Add reference to System.ServiceModel

Add startup code, code example:

using System;
using System.ServiceModel;
namespace basicHttpBindingWCFServer
{
class Program
{
static void Main(string[] args)
{
ServiceHost Host = new ServiceHost(typeof(Service1));
Host.Open();
Console.WriteLine(Host.Description.Endpoints[0].Address);
Console.ReadLine();
Host.Close();
}
}
}

(5) Compile and run

Command line output service address: http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/

Service address can also be viewed in the App.config file in the project

(6) Testing

MEX is now enabled, choose one of the following methods for testing:

  • Access the service address via browser: http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/, service information should be returned
  • Testing with WcfTestClient, default path: C:\Program Files(x86)\Microsoft Visual Studio 14\Common7\IDE\WcfTestClient.exe, connect to http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/, call DoWork(), at this point the server command line outputs Run Server.DoWork(), method call successful
  • Using Svcutil to generate client configuration code, command example: svcutil.exe http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/ /out:1.cs, reference code available at: https://github.com/dotnet/samples/tree/main/framework/wcf/Basic/Binding/Net/Tcp/Default/CS

Note:

App.config is automatically generated by Visual Studio, service address is randomly assigned by App.config, here the service address can also be specified via code, without relying on App.config, method as follows:

Program.cs example:

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace basicHttpBindingWCFServer
{
class Program
{
static void Main(string[] args)
{
ServiceHost host = null;
try
{
Uri baseAddress = new Uri("http://localhost/TestService");
host = new ServiceHost(typeof(Service1), baseAddress);
BasicHttpBinding binding = new BasicHttpBinding();
host.AddServiceEndpoint(typeof(IService1), binding, baseAddress);
if (host.Description.Behaviors.Find() == null)
{
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
host.Description.Behaviors.Add(behavior);
}
host.Open();
Console.WriteLine(host.Description.Endpoints[0].Address);
Console.Read();
host.Close();
}
catch (CommunicationException ce)
{
host.Abort();
}
}
}
}

App.config example:






2. Client Development

(1) Create a New Project

Select Visual C# -> Console Application, name it basicHttpBindingWCFClient

(2) Add Service Reference

Select Add -> Service Reference...

Enter URL: http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/

(3) Modify Program.cs

Code Example:

using basicHttpBindingWCFClient.ServiceReference1;
namespace basicHttpBindingWCFClient
{
class Program
{
static void Main(string[] args)
{
Service1Client service1 = new Service1Client();
service1.DoWork();
}
}
}

(4) Compile and run

At this point, the server command line outputs 'Run Server.DoWork()', indicating the method call succeeded

0x04 Implementing WCF using NetTcpBinding

---

This section uses the command-line implementation of WCF as an example

1. Server-side development

(1) Create a new project

Select Visual C# -> Console Application, name it NetTcpBindingWCFServer

(2) Create a new WCF service

Select Add->New Item..., choose WCF Service, name it Service1.cs

(3) Modify service1.cs

Add implementation code for DoWork, code example:

using System;
namespace NetTcpBindingWCFServer
{
public class Service1 : IService1
{
public void DoWork()
{
Console.Write("Run Server.DoWork()");
}
}
}

(4) Modify Program.cs

Add reference to System.ServiceModel

Add startup code, code example:

using System;
using System.ServiceModel;
namespace NetTcpBindingWCFServer
{
class Program
{
static void Main(string[] args)
{
ServiceHost Host = new ServiceHost(typeof(Service1));
Host.Open();
Console.WriteLine(Host.Description.Endpoints[0].Address);
Console.ReadLine();
Host.Close();
}
}
}

(5) Modify App.config

Line10:

Change to:

Line17:

Change to:

Line22:

Change to:

Line25:

Change to:

Complete code example:































(6) Compile and run

Command line output service address: net.tcp://localhost:1111/Design_Time_Addresses/NetTcpBindingWCFServer/Service1/

(7) Testing

MEX is now enabled, you can choose the following methods for testing:

  • Use WcfTestClient for testing, default path: C:\Program Files(x86)\Microsoft Visual Studio 14\Common7\IDE\WcfTestClient.exe, connect to net.tcp://localhost:1111/Design_Time_Addresses/NetTcpBindingWCFServer/Service1/, call DoWork(), then the server command line outputs Run Server.DoWork(), method call successful
  • Use Svcutil to generate client configuration code, command example: svcutil.exe net.tcp://localhost:1111/Design_Time_Addresses/NetTcpBindingWCFServer/Service1/ /out:1.cs, reference code can be found at: https://github.com/dotnet/samples/tree/main/framework/wcf/Basic/Binding/Net/Tcp/Default/CS

2. Client Development

(1) Create New Project

Select Visual C#->Console Application, name it NetTcpBindingWCFClient

Method is the same as 2. Client Development in 0x03

0x05 Implementing WCF via IIS

---

This section only uses server development as an example, client development follows the same method as command line implementation

1. Server Development

(1) Create New Project

Select Visual C#->WCF->WCF Service Library, name it WcfServiceLibrary1

(2) Publish

Select the project, right-click -> Publish..., set Target location to c:\wcfdemo

(3) Create a new website under the IIS management page

Set the following parameters:

  • Site name: wcfdemo
  • Physical path: c:\wcfdemo
  • IP address: All unassigned
  • Port: 81

Select the website wcfdemo, enter Content View

Select WcfServiceLibrary1.Service1.svc, right-click -> Browse, obtain the URL: http://localhost:81/WcfServiceLibrary2.Service1.svc

(4) Test

MEX is now enabled, choose one of the following methods for testing:

  • Access the service address via browser: http://localhost:81/WcfServiceLibrary2.Service1.svc, service information should be returned
  • Test using WcfTestClient, default path: C:\Program Files(x86)\Microsoft Visual Studio 14\Common7\IDE\WcfTestClient.exe, connect to http://localhost:81/WcfServiceLibrary2.Service1.svc, call GetData(), obtain the return value, method call successful
  • Use Svcutil to generate client configuration code, command example: svcutil.exe http://localhost:81/WcfServiceLibrary2.Service1.svc, reference code available at: https://github.com/dotnet/samples/tree/main/framework/wcf/Basic/Binding/Net/Tcp/Default/CS

0x06 Implementing WCF via Service

---

This section only uses server-side programming as an example; client-side programming follows the same method as command-line implementation.

1. Implementing the server using basicHttpBinding

(1) Create a new project

Select Visual C# -> Console Application, name it WCFService

(2) Create a new Windows Service

Select Add -> New Item..., choose Windows Service, name it Service1.cs

(3) Set service information

Select Service1.cs, right-click -> Add Installer

The ProjectInstaller.cs file is automatically created in the project, adding two components: serviceProcessInstaller1 and serviceInstaller1

Select the serviceProcessInstaller1 component, view properties, set account to LocalSystem

Select the serviceInstaller1 component, view properties, set ServiceName to VulServiceTest1

(4) Edit Program.cs

using System;
using System.ServiceModel;
using System.ServiceProcess;
using System.ServiceModel.Description;
namespace WCFService
{
[ServiceContract]
public interface IVulnService
{
[OperationContract]
void RunMe(string str);
}

public class VulnService : IVulnService
{
public void RunMe(string str)
{
Console.WriteLine(str);
System.Diagnostics.Process.Start("CMD.exe", "/c " + str);
}
}

public class WCFService : ServiceBase
{
public ServiceHost host = null;

public WCFService()
{
ServiceName = "VulnWCFService";
}

public static void Main()
{
ServiceBase.Run(new WCFService());
}

protected override void OnStart(string[] args)
{
if (host != null)
{
host.Close();
}
try
{
Uri baseAddress = new Uri("http://localhost:1112/TestService");
host = new ServiceHost(typeof(VulnService), baseAddress);
BasicHttpBinding binding = new BasicHttpBinding();
host.AddServiceEndpoint(typeof(IVulnService), binding, baseAddress);
if (host.Description.Behaviors.Find() == null)
{
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
host.Description.Behaviors.Add(behavior);
}
host.Open();
}
catch (CommunicationException ce)
{
host.Abort();
}

}
protected override void OnStop()
{
if (host != null)
{
host.Close();
host = null;
}
}
}
}

(5) Start service

Compile to generate WCFService.exe

Install service:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil WCFService.exe

Start service:

sc start VulServiceTest1

Note: Uninstall service

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil /u WCFService.exe

(6) Testing

MEX is now enabled, choose one of the following methods for testing:

  • Access the service address through browser: http://localhost:1112/TestService, which returns service information
  • Test using WcfTestClient, default path: C:\Program Files(x86)\Microsoft Visual Studio 14\Common7\IDE\WcfTestClient.exe, connect to http://localhost:1112/TestService, call RunMe(), input calc in the Value field corresponding to str, execute to launch calc with system privileges, method call successful
  • Generate client configuration code using Svcutil, command example: svcutil.exe http://localhost:1112/TestService /out:1.cs, reference code available at: https://github.com/dotnet/samples/tree/main/framework/wcf/Basic/Binding/Net/Tcp/Default/CS

2. Implement server using NetTcpBinding

Method same as above, difference lies in Program.cs, example code as follows:

using System;
using System.ServiceModel;
using System.ServiceProcess;
using System.ServiceModel.Description;
namespace WCFService
{
[ServiceContract]
public interface IVulnService
{
[OperationContract]
void RunMe(string str);
}

public class VulnService : IVulnService
{
public void RunMe(string str)
{
Console.WriteLine(str);
System.Diagnostics.Process.Start("CMD.exe", "/c " + str);
}
}

public class WCFService : ServiceBase
{
public ServiceHost host = null;

public WCFService()
{
ServiceName = "VulnWCFService";
}

public static void Main()
{
ServiceBase.Run(new WCFService());
}

protected override void OnStart(string[] args)
{

if (host != null)
{
host.Close();
}
try
{
host = new ServiceHost(typeof(VulnService));
host.AddServiceEndpoint(
typeof(IVulnService),
new NetTcpBinding(),
"net.tcp://localhost:1113/TestService");
if (host.Description.Behaviors.Find() == null)
{
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
behavior.HttpGetUrl = new Uri("http://localhost:1114/TestService");
host.Description.Behaviors.Add(behavior);
}
host.Open();
}
catch (CommunicationException ce)
{
host.Abort();
}

}
protected override void OnStop()
{
if (host != null)
{
host.Close();
host = null;
}
}
}
}

Note:

The server has set HttpGetUrl: http://localhost:1114/TestService

0x07 Summary

---

This article introduced the relevant content of WCF development when metadata publishing (MEX) is enabled. The next article will cover the relevant content of WCF development when metadata publishing (MEX) is disabled.