.net 소스 코드 무료 난독화 with obfuscar

Jun 15, 2023 | 0 comments

.net 소스 코드를 난독화 할 수 있는 무료 패키지 중에 하나인 obfuscar 을 이용해서 코드 난독화 하는 과정을 설명합니다.
.net 7 wpf 기반으로 난독화를 하는 과정에서 발생하는 문제를 해결하는 과정이 포함되어 있습니다.
또한, 로컬 폴더 뿐만 아니라 ClickOnce 로 배포되는 어셈블리도 난독화를 적용해서 배포해 보겠습니다.
동일한 환경이 아니더라도 비슷한 문제를 겪는 상황이 많기 때문에 해결 과정을 알고 나면 도움이 될 것 같습니다.

Project 사이트는 Obfuscar Copy on Strikingly 링크를 클릭하시면 확인이 가능합니다.
Github 은 다음을 참조하시면 됩니다.

프로젝트 생성

다음과 같이 WPF 애플리케이션 프로젝트를 생성합니다.(.net Framework 가 아닙니다.)
.Net 7 환경으로 생성하였습니다.

난독화 과정

MainWindow.xaml.cs 파일을 다음과 같이 수정합니다.
난독화를 테스트 하기 위한 간단한 구문 입니다.

using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Windows;

namespace Dot_Net7_WPF_Obfuscar
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public const string ConstStringValue = "난독화 문자열 상수";
        public readonly string ReadonlyStringValue = "난독화 문자열 필드";
        public static void RegisterStartUpProgram()
        {
            Microsoft.Win32.RegistryKey? key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
            if (key != null)
            {
                Assembly curAssembly = Assembly.GetExecutingAssembly();
                var regName = curAssembly.GetName().Name;
                ProcessModule? mainModule = Process.GetCurrentProcess().MainModule;
                if (mainModule != null && !key.GetValueNames().Contains(regName))
                {
                    key.SetValue(regName, mainModule.FileName);
                }
            }
        }
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Obfuscar package 추가

nuget package 에서 Obfuscar 를 검색해서 다음과 같이 추가합니다.

Obfuscar 설정 파일 추가

Obfuscar.xml 을 추가한 다음 다음과 같이 작성합니다.
설정값 목록은 다음 링크 를 참고하시면 됩니다. (Configuration — obfuscar 2.2 documentation)
지정되지 않은 설정은 Default 값을 그대로 사용하고자 합니다.

<?xml version='1.0'?>
<Obfuscator>
  <Var name="InPath" value=".\bin\Debug\net7.0-windows" />
  <Var name="OutPath" value="$(InPath)\Obfuscated" />
  
  <Var name="KeepPublicApi" value="true" />
  <Var name="HidePrivateApi" value="true" />
  <Var name="HideStrings" value="true" />
  
  <Module file="$(InPath)\Dot Net7 WPF Obfuscar.dll" />
</Obfuscator>

빌드 후 이벤트 추가

프로젝트 속성의 빌드 후 이벤트를 다음과 같이 추가합니다.

cd $(ProjectDir)
"$(Obfuscar)" Obfuscar.xml

추가 어셈블리 경로 지정

솔루션을 다시 빌드 해보면 다음과 같은 에러가 발생합니다.
5,6 번 라인의 에러를 보면 PresentationFramework, Version=7.0.0.0 어셈블리 때문에 에러가 발생했음을 알 수 있습니다.
일반 콘솔 어플리케이션이 아니라 WPF 프로젝트 생성했기 때문에 별도 프레임워크가 참조되었습니다.

1>Dot Net7 WPF Obfuscar -> C:\Repo\[Github]\Dot Net7 WPF Obfuscar\Dot Net7 WPF Obfuscar\bin\Debug\net7.0-windows\Dot Net7 WPF Obfuscar.dll
1>Note that Rollbar API is enabled by default to collect crashes. If you want to opt out, please run with -s switch
1>Loading project Obfuscar.xml...
1>An error occurred during processing:
1>Unable to find assembly:  .\bin\Debug\net7.0-windows\Dot Net7 WPF Obfuscar.dll
1>Failed to resolve assembly: 'PresentationFramework, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
1>C:\Repo\[Github]\Dot Net7 WPF Obfuscar\Dot Net7 WPF Obfuscar\Dot Net7 WPF Obfuscar.csproj(19,5): error MSB3073: "obfuscar.console Obfuscar.xml" 명령이 종료되었습니다(코드: 1).
1>"Dot Net7 WPF Obfuscar.csproj" 프로젝트를 빌드했습니다. - 실패

