1. 메모리 섹션 확인

- Bash에서

readelf -S ./파일명
readelf -S ./파일명 | grep -E '\.got|\.plt|\.bss|\.data'

readelf -S ./vuln          # 섹션 주소 확인
readelf -r ./vuln          # GOT relocation 확인
objdump -R ./vuln          # GOT에 들어가는 함수 주소 확인
objdump -d ./vuln          # PLT 포함 디스어셈블

objdump -R ./vuln

- gdb 에서

info files
# 필터링
maintenance info sections
maintenance info sections .got

- pwn

elf = ELF('./vuln')

print(hex(elf.got['puts']))
print(hex(elf.plt['puts']))
print(hex(elf.symbols['main']))

2. 입력 넣기

- 파일 내용 stdin

run < input.txt
 

- payload 바로 넣기

run <<< $(python3 -c 'print("A"*100)')
보통은 아래 코드
python3 -c 'print("A"*100)' > input.txt
gdb ./vuln
 

gdb 에서

run < input.txt
 

3. 메모리 값 변경

- 특정 주소에 int 값 쓰기

set *(int*)0x404000 = 1234
- 특정 주소에 1바이트 쓰기
set *(char*)0x404000 = 0x41

- 특정 주소에 long 값 쓰기

set {long}0x404000 = 0xdeadbeef
 

- 실행 흐름 변경

set $rip = 0x401234
- 레지스터 변경
set $eip = 0x08049186
 

 


4. 프로세스 / 매핑 확인

- 메모리 매핑 보기
PIE, libc base, stack, heap 주소 확인할 때 자주 씀

info proc mappings
- 프로세스 정보
info proc
- 로드된 공유 라이브러리
info sharedlibrary
 

5. ASLR 관련

- gdb 안에서 ASLR on/off

set disable-randomization on
set disable-randomization off
 

- 현재 설정 확인

show disable-randomization
 

6. attach 관련

실행 중인 프로세스에 붙기

gdb -p PID
 

gdb 안에서는

attach PID
 

detach

detach
 

6. pwndbg에서 자주 쓰는 명령어

- 현재 상태

context
 

- 메모리 매핑

vmmap
- 패턴 생성 / offset 찾기
cyclic 100
 
cyclic -l 0x6161616c
 

- 스택 보기 / 32bit

telescope $rsp
telescope $esp
 

- heap 보기

heap
 

- glibc heap bins 보기

bins
 

- heap chunk 시각적으로 보기

vis_heap_chunks
- 메모리에서 hex 값 검색
search -x deadbeef
- 문자열 검색
search "/bin/sh"
 

- 가젯

rop
 

7. 시스템해킹에서 특히 많이 쓰는 조합

함수 주소 확인

p system
p puts
p printf
p win
 

현재 스택 보기

x/30gx $rsp
 

또는 pwndbg

telescope $rsp
 

현재 실행 위치 보기

x/10i $rip
 

GOT 확인

got
 

또는 기본 gdb

info files
maintenance info sections .got
 

libc base 확인

vmmap libc
 

/bin/sh 찾기

search "/bin/sh"
 

보호기법 확인

checksec
 

8. 제일 자주 쓰는 핵심

b main
r
c
ni
si
x/20gx $rsp
x/20i $rip
i r
p system
info proc mappings
info files
disas main
 

pwndbg면 추가로

checksec
vmmap
got
plt
telescope $rsp
cyclic 100
cyclic -l 값
search "/bin/sh"

'computer basics' 카테고리의 다른 글

[GDB] GDB 기초  (0) 2026.02.10
[Linux] Linux Memory Layout  (0) 2026.02.10

1. GNU Debugger (GDB)

설치

sudo apt-get install gdb

pwndbg

git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh

 

- GDB vs. pwndbg

: gdb는 리눅스 기본 디버거, 명령어 위주로 가독성 낮고 직접 다 쳐야함

: pwndbg는 gdb 위에서 돌아가는 확장 플러그인으로 스택, 레지스터, 힙, pie, alsr 한눈에 보여줌


2. 사용 방법

1) 파일 불러오기

file ./debugee

디버깅 정보 포함: 컴파일 할때 -g 옵션을 주어 컴파일함

근데 대부분의 바이너리는 -g 옵션 없이 컴파일한 바이널임

2) 실행 흐름 제어

'run'

디버거는 프로그램을 실행시키면서 분석하는 도구

pwndbg> run <프로그램 인자>

 

'break & continue'

