OS 보안 기능으로 인해 커널 메모리의 후킹이나 수정이 제한되므로, 해당 보안 기능을 비활성화한 OS를 직접 빌드하여 설치해야 한다.
이 가이드는 특정 단말기를 예시로 설명하고 있지만, 엑시노스 칩셋을 사용하는 다른 삼성 기기들도 얼마든지 적용이 가능하다. 리니지OS 홈페이지에서 본인의 모델을 검색해 ZIP 파일을 다운로드한 뒤, 아래와 같은 순서로 시도하면 된다.

준비물
OS : Ubuntu 24.03 LTS
단말기 : 갤럭시 S6 LITE (OEM 잠금 해제 된)

진행 순서
1. 태블릿에 공식 리니지 OS 설치
2. 리눅스에서 리니지 OS 빌드
- 커널 버전이 높을수록 적용된 보안 기능이 많아지므로, 가능한 한 낮은 커널 버전(필자가 설치한 롬은 4 버전 커널) 을 사용하여 진행한다.
3. 태블릿에 빌드한 리니지 OS 설치
4. 크로스 컴파일러로 커널 빌드
5. syscall 후킹 lkm 빌드

1. 태블릿에 공식 리니지 OS 설치

1. 드라이버 설치 후 재부팅 : https://github.com/daynix/usbdk/releases/latest
heimdall : https://blob.lineageos.org/downloads/heimdall/Heimdall-Windows-v2.2.2-120625.zip
2. 전원을 끈 후, 볼륨 상 + 볼륨 하를 동시에 누르면서, 1초후에 usb를 연결하고, 볼륩 상을 눌러 다운로드 모드에 진입한다.
3. https://b4.timschumi.net/lineage-archive/lineage-20.0-20240629-nightly-gta4xlwifi-signed.zip 다운로드
4. zip을 해제한 후, recovery.img 설치

heimdall flash --RECOVERY recovery.img

5. 위 명령어를 실행하면 바로 재부팅이 되는데, 볼륨 상 + 파워를 길게 눌러 리커버리 모드 진입  
6. Factory Reset -> 3개 전부 실행
7. 메인 메뉴로 이동 후 Apply update-> apply from adb 후 아래 명령어 실행

adb -d sideload lineage-20.0-20240629-nightly-gta4xlwifi-signed.zip

8. 재부팅 후, 개발자 옵션에서(설정 -> 시스템에 위치) adb 디버깅 enable 및 디버깅 시 루트 권한 사용 enable 

2. 리눅스에서 리니지 OS 빌드

$ sudo apt-get install python-is-python3 brotli repo adb bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf imagemagick protobuf-compiler python3-protobuf lib32readline-dev lib32z1-dev libdw-dev libelf-dev libgnutls28-dev lz4 libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev
$ wget https://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2_amd64.deb && sudo dpkg -i libtinfo5_6.3-2_amd64.deb && rm -f libtinfo5_6.3-2_amd64.deb
$ wget https://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2_amd64.deb && sudo dpkg -i libncurses5_6.3-2_amd64.deb && rm -f libncurses5_6.3-2_amd64.deb
$ git config --global user.email "abc@lol.com"
$ git config --global user.name "kim kim"
$ mkdir -p ~/android/lineage
$ export USE_CCACHE=1
$ export CCACHE_EXEC=/usr/bin/ccache
$ echo 'ccache -M 50G' >> ~/.bashrc
$ source ~/.bashrc
$ cd ~/android/lineage
$ repo init -u https://github.com/LineageOS/android.git -b lineage-20.0 --git-lfs --no-clone-bundle
$ repo sync
$ source build/envsetup.sh
$ croot
$ breakfast gta4xlwifi # 빌드 중 오류 발생은 당연함. 무시하고 아래 명령어 실행
$ cd ~/android/lineage/device/samsung/gta4xlwifi
$ ./extract-files.sh
$ cd ~/android/lineage
$ breakfast gta4xlwifi # 여기서 빌드 오류가 발생하면 안됨
# 보안 기능 off
$ sed -i \
-e 's/CONFIG_EXYNOS_KERNEL_PROTECTION=y/CONFIG_EXYNOS_KERNEL_PROTECTION=n/' \
-e 's/CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y/CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=n/' \
-e 's/CONFIG_STRICT_KERNEL_RWX=y/CONFIG_STRICT_KERNEL_RWX=n/' \
-e 's/CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y/CONFIG_ARCH_HAS_STRICT_MODULE_RWX=n/' \
-e 's/CONFIG_STRICT_MODULE_RWX=y/CONFIG_STRICT_MODULE_RWX=n/' \
-e 's/CONFIG_EXYNOS_CONTENT_PATH_PROTECTION=y/CONFIG_EXYNOS_CONTENT_PATH_PROTECTION=n/' \
-e 's/CONFIG_HAVE_ARCH_SECCOMP_FILTER=y/CONFIG_HAVE_ARCH_SECCOMP_FILTER=n/' \
~/android/lineage/kernel/samsung/gta4xl/arch/arm64/configs/exynos9611-gta4xlwifi_defconfig
# 보안 기능 삭제 (https://codetronik.tistory.com/155)
$ sed -i -e '/struct vm_struct \*area;/ s/^/\/\//' \
-e '/area = find_vm_area/,/return -EINVAL;/ s/^/\/\//' \
~/android/lineage/kernel/samsung/gta4xl/arch/arm64/mm/pageattr.c
$ croot
$ brunch gta4xlwifi
$ cd $OUT # 출력 파일 확인