Obfuscar 프로젝트 사이트 (Configuration — obfuscar 2.2 documentation) 를 확인해 보면
2.2.5 버전 이후에 AssemblySearchPath 설정이 추가되었습니다.
그래서 설정 파일을 다음과 같이 수정한 다음 다시 빌드해 보면 정상적으로 빌드가 되는 것을 알 수 있습니다.

<?xml version='1.0'?>
<Obfuscator>
  <Var name="InPath" value=".\bin\Debug\net7.0-windows" />
  <Var name="OutPath" value="$(InPath)\Obfuscated" />
  
  <Var name="KeepPublicApi" value="true" />
  <Var name="HidePrivateApi" value="true" />
  <Var name="HideStrings" value="true" />

  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.5" />
  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\7.0.5" />
  
  <Module file="$(InPath)\Dot Net7 WPF Obfuscar.dll" />
</Obfuscator>

그리고, 난독화 되기 전의 어셈블리는 $(InPath)\Dot Net7 WPF Obfuscar.dll 에 위치하고
난독화가 된 결과물은 하위폴더(Obfuscated) 에 생성이 됩니다.

난독화 전과 후 비교

디컴파일러 중에는 ILSPY 가 유명하지만 개인적으로 JetBrains 의 DotPeek 을 예전부터 사용하고 있어서 DotPeek 으로 비교해 보겠습니다.

난독화 적용 전

난독화가 적용되지 않은 경우는 기존 소스의 내용이 그대로 보이게 됩니다.

난독화 적용 후

난독화가 적용된 경우 샘플에 보여지는 소스 코드는 단순해서 크게 차이가 나지 않는 듯 하지만
코드 양이 늘어날 수록 더욱 파악이 어려워 집니다.
그리고, 문자열의 경우 특이하게도 const 로 지정한 컴파일 상수의 경우

컴파일 타임에 결정되는 컴파일 상수의 특성상 난독화가 적용되지 않는 것을 볼 수 있습니다.

기본값을 대부분 그대로 유지 했을 경우이며 확실한 이유는 확인하지 못하였습니다.

혹시, 보안상의 이유로 노출 되어서는 않되는 라이센스 키 등을 컴파일 상수로 지정하는 것은 피해야 할 것으로 보입니다.
저의 경우 const 대신 static readonly 로 대체해서 사용하였습니다.
두 경우 컴파일 타임과 런타임의 차이가 있지만 난독화를 적용한다는 가정 하에 런타임 사용을 권장합니다.

빌드 경로에 덮어쓰기

난독화 경로(bin\Debug\net7.0-windows\Obfuscated)의 어셈블리를 빌드 결과물 경로(bin\Debug\net7.0-windows) 로 수동으로 복사하기 번거로우니
다음 스크립트를 빌드 후 이벤트 마지막에 추가하면 난독화된 어셈블리를 빌드 시 자동으로 덮어쓰기 할 수 있습니다.
다시 빌드후 빌드 결과물 경로(bin\Debug\net7.0-windows)의 어셈블리를 확인해 보면 난독화가 적용되어 있는 것을 확인할 수 있습니다.

cd $(ProjectDir)
"$(Obfuscar)" Obfuscar.xml
copy "$(OutputPath)\Obfuscated\$(AssemblyName).dll" "$(OutputPath)\$(AssemblyName).dll"

난독화 적용 후 게시할 때 문제점 및 해결

일단 소스 코드를 난독화 한 어셈블리를 생성하는 것까지는 완료가 되었습니다.
해당 폴더를 Portable 형태로 배포하는 경우는 문제가 없습니다.
하지만, 게시(Azure, Clickonce, Docker, 폴더 등)하는 경우에는 문제가 발생합니다.
게시하는 경우 빌드 후 바로 게시하는 과정이 이루어지기 때문에 난독화된 파일을 복사하는 과정에서 문제가 발생합니다.
이후 과정은 로컬 폴더로 배포할 때 난독화를 적용하는 방법에 대해 알아보겠습니다.