break로 breakpoint 잡음

continue로 실행 재개하고 다음 중단점까지 실행함, breakpoint없으면 끝까지 실행

-> 여러번 실행하고 싶으면 'c <숫자>' 입력

 

'entry & start'

리눅스는 실행파일의 형식으로 ELF(Executable and Linkable Format)를 규정하고 있음

ELF-> 헤더 + 여러 섹션으로 구성되어있음

           헤더 -> 실행에 필요한 여러 정보

           섹션 -> 머신 코드, 프로그램 문자열 등 데이터

 

ELF의 헤더 중 진입점(Entry Point, EP)라는 필드가 있음, 운영체제는 ELF를 실행할 때, EP의 명령어부터 프로그램을 실행함

'readelf' 명령어로 확인할 수 있음

ep가 0x401050임을 알 수 있음

 

start 명령어는 gdb에서 main()부터 분석할 수 있게 함

si(Step into) : 함수 흐름대로 진행, 함수에 들어감

ni(next instruction): 함수 스택프레임 건너뛰고 진행됨

finish: si한 후 함수 스택프레임 길어지면 원래 흐름대로 돌아감

 


3. 디버깅을 위해 사용하는 명령어

1) INFO

'info reg ~', 'info breakpoints'

pwndbg> b $rdi

info reg -> 단축어로 i r

info breakpoints -> 단축어로  i b

disable 1 -> 1번 중단점 비활성화

enable 1 -> 1번 중단점 활성화

delete 1 -> 중단점 1 삭제 d 1

 

2) disassemble

disass 로 사용가능

u, nearpc, pdisass -> 디어셈블된거 가독성 좋게 바꿔줌

 

 

3) examine / x/s ..

'x/< 포맷 및 크기>' 'x/<개수><포맷 및 크기>

ex)

pwndbg> x/5i $rip
=> 0x4004e7 <main>:     push   rbp
   0x4004e8 <main+1>:   mov    rbp,rsp
   0x4004eb <main+4>:   sub    rsp,0x10
   0x4004ef <main+8>:   mov    DWORD PTR [rbp-0xc],0x0
   0x4004f6 <main+15>:  mov    DWORD PTR [rbp-0x8],0x1

 

4) telescope

강력한 메모리 덤프임, 메모리가 참조하고 있는 주소를 재귀적으로 탐색하여 값을 보여줌

pwndbg> tele $rsp
00:0000│ rsp  0x7fffffffc228 —▸ 0x7ffff7a05b97 (__libc_start_main+231) ◂— mov    edi, eax
01:0008│      0x7fffffffc230 ◂— 0x1
02:0010│      0x7fffffffc238 —▸ 0x7fffffffc308 —▸ 0x7fffffffc557 ◂— '/home/dreamhack/debugee'
03:0018│      0x7fffffffc240 ◂— 0x100008000
04:0020│      0x7fffffffc248 —▸ 0x4004e7 (main) ◂— push   rbp
05:0028│      0x7fffffffc250 ◂— 0x0
06:0030│      0x7fffffffc258 ◂— 0x71eb993d1f26e436
07:0038│      0x7fffffffc260 —▸ 0x400400 (_start) ◂— xor    ebp, ebp

 

 

5) vmmap

가상의 메모리 레이아웃을 보여줌,  프로그램이 실행된 상태에서 이용 가능

pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
             Start                End Perm     Size Offset File
          0x400000           0x401000 r--p     1000      0 /home/dreamhack/debugee
          0x401000           0x402000 r-xp     1000   1000 /home/dreamhack/debugee
          0x402000           0x403000 r--p     1000   2000 /home/dreamhack/debugee
          0x403000           0x404000 r--p     1000   2000 /home/dreamhack/debugee
          0x404000           0x405000 rw-p     1000   3000 /home/dreamhack/debugee
          0x405000           0x426000 rw-p    21000      0 [heap]
    0x7ffff7d7f000     0x7ffff7d82000 rw-p     3000      0 [anon_7ffff7d7f]
    0x7ffff7d82000     0x7ffff7daa000 r--p    28000      0 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7daa000     0x7ffff7f3f000 r-xp   195000  28000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7f3f000     0x7ffff7f97000 r--p    58000 1bd000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7f97000     0x7ffff7f9b000 r--p     4000 214000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7f9b000     0x7ffff7f9d000 rw-p     2000 218000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7f9d000     0x7ffff7faa000 rw-p     d000      0 [anon_7ffff7f9d]
    0x7ffff7fbb000     0x7ffff7fbd000 rw-p     2000      0 [anon_7ffff7fbb]
    0x7ffff7fbd000     0x7ffff7fc1000 r--p     4000      0 [vvar]
    0x7ffff7fc1000     0x7ffff7fc3000 r-xp     2000      0 [vdso]
    0x7ffff7fc3000     0x7ffff7fc5000 r--p     2000      0 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7fc5000     0x7ffff7fef000 r-xp    2a000   2000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7fef000     0x7ffff7ffa000 r--p     b000  2c000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7ffb000     0x7ffff7ffd000 r--p     2000  37000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7ffd000     0x7ffff7fff000 rw-p     2000  39000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffffffde000     0x7ffffffff000 rw-p    21000      0 [stack]
