
Android용 맞춤형 Kali NetHunter 커널 빌드에 대한 단계별 가이드: 소스 확보, 툴체인 선택, 크로스 컴파일, 플래싱.
Nethunter 기기를 설정하려는 대부분의 사람들에게 가장 큰 장벽은 커널 요구 사항입니다. 기기에 이미 사전 빌드된(그리고 유지 관리되는) 커널이 없다면, 직접 커널을 빌드하라는 안내를 받게 될 것입니다. 이 과정에 대한 문서는 이미 많이 있지만, 제 경험상 어떤 내용이 자신의 경우에 해당하는지 아닌지 파악하기 어려울 수 있습니다.
이 문제는 나쁜 놈들 클릭베이트성 제목의 가이드를 쓰는 사람들, 예를 들어 “어떤 Android 기기에서든 Nethunter 커널을 빌드하자!” 또는 “10분 만에 Nethunter 커널 컴파일하는 법 배우기!” 같은 거짓 약속을 하는 사람들 때문에 더 악화됩니다. 또한 2025년 인터넷의 불행한 현실로, 많은 멍청이들 사람들이 ChatGPT나 다른 대규모 언어 모델이 자신의 질문에 대한 권위 있는 답변을 가지고 있다고 생각하지만, 그 모델들이 실제로 가진 것은 앞서 언급한 나쁜 놈들에게서 긁어 모은 정보일 뿐입니다.
저는 이 가이드를 가능한 한 철저하고 정직하게 작성하고 있습니다. 하지만 이 문서가 이 과정에서 읽어야 할 유일한 문서가 되도록 의도된 것은 아닙니다. 분명 이 문서가 답할 수 없는 질문이 생길 것입니다. 그러한 질문에 대한 답은 관련 소프트웨어 문서에서 찾으시고, YouTube나 ChatGPT에서는 찾지 마시기 바랍니다.
이 과정의 어떤 단계를 시작하기 전에, 이미 다음을 완료해 두어야 합니다:
apt update && apt upgrade -y (선택 사항: 메타패키지 추가)이 과정을 완료하려면 다음이 필요합니다:
cd, rm, ls, mkdir, find, diff, grep, 등)vim, 그 외에는 nano)build-devel, Debian 계열은 build-essential) – 일부 커널 Makefile에서 필요로 하므로 Perl + Python3도 설치하는 것이 좋습니다.내 기기에서도 가능할까?
Linux 커널은 카피레프트 라이선스인 GNU General Public License 2.0으로 라이선스되어 있습니다. 즉, Linux 커널의 소스 코드는 자유롭게 배포되며 원하는 대로 소스 코드를 수정할 수 있지만(각 Android 제조사가 그렇게 해 왔듯이), 그러나 수정 결과물인 소스 코드 역시 자유롭게 배포되어야 합니다.
놀랍지도 않게도, GPL 라이선스 코드를 사용하는 거대 기업들 중 상당수가 이 라이선스의 조항을 무시합니다. 그들은 소스 코드 배포를 거부하거나 일부만 공개합니다(대개 망가졌거나 오래되었거나 인라인 바이너리 블롭이 포함된 형태로). 기기용 커널의 소스 코드를 구할 수 없다면, 그 기기용 Nethunter 커널을 만들 방법은 없습니다.
부트로더 잠금을 해제하고 커스텀 ROM을 설치할 수 있는지 여부도 기기 제조사의 변덕에 크게 좌우됩니다. 제조사가 부트로더 잠금 해제를 허용하고 Magisk로 휴대폰을 루팅할 수 있었다 하더라도, 디바이스 트리를 공개하지 않으면 기기용 커스텀 ROM이 없을 가능성이 높습니다. 이런 경우, 그들이 공개한 커널 소스 코드(있다면)가 출시 이후 전혀 관리되지 않았거나, 수정 없이는 빌드조차 되지 않을 가능성이 매우 높습니다. 다른 누군가가 당신의 기기를 위해 무언가(커널, ROM, 리커버리)를 유지 관리하고 있는 모습이 보이지 않는다면, 그 기기를 완전한 Nethunter로 만드는 것은 불가능하지는 않더라도 매우 어려울 것입니다.
커널 버전에 관한 참고 사항
당신의 기기에 정기적으로 업데이트되고 유지 관리되는 커스텀 ROM/커널/리커버리가 있다고 가정해 봅시다. 하지만 Nethunter 커널만 존재하지 않는다고요. 이 경우에는 이 과정을 완료할 수 있어야 하지만, 그 과정은 기기가 사용하는 Linux 커널 버전에 따라 달라집니다.
이 가이드의 정보는 제가 4.14.x 커널을 수정한 경험을 바탕으로 합니다. 3.x 커널에 적용되는 GCC 툴체인(우리가 사용할 LLVM/clang 대신) 사용에 대해 다루는 오래된 가이드도 있습니다. 기기가 5.x/6.x 버전의 Linux 커널을 사용한다면, 이 가이드의 정보만으로는 이 과정을 완료하기에 충분하지 않습니다. Android 빌드 방식은 수시로 바뀌므로, GKI 커널과 Bazel/Kleaf 사용을 다루는 가이드를 찾아보시기 바랍니다.
기기용 커널 소스가 포함된 저장소를 찾는 좋은 방법은 해당 기기의 코드네임을 사용하는 것입니다. 모든 Android 기기에는 코드네임이 있습니다. 일부 제조사(예: OnePlus)는 다른 제조사(예: Samsung)보다 이 작명을 조금 더 재미있게 하기도 하지만요. 제 Xiaomi Poco X3 NFC의 코드네임은 “surya”이고, 제 Samsung A51의 코드네임은 “SM-A515F”입니다. 일반적으로 커널 소스 저장소는 android_kernel_MANUFACTURER_CODENAME 명명 규칙을 따릅니다. 여기서 제조사는 모회사, 즉 android_kernel_xiaomi_surya이지 android_kernel_poco_surya가 아닙니다. 하지만 기기의 SoC(시스템 온 칩)를 기준으로 한 저장소도 있을 수 있으며, 같은 SoC를 사용하는 다른 기기의 소스 파일을 포함하도록 “통합”된 경우도 있습니다. 제가 언급한 Samsung이 그런 경우로, 소스 저장소 이름은 android_kernel_samsung_exynos9611입니다. github/gitlab을 살펴보고 무엇을 찾을 수 있는지 확인해 보세요.
이 가이드에서는 surya에 최신 LineageOS 22.2(2025-08-04 빌드)를 사용할 예정이므로, LineageOS 저장소에서 커널 소스를 클론하려고 합니다. 하지만 그 전에 기기에서 커널 빌드에 사용할 컴퓨터로 두 파일 /proc/config.gz와 /proc/version을 복사하고 싶습니다.
첫 번째 파일인 /proc/config.gz를 /sdcard에 복사하고, ADB로 기기에서 가져온 다음 gunzip으로 압축을 풀고 이름을 바꿀 수도 있습니다. 하지만 단계가 너무 많아 보여서, 대신 저는 이렇게 했습니다:

그런 다음 기기 자체에서 (root로) 다음을 실행했습니다:

여기서 무슨 일이 일어나고 있는 걸까요?
내 노트북에서: nc(netcat) -l(들어오는 연결 수신 대기) -p(포트) 4545(실제로는 1024-65535 사이의 아무 숫자나 가능하지만, 저는 보통 4545를 사용합니다) >(파일에 쓰기) surya-defconfig-lineageos22.2-20250804(설명적인 파일 이름) <(파일에서 입력받기) /dev/null(널 장치 – 키보드를 건드리더라도 입력된 키 입력이 수신 중인 파일로 전송되어 망치는 일을 방지합니다).
휴대폰에서: zcat(연결을 위한 cat 명령과 비슷하지만 gzip 압축 파일용) /proc/config.gz(현재 실행 중인 커널이 빌드될 때 사용된 커널 구성) |(그 프로세스의 출력을 다음 프로세스의 입력으로 전송) nc(다시 netcat) 192.168.1.42(내 노트북의 로컬 IP 주소) 4545(앞서 설정한 포트)
이렇게 하면 현재 실행 중인 커널을 빌드할 때 사용된 .config 파일을 얻을 수 있을 것으로 예상되지만, 항상 그런 것은 아닙니다. 일부 최신 기기/최신 ROM 빌드는 /proc/config.gz에 저장된 config가 스톡 커널 빌드에 사용된 .config와 일치하지 않으면 부팅을 거부합니다. 다행히도 이 검사가 전부입니다(커널 전체의 SHA256 체크섬처럼 훨씬 깨기 어려운 것이 아니라). 그래서 몇몇 영리한 사람들은 자신들의 수정에도 불구하고 /proc/config.gz의 파일을 스톡 커널과 일치하도록 스푸핑하는 방법을 고안했습니다. 기기의 파일이 진짜인지 스푸핑된 것인지 확실하지 않다면, zcat /proc/config.gz | head를 실행한 다음 uname -r을 실행해 보세요. 릴리스 번호가 일치하지 않으면 /proc 안의 파일은 스푸핑된 것입니다. 그런 경우에도 이 가이드를 계속 진행할 수는 있지만, 추출된 config와 커널 소스의 arch/arm64/configs 디렉터리에서 찾을 수 있는 일부 파일을 비교하기 위해 diff를 실행하는 것이 좋습니다.
/proc/version의 경우, 그 파일을 보내는 것이 그렇게 필요하지 않을 수도 있습니다. 실제로 필요한 것은 커널을 컴파일하는 데 사용된 clang/ld.lld 버전 정보뿐이니까요. 그러니 그냥 cat /proc/version을 실행해서 살펴보면 됩니다:

이런! 이 커널을 빌드한 사람이 약간 “실수”를 한 것 같습니다. Makefile에 clang으로 실행한 모든 -CFLAGS는 기록했지만 Clang 버전을 기록하지 않았네요. 하지만 그들이 사전 빌드된 Android 툴체인과 ld.lld 버전 19.0.1을 사용했다는 것은 알 수 있습니다.
여기 조금 더 도움이 되는 이미지가 있습니다. 첫 번째 출력은 Samsung A51에 새 커널을 수정, 빌드, 설치하기 전의 /proc/version이고, 두 번째 출력은 현재의 /proc/version입니다.

뭔가 눈에 띄나요? (아니요, 제 이상한 사용자 이름과 호스트네임 말고요).
사용할 툴체인을 고르는 가장 좋은 비결은 현재 실행 중인 커널을 컴파일한 정확한 툴체인을 사용하는 것입니다.
이 경우에는 Neutron clang 18.0.0git이었고, 찾기가 꽤 쉬웠습니다:

그런데 이것 좀 보세요. md5sum까지 모두 일치합니다.
재미 삼아, 훨씬 오래된 기기인 Samsung J7(2016), 코드네임 j7xelte의 /proc/version 문자열을 잠깐 살펴보겠습니다:

이 기기는 커널 컴파일에 여전히 GCC 툴체인을 사용할 만큼 오래된 기기입니다.
그런데 “gcc version 4.9.x 20150123 prerelease”로 검색하면 저장소가 두 개 나옵니다:

그렇다면 어떤 것을 다운로드해야 할까요?
답: 둘 다. GCC는 Clang과 다른 점이 있는데, 크로스 컴파일용 컴파일러/binutils/링커 등을 빌드할 때 각 “타깃 트리플”마다 별도의 툴체인을 빌드해야 한다는 것입니다. 타깃 트리플은 (아마도) 다음 형식을 취합니다:
machine-vendor-operating_system
하지만 곧 알게 되겠지만, 이 “규칙”에는 수백만 가지 예외가 있습니다. 그럼 “machine”부터 시작해 봅시다.
이 문서의 “필요한 것” 섹션에서 저는 GNU/Linux를 실행하는 Intel 또는 AMD 프로세서를 사용하는 64비트 컴퓨터가 필요하다고 말했습니다. 그 이유는 우리가 사용할 툴체인이 x86_64-linux-gnu에서 실행되도록 컴파일되었기 때문입니다.