3. 태블릿에 빌드한 리니지 OS 설치

1. 드라이버 설치 후 재부팅 : https://github.com/daynix/usbdk/releases/latest
heimdall : https://blob.lineageos.org/downloads/heimdall/Heimdall-Windows-v2.2.2-120625.zip
2. 전원을 끈 후, 볼륨 상 + 볼륨 하를 동시에 누르면서, 1초후에 usb를 연결하고, 볼륩 상을 눌러 다운로드 모드에 진입한다.
3. 빌드 한 recovery.img 설치

heimdall flash --RECOVERY recovery.img --no-reboot

4. 재부팅을 위해  볼륨 하 + 파워를 8~10초간 누르고 있다가 손 뗌
5. 재부팅 되면 볼륨 상 + 파워를 길게 눌러 리커버리 모드 진입  
6. Factory Reset -> 3개 전부 실행
7. 메인 메뉴로 이동 후 Apply update-> apply from adb 후 아래 명령어 실행

 adb -d sideload lineage-20.0-20251230-UNOFFICIAL-gta4xlwifi.zip

8. gapps 다운로드 https://github.com/MindTheGapps/13.0.0-arm64/releases/download/MindTheGapps-13.0.0-arm64-20231025_200931/MindTheGapps-13.0.0-arm64-20231025_200931.zip

 adb -d sideload MindTheGapps-13.0.0-arm64-20231025_200931.zip

9. 재부팅

4. 크로스 컴파일러로 커널 빌드

cd ~
git clone https://github.com/Shubhamvis98/toolchains
export PATH="/home/code/toolchains/clang-r428724/bin:/home/code/toolchains/aarch64-linux-android-4.9/bin:$PATH"
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-android-
export CLANG_TRIPLE=aarch64-linux-gnu-
cd ~/android/lineage/kernel/samsung/gta4xl 
make clean
make mrproper
make exynos9611-gta4xlwifi_defconfig
make menuconfig  -> 실행 후 <Save> 클릭
make -j16 CC=clang

커널 소스 수정 (오류 발생 시)

# 파일 내 모든 "/drivers/misc/tzdev/"를 "drivers/misc/tzdev/"로 변경
sed -i 's|"/drivers/misc/tzdev/|"drivers/misc/tzdev/|g' drivers/misc/tzdev/tz_deploy_tzar.c

5. syscall 후킹 lkm 빌드

아래 2개의 파일을 작성한다.

// Makefile
hook-objs := main.o
obj-m += hook.o

KERNEL_PATH := ~/android/lineage/kernel/samsung/gta4xl
CCPATH := /home/code/toolchains/clang-r428724/bin:/home/code/toolchains/aarch64-linux-android-4.9/bin
ARCH=arm64

export PATH := ${CCPATH}:${PATH}
export CLANG_TRIPLE = aarch64-linux-gnu-
export CROSS_COMPILE = aarch64-linux-android-

all:
	make CC=clang ARCH=$(ARCH) CFLAGS=$(CFLAGS) -C $(KERNEL_PATH) M=$(PWD) modules -j$(nproc --all)

clean:
	make -C $(KERNEL_PATH) M=$(PWD) clean
// main.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ftrace.h> // kallsyms_lookup_name()
#include <linux/uaccess.h> // copy_to_user()
#include <linux/slab.h>
#include <asm/set_memory.h>
#include <linux/nls.h>
#include "util.h"