솔루션 구성 변경

게시할 예정이므로 구성을 Debug 에서 Release 로 변경합니다.

Obfuscar 설정 파일 수정

Obfuscar.xml 파일을 다음과 같이 수정합니다.
Debug 폴더를 Release 폴더로 수정하였습니다.

<?xml version='1.0'?>
<Obfuscator>
  <Var name="InPath" value=".\bin\Release\net7.0-windows" />
  <Var name="OutPath" value="$(InPath)\Obfuscated" />
  
  <Var name="KeepPublicApi" value="true" />
  <Var name="HidePrivateApi" value="true" />
  <Var name="HideStrings" value="true" />

  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.5" />
  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\7.0.5" />
  
  <Module file="$(InPath)\Dot Net7 WPF Obfuscar.dll" />
</Obfuscator>

게시 프로필 추가

솔루션 탐색기의 프로젝트에서 게시 프로필을 다음과 같이 추가합니다.
게시 메뉴를 클릭합니다.

폴더를 선택한 다음 다음 버튼을 클릭합니다.

다시 한번 폴더를 선택한 다음 다음 버튼을 클릭합니다.

다음과 같이 기본 설정값 그대로 확인한 다음 마침 버튼을 클릭합니다.

그러면 다음과 같이 게시 프로필이 정상적으로 추가되었음을 알려줍니다.

닫기 버튼을 클릭하면 다음과 같이 게시 페이지가 활성화가 되고, 우측 상단의 게시 버튼을 클릭합니다.

게시 후 난독화가 적용 안됨

난독화 경로(bin\Release\net7.0-windows\Obfuscated)와 빌드 결과물 경로(bin\Release\net7.0-windows)의 어셈블리는 난독화가 되어있지만
게시 경로(bin\Release\net7.0-windows\publish) 어셈블리는 난독화가 되어 있지 않습니다.
이를 해결하기 위해 난독화 하는 시점을 변경해 주어야 합니다.

난독화 적용 시점 변경

빌드가 완료된 후가 아니라 컴파일 후 난독화 처리를 하게 수정할 것입니다.
또한 Release 모드 일때만 난독화를 하게끔 같이 수정하겠습니다.

프로젝트 파일 수정

솔루션 탐색기에서 프로젝트를 클릭하거나 탐색기에서 직접 프로젝트 파일을 열어보면,
다음 처럼 빌드 후 이벤트가 적용된 부분을 확인할 수 있습니다.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net7.0-windows</TargetFramework>
    <RootNamespace>Dot_Net7_WPF_Obfuscar</RootNamespace>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Obfuscar" Version="2.2.37">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="cd $(ProjectDir)&#xD;&#xA;&quot;$(Obfuscar)&quot; Obfuscar.xml&#xD;&#xA;copy &quot;$(OutputPath)\Obfuscated\$(AssemblyName).dll&quot; &quot;$(OutputPath)\$(AssemblyName).dll&quot;" />
  </Target>

</Project>

빌드 후 이벤트가 적용된 부분을 삭제한 다음 다음과 같이 수정합니다.
Release 모드 일때 컴파일이 완료된 후 실행되는 명령을 추가하였습니다.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net7.0-windows</TargetFramework>
    <RootNamespace>Dot_Net7_WPF_Obfuscar</RootNamespace>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Obfuscar" Version="2.2.37">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <!--<Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="cd $(ProjectDir)&#xD;&#xA;&quot;$(Obfuscar)&quot; Obfuscar.xml&#xD;&#xA;copy &quot;$(OutputPath)\Obfuscated\$(AssemblyName).dll&quot; &quot;$(OutputPath)\$(AssemblyName).dll&quot;" />
  </Target>-->
  
  <Target Name="Obfuscation" AfterTargets="AfterCompile" Condition="'$(Configuration)' == 'Release'">
    <!--Optional to log a message.-->
    <Message Text="Obfuscating..." Importance="high" />
    <Exec Command="obfuscar.console Obfuscar.xml" />
    <Exec Command="COPY &quot;$(ProjectDir)$(IntermediateOutputPath)Obfuscated\$(TargetFileName)&quot; &quot;$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName)&quot;" />
  </Target>
  
