리플렉션을 이용해 닷넷 LicenseManager를 우회할 수 있는 사례
닷넷에는 LicenseManager라는 타입이 제공되어 기본적으로 이를 이용해 쉽게 라이선스 적용을 할 수 있습니다. 이 타입의 기본적인 사용법은 다음의 글에서 이미 살펴봤었습니다.
닷넷 System.ComponentModel.LicenseManager를 이용한 라이선스 적용
; https://www.sysnet.pe.kr/2/0/1045
그리고 우회할 수 있는 사례도 소개한 적이 있군요. ^^
AppDomain.GetEntryAssembly()를 우회하는 방법
; https://www.sysnet.pe.kr/2/0/566
라이선스까지도 뛰어넘는 .NET Profiler
; https://www.sysnet.pe.kr/2/0/1046
오늘은 우회할 수 있는 경우의 수를 하나 더 발견했습니다.
해당 어셈블리는 통신을 연결하기 전 다음과 같은 식의 라이선스 체크를 하는 코드를 포함하고 있었습니다.
public class MySocketServer : BaseClass
{
// ...[생략]...
public override void ConnectToServer()
{
if (this.State != ConnectionState.Open)
{
License license = MyLicense.GetLicense(LicenseManager.CurrentContext, typeof(MySocketServer), this, false);
if (license == null)
{
throw new ProductException();
}
try
{
base.ConnectToServer();
}
catch (Exception ex)
{
throw;
}
}
}
}
라이선스 체크는 서버에 연결하기 전 단 한번만 하고 있었으며, 그 외의 모든 실질적인 코드 수행은 internal로 정의된 BaseClass 클래스의 메서드에 일임하고 있었습니다.
물론, 이것이 구조적으로는 좋지만 라이선스 우회에는 아주 쉬운 사례중의 하나가 됩니다. 왜냐하면, 해당 인스턴스를 new로 생성한 다음 base.ConnectToServer만 호출해 주면 되기 때문입니다.
static class Program
{
static void Main(string[] args)
{
MySocketServer dc = new MySocketServer();
MethodInfo mi = typeof(BaseClass).GetMethod("ConnectToServer");
mi.InvokeNotOverride(dc, null);
}
}
사실 이것 때문에 지난번 글이 씌여진 것입니다.
override 메서드가 정의된 타입의 인스턴스로 base 메서드를 호출하는 방법
; https://www.sysnet.pe.kr/2/0/1564
개인적으로 역공학등의 방법을 이용해 라이선스를 무력화시키는 것을 일부러 공부하거나 하지는 않습니다. 단지, 프로그래머로써 공부하다 보니 어쩔 수 없이 보이게 되는 부분들이 있습니다.
어쨌든, 이 글을 통해서 여러분들 중에 라이선스를 적용한 제품을 판매하고 있다면 이런 결함이 있는 것은 아닌지 한번쯤 검토해 보는 것도 좋을 듯 싶습니다. 제 경험상, 서버 용 제품으로 판매하는 경우는 라이선스가 다소 허술해도 되지만... 불특정 다수의 클라이언트를 대상으로 판매하는 경우라면 이를 심각하게 고려해 봐야 합니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]