MODULE_AUTHOR("codetronik");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("Anti Android Root Detector");

u64 *sys_call_table;

typedef asmlinkage int (*_original_faccessat)(int dfd, const char __user *filename, int mode);
_original_faccessat org_faccessat;

static int (*p_set_memory_rw)(unsigned long, int);

asmlinkage int hook_faccessat(int dfd, const char __user *filename, int mode)
{
	pr_info("[CODETRONIK] hello");
	return org_faccessat(dfd, filename, mode);
}

int init_module(void)
{
	sys_call_table = (u64*)kallsyms_lookup_name("sys_call_table");	
	pr_info("[CODETRONIK] syscall table %016lx", sys_call_table);
	p_set_memory_rw = (void*)kallsyms_lookup_name("set_memory_rw");
	p_set_memory_rw((unsigned long)sys_call_table, 1);
		
	org_faccessat = (_original_faccessat)sys_call_table[__NR_faccessat];
	sys_call_table[__NR_faccessat] = (u64)hook_faccessat;
	return 0;
}

void cleanup_module(void)
{
	sys_call_table[__NR_faccessat] = (u64)org_faccessat;
}

빌드 및 모듈 설치 방법

$ make
$ adb root
$ adb push hook.ko /data/local/tmp
gta4xlwifi:/ $ adb shell
gta4xlwifi:/ $ insmod /data/local/tmp/hook.ko

정상적으로 모듈이 설치되었으면, dmesg로 로그를 확인할 수 있다.

https://download.lineageos.org/gta4xlwifi에서 recovery.img  및 lineage-23.0-20251213-nightly-gta4xlwifi-signed.zip 다운로드

이미 oem언락 된 상태라면 1~3 과정은 생략

1. adb 디버그 허용, oem 언락 허용(빌드버전 연타하면 나옴)

2. 파워 off 후 볼륨 상 + 볼륨 하(One UI 3.0이상,보통 안드로이드11버전)를 동시에 누르면서, 1초후에 usb를 연결한다. (연결되어있는 상태면 안되고 타이밍 맞게 연결해줘야됨) 잠시 후 다운로드 모드로 진입하게 된다.

볼륨상을 길게 눌러 부트로더 언락을 진행한다.

3. 초기화 완료되면 다시 빌드버전 연타한 후 oem이 언락되어 있는지 확인

4. 2번처럼 한 후에 언락이 아닌 볼륨 업을 한번만 누른 후 다운로드 모드로 진입. 

5. odin 3.14.1 다운로드 및 실행

6. AP에 recovery.tar 지정 (7zip으로 recovery.tar로 압축) 및 start

7. 기존 설치된 OS로 재부팅되면, 다운로드 모드로 재 진입

8. 볼륨 하 + 전원 7초간 눌러 강제 재부팅 -> 화면 꺼지자마자 볼륨 상 + 전원으로 바꿔 누르기 -> 삼성 로고 나오면 전원 키 떼고 볼륨 상 유지.

9. Factory Reset -> 3개 전부 실행

10. 메인 메뉴로 이동 후 Apply update-> apply from adb 선택 후 cmd 실행

adb sideload lineage-23.0-20251213-nightly-gta4xlwifi-signed.zip