0xffffffffff600000 0xffffffffff601000 --xp     1000      0 [vsyscall]
pwndbg>

** 파일 매핑?

-> 어떤 파일을 메모리에 적재하는 것을 파일 매핑이라고 함

 

6) backtrace

 bt 라는 명령어로 콜 스택을 확인할 수 있음, 어떤 인자가 어디서왔는지 추적 가능

pwndbg> b add
Breakpoint 1 at 0x40113e
pwndbg> r
[중략]
pwndbg> bt
#0  0x000000000040113e in add ()
#1  0x0000000000401177 in main ()
#2  0x00007ffff7dce1ca in __libc_start_call_main (main=main@entry=0x40114e <main>, argc=argc@entry=1, argv=argv@entry=0x7fffffffc938) at ../sysdeps/nptl/libc_start_call_main.h:58
#3  0x00007ffff7dce28b in __libc_start_main_impl (main=0x40114e <main>, argc=1, argv=0x7fffffffc938, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
    stack_end=0x7fffffffc928) at ../csu/libc-start.c:360
#4  0x0000000000401075 in _start ()
pwndbg>

 

 

7) dump memory

프로세스 메모리 상태를 파일로 저장하는 명령어

dump memory <파일명> <시작주소> <끝주소>

 

8) context

pwndbg는 주요 메모리들의 상태를 프로그램이 실행되고 있는 context라고 부름

기본적으로 프로그램이 중단되면 ctx를 출력하지만 별도로 ctx 명령어로 실행할 수도 있음

4개의 영역 -> reg, disasm(rip부터 여러 줄에 걸쳐 디스어셈블된 결과), stack(rsp부터 스택의 값), backtrace(현재 rip에 도달할 때까지 어떤 함수들이 중첩되어 호출됐는지 보여줌)

 

 

9) set

프로세스 메모리 상태를 변경할 수 있는 명령어

주로 레지나 특정 주소의 메모리 값을 변경함

실행 중에서 가능

set <주소/레지스터> = <변경할 값>
pwndbg> set $rax = 0
pwndbg> set $rsp = $rbp

자료형 변경

pwndbg> set *(unsigned int*)0x400000 = 10
# 0x400000 주소를 unsigned int * 형으로 역참조 후 여기에 정수 10을 저장한 것

pwndbg> set *(float*)0x400010 = 3.14
# 0x400010 주소를 float* 형으로 역참조 후 여기에 부동소수점 값 3.14 저장

타입크기

unsigned byte 1 byte
unsigned int 4 bytes
unsigned long 8 bytes

 

'computer basics' 카테고리의 다른 글

[GDB 명령어] 명령어 모음  (0) 2026.05.15
[Linux] Linux Memory Layout  (0) 2026.02.10

1. 메모리 레이아웃

프로세스가 실행될 때 각 프로세스는 독립된 메모리 공간을 할당

이때 메모리 공간은 용도에 따라 여러 영역으로 나뉘고 특정한 목적을 갖음

메모리 영역을 나누면 용도에 맞게 권한 부여 가능 -> read, write,execute)

 

리눅스에서는 프로세스 메모리를 5가지 segment로 구분

segment: 데이터의 용도별로 메모리 구획을 나눈 것

ex) code, data, bss, heap, stack


2. 세그먼트

1) 코드 세그먼트 (Code Segment)

코드 세그먼트는 실행 가능한 기계어 코드가 위치하는 영역, 텍스트 세그먼트(text segment)라고 부름

-> read, execute 가능 but write은 안 됨 code overwirte이 가능하기 때문

ex)

section .text
    global _start