</Project>

Obfuscar 설정 파일 수정

Obfuscar.xml 파일도 다음과 같이 수정합니다.
InPath 를 IntermediateOutputPath 로 수정하였습니다.

<?xml version='1.0'?>
<Obfuscator>
  <Var name="InPath" value=".\obj\Release\net7.0-windows" />
  <Var name="OutPath" value="$(InPath)\Obfuscated" />
  
  <Var name="KeepPublicApi" value="true" />
  <Var name="HidePrivateApi" value="true" />
  <Var name="HideStrings" value="true" />

  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.5" />
  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\7.0.5" />
  
  <Module file="$(InPath)\Dot Net7 WPF Obfuscar.dll" />
</Obfuscator>

Obfuscar Global Tool 로 대체

프로젝트 단위로 매번 Package 를 추가하는 것보다 Obfuscar Global Tool 을 해당 머신에 Gloabl package 로 설치해 두면 좀 더 편리합니다.

Global Tool 설치

다음 링크를 참고해서 해당 Package 를 Global 로 추가합니다.(NuGet Gallery | Obfuscar.GlobalTool 2.2.37)
명령 프롬프트에서 다음과 같이 입력하면 최신버전의 Package 가 Global 로 설치됩니다.

dotnet tool install --global Obfuscar.GlobalTool

프로젝트 Nuget package 제거

프로젝트에서 앞에서 설치한 Obfuscar package 를 제거합니다.

게시 후 난독화 여부 확인

이제 게시 페이지로 다시 와서 게시해 보면 게시 폴더에 있는 어셈블리도 난독화가 적용된 것을 확인할 수 있습니다.
로컬 폴더 뿐만 아니라 ClickOnce 로 배포하는 경우에도 난독화가 적용됩니다.

Github

해당 예제의 소스 코드는 다음 Github repository 를 참조하시면 됩니다.

Learn more on this topic

Related Blog Posts

C# 으로 사용자 입력을 받아 동작하는 콘솔 프로그램 구현

C# 으로 사용자 입력을 받아 동작하는 콘솔 프로그램 구현

네이버 지식인에서 우연히 보게 된 누군가의 질문... c# 콘솔 형태의 프로그램이며, 일정 갯수의 숫자를 데이터로 입력 받아 최대값/최소값 등을 구하거나 종료할 수 있는 기능을 하는 프로그램이 요구사항 이었다 내가 답변한 원문은 여기 : C# 프로그래밍 질문 : 지식iN (naver.com) 네이버 지식인 링크 실제 프로그램이 실행되는 스크린샷은 다음 이미지와 같습니다. 프로그램이 실행되면 메뉴 설명을 출력합니다. 메뉴 선택에서 0~3 까지 숫자를 입력 받아 메뉴 선택의...

read more
Blazor bootstrap theme sample

Blazor bootstrap theme sample

전체 소스 코드는 다음 Github 의 BlazorBootswatchTheme 폴더에 있습니다 https://github.com/kkomzi7179/BlazorWASMSample .net 으로 생성된 blazor wasm 기본 템플릿은 bootstrap 을 기반으로 하고 있습니다. 그리고 bootstratp 을 기반으로 다양한 테마를 제공하는 bootswatch 오픈소스 프로젝트가 있습니다. https://github.com/thomaspark/bootswatch MIT...

read more

Join in the conversation

Leave a Comment

0 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

무료 온라인 전광판

전광판

텍스트를 입력하고 텍스트 효과 및 배경효과 를 변경해서 전체화면으로 표시할 수 있는 전광판 용도로 사용하실 수 있습니다. 각종 스포츠 및 공연 관람시 응원 용도로 사용이 가능합니다.

Carousel

여러개의 슬라이드를 추가하여 프레젠테이션 및 이미지 슬라이드 용도로 사용하실 수 있습니다. 브라우저가 포함된 IT 기기로 큰 모니터에 연결하여 매장 내 공지사항 및 메뉴소개를 이미지로 표시할 수 있습니다.

Pin It on Pinterest

Shares
Share This

Share This

Share this post with your friends!

Shares