Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

(시리즈 글이 11개 있습니다.)
.NET Framework: 404. 리플렉션을 이용해 닷넷 LicenseManager를 우회할 수 있는 사례
; https://www.sysnet.pe.kr/2/0/1565

.NET Framework: 428. .NET Reflection으로 다차원/Jagged 배열을 구분하는 방법
; https://www.sysnet.pe.kr/2/0/1653

.NET Framework: 537. C# - Reflection의 박싱 없이 값 형식을 다루는 방법
; https://www.sysnet.pe.kr/2/0/10866

.NET Framework: 685. C# - 구조체(값 형식)의 필드를 리플렉션을 이용해 값을 바꾸는 방법
; https://www.sysnet.pe.kr/2/0/11312

.NET Framework: 785. public으로 노출되지 않은 다른 어셈블리의 delegate 인스턴스를 Reflection으로 생성하는 방법
; https://www.sysnet.pe.kr/2/0/11583

.NET Framework: 842. .NET Reflection을 대체할 System.Reflection.Metadata 소개
; https://www.sysnet.pe.kr/2/0/11930

.NET Framework: 924. C# - Reflection으로 변경할 수 없는 readonly 정적 필드
; https://www.sysnet.pe.kr/2/0/12256

.NET Framework: 1045. C# - 런타임 시점에 이벤트 핸들러를 만들어 Reflection을 이용해 구독하는 방법
; https://www.sysnet.pe.kr/2/0/12609

.NET Framework: 1046. C# - 컴파일 시점에 참조할 수 없는 타입을 포함한 이벤트 핸들러를 Reflection을 이용해 구독하는 방법
; https://www.sysnet.pe.kr/2/0/12610

닷넷: 2155. C# - .NET 8 런타임부터 (Reflection 없이) 특성을 이용해 public이 아닌 멤버 호출 가능
; https://www.sysnet.pe.kr/2/0/13436

닷넷: 2249. C# - 부모의 필드/프로퍼티에 대해 서로 다른 자식 클래스 간에 Reflection 접근이 동작할까요?
; https://www.sysnet.pe.kr/2/0/13608




리플렉션을 이용해 닷넷 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




개인적으로 역공학등의 방법을 이용해 라이선스를 무력화시키는 것을 일부러 공부하거나 하지는 않습니다. 단지, 프로그래머로써 공부하다 보니 어쩔 수 없이 보이게 되는 부분들이 있습니다.

어쨌든, 이 글을 통해서 여러분들 중에 라이선스를 적용한 제품을 판매하고 있다면 이런 결함이 있는 것은 아닌지 한번쯤 검토해 보는 것도 좋을 듯 싶습니다. 제 경험상, 서버 용 제품으로 판매하는 경우는 라이선스가 다소 허술해도 되지만... 불특정 다수의 클라이언트를 대상으로 판매하는 경우라면 이를 심각하게 고려해 봐야 합니다.





[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 6/9/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 91  92  93  94  95  96  97  98  [99]  100  101  102  103  104  105  ...
NoWriterDateCnt.TitleFile(s)
11457정성태2/17/201823972.NET Framework: 732. C# - Task.ContinueWith 설명 [1]파일 다운로드1
11456정성태2/17/201829705.NET Framework: 731. C# - await을 Task 타입이 아닌 사용자 정의 타입에 적용하는 방법 [7]파일 다운로드1
11455정성태2/17/201818618오류 유형: 451. ASP.NET Core - An error occurred during the compilation of a resource required to process this request.
11454정성태2/12/201827507기타: 71. 만료된 Office 제품 키를 변경하는 방법
11453정성태1/31/201819459오류 유형: 450. Azure Cloud Services(classic) 배포 시 "Certificate with thumbprint ... doesn't exist." 오류 발생
11452정성태1/31/201824987기타: 70. 재현 가능한 최소한의 예제 프로젝트란? [3]파일 다운로드1
11451정성태1/24/201819224디버깅 기술: 111. windbg - x86 메모리 덤프 분석 시 닷넷 메서드의 호출 인자 값 확인
11450정성태1/24/201834487Windows: 146. PowerShell로 원격 프로세스(EXE, BAT) 실행하는 방법 [1]
11449정성태1/23/201821863오류 유형: 449. 단위 테스트 - Could not load file or assembly 'Microsoft.VisualStudio.QualityTools.VideoRecorderEngine' or one of its dependencies. [1]
11448정성태1/20/201819322오류 유형: 448. Fakes를 포함한 단위 테스트 프로젝트를 빌드 시 CS0619 관련 오류 발생
11447정성태1/20/201820678.NET Framework: 730. dotnet user-secrets 명령어 [2]파일 다운로드1
11446정성태1/20/201821727.NET Framework: 729. windbg로 살펴보는 GC heap의 Segment 구조 [2]파일 다운로드1
11445정성태1/20/201819610.NET Framework: 728. windbg - 눈으로 확인하는 Workstation GC / Server GC
11444정성태1/19/201819707VS.NET IDE: 125. Visual Studio에서 Selenium WebDriver를 이용한 웹 브라우저 단위 테스트 구성파일 다운로드1
11443정성태1/18/201820235VC++: 124. libuv 모듈 살펴 보기
11442정성태1/18/201818086개발 환경 구성: 353. ASP.NET Core 프로젝트의 "Enable unmanaged code debugging" 옵션 켜는 방법
11441정성태1/18/201816624오류 유형: 447. ASP.NET Core 배포 오류 - Ensure that restore has run and that you have included '...' in the TargetFrameworks for your project.
11440정성태1/17/201819910.NET Framework: 727. ASP.NET의 HttpContext.Current 구현에 대응하는 ASP.NET Core의 IHttpContextAccessor/HttpContextAccessor 사용법파일 다운로드1
11439정성태1/17/201824702기타: 69. C# - CPU 100% 부하 주는 프로그램파일 다운로드1
11438정성태1/17/201819469오류 유형: 446. Error CS0234 The type or namespace name 'ITuple' does not exist in the namespace
11437정성태1/17/201818747VS.NET IDE: 124. Platform Toolset 설정에 따른 Visual C++의 헤더 파일 기본 디렉터리
11436정성태1/16/201821013개발 환경 구성: 352. ASP.NET Core (EXE) 프로세스가 IIS에서 호스팅되는 방법 - ASP.NET Core Module(AspNetCoreModule) [4]
11435정성태1/16/201822141개발 환경 구성: 351. OWIN 웹 서버(EXE)를 IIS에서 호스팅하는 방법 - HttpPlatformHandler (Reverse Proxy)파일 다운로드2
11434정성태1/15/201822485개발 환경 구성: 350. 사용자 정의 웹 서버(EXE)를 IIS에서 호스팅하는 방법 - HttpPlatformHandler (Reverse Proxy)파일 다운로드2
11433정성태1/15/201820567개발 환경 구성: 349. dotnet ef 명령어 사용을 위한 준비
11432정성태1/11/201826311.NET Framework: 726. WPF + Direct2D + SharpDX 출력 C# 예제파일 다운로드2
... 91  92  93  94  95  96  97  98  [99]  100  101  102  103  104  105  ...