adb sideload MindTheGapps-16.0.0-arm64-20250812_214353.zip (https://wiki.lineageos.org/gapps/ 에서 다운로드)

adb sidelaod Magisk-v30.6.zip (https://github.com/topjohnwu/Magisk/releases 에서 최신 버전 apk 다운로드 후, 확장자를 zip으로 변경)

adb shell에서만 su가 필요하다면, Magisk를 설치하지 말고 개발자 옵션에서 "디버깅 시 루트 권한 사용" 체크 후 adb root -> adb shell로 접속

11. 재부팅

git clone https://github.com/microsoft/vcpkg C:\vcpkg
cd vcpkg
bootstrap-vcpkg.bat
vcpkg integrate install
vcpkg install folly:x64-windows
vcpkg install folly:x64-windows --head
#include <folly/portability/Windows.h>
#include <folly/init/Init.h>
#include <folly/logging/Init.h>
#include <folly/logging/xlog.h>
#include <folly/logging/StreamHandlerFactory.h>
#include <folly/logging/FileHandlerFactory.h>
#include <print>

int main(int argc, char** argv)
{
	SetConsoleOutputCP(CP_UTF8);

	folly::Init init(&argc, &argv);

	auto& db = folly::LoggerDB::get();
	db.registerHandlerFactory(std::make_unique<folly::StreamHandlerFactory>(), true);
	db.registerHandlerFactory(std::make_unique<folly::FileHandlerFactory>(), true);

	try {
		folly::initLogging(R"JSON(
			{
				"handlers": {
					"hconsole": {
						"type": "stream",
						"options": {
							"stream": "stderr",
							"formatter": "glog"
						}
					},
					"hfile": {
						"type": "file",
						"options": {
							"path": "logs/myapp_{Y}{m}{d}_{H}{M}{S}.log",
							"formatter": "glog",
							"level": "INFO",
							"max_file_size": 10485760,
							"max_files": 30,
							"buffer_size": 1048576,
							"append": true,
							"timestamp_precision": "millisecond"
						}
					}
				},
				"categories": {
					".": {
						"level": "DBG",
						"handlers": [
							"hconsole", 
							"hfile"
						]
					}
				}
			}
		)JSON");
	}
	catch (const std::exception& ex) {
		std::println(stderr, "[log-init] {}", ex.what());
		return -1;
	}

	XLOG(INFO) << "info";
	XLOGF(INFO, "formatted info={}", 1000);
	XLOG(DBG) << "debug";
	XLOG(WARN) << "warning";
	XLOG(ERR) << "error";

	return 0;
}

구성 속성 -> C/C++ ->
1. -> 전처리기 -> 전처리기 정의 -> GLOG_USE_GLOG_EXPORT
2. -> 외부 include 지시문 -> 외부 헤더 경고 수준 -> 모든 경고 해제(/external:W0)
3. -> 명령줄 - > /utf-8 추가

 

 

'Language > C++' 카테고리의 다른 글

[poco] 로그 예제  (0) 2025.07.22
[C++20] std::span  (0) 2025.05.25
[C++] 함수 const 선언 정리  (0) 2024.09.12

1. 새 프로젝트 만들기 → Empty WDM Driver
2. 프로젝트 생성 후 .inf 파일 삭제
3. 프로젝트에 main.cpp 추가
4. IDE → 보기 → 다른 창 → 속성 관리자 클릭
5. Debug | x64 선택 후 우 클릭 → 새 프로젝트 속성 시트 추가 → 속성 시트(.props) 추가
6. 추가 한 속성 시트 우 클릭 → 속성 클릭
7. 공용 속성 → 사용자 매크로 → 매크로 추가
이름 : DisableKernelFlag
값 : true
8. 프로젝트 →  속성 → 구성 속성 → C/C++ → 코드 생성 → C++ 예외 처리 가능 → 예(/EHsc)
9. 프로젝트 →  속성 → 구성 속성 → 일반  → C++ 언어 표준 → 미리 보기 - ISO C++23 표준
10. x64 Native Tools Command Prompt for VS 2022 실행
11. vcrtl 다운로드 및 vcrtl 프로젝트 실행

git clone https://github.com/avakar/vcrtl
cd vcrtl
cmake .
vcrtl.sln

12. vcrtl 프로젝트 →  속성 → 구성 속성 → 일반  → C++ 언어 표준 → 미리 보기 - ISO C++23 표준
13. vcrtl 빌드 및 산출물 .lib을 내 프로젝트에 복사
14. 내 프로젝트 →  속성 → 구성 속성 → 링커 → 입력 → 추가 종속성 → vcrtl_driver.lib
15. main.cpp 작성 및 빌드

#include <ntifs.h>

EXTERN_C VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
	UNREFERENCED_PARAMETER(DriverObject);
}

EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath)
{

	UNREFERENCED_PARAMETER(RegPath);
	DriverObject->DriverUnload = DriverUnload;

	try {
		throw 1;
	}
	catch (int i) {
		KdPrint(("catch");
	}

	return STATUS_SUCCESS;
}

 

 

제목 설명
Empty Static Library for Drivers (Universal) 유니버설 드라이버용 정적 드라이버 라이브러리를 만들기 위한 빈 프로젝트
WinUSB Application (Universal) USB 장치에 액세스하기 위한 유니버설 애플리케이션 스켈레톤
Kernel Mode Driver, USB (KMDF) Kernel-Mode Driver Framework(KMDF)를 사용하는 USB 장치 프로젝트. 기본값으로 유니버설 드라이버로 빌드됨
Filter Driver: NDIS NDIS 필터 드라이버용 프로젝트. 기본값으로 유니버설 드라이버로 빌드됨
User Mode Driver, USB (UMDF v2) User-Mode Driver Framework v2(UMDF2)를 사용하는 USB 장치 프로젝트. 기본값으로 유니버설 드라이버로 빌드됨
Driver Install Package 하나 이상의 드라이버 프로젝트에서 생성된 드라이버 파일을 포함하는 드라이버 패키지를 만드는 프로젝트
WinUSB INF Driver Package USB 장치에 WinUSB를 로드하는 데 사용할 수 있는 .INF 파일을 드라이버 패키지에 생성
Kernel Mode Driver (KMDF) Kernel-Mode Driver Framework(KMDF)를 사용하는 기본 프로젝트. 기본값으로 유니버설 드라이버로 빌드됨
Kernel Mode Driver, Empty (KMDF) Kernel-Mode Driver Framework(KMDF)를 사용하는 빈 프로젝트. 기본값으로 유니버설 드라이버로 빌드됨
User Mode Driver (UMDF v2) User-Mode Driver Framework v2(UMDF2)를 사용하는 기본 프로젝트. 기본값으로 유니버설 드라이버로 빌드됨
User Mode Driver, Empty (UMDF v2) User-Mode Driver Framework v2(UMDF2)를 사용하는 빈 프로젝트. 기본값으로 유니버설 드라이버로 빌드됨
Empty WDM Driver WDM 드라이버를 만들기 위한 빈 프로젝트
Printer Driver v4 V4 프린터 드라이버 프로젝트(GPD 또는 PPD 기반). 프린터 드라이버는 Windows 데스크톱 장치에서만 실행 가능
Printer Driver v4 Property Bag V4 프린터 드라이버의 프로퍼티 백(project) 프로젝트. 프린터 드라이버는 Windows 데스크톱 장치에서만 실행 가능
Printer XPS Render Filter 프린터 드라이버용 XPS 렌더 필터 프로젝트. 프린터 드라이버는 Windows 데스크톱 장치에서만 실행 가능
Empty Desktop Application for Drivers (Universal) 유니버설 드라이버와 상호작용하는 애플리케이션을 만들기 위한 빈 프로젝트

 

특징

- 업그레이드 및 설치 시, 기존 서비스는 중지한 후 설치함

- 언인스톨러는 설정 > 앱 > 설치된 앱에서 확인 가능

- 언인스톨 시, 기존 서비스를 중지하고 제거함

- GUID가 같으면 설치되지 않음

 

테스트 서비스 프로그램 만들기

1. Visual Studio 2022 → 새 프로젝트 만들기 → 작업자 서비스 선택하여 프로젝트 생성

2. NuGet 패키지 관리자로 아래 두 개 설치

3. Program.cs 를 아래와 같이 코딩 후 빌드

using WorkerService1;
using Microsoft.Extensions.Hosting.WindowsServices;

var builder = Host.CreateApplicationBuilder(args);
// Windows 서비스로 동작하도록
builder.Services.AddWindowsService(o =>
{
    o.ServiceName = "My Worker Service";
});
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

4. 단일 배포 파일 생성

dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:SelfContained=true

 

WiX v4 설치 후 구성

다운로드 및 설치 : https://marketplace.visualstudio.com/items?itemName=FireGiant.FireGiantHeatWaveDev17

1. Visual Studio 2022 → 새 프로젝트 만들기 → MSI Package 선택하여 프로젝트 생성

2. 코드 수정 및 빌드

// ExampleComponents.wxs
<!-- ExampleComponents.wxs -->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
     xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
	<Fragment>
		<ComponentGroup Id="ExampleComponents" Directory="INSTALLFOLDER">
			<Component>
				<File Id="Service1"
					  Source="C:\Users\codetronik\source\repos\WorkerService1\WorkerService1\bin\Release\net8.0\win-x64\publish\WorkerService1.exe"
					  KeyPath="yes" />

				<!-- 서비스 등록 -->
				<ServiceInstall
					Name="MyService1"
					DisplayName="My Service"
					Description="Service example"
					Type="ownProcess"
					Start="auto"
					Account="LocalSystem"
					ErrorControl="normal"/>

				<!-- 설치/업그레이드/제거 시 제어 -->
				<ServiceControl
					Name="MyService1"
					Stop="both"
					Start="install"
					Remove="uninstall"
					Wait="yes"/>

			</Component>
		</ComponentGroup>
	</Fragment>
</Wix>

// Folder.wxs
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
	<Fragment>
		<StandardDirectory Id="ProgramFiles64Folder">
			<Directory Id="INSTALLFOLDER"
					   Name="!(bind.Property.Manufacturer) !(bind.Property.ProductName)" />
		</StandardDirectory>
	</Fragment>
</Wix>

// Package.en-us.wxl
<!--
This file contains the declaration of all the localizable strings.
-->
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">

  <String Id="DowngradeError" Value="A newer version of [ProductName] is already installed." />

</WixLocalization>

// Package.wxs
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
	<Package Id="MyServicePkg"
			 Name="ServiceExample"
			 Manufacturer="Codetronik"
			 Version="1.0.0.0"
			 UpgradeCode="{1B29FC40-CA47-1067-131D-00DD010662DA}">
		<MajorUpgrade Schedule="afterInstallValidate"
					  DowngradeErrorMessage="!(loc.DowngradeError)" />
		<Feature Id="Main">
			<ComponentGroupRef Id="ExampleComponents" />
		</Feature>
	</Package>
</Wix>

 

 

환경 : Ubuntu 24.04.3 / 램 16G

SaaS를 사용 못하는 내부망에서 사용하기 위함

2025.08.12 기준

1. 도커 설치 (https://docs.docker.com/engine/install/ubuntu/ 참조)

$ wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/containerd.io_1.7.27-1_amd64.deb && \
wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/docker-ce-cli_28.3.3-1~ubuntu.24.04~noble_amd64.deb && \
wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/docker-ce_28.3.3-1~ubuntu.24.04~noble_amd64.deb && \
wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/docker-buildx-plugin_0.26.1-1~ubuntu.24.04~noble_amd64.deb && \
wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/docker-compose-plugin_2.39.1-1~ubuntu.24.04~noble_amd64.deb
$ sudo dpkg -i ./containerd.io_1.7.27-1_amd64.deb ./docker-ce-cli_28.3.3-1~ubuntu.24.04~noble_amd64.deb ./docker-ce_28.3.3-1~ubuntu.24.04~noble_amd64.deb ./docker-buildx-plugin_0.26.1-1~ubuntu.24.04~noble_amd64.deb ./docker-compose-plugin_2.39.1-1~ubuntu.24.04~noble_amd64.deb
$ sudo service docker start & sudo docker run hello-world

2. 리버스 프록시 설치

$ sudo apt-get install nginx
# 인증서 만들기
$ IP=192.168.130.189
$ sudo openssl req -x509 -newkey rsa:2048 -days 825 -nodes -subj "/CN=${IP}" -addext "subjectAltName = IP:${IP}" -keyout /etc/ssl/private/sentry-ip.key -out /etc/ssl/certs/sentry-ip.crt
$ sudo vim /etc/nginx/sites-available/sentry.conf
# 80 -> 443 리다이렉트
server {
  listen 80;
  return 301 https://$host$request_uri;
}

# HTTPS 종단 (IP 기반, 기본 서버)
server {
  listen 443 ssl http2;

  ssl_certificate     /etc/ssl/certs/sentry-ip.crt;
  ssl_certificate_key /etc/ssl/private/sentry-ip.key;

  client_max_body_size 50m;

  location / {
    proxy_set_header Host               $host;
    proxy_set_header X-Forwarded-Host   $host;
    proxy_set_header X-Forwarded-Proto  https;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:9000;
  }
}
$ sudo ln -s /etc/nginx/sites-available/sentry.conf /etc/nginx/sites-enabled/sentry.conf
$ sudo nginx -t
$ sudo systemctl reload nginx

3. Self-Hosted Sentry 설치 (https://develop.sentry.dev/self-hosted/ 참조)

$ sudo apt-get install git curl
$ VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/getsentry/self-hosted/releases/latest)
$ VERSION=${VERSION##*/}
$ git clone https://github.com/getsentry/self-hosted.git
4 cd self-hosted
$ git checkout ${VERSION}
$ sudo ./install.sh

$ vim sentry/config.yml
system.url-prefix: "https://192.168.130.189"
$ vim sentry/sentry.conf.py
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
USE_X_FORWARDED_HOST = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SOCIAL_AUTH_REDIRECT_IS_HTTPS = True
CSRF_TRUSTED_ORIGINS = ["https://192.168.130.189"]
$ sudo sed -i -E 's|proxy_set_header[[:space:]]+X-Forwarded-Proto[[:space:]]+\$scheme;|proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;|g' nginx.conf

$ sudo docker compose up --wait

4. curl  + sentry 에러 전송 예제

라이브러리 설치

$ sudo apt install -y libcurl4-openssl-dev
$ git clone --recursive https://github.com/getsentry/sentry-native.git
$ cd sentry-native
$ cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo   # 백엔드는 기본값 사용
$ cmake --build build --parallel
$ sudo cmake --install build

CMakeLists.txt 생성

cmake_minimum_required(VERSION 3.20)
project(app CXX)

find_package(sentry CONFIG REQUIRED)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE sentry::sentry)
#include <sentry.h>
#include <cstdio>
#include <stdexcept>

int main() {
    const char* DSN = "https://님_공개키@192.168.130.189/2";

    sentry_options_t* options = sentry_options_new();
    sentry_options_set_debug(options, 1);
    sentry_options_set_logger(options,
        [](sentry_level_e lvl, const char* msg, void*) {
            std::fprintf(stderr, "[sentry:%d] %s\n", (int)lvl, msg);
        }, nullptr);

  
    sentry_options_set_dsn(options, DSN);
    sentry_options_set_database_path(options, ".sentry-native");
    sentry_options_set_ca_certs(options, "아까만든인증서.crt");
    sentry_options_set_release(options, "myproject@1.0.0");    
    sentry_options_set_handler_path(options, "/usr/local/bin/crashpad_handler");

    // 원한다면 환경/태그
    sentry_options_set_environment(options, "dev");
    
    if (sentry_init(options) != 0) {
        throw std::runtime_error("sentry_init failed");
    }

    // 테스트 이벤트
    std::array<void*, 256> frames{};
    int n = backtrace(frames.data(), frames.size());

    sentry_value_t st  = sentry_value_new_stacktrace(frames.data(), n);
    sentry_value_t exc = sentry_value_new_exception("error", std::string(msg).c_str());
    sentry_value_set_by_key(exc, "stacktrace", st);

    sentry_value_t evt = sentry_value_new_event();
    sentry_event_add_exception(evt, exc);
    sentry_capture_event(evt);

    // 크래시
    int* p = nullptr; *p = 42;

    sentry_close();
}

4. sentry-cli 설치 및 환경 설정

https://192.168.130.189/settings/account/api/auth-tokens/new-token/ 에서 토큰 생성

$ curl -sL https://sentry.io/get-cli/ | bash
# 환경 파일 설정
$ vim ~/.sentryclirc
[defaults]
url = https://192.168.130.189
org = sentry # 조직 slug
project = agent # 프로젝트 slug

[http]
verify_ssl = false

[auth]
token = 님_토큰

# 정상 동작 확인
$ sentry-cli info
# 조직 slug 확인
$ sentry-cli organizations list
+----+--------+--------+--------------+---------------+--------------+
| ID | Name   | Slug   | Date Created | Early Adopter | Requires 2FA |
+----+--------+--------+--------------+---------------+--------------+
| 1  | Sentry | sentry | 2025-08-12   | false         | false        |
+----+--------+--------+--------------+---------------+--------------+
# 프로젝트 slug 확인
$ sentry-cli projects list -o sentry
+----+----------+--------+----------+
| ID | Slug     | Team   | Name     |
+----+----------+--------+----------+
| 1  | internal | Sentry | Internal |
| 2  | agent    | Sentry | agent    |
+----+----------+--------+----------+

# 파일 유효성 확인
$ sentry-cli debug-files check 님_실행파일
# 분리 심볼 생성
objcopy --only-keep-debug 님_실행파일 님_실행파일.debug
objcopy --add-gnu-debuglink=님_실행파일.debug 님_실행파일
# 파일 업로드
$ sentry-cli debug-files upload --include-sources 님_실행파일 님_실행파일.debug

5. 크래시패드 정상 전송을 위해 프로그램을 설치한 pc에 인증서 설치

# sentry 서버에서 인증서 가져와서 루트 인증서에 설정
$ sudo cp sentry-ip.crt /usr/local/share/ca-certificates/sentry-ip.crt
$ sudo update-ca-certificates

'Linux > Dev' 카테고리의 다른 글

VMware + clion + libbpf 구축  (0) 2025.07.08
#include <iostream>
#include <Poco/Logger.h>
#include <Poco/PatternFormatter.h>
#include <Poco/FormattingChannel.h>
#include <Poco/ConsoleChannel.h>
#include <Poco/FileChannel.h>
#include <Poco/SplitterChannel.h>
#include <Poco/AutoPtr.h>
#include <Poco/Thread.h>
#include <Poco/Runnable.h>

using namespace Poco;

class LevelFilterFileChannel : public FileChannel
{
public:
    LevelFilterFileChannel() : FileChannel() {}

    void log(const Message& msg) override
    {
        // debug, trace 로그 제외
        if (msg.getPriority() <= Message::PRIO_INFORMATION)
        {
            FileChannel::log(msg);
        }
    }
};

class MyWorker : public Runnable
{
public:
    void run() override
    {
        Logger& logger = Logger::get("aLogger");
        for (int i = 0; i < 5; ++i)
        {
            logger.notice("Poco Thread is running! i = " + std::to_string(i));
            Poco::Thread::sleep(500); // 0.5초 대기
        }
        logger.information("Poco Thread done.");
    }
};

int main()
{
    AutoPtr<ColorConsoleChannel> colorConsoleChannel(new ColorConsoleChannel);
    AutoPtr<LevelFilterFileChannel> fileChannel(new LevelFilterFileChannel);
    fileChannel->setProperty("path", "myapp.log");
    fileChannel->setProperty("rotation", "50000 K"); // 50,000KB 초과시 회전
    fileChannel->setProperty("archive", "timestamp");
    fileChannel->setProperty("purgeAge", "30 days"); // 30일 초과 로그 파일 삭제

    AutoPtr<PatternFormatter> patternFormatter(new PatternFormatter);
    patternFormatter->setProperty(
        "pattern",
        "[%Y-%m-%d %H:%M:%S] [%p] [PID:%P][TID:%T][TH:%I] %t"
    );
    patternFormatter->setProperty("times", "local");
   
    AutoPtr<FormattingChannel> fcConsole(new FormattingChannel(patternFormatter, colorConsoleChannel));  // 콘솔은 모든 로그
    AutoPtr<FormattingChannel> fcFile(new FormattingChannel(patternFormatter, fileChannel));

    // 콘솔 및 파일 채널로 메시지를 전달
    AutoPtr<SplitterChannel> splitter(new SplitterChannel);
    splitter->addChannel(fcConsole);
    splitter->addChannel(fcFile);  

    Logger& logger = Logger::get("Logger");
    logger.setChannel(splitter);
    logger.setLevel(Message::PRIO_TRACE); // 모든 로그 레벨 허용

    logger.fatal("FATAL 메시지");
    logger.critical("CRITICAL 메시지");
    logger.error("ERROR 메시지");
    logger.warning("WARNING 메시지");
    logger.notice("NOTICE 메시지");
    logger.information("INFO 메시지");
    logger.debug("DEBUG 메시지 - 콘솔만");
    logger.trace("TRACE 메시지 - 콘솔만");

    MyWorker worker;
    Thread thread;
    thread.start(worker);

    // 메인 스레드도 로그 남기기
    for (int i = 0; i < 3; ++i)
    {
        logger.notice("Main thread working... i = " + std::to_string(i));
        std::this_thread::sleep_for(std::chrono::milliseconds(400));
    }

    thread.join();
    logger.information("모든 작업 종료");
}

'Language > C++' 카테고리의 다른 글

[folly] 구축 및 로그 예제  (0) 2025.10.31
[C++20] std::span  (0) 2025.05.25
[C++] 함수 const 선언 정리  (0) 2024.09.12

환경 : ubuntu 24.04.02 LTS

 

# copy & paste 활성화
sudo apt install open-vm-tools open-vm-tools-desktop -y

#재부팅!

# clion 설치
sudo snap install clion --classic

# libbpf 관련 설치
cd ~
sudo passwd root
su
apt install clang clang-tools git libelf-dev make gcc llvm pkg-config libcap-dev libbfd-dev cmake
git clone --recurse-submodules https://github.com/libbpf/libbpf
git clone --recurse-submodules https://github.com/libbpf/bpftool
cd libbpf/src
make install
cd ~/bpftool/src
make install

'Linux > Dev' 카테고리의 다른 글

[가이드] Self-Hosted Sentry 설치 + cpp + 콜스택 추적 예제  (0) 2025.08.12

+ Recent posts