mytechnotalent/Reverse-Engineering · 저자 Kevin Thomas · 언어 Assembly · 시작 2020-02-14 · 라이선스 Apache-2.0 · ★ 13,998 · shallow clone 소스 직접 분석)
리버스 엔지니어링은 완성된 프로그램에서 원래 설계를 되짚어 내는 일이다. 우리가 평소 하는 건 순방향이다 — C나 Rust로 소스를 쓰면 컴파일러가 기계어로 번역해 준다. 리버싱은 그 반대다. 기계어 덩어리만 손에 쥔 채 "이게 무슨 일을 하는가"를 알아내야 한다. 소스도, 주석도, 변수 이름도 없다.
컴파일은 되돌릴 수 없는 요리에 가깝다. 계란과 밀가루를 섞어 구우면 다시 계란으로 못 돌아간다. 컴파일러도 마찬가지다. 변수 이름, 주석, 코드 구조 대부분을 버리고 기계가 실행할 숫자 덩어리만 남긴다.
그럼에도 알아낼 수 있는 이유는, 요리에 흔적이 남기 때문이다. 반죽 결에서 밀가루의 종류가 보이고, 굽는 방식에서 오븐 온도가 짐작된다. 기계어에도 똑같다 — 함수 호출 규약, 스택 정리 방식, 문자열 상수, API 호출이 그대로 남는다. 이 강의가 550개 레슨 내내 훈련시키는 게 바로 그 흔적을 읽는 눈이다.
이 저장소가 다루는 범위는 상당히 넓다. 데스크톱 CPU(x86 · x64), 스마트폰과 라즈베리파이의 CPU(ARM-32 · ARM-64), 아두이노의 8비트 마이크로컨트롤러(AVR ATmega328P), 그리고 요즘 뜨는 개방형 아키텍처(RISC-V)까지. 여기에 WebAssembly를 마이크로컨트롤러에 올려 리버싱하는 최신 코스까지 붙었다.
저자는 Kevin Thomas(mytechnotalent)로, 해커 커뮤니티 DC540(DEF CON 그룹)을 운영하고 Ouroboros라는 하드웨어 해킹 배지도 만들어 판다. 저장소에는 그 배지의 암호 엔진 설명 PDF와 회로도(Fritzing .fzz)까지 들어 있다.
2020년 2월 14일에 시작해 오늘까지 6년 5개월. README 맨 위에는 언제나 「Today's Tutorial [날짜]」가 붙어 있고, 오늘 자는 Lesson 255: Hacking Rust Course (Chapter 10: Functions)다. 클론해서 확인해 보면 레슨 번호가 1번부터 550번까지 하나도 빠짐없이 이어진다 — 중간에 포기하고 건너뛴 흔적이 없다. 무료 교육 자료가 흔한 시대에 희소한 건 콘텐츠가 아니라 지속성이고, 이 저장소의 별은 대부분 거기에 붙은 표다.
x86 책 따로, ARM 책 따로 사서 보면 설명 스타일과 난이도가 제각각이라 머릿속에서 연결이 안 된다. 이 커리큘럼은 6종을 전부 같은 사람이, 같은 순서로 가르친다. 그래서 "x86에서 배운 스택 개념이 ARM에서는 어떻게 달라지는가"가 자연스럽게 비교된다. 실제로 각 코스가 거의 같은 뼈대를 반복한다 — 숫자 체계 → 레지스터 → 스택 → 명령어 → 실습.
430페이지 PDF 책 Reversing for Everyone이 저장소 안에 통째로 들어 있다(25MB). 위성 저장소마다 별도 PDF 책이 또 있다 — Hacking_Windows.pdf, Hacking Rust.pdf, hacking-bits.pdf, Hacking-RISC-V.pdf. 라이선스가 Apache-2.0이라 교육용 재배포·번역·2차 저작이 명시적으로 허용된다. (앞서 살펴본 라이선스 없는 저장소들과 대비되는 지점이다.)
후반부 코스는 대부분 실물 하드웨어를 쓴다. Raspberry Pi Pico/RP2350, ESP32-C3(RISC-V), ATmega328P(아두이노), micro:bit. 저장소에 Fritzing 회로도 3종(static RE schematic·dynamic RE schematic·oled and button schematic)이 들어 있고, Assembler 코스 24강은 LCD·시프트 레지스터·스테퍼 모터·릴레이·적외선 리모컨을 전부 순수 AVR 어셈블리로 제어한다. 화면 속 개념이 아니라 손에 잡히는 결과물로 끝난다는 게 완주율을 크게 높인다.
보통의 온라인 강의가 요리 동영상이라면, 이 커리큘럼은 6년째 매일 문 여는 요리 학원에 가깝다. 진도가 정해져 있고, 오늘 배울 게 칠판에 적혀 있고, 초급반(x86)부터 고급반(RISC-V·Wasm)까지 반이 나뉘어 있다. 그리고 수강료가 없다.
| 코스 | 레슨 | 번호대 | 무엇을 배우나 |
|---|---|---|---|
| x86 Course | 40 | 1–40 | 맬웨어 분석 개론 → 2진수·16진수 → 레지스터·플래그·스택·힙 → Linux/vim → ASM 6종 실습(작성·디버깅·해킹 3연타) |
| ARM-32 Course 1 | 25 | 41–65 | ARM 레지스터·CPSR·링크 레지스터·부트 절차·폰노이만 구조·명령어 파이프라인 |
| ARM-32 Course 2 | 49 | 66–114 | ARM 심화 — 가장 긴 코스 |
| ARM-32 Project | 6 | 115–120 | Hello World·int·float·double·char·char 포인터 해킹 실전 6종 |
| x64 Course | 43 | 121–163 | 트랜지스터·논리 게이트부터 다시 쌓아 올리는 64비트 과정 |
| ARM-64 Course | 20 | 164–183 | 64비트 ARM(AArch64) |
| Pico Hacking | 20 | 184–203 | Raspberry Pi Pico 개발환경 → Hello World → 디버깅 → 해킹 |
| Hacking Windows | 30 | 204–233 | 순수 어셈블리 Win32 MessageBox → x86/x64 디버깅·해킹 |
| Go Hacking | 12 | 234–245 | Go 바이너리 리버싱(런타임이 큰 언어의 특징) |
| Hacking Rust | 15 | 246–260 | Rust 바이너리 리버싱 — 오늘의 강의가 여기(Ch.10 함수) |
| Embedded Rust ×2 | 11 | 261–271 | Embassy 프레임워크로 Pico·micro:bit 임베디드 Rust |
| Embedded Assembler | 11 | 272–282 | 임베디드 어셈블리 입문 |
| Embedded Hacking | 40 | 283–322 | 임베디드 해킹 대형 코스 |
| Hacking Bits | 10 | 323–332 | 옴의 법칙·전자공학 기초 → 2진수 → ATmega328P 구조 → 툴체인 |
| Hacking RISC-V | 9 | 333–341 | ESP32-C3로 배우는 개방형 ISA. PlatformIO 환경 |
| RP2350 드라이버 ×6 | 180 | 342–521 | UART·Blink·Button 드라이버를 ARM판과 RISC-V판 각각 30강씩. 전체의 3분의 1 |
| Wasm ×5 | 5 | 522–526 | WebAssembly 컴포넌트를 RP2350 베어메탈에 올려 UART·LED·버튼·서보 제어 + 각각의 RE 튜토리얼 |
| Assembler Course | 24 | 527–550 | 순수 AVR 어셈블리로 Serial·LCD·온도계·시프트레지스터·7세그먼트·DC/스테퍼 모터·릴레이·IR 리모컨 |
표를 보면 무게중심이 어디로 옮겨갔는지 보인다. 초창기(2020~)는 x86·ARM 어셈블리 기초였는데, 최근 몇 년은 RP2350 마이크로컨트롤러 드라이버를 ARM판·RISC-V판으로 나란히 짜는 데 180강을 썼다. 같은 하드웨어를 두 아키텍처로 반복하는 구성이라, ISA 비교 학습에는 최적이지만 리버싱 자체를 배우려는 사람에겐 분량이 과하게 느껴질 수 있다. 목적에 맞게 골라 듣는 게 낫다.
경로 추천을 하나 하자면 이렇다. 리버싱이 목적이면 x86(1–40) → x64(121–163) → Hacking Windows(204–233) → Go/Rust(234–260)까지 약 145강이면 데스크톱 바이너리 분석의 기본기가 선다. 임베디드가 목적이면 Hacking Bits(323–332)로 전자공학 기초를 깔고 Assembler Course(527–550)로 바로 넘어가는 게 빠르다.
이게 가장 먼저 이해해야 할 사실이다. 저장소 이름은 Reverse-Engineering이지만, 내용물의 대부분은 여기 없다. README를 파싱해 보면 링크가 583개인데, 그 분포가 구조를 그대로 드러낸다.
한 곳만 보면 전체 지도가 보인다. 550강이 번호순으로 한 페이지에 늘어서 있으니, "지금 내가 어디쯤 왔고 다음은 뭔가"가 스크롤 한 번에 파악된다. 저자 입장에서도 코스마다 저장소를 나눠 두면 각 코스를 독립적으로 관리·배포할 수 있다. Hacking-Rust만 필요한 사람은 그 저장소만 클론하면 된다.
이 저장소는 도서관 카드 목록함이다. 목록함 자체에는 책이 없다. 대신 "3층 A열 12번에 이 책이 있다"는 카드가 550장 꽂혀 있다. 목록함이 있어야 도서관을 쓸 수 있다는 점에서 필수적이지만, 목록함을 통째로 집에 가져와도 책은 한 권도 안 딸려 온다.
초기 코스(레슨 1~203)의 링크를 세어 보면 199개가 전부 0xinfection.github.io/reversing 한 주소다. 즉 "레슨 27을 보려면" 그 e-book을 열고 해당 챕터를 직접 찾아가야 한다. 레슨 단위 딥링크가 아니다. 550강 중 200강 가까이가 이런 상태라, 초심자가 처음 부딪히는 마찰이 바로 여기다.
반면 후기 코스(Hacking Windows 이후)는 각 위성 저장소의 PDF나 lessons/NNN/lesson.md로 정확히 연결된다 — 시간이 지나며 저자도 이 문제를 인지하고 방식을 바꾼 흔적이다.
0xinfection.github.io는 저자 본인의 도메인이 아니다(다른 사람의 GitHub Pages에 호스팅된 e-book이다). 그 페이지가 내려가면 초기 200강의 학습 경로가 통째로 끊긴다. 다행히 같은 책의 PDF가 저장소 안에 reversing-for-everyone.pdf로 들어 있으니 그걸 받아 두는 게 안전하다 — 이 문서를 읽는 사람이 지금 바로 해 둘 만한 일이다.
2,978줄짜리 마크다운 한 파일이다. GitHub 웹에서 열면 스크롤이 길어 브라우저가 버벅이고, 모바일에서는 특히 심하다. 목차가 앵커 링크로 붙어 있긴 하지만, 레슨 번호로 점프하는 수단은 없다. "레슨 384가 뭐였지"를 찾으려면 Ctrl+F가 유일한 방법이다. 코스별 파일 분리나 정적 사이트 생성(예: GitHub Pages + mkdocs)이면 크게 나아질 지점이다.
클론해서 du를 재 보면 작업 트리만 423MB다. 그런데 .gitignore는 단 11바이트다. 그 결과 Visual Studio가 뱉은 중간 산출물이 전부 커밋돼 있다 — .obj · .pdb · .ilk · vc142.idb · *.tlog/*(빌드 로그) · CppClean.log. §5의 파일 목록을 보면 실제 소스(main.asm · main.c)보다 빌드 찌꺼기가 10배 이상 많다. 교육 저장소에서 흔히 보는 실수지만, 학습자가 클론할 때 그대로 비용이 된다.
.gitattributes 두 줄*.asm linguist-detectable=true
*.c linguist-detectable=false
GitHub 저장소 페이지의 언어 비율 막대를 조작하는 설정이다. .asm은 세고, .c는 세지 말라는 뜻. 그래서 이 저장소는 GitHub에 "Assembly"로 표시된다 — 실제로는 C 코드가 더 많은데도. 기술적으로 정당한 기능이고 "이 저장소의 정체성은 어셈블리다"라는 저자의 선언으로 읽히지만, 저장소 언어 표시는 언제나 사실이 아닐 수 있다는 걸 보여 주는 좋은 사례이기도 하다.
이 저장소에 실제로 들어 있는 소스 중 가장 상징적인 파일이 0x0001-hello_world-x86/main.asm이다. 순수 MASM 어셈블리로 윈도우 메시지 박스를 띄운다.
.686
.model flat, stdcall
.stack 4096
extrn ExitProcess@4: proc ;1 param 1x4
extrn MessageBoxA@16: proc ;4 params 4x4
.data
msg_txt db "Hello World", 0
msg_caption db "Hello World App", 0
.code
main:
push 0 ;UINT uType
lea eax, msg_caption ;LPCSTR lpCaption
push eax
lea eax, msg_txt ;LPCSTR lpText
push eax
push 0 ;HWND hWnd
call MessageBoxA@16
push 0
call ExitProcess@4
end main
@16의 의미 (stdcall name decoration)MessageBoxA@16의 숫자 16은 "인자들이 스택에서 차지하는 총 바이트 수"다. 인자 4개 × 4바이트 = 16. 이게 이름에 붙는 이유는 stdcall 규약에서 함수가 스스로 스택을 정리하기 때문이다 — 몇 바이트를 치울지 알아야 하니 이름에 박아 둔다. 리버싱에서 이게 중요한 이유: 디스어셈블한 코드에서 @숫자나 함수 끝의 ret 16을 보면 인자가 몇 개였는지 역산할 수 있다. 심볼이 지워진 바이너리에서도 함수 시그니처를 복원하는 첫 단서가 된다.
또 하나 눈여겨볼 건 x86판과 x64판이 나란히 있다는 점이다. 같은 프로그램을 두 아키텍처로 짜 놓고 디스어셈블 결과를 비교하면, 32비트의 push-기반 인자 전달이 64비트에서 레지스터(RCX·RDX·R8·R9) 기반으로 바뀌는 게 눈으로 보인다. 이 커리큘럼 전체를 관통하는 학습 방식이 여기 압축돼 있다.
0x0007-copyfile/ 폴더 안의 파일들은 0x000b-copyfile.sln · 0x000b-copyfile.vcxproj · 0x000b-copyfile.exe다. 폴더는 7번인데 내용물은 11번(0x000b)이다. 예제를 재배치하면서 프로젝트 파일명을 안 바꾼 흔적으로 보인다.
또 번호가 0x0001 → 0x0006 → 0x0007 → 0x0010 → 0x0011 → 0x0012 → 0x0013으로 건너뛴다. 0x0002~0x0005, 0x0008~0x000f가 통째로 비어 있다. 강의에서는 그 번호를 언급하는데 저장소에는 없는 상태라, "내가 뭘 놓쳤나" 하고 헤매기 쉽다. 없는 게 정상이라는 걸 알고 넘어가면 된다.
.i64)를 열려면 IDA Pro가 필요하다저장소에 커밋된 .i64 파일 13개는 IDA Pro가 분석 결과를 저장한 데이터베이스다. 무료판 IDA Free는 버전에 따라 이 파일을 못 열거나 기능이 제한된다. 학습자 입장에서 현실적인 대안은 무료 오픈소스 Ghidra로 같은 .exe를 직접 열어 분석하는 것이다 — 저자도 Ghidra 플러그인(G-AVR·G-Pulley)을 따로 만들어 배포하고 있으니 방향이 어긋나지도 않는다.
x86 코스의 레슨 제목을 보면 규칙이 바로 보인다.
Lesson 22: ASM Program 1 [Moving Immediate Data]
Lesson 23: ASM Debugging 1 [Moving Immediate Data]
Lesson 24: ASM Hacking 1 [Moving Immediate Data]
Lesson 25: ASM Program 2 [Moving Data Between Registers]
Lesson 26: ASM Debugging 2 [Moving Data Between Registers]
Lesson 27: ASM Hacking 2 [Moving Data Between Registers]
... 6세트 반복 (레슨 22~39)
같은 주제를 세 번, 다른 관점으로 돈다. 이게 이 커리큘럼의 핵심 교수법이고, Hacking Windows·Pico·Rust 코스에서도 그대로 반복된다.
Program(짓기): 먼저 자기 손으로 어셈블리를 짜서 돌린다. 남의 코드를 읽기 전에 "이 명령어가 무슨 일을 하는지"를 몸으로 안다.
Debug(들여다보기): 그 프로그램을 디버거에 걸고 한 줄씩 실행하며 레지스터·메모리·스택이 어떻게 변하는지 관찰한다. 내가 짠 코드니까 정답을 이미 아는 상태로 관찰 훈련을 한다 — 이게 결정적이다. 모르는 바이너리부터 시작하면 관찰과 추측이 뒤섞여 실력이 안 는다.
Hack(부수기): 마지막으로 그 바이너리의 메모리나 명령어를 직접 고쳐 동작을 바꾼다. 조건 분기를 뒤집거나 값을 덮어쓴다. "읽을 줄 안다"에서 "바꿀 줄 안다"로 넘어가는 단계이자, 리버싱이 실제로 쓰이는 방식(패치·크랙·취약점 익스플로잇)의 축소판이다.
교육학적으로 보면 "자기가 만든 것을 분석 대상으로 삼는다"는 게 이 설계의 요체다. 학습자는 정답(소스 코드)을 손에 쥔 채 문제(기계어)를 푼다. 답을 아니까 디스어셈블 결과와 원본 소스를 1:1로 대응시키며 "컴파일러가 이걸 이렇게 바꾸는구나"를 익힐 수 있다. 이 대응 감각이 쌓이면, 나중에 소스 없는 바이너리를 봐도 "이건 for 루프였겠다"가 보이기 시작한다.
코스별 초반 레슨 제목을 나란히 놓으면 반복 구조가 드러난다.
| 단계 | x86 Course | ARM-32 Course 1 | x64 Course | Hacking RISC-V |
|---|---|---|---|---|
| 동기 | Goals · Techniques · 맬웨어 종류 | The Meaning Of Life | The Cyber Revolution | Why RISC-V |
| 수의 표현 | 2진수 · 16진수 | 수 체계 · 2진 덧셈/뺄셈 | 트랜지스터 · 논리게이트 · 수 체계 | 2진수 · 16진수 |
| 하드웨어 | 트랜지스터와 메모리 · 바이트/워드 | 워드 길이 · 레지스터 | — | ESP32-C3 보드 |
| CPU 상태 | 범용/세그먼트/IP/제어 레지스터 · 플래그 | PC · CPSR · LR · SP | — | — |
| 메모리 | 스택 · 힙 | 부트 절차 · 폰노이만 · 파이프라인 | — | Advanced OPS(메모리·비트 조작) |
| 실습 | Program/Debug/Hack ×6 | ADD 등 명령어별 | 동일 패턴 | PlatformIO 프로젝트 |
이 반복이 지루함이자 강점이다. 이미 x86을 뗀 사람이 ARM 코스를 들으면 앞부분 10강은 거의 복습이라 지루하다. 하지만 "레지스터"라는 같은 이름이 아키텍처마다 몇 개이고 어떤 규칙으로 쓰이는지를 나란히 놓고 보게 되므로, ISA(명령어 집합 구조)라는 개념이 추상적 지식에서 구체적 감각으로 바뀐다.
제목만 보면 맬웨어 분석·바이너리 크랙을 기대하게 되는데, 실제 550강의 절반 이상은 어셈블리 프로그래밍과 임베디드 드라이버 작성이다. RP2350 드라이버 6코스 180강 + Assembler 24강 + Embedded Hacking 40강만 해도 244강이다. 리버싱의 기반 체력(어셈블리 독해력)을 기르는 데는 최고지만, "패킹된 맬웨어를 언패킹하는 법" 같은 실전 기법은 이 커리큘럼의 범위가 아니다. 기대치를 맞춰 두는 게 좋다.
로컬 예제 7종이 전부 Visual Studio 솔루션(.sln/.vcxproj)이고, 대상은 Win32 API다. macOS나 리눅스만 쓰는 사람은 이 부분을 그대로 따라 할 수 없다(VM이 필요하다). 반대로 후반 임베디드 코스는 PlatformIO·Rust 툴체인이라 크로스 플랫폼이다. 코스마다 요구 환경이 다르다는 걸 시작 전에 확인해야 시간을 아낀다.
README 최상단에 Discord 초대와 하드웨어 배지 $29.99 판매 링크(유튜브 프로모 영상 포함)가 배치돼 있다. 강의 자체는 전부 무료이고 Apache-2.0이므로 부정직한 구조는 아니다. 다만 "완전 무료 교육 자료"를 기대하고 들어왔다가 상단 절반이 홍보인 걸 보면 인상이 갈린다. 사실로 인지하고 스크롤을 내리면 그만이다. 배지 자체도 저장소에 암호 엔진 문서·수식 11종이 공개돼 있어 학습 자료로서의 값어치는 실재한다.
| 코스 계열 | 필요한 것 | 비용 |
|---|---|---|
| x86 · x64 (레슨 1–163) | Linux(VM 가능) · NASM/GAS · GDB · vim. 강의가 리눅스 설치와 vim 사용법부터 가르친다 | 무료 |
| Hacking Windows (204–233) | Windows + Visual Studio(MASM 포함) · x64dbg 또는 IDA/Ghidra | 무료(VS Community) |
| 로컬 예제 0x0001–0x0013 | Visual Studio · 디스어셈블러. 커밋된 .i64는 IDA Pro용 — Ghidra로 .exe를 직접 열 것 | 무료(Ghidra) / IDA Pro는 유료 |
| ARM-32/64 (41–183) | 라즈베리파이 또는 QEMU ARM 에뮬레이션 | 무료~5만원대 |
| Pico · RP2350 (184–203, 342–521) | Raspberry Pi Pico 2 (RP2350) · SWD 디버그 프로브 · Pico SDK | 1~2만원 + 프로브 |
| Hacking Bits · Assembler (323–332, 527–550) | ATmega328P(아두이노 우노) · 브레드보드 · LCD/시프트레지스터/모터/릴레이/IR 등 부품 · avr-gcc·avrdude | 부품 키트 3~5만원 |
| Hacking RISC-V (333–341) | ESP32-C3 개발보드 · PlatformIO | 1만원 내외 |
| Embedded Rust · Wasm (261–271, 522–526) | Rust 툴체인 · Embassy · wasm32 타깃 · RP2350 또는 micro:bit | 무료 + 보드 |
x86 · ARM-32 · x64 · ARM-64 · Hacking Windows · Go · Rust까지 약 260강은 하드웨어가 전혀 필요 없다. ARM 파트도 QEMU 에뮬레이션으로 대체 가능하다. 여기까지 완주한 뒤에도 계속하고 싶으면 그때 보드를 사는 게 합리적이다. 먼저 reversing-for-everyone.pdf를 내려받아 두는 것이 첫 단계다(§4 불편 2 참고).
0x0001-hello_world-x86 Debug/의 .exe를 Ghidra로 열고, 디스어셈블 결과를 §5의 main.asm 원본과 한 줄씩 대조한다. push 순서가 인자 순서의 역순인 이유, MessageBoxA가 어떻게 임포트 테이블에 잡히는지를 확인하면 성공. 그다음 x64판으로 같은 걸 해서 인자 전달이 레지스터로 바뀐 것을 눈으로 확인한다.
README를 파싱해 레슨 번호 · 코스명 · 제목 · 링크를 CSV나 JSON으로 뽑는 스크립트를 짠다(정규식 ^## Lesson (\d+): (.+?) \((.+)\)부터 시작하면 된다). 그런 다음 내 목표에 맞는 순서로 재정렬한 개인 학습 플랜을 만든다. §4에서 지적한 "레슨 번호로 점프할 수 없다"는 문제를 스스로 해결하는 셈이고, 덤으로 진도 체크리스트가 생긴다.
커리큘럼을 따라가는 대신 패턴만 빌려온다. (a) C로 "비밀번호를 맞히면 통과"하는 20줄짜리 프로그램을 짠다. (b) GDB나 x64dbg로 한 줄씩 실행하며 비교 명령(cmp)과 분기(jne)를 찾는다. (c) 그 분기를 바이트 단위로 패치해 어떤 비밀번호를 넣어도 통과하게 만든다. 이 한 세트를 완주하면 550강의 핵심 사이클을 몸으로 이해한 것이다.
int add(int a, int b) { return a + b; } 딱 하나를 x86-64 · ARM64 · RISC-V로 각각 컴파일한다(리눅스에서 크로스 컴파일러 3종이면 되고, 보드는 필요 없다). objdump -d로 세 결과를 나란히 놓고 인자가 어느 레지스터로 오는지 · 반환값이 어디로 가는지 · 함수 프롤로그/에필로그가 어떻게 다른지를 표로 정리한다. 이 커리큘럼이 6종 아키텍처를 반복하는 이유를 30분 만에 체감할 수 있다.
Hello World를 C · Go · Rust로 각각 컴파일해 파일 크기와 함수 개수를 비교한다. C는 수십 KB인데 Go는 1MB를 훌쩍 넘고, 심볼 테이블에 runtime.* 함수가 수천 개 뜬다. 왜 그런지(정적 링크된 런타임·가비지 컬렉터·고루틴 스케줄러) 조사하고, "언어별로 리버싱 난이도가 왜 다른가"를 한 페이지로 정리한다. 이 커리큘럼의 Go(12강)·Rust(15강) 코스가 왜 따로 있는지에 대한 답이 여기 있다.
AVR 부품 키트가 없어도 simavr이나 SimulIDE로 ATmega328P를 시뮬레이션할 수 있다. Assembler 코스의 Blink(Ch.2)부터 시프트 레지스터(Ch.16)까지를 시뮬레이터에서 돌려 본다. 실물의 손맛은 없지만 타이머 레지스터 설정과 비트 조작이라는 핵심은 그대로 배울 수 있고, 나중에 보드를 샀을 때 바로 써먹을 수 있다.
이 커리큘럼은 개념 중심이라 도구 숙련은 따로 채워야 한다. 무료 경로로는 Ghidra(NSA 공개 · 디컴파일러 내장 · 스크립팅 가능)가 중심이고, 동적 분석은 x64dbg(Windows) · GDB + pwndbg/GEF(Linux)다. 여기에 Frida(실행 중 프로세스에 JS로 후킹)를 얹으면 모바일 앱과 게임 분석까지 열린다. 저자가 만든 Ghidra 플러그인 G-AVR·G-Pulley를 읽어 보면 디스어셈블러를 확장하는 법도 배울 수 있다.
§6 한계 1에서 짚었듯 실전 기법은 범위 밖이다. 이어서 볼 것: 패킹/언패킹(UPX부터 시작), 안티디버깅 우회, 바이너리 diffing(BinDiff — 패치 전후를 비교해 취약점을 역산), 심볼릭 실행(angr). 훈련장으로는 crackmes.one과 pwnable.kr, 그리고 이 저장소 저자가 만든 DC540 CTF 9종(dc540-0x00001~0x00009)이 바로 이어지는 난이도다.
리버싱은 결국 컴파일러가 한 일을 거꾸로 읽는 것이므로, 컴파일러를 알면 속도가 붙는다. Compiler Explorer(godbolt.org)에서 C 코드를 치면 어셈블리가 실시간으로 나오는데, -O0과 -O2를 토글하며 최적화가 코드 구조를 얼마나 뭉개는지 보는 게 가장 효율적인 훈련이다. 그다음 ABI 문서(System V AMD64 · AAPCS64 · RISC-V calling convention)를 직접 읽으면, 과제 4의 비교표가 "왜 그런지"까지 설명된다.
이 커리큘럼의 후반 무게중심이 여기다. 이어서 볼 것: 펌웨어 추출(SPI 플래시 덤프 · JTAG/SWD), binwalk로 펌웨어 이미지 해부, 글리칭/폴트 인젝션(전압·클럭을 흔들어 보안 검사를 건너뛰기), 사이드채널 분석. Ouroboros 배지의 암호 엔진 문서(LFSR · ARX · Davies-Meyer · CTR 모드 수식 11종)가 경량 암호 구현을 실물로 뜯어보는 좋은 출발점이다.
| 용어 | 뜻 |
|---|---|
| 리버스 엔지니어링 | 컴파일된 프로그램에서 원래 동작·설계를 되짚어 내는 일. 소스·주석·변수명이 없는 상태에서 시작 |
| 정적 분석 | 실행하지 않고 디스어셈블러로 코드를 읽는 방식. 악성코드에 안전 |
| 동적 분석 | 디버거로 실제 실행하며 레지스터·메모리 변화를 관찰하는 방식 |
| 디스어셈블러 | 기계어 → 어셈블리 텍스트로 되돌리는 도구. IDA(유료) · Ghidra(무료) · objdump |
| 디컴파일러 | 한 단계 더 나아가 C 비슷한 의사코드까지 복원. Ghidra에 내장 |
| ISA | 명령어 집합 구조. CPU가 이해하는 명령어 목록과 규칙. x86-64 · ARM64 · RISC-V 등 |
| 레지스터 | CPU 안의 초고속 저장소 몇 개. 아키텍처마다 개수·이름·용도 규칙이 다르다 |
| 스택 / 힙 | 지역변수·함수 호출 흔적이 쌓이는 영역 / 실행 중 크기가 정해지는 동적 할당 영역 |
| 호출 규약 | 함수 인자를 어디로 넘기고 스택은 누가 치우는지에 대한 약속. stdcall · cdecl · System V 등 |
| name decoration | MessageBoxA@16처럼 인자 크기를 이름에 붙이는 것. 인자 개수 역산의 단서 |
| MASM / NASM | Microsoft / Netwide 어셈블러. 문법이 다르지만 같은 x86 기계어를 낸다 |
| ATmega328P | 아두이노 우노의 8비트 AVR 마이크로컨트롤러. Assembler 코스의 주 무대 |
| RP2350 | Raspberry Pi Pico 2의 칩. ARM 코어와 RISC-V 코어를 둘 다 갖고 있어 비교 학습에 이상적 |
| ESP32-C3 | RISC-V 코어를 쓰는 저가 Wi-Fi 마이크로컨트롤러. RISC-V 코스의 보드 |
| WebAssembly (Wasm) | 브라우저용으로 만들어진 이식 가능한 바이트코드. 최근엔 마이크로컨트롤러에도 올린다 |
| Embassy | 임베디드 Rust용 비동기 프레임워크. Embedded Rust 코스에서 사용 |
| PlatformIO | 여러 보드·툴체인을 한 설정으로 다루는 임베디드 개발 환경 |
| Fritzing (.fzz) | 브레드보드 회로도 편집기 파일. 저장소에 회로도 3종의 원본이 포함 |
| linguist-detectable | GitHub 언어 통계에 특정 확장자를 포함/제외하는 .gitattributes 설정 |
reversing-for-everyone.pdf(약 430p)를 내려받아 두는 편이 안전하다0x00009 (MicroPython · C · 어셈블러 · Windows CTF)