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

비밀번호

댓글 작성자
 




... 31  32  33  34  [35]  36  37  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
13098정성태7/13/202215862개발 환경 구성: 647. Azure - scale-out 상태의 App Service에서 특정 인스턴스에 요청을 보내는 방법 [1]
13097정성태7/12/202214841오류 유형: 817. Golang - binary.Read: invalid type int32
13096정성태7/8/202218096.NET Framework: 2030. C# 11 - UTF-8 문자열 리터럴
13095정성태7/7/202215534Windows: 208. AD 도메인에 참여하지 않은 컴퓨터에서 Kerberos 인증을 사용하는 방법
13094정성태7/6/202215149오류 유형: 816. Golang - "short write" 오류 원인
13093정성태7/5/202215743.NET Framework: 2029. C# - HttpWebRequest로 localhost 접속 시 2초 이상 지연
13092정성태7/3/202217783.NET Framework: 2028. C# - HttpWebRequest의 POST 동작 방식파일 다운로드1
13091정성태7/3/202216355.NET Framework: 2027. C# - IPv4, IPv6를 모두 지원하는 서버 소켓 생성 방법
13090정성태6/29/202215992오류 유형: 815. PyPI에 업로드한 패키지가 반영이 안 되는 경우
13089정성태6/28/202216656개발 환경 구성: 646. HOSTS 파일 변경 시 Edge 브라우저에 반영하는 방법
13088정성태6/27/202214986개발 환경 구성: 645. "Developer Command Prompt for VS 2022" 명령행 환경의 폰트를 바꾸는 방법
13087정성태6/23/202218399스크립트: 41. 파이썬 - FastAPI / uvicorn 호스팅 환경에서 asyncio 사용하는 방법 [1]
13086정성태6/22/202218300.NET Framework: 2026. C# 11 - 문자열 보간 개선 2가지파일 다운로드1
13085정성태6/22/202217528.NET Framework: 2025. C# 11 - 원시 문자열 리터럴(raw string literals)파일 다운로드1
13084정성태6/21/202217026개발 환경 구성: 644. Windows - 파이썬 2.7을 msi 설치 없이 구성하는 방법
13083정성태6/20/202217426.NET Framework: 2024. .NET 7에 도입된 GC의 메모리 해제에 대한 segment와 region의 차이점 [2]
13082정성태6/19/202216398.NET Framework: 2023. C# - Process의 I/O 사용량을 보여주는 GetProcessIoCounters Win32 API파일 다운로드1
13081정성태6/17/202215070.NET Framework: 2022. C# - .NET 7 Preview 5 신규 기능 - System.IO.Stream ReadExactly / ReadAtLeast파일 다운로드1
13080정성태6/17/202216635개발 환경 구성: 643. Visual Studio 2022 17.2 버전에서 C# 11 또는 .NET 7.0 preview 적용
13079정성태6/17/202213906오류 유형: 814. 파이썬 - Error: The file/path provided (...) does not appear to exist
13078정성태6/16/202217449.NET Framework: 2021. WPF - UI Thread와 Render Thread파일 다운로드1
13077정성태6/15/202218498스크립트: 40. 파이썬 - PostgreSQL 환경 구성
13075정성태6/15/202215165Linux: 50. Linux - apt와 apt-get의 차이 [2]
13074정성태6/13/202215989.NET Framework: 2020. C# - NTFS 파일에 사용자 정의 속성값 추가하는 방법파일 다운로드1
13073정성태6/12/202216441Windows: 207. Windows Server 2022에 도입된 WSL 2
13072정성태6/10/202216514Linux: 49. Linux - ls 명령어로 출력되는 디렉터리 색상 변경 방법
... 31  32  33  34  [35]  36  37  38  39  40  41  42  43  44  45  ...