_start:
    mov rax, 1
    mov rdi, 1
    mov rsi, message
    mov rdx, message_len
    syscall

    mov rax, 60
    xor rdi, rdi
    syscall

-> .text 세그먼트에 기계 코드가 자리잡힘 

 

2) 데이터 세그먼트 (Data Segment)

컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치함

cpu가 데이터를 읽음 -> read 권한이 부여됨

  • data 세그먼트: 쓰기 가능 / 전역 변수 ..
  • rodata(read-only data) 세그먼트: 쓰기 불가능 / 전역 상수
int data_num = 31337;                       // data
char data_rwstr[] = "writable_data";        // data
const char data_rostr[] = "readonly_data";  // rodata
char *str_ptr = "readonly";  // str_ptr은 data, 문자열은 rodata

int main() { ... }

 

3) BSS 세그먼트 (BSS Segment, Block Started By Symbol Segment)

컴파일 시점에 값이 정해지지 않은 전역 변수가 위치하는 메모리 영역

개발자가 선언만 하고 초기화하지 않은 전역변수 등이 있음

프로그램이 시작될 떄, 모두 0으로 값이 초기화됨

-> read, write, execute 권한이 부여됨

ex)

int bss_data;

int main() {
  printf("%d\n", bss_data);  // 0
  return 0;
}

-> bss_data가 BSS 세그먼트에 위치

4) 스택 세그먼트 (Stack Segment)

프로세스의 스택이 위치하는 영역으로 함수의 매개변수나 지역 변수같은 임시 변수들이 실행 중에 저장됨

NX(Non-Executable) 보호기법이 나오기 전까지 실행 권한이 있었지만 Shellcode injection 기법으로 스택을 호출하게됨

따라서 컴파일 시 기본적으로 NX 보호기법이 활성화되고 실행 권한이 사라짐

-> read, write 권한

 

- Stack Frame

: 스택을 구성하는 단위로 함수가 호출될 때 전달된 매개변수, return-address, 지역 변수를 저장함

  한 프로세스가 실행될 때, 처음부터 얼마 정도의 스택 프레임을 사용하게 될지 몰라서 

  스택이 부족하면 그때마다 확장해줌. 따라서 '아래로 자란다'는 스택이 주소가 큰쪽에서 작은쪽으로 확장하기 때문 (주소 sub)

 

* c언어, 파이썬은 컴파일러에서 스택 프레임을 자동으로 설정해준다.
***어셈블리어는?***
-> '함수 프롤로그'와 '함수 에필로그' 두 방법으로 관리

1. 함수 프롤로그 (Function Prologue)
push ebp
mov ebp, esp
sub esp, 0x100​
- push ebp: 현재 페이스 포인터를 스택에 푸쉬하여 나중에 에필로그 과정에서 복구할 수 있도록 함
- mov ebp, esp: 베이스 포인터를 현재 스택 포인터의 주소로 설정함
- sub esp. 0x100: 스택 프레임 공간 확보

2. 함수 에필로그 (Function Epilogue)
mov esp, ebp
pop ebp
ret​

- mov esp, ebp: esp를 ebp의 주소로 바꿈
- pop ebp: 푸쉬했던 베이스 포인터의 값을 다시 pop 연산으로 ebp에 넣은 후 스택에서 제거
- ret: 함수 호출 전 주소로 돌아감

leave
ret

mov esp, ebp; pop ebp -> leave로 가능 x86 내장 명령어

 

5) 힙 세그먼트 (Heap Segment)

힙 데이터가 위치하는 세그먼트로 스택과 마찬가지로 동적 할당 가능

리눅스에서는 스택과 반대방향으로 자란다. 즉, 주소가 커지는 쪽으로 자람

 

c언어에서는 malloc(), calloc() 등의 함수로 호출해서 할당받는 메모리가 이 세그먼트에 위치

-> read, write 가능

어셈블리어에서는 sys_brk(), mmap()와 같은 시스템 로 힙 세그먼트 관리할 수 있음

ex)

int main() {
  int *heap_data_ptr =
      malloc(sizeof(*heap_data_ptr));  // 동적 할당한 힙 영역의 주소를 가리킴
  *heap_data_ptr = 31337;              // 힙 영역에 값을 씀
  printf("%d\n", *heap_data_ptr);  // 힙 영역의 값을 사용함
  return 0;
}

'computer basics' 카테고리의 다른 글

[GDB 명령어] 명령어 모음  (0) 2026.05.15
[GDB] GDB 기초  (0) 2026.02.10

+ Recent posts